I have a form to edit properties of something and I need to add a visual cue to show a user if a part is read only and can't be edited. My idea was to have a watermark style text appear over part of the form. An example of what I'm thinking is below
I'm having trouble getting text to display like that. I tried going more simple with a label but I cannot get the background of the label transparent even with the backcolor property.
Is putting text on a form like this possible in a simple manner?
I inserted a transparent png into a picture box and I have the same issue as I did with the label. I set the picture box backcolor to transparent and that didn't change anything.
I have a form to edit properties of something and I need to add a visual cue to show a user if a part is read only and can't be edited. My idea was to have a watermark style text appear over part of the form. An example of what I'm thinking is below
I'm having trouble getting text to display like that. I tried going more simple with a label but I cannot get the background of the label transparent even with the backcolor property.
Is putting text on a form like this possible in a simple manner?
It seems like that would be irritating to the users to me. Why not disable the text boxes?
I agree that the standard approach is to disable the controls. But if you intend to achieve that, you need to create a custom control that rotates and is transparent at the same time which is complex in nature.
The first time a red letter is covering something someone needs to see will draw some attention. Like a couple digits of the "Part Number". By the way, does that last label say Designs or designer?
You can't easily do this with Windows Forms, and I'm never 100% certain it's possible.I'm at home so I can't demonstrate but I can give you some search terms and history lessons.
The shortest possible story: WPF is the only Desktop-oriented framework that will get you easy transparency. UWP is a grandchild of WPF so it also gives you free transparency. Those are the best "solutions" to this problem.
For the rest of the solutions, a short history lesson.
WinForms is old. Really really old. It's a layer on top of GDI+, which is the Windows 2000 layer over GDI, which is the graphics system developed for Windows 3. The world was very different in Windows 3. You didn't have a GPU. You didn't have VRAM. All "controls" were rectangles and there was no such thing as transparency because they were not allowed to overlap (at least for a while). Windows 2k added more features, but unfortunately Windows Forms doesn't directly expose those.
So what "transparent" means to Windows Forms is "use the Form's background color". If you're in a world where controls never overlap, this basically works. I think it even works if the Form has a background image, but don't quote me on that. HOWEVER.
Win2K introduced the Window Style WS_EX_TRANSPARENT, and with it a new form of transparency. Partial transparency. If your control has this Window Style set (which you can do by overriding CreateParams), and if you do a few other incantations, you can get it.
What's "partial transparency"? Well, the way it works is if a control has that Window Style set, it forces every other control "beneath" it to render first. Then, any portions of its background that are transparent gets the pixels from those controls. Voila, transparent. But the pixel in the control HAS to be transparent. It can't be "partially transparent grey" or anything else that requires blending. And I can't remember properly, but I'm not sure if anything you render over those regions gets antialiased properly.
WPF and its descendants have true alpha blending. That means instead of "the pixel has to be fully transparent", you can use a partially-transparent color. And it will blend with other partially-transparent pixels beneath just like you'd expect.
Anyway, back to WinForms.
You might be able to succeed by overriding your Form's Paint event, but I have a suspicion it will render the controls after your drawing and if that's the case it won't work. You can do some trickery to take a cropped screenshot, render text over it, then display that as an image over the controls. Maybe that's some jank you don't want to try.
If that's the case, somewhere out there you can certainly find examples of Label controls that use WS_EX_TRANSPARENT. There used to be a really good one on Bob Powell's site, but a few years ago it disappeared from the internet. Had I known that would happen, I would've archived it. But I'm positive someone else has done an example of it before.
If that doesn't work, well... sometimes we want to do things that just aren't practical, and we have to find another way to accomplish the goal.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
On my machine JMC's code from the link in Kebo's post (#6) doesn't draw "over" combo boxes or text boxes. I didn't test all controls. I did note that it drew over labels and buttons.
You could always use a little hack and place a transparent borderless form overtop of your form and draw the watermark text in that form.
As a quick example, I just created a project with form1 (added a few controls to it) and form2 (a borderless form with a magenta background). I set the Transparency key for Form2 to magenta.
The code in Form1 for the example.
Code:
Public Class Form1
Dim WaterMark As New Form2
Private Sub ResizeWatermark(sender As Object, e As System.EventArgs) Handles Me.Move, Me.Resize
WaterMark.Bounds = Me.Bounds
End Sub
Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
WaterMark.Show(Me)
WaterMark.Bounds = Me.Bounds
End Sub
End Class
The code in Form2
Code:
Public Class Form2
Private BigFont As New Font("MicrosoftSansSerif", 36)
Private Sub Form2_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.TranslateTransform(100, 400)
e.Graphics.RotateTransform(-30)
e.Graphics.DrawString("Read Only Part", BigFont, Brushes.Red, New Point(0, 0))
End Sub
End Class
vs2010 project attached.
Last edited by passel; Oct 6th, 2017 at 02:55 AM.
Reason: Added picture
If you want that section to be read-only then why not just make it read-only? Disabled controls look different to enabled ones specifically as a visual cue to the user that they cannot edit them. It seems to me that you're trying to solve a problem that doesn't exist.
Ok ... if you really want to do it this way .. yes it is possible ... but not simple...
I have done stuff like this, on my own ... but later found sparkle (I don't use it personally tho)... but look into it ... It should make what you want to do quite easy...
Just put the read-only controls on a panel and use sparkle on that!
Finally able to play with this more, programming isn't my day job.
The bottom field shown is "Designer" and this is a form to edit properties on a CAD drawing. As for why I want red text saying read only part, my cad program changed their api and library parts can longer be edited. So I want a flashy way to alert people of a sudden change they may or may not fully understand. I can only image them being confused when the select button is disabled on random parts, so they are unable to modify those parts.
@passel
Thanks for posting that example. That is a simple trick and does exactly what I am looking for.
Final result (some fields blanked out)
When playing with passel's example code, I noticed the funny behavior below. It seems the bounds of a standard window is larger than the window appears. So the watermark can extend off of the main form. Making the bounds of the watermark form smaller than the main form bounds is a simple fix I played with. Also if the main form is a fixed size or has a minimum size this shouldn't matter. Just sharing for anyone finding this in the future.
Fix to keep watermark text over main form.
WaterMark.Bounds = New Rectangle(Me.Bounds.Left, Me.Bounds.Top, Me.Bounds.Width - 10, Me.Bounds.Height - 10)
For those concerned about being able to read the part number, add a line to set the opacity of the WaterMark form to whatever value you feel appropriate, for example, 50%, so you can read through the text.
Code:
Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
WaterMark.Opacity = 0.5
WaterMark.Show(Me)
WaterMark.Bounds = Me.Bounds
End Sub
For those concerned about being able to read the part number, add a line to set the opacity of the WaterMark form to whatever value you feel appropriate, for example, 50%
Logically I can't make that assumption, not knowing whether the part number is important or not since it is something that can't be changed it may not be. That is up to the designer and it wasn't a requirement of the original example. (And of course it is such an easy thing to do since it is a basic property of the form, it is pretty much a given that if you want it, use it).