User Drawn Controls are using the previous Forms Background - c#

I have several user drawn controls on a form, unfortunately when the form is shown the user drawn controls are showing the previous forms background rather than the current forms background.
The OnPaint event is very simple, and the OnBackgroundPaint event is empty...
Like this:
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.DrawImageUnscaled(_bmpImage, 0, 0);
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
//Leave empty...
}
How do I get the current background to be the transparency that is shown, rather than the background of the previous form?

You need to set the window style - here's a nice basic article.

You seem to be overriding the OnPaintBackground method not do anything about the background. Since you're leaving it empty, you probably shouldn't override it in the first place. What happens when you just let the default OnPaintBackground handler do its job? Shouldn't that automatically draw the current control's background properly?
P.S. I've never worked with custom painting .Net controls. I'm merely speculating in an attempt to help find a solution to your problem. Forgive me if what I'm suggesting is completely off...

Related

windows.forms.panel calling onPaint twice

I have a panel with multiple panels inside of it. I have overridden OnPaint in the master panel to the following:
protected override void OnPaint(PaintEventArgs e)
{
Graphics graph = e.Graphics;
graph.Clear(Color.Black);
InvokePaintBackground(this, e);
graph.ScaleTransform(scale, scale);
foreach (childPanel child in childPanels)
{
child.onPaint(this, e);
}
graph.ResetTransform();
}
The problem I have is that the onPaint function of the first control (control in spot 0) is being called twice so I am getting two versions of the child panel, one with scaling, and one without. The second onPaint seems to be called by the child control itself.
How do I keep it from doing this?
That's because all Control objects do their own painting and the method is called automatically by Windows. The solution is to not rely on this sort of functionality at all - get rid of the panels, or set Visible to false.
Why on earth are you calling OnPaint on the child control? Windows will manage the paint calls on its own. You should never call them directly, especially with the graphics context you received from a separate paint call!
If you need to request a child control to be painted, use the Invalidate method instead. It marks a region (or entire control) as invalid so that Windows will paint it. The upside to that is that Windows is smart enough to know that if you invalidate it multiple times in the same paint cycle, it won't re-draw multiple times.
It is the inherent behavior. You can simply use a private bool secondCall; sort of a variable and do the scaling only on the second call.

C# ToolStrip is transparent but border is still visible?

I have a ToolStrip in a C# application that I set the background color to Transparent. This reveals the underlying form's color but unfortunately the ToolStrip border is still visible.
I've implemented a Custom Renderer and overridden the DrawBoarder method to not draw anything but that seems to apply to all of the contained buttons as well (i.e the menu on drop down buttons are also drawn without a border).
So I'm stuck. What's the best way to draw transparent the entire ToolStrip but leave the buttons alone?
I have tried just overriding the OnRenderToolStripBorder method and it seems it doesn't affect the buttons at all. Have you tried it like this?
public class TestStripRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
}
}
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
if( e.ToolStrip.GetType().Name != "MyCustomToolStrip" )
{
base.OnRenderToolStripBorder(e);
}
}
Since you are trying to make the toolstrip hidden but keep the buttons, I have to put this out there.
Do you even need the toolstrip?
It might be better if you just used buttons in the application without the seemingly unneeded toolstrip.

Problems with overriding OnPaint and grabbing mouse events in C# UserControl containing other controls

