Redrawing a control covered by another window and is uncovered again (C# .NET 2.0)

Cyrilix

2[H]4U
Joined
Jan 21, 2005
Messages
2,188
I'm having a bit of difficulty figuring out which event is related to "having your control covered by another window and then having it uncovered". I thought at first it would be the Invalidated event because my understanding is that if there's a portion of the control that needs redrawing that event is fired. I tried doing a call to Invalidate() during that event. Of course, you can see that the logic is circular. It gets invalidated, so you invalidate it again to redraw it, which invalidates it. Needless to say, it didn't work.

I should probably mention the following:

-Whatever I'm trying to draw is dynamic, sort of like a graph. Before drawing it, the lines and bars that make up the graph have to be calculated.
-The control that I want redrawn is a child control of a parent control, not the actual form itself.

Thanks.
 
I'm having a bit of difficulty figuring out which event is related to "having your control covered by another window and then having it uncovered". I thought at first it would be the Invalidated event because my understanding is that if there's a portion of the control that needs redrawing that event is fired. I tried doing a call to Invalidate() during that event. Of course, you can see that the logic is circular. It gets invalidated, so you invalidate it again to redraw it, which invalidates it. Needless to say, it didn't work.

I should probably mention the following:

-Whatever I'm trying to draw is dynamic, sort of like a graph. Before drawing it, the lines and bars that make up the graph have to be calculated.
-The control that I want redrawn is a child control of a parent control, not the actual form itself.

Thanks.

sounds like a got focus/lost focus event area...
 
Well, I tried that one, but it didn't work either. What it's currently doing right now is... when you move another window over it, and then remove that window, the control will look entirely black (which happens to be its background color).
 
Well, I tried that one, but it didn't work either. What it's currently doing right now is... when you move another window over it, and then remove that window, the control will look entirely black (which happens to be its background color).

Okay..maybe I miss understood.. so you are telling me window A is being covered (partially or fully) by window B.. window A may or may not regain focus once window B is gone (gone where I am not sure)...

If window B is a child of window A.. how was it spawned? Show or Show Dialog? if it is the later then closing it should snap window A back to focus and kick a redraw in..
 
So lets say I create a Window A with some kind of panel and a drawing created in GDI+ directly on top of it. Then, I open up My Computer, and the explorer window pops up, and I drag it overtop of my Window A. Then, I drag it off of Window A. Window A, which still has no focus, no longer has the GDI+ drawing that I drew. It only has the background color. The only way to get the image to show again is if I call some kind of Invalidate(), Refresh(), etc. The problem for me is figuring out when I should be calling this so that as soon as I uncover a bit of Window A (after it is covered by Window B, the explorer window), the part that I uncovered will redraw itself with what it had before it was covered.

I apologize for the delay in responding.
 
So lets say I create a Window A with some kind of panel and a drawing created in GDI+ directly on top of it. Then, I open up My Computer, and the explorer window pops up, and I drag it overtop of my Window A. Then, I drag it off of Window A. Window A, which still has no focus, no longer has the GDI+ drawing that I drew. It only has the background color. The only way to get the image to show again is if I call some kind of Invalidate(), Refresh(), etc. The problem for me is figuring out when I should be calling this so that as soon as I uncover a bit of Window A (after it is covered by Window B, the explorer window), the part that I uncovered will redraw itself with what it had before it was covered.

I apologize for the delay in responding.

Okay.. i see what you are saying.. Are you creating a straight up form (window A) with the toolbox components, or did you construct something on your own? If it is the former then this problem shouldn't exist. Unless you did something with a suspend/resume layout... You mucked up the draw code or something.. if it's the latter than that is a whole different bucket of questions and/or zipping up your code and mailing it to me... or you should have your component inherit from a MS component..
 
It's not 100% straight up Toolbox components but it more or less is. The control that I want to redraw actually inherits the PictureBox, but simply overrides the OnPaint to reduce the size of the ClipRectangle. The thing is, though, back when I used just a PictureBox directly under the main form, it was fine without requiring any extra code. Now, I've put an additional layer in the hierarchy so it goes Main Form -> Panel -> PictureBox with OnPaint override, and it doesn't work anymore. I'm thinking that the form itself actually knows when things need to be redrawn, and simply alerts all of its child controls. The Panel, on the other hand, may not know this, so when the form alerts the Panel, the Panel just sits there and doesn't alert the PictureBox.

Unfortunately, this is work-related so I can't exactly send the code, but I'll try my best to explain what I can. Whatever stuff with Suspend/Resume layout is not my code, but rather, the designer code.
 
Doing an:

Invalidate()
Update()

...should work. Also make sure DoubleBuffering is enabled on your form.

If this doesn't work it's quite likely the Panel is screwing it up because I've never had a problem with drawings being erased.

A quick google came up with this:
http://www.msnewsgroups.net/group/microsoft.public.dotnet.languages.csharp/topic915.aspx

Seems like it could fix your problem.

Btw as for when you should be calling invalidate/update.

Here's how I did it (it's for an app that draws a line at a specific degree based on the user's input). The degree is entered on a form that's separate from the form that's drawing it.

[In your graph form -- ie. the one that's literally being drawn on]
Code:
        public double SetDegree
        {
            set
            {
                degree = value;
            }
        }

        public void UpdateDegree(double newDegree)
        {
            degree = newDegree;

            this.Invalidate();
            this.Update();
        }

[Somewhere in the form's paint event (or in your case I guess the PictureBox)]
Access the 'degree' property.

At this point just create a new instance of your graph form and call the UpdateDegree(x) Method.
 
Hi ShoeLace,

So far, I know that I have to call those methods. In fact, just calling Invalidate is enough from what I've tested. What I don't know is when to call it. What kind of event actually exists to determine when someone covers up your window? I'm sure if I had a certain draw operation, that I could just call Invalidate everytime I drew it, but right now, I'm drawing something (which is not redrawn until I want to change the drawing itself), and then it's being covered and not being uncovered.

Edit: Someone sent me this link: PictureBox

It looks like I'm not supposed to just be drawing directly onto a PictureBox, but am supposed to use a Panel and override the Panel's PaintEventHandler.
 
Code:
protected override void OnPaint(PaintEventArgs pe)
{
   // Call the OnPaint method of the base class.
[COLOR="Red"][B]   base.OnPaint(pe);[/B][/COLOR]

   //your code here
}

I assume you are calling the base on paint first, right? That should take care of your problems... that or your clip rectangle is jacked up..
 
Actually, I was calling it after. I set the ClipRectangle, then called base.OnPaint(). My logic was... first, I need to set the clip rectangle to define my boundaries. Then, I just let the base draw with those boundary parameters, but maybe I'm thinking of it the wrong way. Perhaps, it goes like: First, I draw the image. Then, I specify the boundaries and cut off whatever is already there, in which case, I would need to call base first.

Edit: I just tried it with calling the base.OnPaint() before and it works! :D Unfortunately, it also means that my clipping code no longer works. I was doing something like this before:

Code:
protected override void OnPaint(PaintEventArgs e)
{
    RectangleF clipBounds = e.Graphics.ClipBounds;
    clipBounds.Location = new PointF(2.0f, 0.0f);
    clipBounds.Width = clipBounds.Width - 4.0f;
    e.Graphics.Clip = new Region(clipBounds);

    base.OnPaint(e);
}
If I move the OnPaint on top, it's as if I had never written the Clip code. Basically, I'm just trimming two pixels from the left and right.

Thanks a bunch to everyone that helped out. I should probably read a UI book before trying to implement everything rather than just picking it up from scratch with no experience at all.
 
Actually, I was calling it after. I set the ClipRectangle, then called base.OnPaint(). My logic was... first, I need to set the clip rectangle to define my boundaries. Then, I just let the base draw with those boundary parameters, but maybe I'm thinking of it the wrong way. Perhaps, it goes like: First, I draw the image. Then, I specify the boundaries and cut off whatever is already there, in which case, I would need to call base first.

Edit: I just tried it with calling the base.OnPaint() before and it works! :D Unfortunately, it also means that my clipping code no longer works. I was doing something like this before:

Sorry, this is VB
Code:
protected override void OnPaint(PaintEventArgs e)
{
    RectangleF clipBounds = e.Graphics.ClipBounds;
    clipBounds.Location = new PointF(2.0f, 0.0f);
    clipBounds.Width = clipBounds.Width - 4.0f;
    e.Graphics.Clip = new Region(clipBounds);

    base.OnPaint(e);
}
If I move the OnPaint on top, it's as if I had never written the Clip code. Basically, I'm just trimming two pixels from the left and right.

Thanks a bunch to everyone that helped out. I should probably read a UI book before trying to implement everything rather than just picking it up from scratch with no experience at all.

Side note, why are you redoing the clip bounds each time? In the New make up your clip rectangle and set it there..

Code:
'-- Declarations
    Private g As Graphics
'-- in the new 
    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        Init()
        '-- graphics setting.. sets clip area
        g = CreateGraphics()
       '-- fill in your numbers for x, y, width, height
        g.Clip = New Region(New RectangleF(0, 1, 30, 50))
    End Sub

'-- in events
    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        g.Clear(Me.BackColor)
'-- use the draw from g not from e.graphics
    End Sub
 
Back
Top