I developed some components with their own OnPaint-override where I draw them.
I now added a status panel which is designed to overlap topmost with part of my form. I use a alpha-blended color to gray out the underlying controls and display a text on it.
Unfortunately some of my underlying custom controls paint themselves after the status bar and so draw themselves above the status bar. Debugging I found out that first the status bar on paint event was called, later the paint event of the underlying controls.
How can I make sure the proper order is used to paint?
When underlying components draw themselves the components infront of them should always be automatically invalidate so they redraw themselves but that is not happing. I also called SendToFront on the statusbar but that did not helper neither. So I am also asking what is the proper mechanism to maintain the order and how do the core components handle that.
Edit: I also run in this problem: With every run of my OnPaint-event my overlay gets more and more opaque because it draws with alpha=128--red again and again on itself.
To eliminate external factors (like variations between XP, Vista, Win7), you could:
blend the "status panel" graphics onto each control in their OnPaint handlers, so you don't need to mess about with a semi-transparent status window to achieve the desired display.
use one opaque control (essentially the status panel) and render the final image you want into it by compositing the graphics from the individual controls, which would elimimnate any uncertainty over how the rendering process will operate. This would mean that you'd have to add custom click handling, but that's usually a fairly trivial addition - one easy way around this is to put the main "display control" behind a set of invisible controls (the buttons) so that all the click handling can work as normal, but the painting is delegated to a single control.
Related
I have a set of custom controls and a list of geometric objects that I need to draw on the same handle.
I override the OnPaint procedure, put the base.OnPaint(e) in the first line and commence with the drawing of the geometric objects (via e.Graphics.DrawLine etc.).
Those are in a locked list and decay after a while.
Also the customized controls can move around the window.
Now this is almost working as intended except for this fun fact:
The geometric shapes appear only after a control is moved along/above their layouts.
I was able to reproduce this in a small environment: PASTEBIN
I tried flushing the graphics object; save/restore; changing Clip.
Nothing seemed to work.
I am guessing that regions only get invalidated and repainted once a control is present. But how can I force them to be drawn anyways?
Control.Invalidate will tell the framework that the control needs to be redrawn. It does this automatically to redraw controls after, for example, the mouse has obscured part of it, but it will only redraw a the small section that the mouse covered (hence why you end up with a "(re)painting with the mouse" effect. Also moving a window will force it to redraw, as does covering it with another window and then moving that window away again.
But if you are doing a bunch of custom painting, you need to let it know that the control needs to be redrawn by calling Invalidate yourself.
I am using c# winforms to show an Image. The displaying of the image is done using a user control. Now I want to provide the user to draw lines, put other small images, write text etc over the image on an overlay control. How can I provide this functionality? If I use another user control to show the overlay control with transparent back, will that work?? any other solution will be welcome.
You might try approaching this with a canvas (Panel) that handles painting the image as the background and all the annotations/markup afterwards. This will make the foreground appear to be transparent. I expect you'll want to set Control.DoubleBuffer for performance.
You might experiment with setting the style ControlStyles.AllPaintingInWmPaint. Also, try overriding Control.OnPaintBackground and do nothing, and override Control.OnPaint and do all your painting inside there.
If performance is still unacceptable, pay close attention to the PaintEventArgs.ClipRect property. This is the only area you need to paint. The trick is figuring out which of your annotations/overlays intersect with this rectangle and painting them in the correct order.
Either this canvas or a higher level control will need to track mouse movement so you know where to draw the lines, paste images, etc.
I have a User Control that has some WinForm Controls inside. I want to be able to paint those inner controls myself (for scrolling purposes, some of them will remain, others will move).
Even when I override the OnPaint and the OnPaintBackground method, those controls keeps showing on my usercontrol which is completely black now because there is no painting methods on it.
Is there a way I can suppress those controls from been painted and then paint them by myself with the DrawToBitmap method of each control?
Yes. Remove them from (or better yet, never add them to) the UserControl's set of child controls. Simulating interaction with the controls is going to be a PITA, though.
Do you just need the controls to "look" like they're there. Or do they need to actually be there? If its the latter, you would be better off faking the scrolling somehow by just repositioning the controls manually.
Trying to re-invent the windowing system is an exercise in pain. You will be better off if you learn and work within its paradigms.
If you don't need interaction, just set every child control .Visible = false.
Otherwise, have you tried WM_SETREDRAW?
I have a Control that can overlay multiple C# user controls in my GUI. This control has a semi-transparent background in order to 'grey-out' portions of the GUI and the class looks somethink like this:
public greyOutControl: UserControl
{
// Usual stuff here
protected overide OnPaint()
{
paintBackround();
base.OnPaint();
}
}
Currently the control sometimes gets caught in a loop and constantly re-draws the background, making the semi-transparent color appear less and less transparent.
My idea to combat this is the following (in broad terms):
1) Determine what controls the greyOutControl is on top of
2) call Refresh() on those controls to update the display
3) continue drawing the greyOutControl.
My question is: How can I determine which controls the greyOutControl overlaps?, or is there a way that I can refresh only the part of the GUI that greyOutControl covers?
Why don't you keep track of your transparent controls and paint them after all the other controls are drawn?. Painting anything at the top of the Z-order shouldn't cause the other controls to be repainted.
I don't see a direct way of finding the overlapping controls. I think you might need to check the whole control tree to find out that. About refreshing, you can use Control.Invalidate(Rectangle) method to specify which part to refresh.
The solution to this problem I found was to programmatically take a screen shot of the area being overlayed and then use that image as the background for the control being overlayed. This then allows you to put the alpha overlay into the image within the OnPaint() method and the control to draw itself correctly.
This does have the disadvantage that the background isn't updated in the overlapping control, but unless there was a number of event handlers watching if something changes and then update the overlayed control I cant see any way around the issue. Sometimes I regret not trying to use WPF!
I'm creating a plugin to a software that skins the form I created. However, the button are not skin based on them and a standard gray button is shown. Asking on the software forum pointed me that .NET forms control are owner-draw and therefor my button won't redraw with the correct style instead of creating a non ownerdraw button.
All controls in the system.windows.forms namespace seem to be ownerdraw.
So how can I create a standar C++ PUSHBUTTON in .NET?
Currently codding in C# if that helps.
Thx
The controls in Windows.Forms are not owner-drawn, but rather system-drawn. This is how Windows paints them by default, be it a Button, TextBox or what else. You can override the drawing either by specifying that the control should be owner-drawn (that is: you are responsible for drawing it) - some controls support that, a couple of them even with a finer granularity (see ListView), or you can override the painting completely in OnPaint event of any Control descendant.
Your question is rather confusing - as I understand the buttons you create in your plug-in are not skinned. Obviously what you need is to tell this skinning framework to paint these buttons. There probably is or should be some component that you drop onto the plug-in form or method you call that will inject the skinning painting routines into your plug-in.
It sounds like you want to set the FlatStyle property of your button to FlatStyle.System. Windows Forms buttons are indeed, by default, owner draw at the WinAPI level, and are drawn by the framework.
Have you tried setting the FlatStyle to another value, such as Flat or Popup, just to see if that stops it being skinned?
also setting Flaststyle = Standard (as opposed to system) might solve your problem
Standard was the default and therefor wasn't reskinned. When setted to flat, I get a background color and a foreground color, but lose the round corner end the hover effect suggesting that the control is not reskinned and just color style is applyed. Flat is the only version not grey, but I lose some of button feature (hover, round corner)