Displaying controls on an alpha-blended form - winforms

I tried the Visual C# Kicks code for an alpha-blended form. This works (as soon as I remove the TransparencyKey property); that is, I can use the W3C's PNG alpha test image and see other windows underneath, but makes all controls on the form invisible. Presumably, they simply aren't painted, as OnPaint is overridden. I tried calling the superclass's OnPaint:
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
UpdateFormDisplay()
MyBase.OnPaint(e)
End Sub
, but this didn't change anything. (Calling MyBase.OnPaint first doesn't make any difference either.)
Unfortunately most articles about alpha-blended forms focus on pure splash screens without any controls on them — but we need a panel which first shows sign-in fields, then a progress bar.
The controls, by the way, do not need transparency; it's only on the outer edges that the PNG's transparency truly matters. So faking this by adding another form on top of this all (with the two always moving in tandem) might suffice, but I'd prefer a smoother solution.

Try putting this in your form ctor after InitializeComponents();
base.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);

Related

Painting over a custom control that already paints

I created several custom .NET Winform controls that inherit from UserControl. One of them, ArrowButton, shares a lot of properties with another, slightly simpler one called CustomButton. ArrowButton is essentially CustomButton but with an arrow drawn next to the text. Both of them currently add a common Button to the UserControl base and then have Paint events call functions that draw the gradiant background, customized text, and arrow graphics in the case of the ArrowButton. This works fine.
But then I started thinking it would make sense to have the ArrowButton use a CustomButton instead of the normal button so that it gets the background and text from that, and all ArrowButton would have to do is draw the arrow on top of it.
I replaced the Button in ArrowButton with CustomButton. So far so good. But when it runs, it just looks like a CustomButton and the arrow part is never being drawn. As far as I can tell, the painting code in ArrowButton is not being called. Or possibly being painted over by the CustomButton.
So is it possible to have CustomButton paint first and then ArrowButton paint on top of it in an additive fashion? And if so should I be doing so using
void InitializeComponent(void)
{
this->CustmBtn = (gcnew CustomButton());
....
this->CustmBtn->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &ArrowButton::ArrowBtn_Paint);
overriding OnPaint(), or using some other method? I'm working in C++/CLI but C# examples will probably work too.
Edit - Extra details:
I changed ArrowButton to inherit from CustomButton instead of UserControl. This definitely seems like the way to go since I get to auto-inherit all of the properties from CustomButton and it still works fine in the VStudio designer. That said, it still refuses to draw the arrow. And I confirmed (using Console::WriteLine() calls) that both the Paint event function and my OnPaint() override functions where I'm trying to do the arrow paint are never getting called at all.
I came up with a solution of my own and as far as I can tell its a good one. Feels a lot simpler then the transparency or Region clipping-based workarounds I've seen in similar questions too.
I added this to CustomButton:
virtual void ExtraChildDraw(Graphics^ grph) {}
At the end of my CustomButton paint event function I call it and pass in the PaintEventArgs->Graphics reference I had been using there. Since it uses the default version of the function in the base class, it does nothing extra.
Then in ArrowButton or any other child-class I want to make of CustomButton I override the function and do all the extra 2D painting I want to add on top of what CustomButton does. It works great and even shows up correctly in the VStudio designer.

A combination of winforms' controls as a prefab?

In our winforms application we often have a situation where the same panel is used in different forms. Right now I simply copy the code and the designer elements from form to form but that is obviously a terrible practice.
So I thought of making a class that could be easily added to a different form as a "component". The only problem is to be able to prototype and maintain this panel in the visual designer in such a way that if I want to change the panel's appearance in the future it gets changed for every class instance I created.
For instance I have a panel that provides search functionality:
Alongside with the code for click/textChanged events. I want to encapsulate it in a class, which I would be able to instantiate and initialize in any form's constructor to instantly add these controls (alongside events) into that form. Now it is not necessary for me to see the controls in the designer of the recepient form, however, I need to be able to see them in the designer somewhere in order to modify them if I would ever require that.
And if I do modify the appearance somehow (for instance add an extra button) these controls instantly change across the entire project, everywhere I instantiated the class.
I do know that all this can easily be done just creating a new form and encapsulating everything in it, I just wonder if it can be done for a group of controls instead.
You just described the perfect use of a User Control. It's easy to use and direct.
First Add a user COntrol to the project:
Then add the desired controls on the user control:
Build the project and you will see the UserControl on the toolbox:
Add them to the form as a standard control:
If you change the code for the user control (in this case adding a button click handler) uit will affect all the intances of that user control:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = "Button Clicked"
End Sub
Note: If you have the Control in another project on the same solution, make sure you build that project too if you make any change.