I've made a control which contains few other controls like PictureBox, Label and TextBox. But I'm having two problems:
1. I tried to paint some things on top of my control and when I'm overriding OnPaint, it results that things I try to draw are under controls that my control contains. Areas on which I would like to draw intersect with controls in ways that are not easy to predict. I mean that it includes something drawn on controls inside as well as on base of control. Is there a simple way to draw something on top of all contents of my control? Setting ForeColor to Transparent isn't a solution that would help me much.
2. I have a problem with grabbing mouse click events when I place my control on a form and add click event handling. It only works when I click on an area not occupied by controls inside. I would like the whole control to react to clicks and other actions like it was one consistent control. How can I redirect/handle these clicks to make them work the way I want?
Thanks in advance for any tips
edit:
Thanks for answer, i hoped for something less complexed.
Finally i decided to do it from scratch, painting all necessary things directly on surface of my UserControl, TextBox shows up only when it is necessary. That solved all of my problems with drawing and events.
MTH
1) Overriding a control's OnPaint event allows you to draw onto that control. Whenever that control is painted, your drawing code will be executed. Then, and only then, will the child controls be drawn on top of that control, each of them with their own OnPaint events executing. Each control is its own window (in the sense of the Windows API), and therefore each is responsible for drawing its own surface. This explains why your graphics are being covered up by the child controls, and why they are only visible in the empty spaces where no child controls have been placed.
The upshot is that drawing on top of multiple controls inside a container is not well-supported. There are a couple of hacks you could try to help get around these limitations, but you may well be disappointed.
The first possible hack is to draw your graphics on the container control as you've already done, and then also draw on top of the child controls themselves. You'll need to override each child control's OnPaint event in order for this to work, however, which immediately presents a problem. A TextBox control (along with a ComboBox, ListView, TreeView, and a handful of other controls) doesn't do its drawing in an OnPaint event; it's drawn natively by the operating system. The possible workarounds for this are so potentially painful that you might as well forget about it and change your design.
The second possible hack is to add another control that sits on top of the container control and do your drawing on its surface. Perhaps the easiest way to do this is by creating something like a transparent panel using the WS_EX_TRANSPARENT extended window style:
public class TransparentPanel : Panel
{
protected override CreateParams CreateParams
{
get
{
const int WS_EX_TRANSPARENT = 0x00000020;
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_TRANSPARENT
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//Do nothing
}
}
2) Again, it becomes relevant that each child control is its own window and handles its own mouse input events. That's why the control whose MouseClick event you've overridden is only detecting the clicks that occur directly on its surface. The other clicks get passed to the child controls, who just ignore them. Events in WinForms are not bubbled up the control hierarchy.
As before, one possible solution is to handle the MouseClick event (and any others you want) for both the container and child controls. If you decide to go this route, I think I would recommend consolidating your logic into a single routine and simply calling that routine from each control's event handler.
If you're looking for something more comprehensive, you might check out Broadcasting Events through a Control Hierarchy, although I haven't taken the time to read it.
Of course, you could also send the relevant mouse input messages to your parent container control from each child control using the SendMessage API function. But I'll leave that as an exercise for the reader because I feel like you asked a simple question expecting a simple answer.

Using Visual Studio 2010 Express to create a surface I can draw to

I'm coming from a Java background and trying to port a simple version of Conway's Game of Life that I wrote to C# in order to learn the language.
In Java, I drew my output by inheriting from JComponent and overriding paint(). My new canvas class then had an instance of the simulation's backend which it could read/manipulate. I was then able to get the WYSIWYG GUI editor (Matisse, from NetBeans) to allow me to visually place the canvas.
In C#, I've gathered that I need to override OnPaint() to draw things, which (as far as I know) requires me to inherit from something (I chose Panel). I can't figure out how to get the Windows forms editor to let me place my custom class. I'm also uncertain about where in the generated code I need to place my class.
How can I do this, and is putting all my drawing code into a subclass really how I should be going about this? The lack of easy answers on Google suggests I'm missing something important here. If anyone wants to suggest a method for doing this in WPF as well, I'm curious to hear it.
Thanks
In Windows Forms, you can simply draw on any control by calling its CreateGraphics method. If you have a panel, for example, you can draw like this:
using (var g = panel1.CreateGraphics()) {
g.DrawString("Hello World", 0, 0);
}
Controls also have a Paint event. Add an event handler by double-clicking the event in the properties window, and you can draw like this:
private void panel1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.DrawString("Hello World", 0, 0);
}
If you want to derive from a control, you can either just do it in code, or create a new user control and change the base class in the code and in the .Designer.cs file (though UserControl or just Control will be fine). If you already have a form in the designer, it's already derived from Form, and you can just override OnPaint.
My advice is: You typically won't need to create a new class if you just want to draw something. Just use the Paint event. If you need to immediately redraw, call Refresh to make the control redraw itself. This should get you going. Note that there is also a protected DoubleBuffered property, which can help you avoid flickering (set it for the form or in your derived control).
I'm not sure what you would do in WPF. I never needed to actually draw something manually in WPF, since the layout and rendering engine is very powerful, and you can just get away with data templates, control templates etc. The point in WPF is that you typically don't draw anything, the engine draws for you.

UserControl OnPaint always has clipRect of {0,0,0,0}

I have a UserControl with a few buttons on it. I want to override OnPaint and paint some other stuff on the control.
So I override OnPaint.
Whenever OnPaint gets called the ClipRectangle is always {0,0,0,0} and so nothing I do gets drawn on the control.
What am I doing wrong?
Ok, Ive sussed it now. Its a bit silly. I had a TableLayoutPanel that was docked to the control. That seems to clip out all the areas that we can paint on.
I created a new control that derives from TableLayoutPanel and used this control instead. Its OnPaint gets the full clip rect.
However, that wasnt any use anyway... It seems I have misunderstood how Windows painting works. I thought I would be able to paint directly over the top of my controls, but this isnt the case. The controls get placed on top of my painting.
Gonna have to mess about with panels to get this working I reckon..

Categories

Resources