Windows Forms user controls on localizable forms cause display issues in Designer

I have a simple user control (just an example): it is 40x100, but resizable. It has two buttons, one anchored at the top, one anchored at the bottom.
It put this control on a form and stretch it to 40x400. This works fine.
But as soon as I switch the form to Localizable = True and change the language to translate any strings, the Designer shows the user control
as if it was 40x100 for both the default an the translated language, i.e. the bottom button is not anchored.
Or better: the bottom button is displayed as if it was not anchored. The control occupies the correct amount of space (40x400), though (see selection highlight). And it displays fine during runtime, this is just a Designer issue.
A picture showing the issue.
Did I miss something here? Is this how it is supposed to work?
Im on VS2010 at the moment, tried the old VS2005 but it's the same there.
Thanks...
I could easily repro this problem by anchoring the second button to the bottom. The Anchor property has a few oddish failure modes, layout isn't always recalculated when it should be. You found one such case. I think the underlying issue is that the Size property is a localizable property as well and the designer fails to fire the required events when it starts a new localization set. Something like that, nothing very trivial.
You'll need to punt this problem and not rely on the Anchor property to get the button positioned correctly. That just takes a one-liner in your UserControl code, like:
protected override void OnResize(EventArgs e) {
button2.Top = this.ClientSize.Height - button2.Height;
base.OnResize(e);
}

performance in C# Application

i use some pictures in my 'MainForm' And My Windows Application was writing by c sharp.
i use this form to start other forms in my project.
And I use some label and panel with Transparent Color.
but when the program started i see many blink in transparent label and panel.
And it is very bad.
How I Can Fix this problem?
Enabling DoubleBuffered as stax suggested above is helpful but it may not be sufficient.
In your form, add the following method override:
protected override void OnPaintBackground(PaintEventArgs e) {}
And, in the OnPaint method, paint the background yourself instead. If you don't do this, drawing the background and painting are separate events, and background painting has higher priority, meaning that it will happen earlier.
Furthermore, if you add child controls (like labels), they receive their own paint background/paint events. You may be able to disable the Label's background. If I do stuff like this, I tend to not use controls but paint the text and the images in one OnPaint.
did you test it on multiple machines.
did you use an updated machine with all the .net service packs needed.
etc

Tag cloud control for WinForms .NET 2.0+

How would you render a tag cloud within a .NET 2.0+ WinForm application?
One solution that I am thinking of would be using the WebBrowser control and generating to some ad-hoc HTML, but that seems to be a pretty heavy solution.
Am I missing something more simple?
How about creating a user control that implements the Flow layout control? You could have a method for "Add(string tagName)" that would create a link label on the fly and add it to the Flow Layout control. The Flow Layout works just like the web, in that controls added to it are put in the order of creation.
Then you only have to add some logic to resize the Link Label based on hit count for that tag.
Well, you'll want a control with these major features:
Automatic layout of variable sized string snippets
Automatic mouse hit testing
Those are a bit hard to come by in WF controls. A RichTextBox with ReadOnly = true gives you the automatic layout, but not the hit testing. A ListBox with DrawItem can give you variable sized strings and hit testing, but not a natural layout.
I think I would use RTB and make hit testing work with the MouseDown event and GetCharIndexFromPosition(), reading back the tag at the clicked location. You'll need a bit of logic to find the starting and ending white space around the word.

Resources