By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,851 Members | 1,079 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,851 IT Pros & Developers. It's quick & easy.

GDI Onpaint Problem/Question in Custom control

P: n/a

I have made a custom control that draws a rectangle when the mouse is down, and does nothing when the mouse is up.
I set/reset a flag in MouseDown/Mouse up and use this to do the drawing in the OnPaint .

The recangle draws correct when i press the mouse, but when i release the mouse the background is not restored

What should i do in the Onpaint to make sure the background (the form) is restored correctly ?

This problem already keeps me busy for 2 days ...

Johan

copy this code in a new win c# app
using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Drawing.Imaging;

using System.Reflection;

namespace WindowsApplication2

{

/// <summary>

/// Summary description for Form1.

/// </summary>

public class Form1 : System.Windows.Forms.Form

{

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

private Hotspot spot ;

public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeComponent();

//

// TODO: Add any constructor code after InitializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.BackColor = System.Drawing.SystemColors.Desktop;

this.ClientSize = new System.Drawing.Size(152, 141);

this.Name = "Form1";

this.Text = "Form1";

this.Load += new System.EventHandler(this.Form1_Load);

}

#endregion

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

private void Form1_Load(object sender, System.EventArgs e)

{

spot=new Hotspot() ;

spot.Size=new Size(50,50);

spot.Location=new Point(40,40);

spot.BringToFront();

spot.Visible=true;

this.Controls.Add(spot);
}

}


public class Hotspot : Control

{

//private Image image;

private bool bPushed;

private Bitmap m_bmpOffscreen;
Brush GrayBrush;

public Hotspot()

{

bPushed = false;

//default minimal size

this.Size = new Size(21, 21);

GrayBrush=new SolidBrush(Color.Gray);

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )

{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering

{

m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);

}

gxOff = Graphics.FromImage(m_bmpOffscreen);
gxOff.Clear(Color.Empty);
if (bPushed)

{

gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10, ClientSize.Height-10);

e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
base.OnPaint(e);

}

protected override void OnPaintBackground(System.Windows.Forms.PaintEventA rgs e )

{

}

protected override void OnMouseDown ( System.Windows.Forms.MouseEventArgs e )

{

bPushed = true;

Invalidate();

}

protected override void OnMouseUp ( System.Windows.Forms.MouseEventArgs e )

{

bPushed = false;

Invalidate();

}

}
}

Nov 15 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
Are you calling the base class paint in your onpaint override?
Are you calling Invalidate() on mouse up?
Did you override background paint - I've seen too many suggestions saying to do this and I don't think for most situations it makes sense.
--
Justin Weinberg

Designing a PrintDocument? Drawing to forms?
Check out GDI+ Architect at www.mrgsoft.com
"Sagaert Johan" <RE*******************@hotmail.com> wrote in message news:uK**************@TK2MSFTNGP12.phx.gbl...

I have made a custom control that draws a rectangle when the mouse is down, and does nothing when the mouse is up.
I set/reset a flag in MouseDown/Mouse up and use this to do the drawing in the OnPaint .

The recangle draws correct when i press the mouse, but when i release the mouse the background is not restored

What should i do in the Onpaint to make sure the background (the form) is restored correctly ?

This problem already keeps me busy for 2 days ...

Johan

copy this code in a new win c# app
using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Drawing.Imaging;

using System.Reflection;

namespace WindowsApplication2

{

/// <summary>

/// Summary description for Form1.

/// </summary>

public class Form1 : System.Windows.Forms.Form

{

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

private Hotspot spot ;

public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeComponent();

//

// TODO: Add any constructor code after InitializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.BackColor = System.Drawing.SystemColors.Desktop;

this.ClientSize = new System.Drawing.Size(152, 141);

this.Name = "Form1";

this.Text = "Form1";

this.Load += new System.EventHandler(this.Form1_Load);

}

#endregion

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

private void Form1_Load(object sender, System.EventArgs e)

{

spot=new Hotspot() ;

spot.Size=new Size(50,50);

spot.Location=new Point(40,40);

spot.BringToFront();

spot.Visible=true;

this.Controls.Add(spot);
}

}


public class Hotspot : Control

{

//private Image image;

private bool bPushed;

private Bitmap m_bmpOffscreen;
Brush GrayBrush;

public Hotspot()

{

bPushed = false;

//default minimal size

this.Size = new Size(21, 21);

GrayBrush=new SolidBrush(Color.Gray);

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )

{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering

{

m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);

}

gxOff = Graphics.FromImage(m_bmpOffscreen);
gxOff.Clear(Color.Empty);
if (bPushed)

{

gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10, ClientSize.Height-10);

e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
base.OnPaint(e);

}

protected override void OnPaintBackground(System.Windows.Forms.PaintEventA rgs e )

{

}

protected override void OnMouseDown ( System.Windows.Forms.MouseEventArgs e )

{

bPushed = true;

Invalidate();

}

protected override void OnMouseUp ( System.Windows.Forms.MouseEventArgs e )

{

bPushed = false;

Invalidate();

}

}
}
Nov 15 '05 #2

P: n/a

there are multiple things wrong in general with your hotspot control
(but they are things you'll learn as you do more with them). However
the two that are causing all your problems is a very small logic error
and a color error.

First, you are clearing your control's surface with the color Empty,
which in fact is no color at all (hence its not clearing anything for
you) and whatever was there before the control took a seat, is still
there after including anything you subsequently draw.

The second is that you seem to have accidently put your drawing to
surface inside your 'bPushed' if statement. This is a subtle but
important error. Since you are drawing to your offscreen bitmap, you
ALWAYS need to draw the bitmap regardless of whether you are doing it
for your pressed or nonpressed state.

Therefore, your draw loop should look as follows,

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e
)
{
Graphics gxOff; //Offscreen graphics

if (m_bmpOffscreen == null) //Bitmap for doublebuffering
m_bmpOffscreen = new Bitmap(ClientSize.Width,
ClientSize.Height);

gxOff = Graphics.FromImage(m_bmpOffscreen);
gxOff.Clear(Color.White); // or whatever color you would
like

if (bPushed)
gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10,
ClientSize.Height-10);

e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
gxOff.Dispose();

base.OnPaint(e);
}
that will fix your problem.
Allen Anderson
http://www.glacialcomponents.com


On Thu, 9 Oct 2003 19:52:23 +0200, "Sagaert Johan"
<RE*******************@hotmail.com> wrote:

I have made a custom control that draws a rectangle when the mouse is down, and does nothing when the mouse is up.
I set/reset a flag in MouseDown/Mouse up and use this to do the drawing in the OnPaint .

The recangle draws correct when i press the mouse, but when i release the mouse the background is not restored

What should i do in the Onpaint to make sure the background (the form) is restored correctly ?

This problem already keeps me busy for 2 days ...

Johan

copy this code in a new win c# app
using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Drawing.Imaging;

using System.Reflection;

namespace WindowsApplication2

{

/// <summary>

/// Summary description for Form1.

/// </summary>

public class Form1 : System.Windows.Forms.Form

{

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

private Hotspot spot ;

public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeComponent();

//

// TODO: Add any constructor code after InitializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.BackColor = System.Drawing.SystemColors.Desktop;

this.ClientSize = new System.Drawing.Size(152, 141);

this.Name = "Form1";

this.Text = "Form1";

this.Load += new System.EventHandler(this.Form1_Load);

}

#endregion

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

private void Form1_Load(object sender, System.EventArgs e)

{

spot=new Hotspot() ;

spot.Size=new Size(50,50);

spot.Location=new Point(40,40);

spot.BringToFront();

spot.Visible=true;

this.Controls.Add(spot);
}

}


public class Hotspot : Control

{

//private Image image;

private bool bPushed;

private Bitmap m_bmpOffscreen;
Brush GrayBrush;

public Hotspot()

{

bPushed = false;

//default minimal size

this.Size = new Size(21, 21);

GrayBrush=new SolidBrush(Color.Gray);

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )

{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering

{

m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);

}

gxOff = Graphics.FromImage(m_bmpOffscreen);
gxOff.Clear(Color.Empty);
if (bPushed)

{

gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Widt h-10, ClientSize.Height-10);

e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
base.OnPaint(e);

}

protected override void OnPaintBackground(System.Windows.Forms.PaintEventA rgs e )

{

}

protected override void OnMouseDown ( System.Windows.Forms.MouseEventArgs e )

{

bPushed = true;

Invalidate();

}

protected override void OnMouseUp ( System.Windows.Forms.MouseEventArgs e )

{

bPushed = false;

Invalidate();

}

}
}


Nov 15 '05 #3

P: n/a
100
Hi Johan,

1. Dont use Color.Empty for clearing the bitmap. This won't clear anything.
You should use color instead.

something like:
gxOff.Clear(this.BackColor);

2. Move
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
out of the if(bPushed) block. You paint the control only if the button is
down. And you don't paint (clear ) anything if the button is up.

Beside I have one suggestion. If you want to paint the whole clent rectangle
by yourself consider setting control styles:

this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint, true);

Even if you have your own offscreen bitmap you should set
ControlStyles.DoubleBuffer style in order to avoid flickering.

HTH
B\rgds
100
Nov 15 '05 #4

P: n/a
Thanks for the reply ,

it did'nt solve my problem ,if i don't push the control, i would like
nothing else to see then my form.(my control must appear invisible to the
user whet it's NOT pushed, it should only be draw a when it's pushed)
"Allen Anderson" <al***@sparkysystems.com> wrote in message
news:c1********************************@4ax.com...

there are multiple things wrong in general with your hotspot control
(but they are things you'll learn as you do more with them). However
the two that are causing all your problems is a very small logic error
and a color error.

First, you are clearing your control's surface with the color Empty,
which in fact is no color at all (hence its not clearing anything for
you) and whatever was there before the control took a seat, is still
there after including anything you subsequently draw.

The second is that you seem to have accidently put your drawing to
surface inside your 'bPushed' if statement. This is a subtle but
important error. Since you are drawing to your offscreen bitmap, you
ALWAYS need to draw the bitmap regardless of whether you are doing it
for your pressed or nonpressed state.

Therefore, your draw loop should look as follows,

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e
)
{
Graphics gxOff; //Offscreen graphics

if (m_bmpOffscreen == null) //Bitmap for doublebuffering
m_bmpOffscreen = new Bitmap(ClientSize.Width,
ClientSize.Height);

gxOff = Graphics.FromImage(m_bmpOffscreen);
gxOff.Clear(Color.White); // or whatever color you would
like

if (bPushed)
gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10,
ClientSize.Height-10);

e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
gxOff.Dispose();

base.OnPaint(e);
}
that will fix your problem.
Allen Anderson
http://www.glacialcomponents.com


On Thu, 9 Oct 2003 19:52:23 +0200, "Sagaert Johan"
<RE*******************@hotmail.com> wrote:

I have made a custom control that draws a rectangle when the mouse is down, and does nothing when the mouse is up.I set/reset a flag in MouseDown/Mouse up and use this to do the drawing in the OnPaint .
The recangle draws correct when i press the mouse, but when i release the mouse the background is not restored
What should i do in the Onpaint to make sure the background (the form) is restored correctly ?
This problem already keeps me busy for 2 days ...

Johan

copy this code in a new win c# app
using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Drawing.Imaging;

using System.Reflection;

namespace WindowsApplication2

{

/// <summary>

/// Summary description for Form1.

/// </summary>

public class Form1 : System.Windows.Forms.Form

{

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

private Hotspot spot ;

public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeComponent();

//

// TODO: Add any constructor code after InitializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.BackColor = System.Drawing.SystemColors.Desktop;

this.ClientSize = new System.Drawing.Size(152, 141);

this.Name = "Form1";

this.Text = "Form1";

this.Load += new System.EventHandler(this.Form1_Load);

}

#endregion

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

private void Form1_Load(object sender, System.EventArgs e)

{

spot=new Hotspot() ;

spot.Size=new Size(50,50);

spot.Location=new Point(40,40);

spot.BringToFront();

spot.Visible=true;

this.Controls.Add(spot);
}

}


public class Hotspot : Control

{

//private Image image;

private bool bPushed;

private Bitmap m_bmpOffscreen;
Brush GrayBrush;

public Hotspot()

{

bPushed = false;

//default minimal size

this.Size = new Size(21, 21);

GrayBrush=new SolidBrush(Color.Gray);

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )

{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering

{

m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);

}

gxOff = Graphics.FromImage(m_bmpOffscreen);
gxOff.Clear(Color.Empty);
if (bPushed)

{

gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Widt h-10, ClientSize.Height-10);
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
base.OnPaint(e);

}

protected override void OnPaintBackground(System.Windows.Forms.PaintEventA rgs e )
{

}

protected override void OnMouseDown ( System.Windows.Forms.MouseEventArgs e )
{

bPushed = true;

Invalidate();

}

protected override void OnMouseUp ( System.Windows.Forms.MouseEventArgs e )
{

bPushed = false;

Invalidate();

}

}
}

Nov 15 '05 #5

P: n/a
Yes, see and try my source in the first post

"Justin Weinberg" <jweinberg@_spamkill_mrgsoft.com> wrote in message news:ed**************@tk2msftngp13.phx.gbl...
Are you calling the base class paint in your onpaint override?
Are you calling Invalidate() on mouse up?
Did you override background paint - I've seen too many suggestions saying to do this and I don't think for most situations it makes sense.
--
Justin Weinberg

Designing a PrintDocument? Drawing to forms?
Check out GDI+ Architect at www.mrgsoft.com
"Sagaert Johan" <RE*******************@hotmail.com> wrote in message news:uK**************@TK2MSFTNGP12.phx.gbl...

I have made a custom control that draws a rectangle when the mouse is down, and does nothing when the mouse is up.
I set/reset a flag in MouseDown/Mouse up and use this to do the drawing in the OnPaint .

The recangle draws correct when i press the mouse, but when i release the mouse the background is not restored

What should i do in the Onpaint to make sure the background (the form) is restored correctly ?

This problem already keeps me busy for 2 days ...

Johan

copy this code in a new win c# app
using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Drawing.Imaging;

using System.Reflection;

namespace WindowsApplication2

{

/// <summary>

/// Summary description for Form1.

/// </summary>

public class Form1 : System.Windows.Forms.Form

{

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

private Hotspot spot ;

public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeComponent();

//

// TODO: Add any constructor code after InitializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.BackColor = System.Drawing.SystemColors.Desktop;

this.ClientSize = new System.Drawing.Size(152, 141);

this.Name = "Form1";

this.Text = "Form1";

this.Load += new System.EventHandler(this.Form1_Load);

}

#endregion

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

private void Form1_Load(object sender, System.EventArgs e)

{

spot=new Hotspot() ;

spot.Size=new Size(50,50);

spot.Location=new Point(40,40);

spot.BringToFront();

spot.Visible=true;

this.Controls.Add(spot);
}

}


public class Hotspot : Control

{

//private Image image;

private bool bPushed;

private Bitmap m_bmpOffscreen;
Brush GrayBrush;

public Hotspot()

{

bPushed = false;

//default minimal size

this.Size = new Size(21, 21);

GrayBrush=new SolidBrush(Color.Gray);

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )

{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering

{

m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);

}

gxOff = Graphics.FromImage(m_bmpOffscreen);
gxOff.Clear(Color.Empty);
if (bPushed)

{

gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10, ClientSize.Height-10);

e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
base.OnPaint(e);

}

protected override void OnPaintBackground(System.Windows.Forms.PaintEventA rgs e )

{

}

protected override void OnMouseDown ( System.Windows.Forms.MouseEventArgs e )

{

bPushed = true;

Invalidate();

}

protected override void OnMouseUp ( System.Windows.Forms.MouseEventArgs e )

{

bPushed = false;

Invalidate();

}

}
}

Nov 15 '05 #6

P: n/a


"100" <10*@100.com> wrote in message
news:Ot*************@TK2MSFTNGP12.phx.gbl...
Hi Johan,

1. Dont use Color.Empty for clearing the bitmap. This won't clear anything. You should use color instead.

something like:
gxOff.Clear(this.BackColor);

2. Move
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
out of the if(bPushed) block. You paint the control only if the button is
down. And you don't paint (clear ) anything if the button is up.

Thats just my problem,i don't want anything to be painted when i don't
press my control,
the only thing i want to see is the form , or the image i draw on the form .

In my form i draw a background image in the forms paint event, and the i
would like to use

my control to create hotspots almost identical as they create hotspots on
images of html pages.

I don't understand why part of the form the is'nt painted correctly if my
control does'nt do any painting by itself.Even if i call the forms
invalidate, the form paint routine seems to skip the area where my control
is.

Johan

Beside I have one suggestion. If you want to paint the whole clent rectangle by yourself consider setting control styles:

this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint, true);

Even if you have your own offscreen bitmap you should set
ControlStyles.DoubleBuffer style in order to avoid flickering.

HTH
B\rgds
100

Nov 15 '05 #7

P: n/a
100
Hi Johan,

Now I see what your issue is. Ok, the problem is that when a control is
created the framework by default sets WS_CLIPCHILDREN windows style to the
underlaying window. This style cause any part of of the client area covered
by a child control to be excluded of the invalid region. As a result all
drawing in those areas are clipped.
What you can do is to reset this style. I don't know if it is good idea to
use such platform dependant features, but this solves your problem. So what
you can do is:

1. Add the following property to your main form:
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.Style &= ~0x02000000; //reset WS_CLIPCHILDREN
return createParams;
}
}

2. Now you have to restore the main form's clent area when the mouse button
is released. You can't simply ignore OnPaint event in the child control.
This will not repaint the main form. You have to do something to fire Paint
event in the parent form. There is my suggestion for the child control's
Paint event implementation:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )
{
base.OnPaint(e); //If you needed it it's better to call it before your
painting
if (bPushed)
{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering
{
m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height,
e.Graphics); //I believe is better to use this constructor
}
gxOff = Graphics.FromImage(m_bmpOffscreen);
//gxOff.Clear(Color.Empty); - I believe it is not necessary sice it
doesnt do anything
gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10,
ClientSize.Height-10);
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
else
{
Parent.Invalidate(this.Bounds, false); //Fires parent's paint event
}
}
HTH
B\rgds
100
"Sagaert Johan" <RE*******************@hotmail.com> wrote in message
news:un**************@TK2MSFTNGP09.phx.gbl...


"100" <10*@100.com> wrote in message
news:Ot*************@TK2MSFTNGP12.phx.gbl...
Hi Johan,

1. Dont use Color.Empty for clearing the bitmap. This won't clear anything.
You should use color instead.

something like:
gxOff.Clear(this.BackColor);

2. Move
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
out of the if(bPushed) block. You paint the control only if the button is down. And you don't paint (clear ) anything if the button is up.

Thats just my problem,i don't want anything to be painted when i don't
press my control,
the only thing i want to see is the form , or the image i draw on the form

..
In my form i draw a background image in the forms paint event, and the i
would like to use

my control to create hotspots almost identical as they create hotspots on
images of html pages.

I don't understand why part of the form the is'nt painted correctly if my
control does'nt do any painting by itself.Even if i call the forms
invalidate, the form paint routine seems to skip the area where my control
is.

Johan

Beside I have one suggestion. If you want to paint the whole clent

rectangle
by yourself consider setting control styles:

this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint, true);

Even if you have your own offscreen bitmap you should set
ControlStyles.DoubleBuffer style in order to avoid flickering.

HTH
B\rgds
100


Nov 15 '05 #8

P: n/a
100
A little correction. It seems like calling invalidate with
invalidateChildren=false is not enough to stop Paint event for the child
control. As a result Parent.Invalidate is called over and over again (like
infinite loop of messages).
More logic has to be put in childe's control Paint event.

The idea I came up with is to use a flag in the child's control class

public class Hotspot : Control

{
private bool mStopPaint = false;
//..... other members

protected override void OnPaint(System.Windows.Forms.PaintEventArgs
e )
{
if(mStopPaint) return;
base.OnPaint(e); //If you needed it it's better to call it before
your painting

if (bPushed)
{
//..... not changed
}
else
{
mStopPaint = true;
Parent.Invalidate(this.Bounds, false); //Fires parent's
paint event
Parent.Update(); //This want return until the parent is not
repainted. We need that in order to mStopPaint flag to work
mStopPaint = false;
}

}
//.....The rest of the class
}
HTH
B\rgds
100

"100" <10*@100.com> wrote in message
news:en**************@TK2MSFTNGP10.phx.gbl...
Hi Johan,

Now I see what your issue is. Ok, the problem is that when a control is
created the framework by default sets WS_CLIPCHILDREN windows style to the
underlaying window. This style cause any part of of the client area covered by a child control to be excluded of the invalid region. As a result all
drawing in those areas are clipped.
What you can do is to reset this style. I don't know if it is good idea to
use such platform dependant features, but this solves your problem. So what you can do is:

1. Add the following property to your main form:
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.Style &= ~0x02000000; //reset WS_CLIPCHILDREN
return createParams;
}
}

2. Now you have to restore the main form's clent area when the mouse button is released. You can't simply ignore OnPaint event in the child control.
This will not repaint the main form. You have to do something to fire Paint event in the parent form. There is my suggestion for the child control's
Paint event implementation:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )
{
base.OnPaint(e); //If you needed it it's better to call it before your painting
if (bPushed)
{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering
{
m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height, e.Graphics); //I believe is better to use this constructor
}
gxOff = Graphics.FromImage(m_bmpOffscreen);
//gxOff.Clear(Color.Empty); - I believe it is not necessary sice it doesnt do anything
gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10,
ClientSize.Height-10);
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
else
{
Parent.Invalidate(this.Bounds, false); //Fires parent's paint event }
}
HTH
B\rgds
100
"Sagaert Johan" <RE*******************@hotmail.com> wrote in message
news:un**************@TK2MSFTNGP09.phx.gbl...


"100" <10*@100.com> wrote in message
news:Ot*************@TK2MSFTNGP12.phx.gbl...
Hi Johan,

1. Dont use Color.Empty for clearing the bitmap. This won't clear anything.
You should use color instead.

something like:
gxOff.Clear(this.BackColor);

2. Move
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
out of the if(bPushed) block. You paint the control only if the button is down. And you don't paint (clear ) anything if the button is up.

Thats just my problem,i don't want anything to be painted when i don't
press my control,
the only thing i want to see is the form , or the image i draw on the form .

In my form i draw a background image in the forms paint event, and the i
would like to use

my control to create hotspots almost identical as they create hotspots

on images of html pages.

I don't understand why part of the form the is'nt painted correctly if my control does'nt do any painting by itself.Even if i call the forms
invalidate, the form paint routine seems to skip the area where my control is.

Johan

Beside I have one suggestion. If you want to paint the whole clent

rectangle
by yourself consider setting control styles:

this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint, true);

Even if you have your own offscreen bitmap you should set
ControlStyles.DoubleBuffer style in order to avoid flickering.

HTH
B\rgds
100



Nov 15 '05 #9

P: n/a
Hi
Thanks for your reply , now it works just as i would like !!!!!!!!!!!

I have put the Parent.Invalidate in the controls MouseUp event ,this seems
to be enough.

Now my next problem is how to solve this issue in the Compact framework
,since CF does not have the CreateParams method...

Best regards Johan http://www.qsl.net/on5di/


"100" <10*@100.com> wrote in message
news:OX****************@TK2MSFTNGP09.phx.gbl...
A little correction. It seems like calling invalidate with
invalidateChildren=false is not enough to stop Paint event for the child
control. As a result Parent.Invalidate is called over and over again (like
infinite loop of messages).
More logic has to be put in childe's control Paint event.

The idea I came up with is to use a flag in the child's control class

public class Hotspot : Control

{
private bool mStopPaint = false;
//..... other members

protected override void OnPaint(System.Windows.Forms.PaintEventArgs
e )
{
if(mStopPaint) return;
base.OnPaint(e); //If you needed it it's better to call it before your painting

if (bPushed)
{
//..... not changed
}
else
{
mStopPaint = true;
Parent.Invalidate(this.Bounds, false); //Fires parent's
paint event
Parent.Update(); //This want return until the parent is not repainted. We need that in order to mStopPaint flag to work
mStopPaint = false;
}

}
//.....The rest of the class
}
HTH
B\rgds
100

"100" <10*@100.com> wrote in message
news:en**************@TK2MSFTNGP10.phx.gbl...
Hi Johan,

Now I see what your issue is. Ok, the problem is that when a control is
created the framework by default sets WS_CLIPCHILDREN windows style to the
underlaying window. This style cause any part of of the client area

covered
by a child control to be excluded of the invalid region. As a result all
drawing in those areas are clipped.
What you can do is to reset this style. I don't know if it is good idea to use such platform dependant features, but this solves your problem. So

what
you can do is:

1. Add the following property to your main form:
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.Style &= ~0x02000000; //reset WS_CLIPCHILDREN
return createParams;
}
}

2. Now you have to restore the main form's clent area when the mouse

button
is released. You can't simply ignore OnPaint event in the child control.
This will not repaint the main form. You have to do something to fire

Paint
event in the parent form. There is my suggestion for the child control's
Paint event implementation:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )
{
base.OnPaint(e); //If you needed it it's better to call it before

your
painting
if (bPushed)
{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering
{
m_bmpOffscreen = new Bitmap(ClientSize.Width,

ClientSize.Height,
e.Graphics); //I believe is better to use this constructor
}
gxOff = Graphics.FromImage(m_bmpOffscreen);
//gxOff.Clear(Color.Empty); - I believe it is not necessary sice

it
doesnt do anything
gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10,
ClientSize.Height-10);
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
else
{
Parent.Invalidate(this.Bounds, false); //Fires parent's paint

event
}
}
HTH
B\rgds
100
"Sagaert Johan" <RE*******************@hotmail.com> wrote in message
news:un**************@TK2MSFTNGP09.phx.gbl...


"100" <10*@100.com> wrote in message
news:Ot*************@TK2MSFTNGP12.phx.gbl...
> Hi Johan,
>
> 1. Dont use Color.Empty for clearing the bitmap. This won't clear
anything.
> You should use color instead.
>
> something like:
> gxOff.Clear(this.BackColor);
>
> 2. Move
> e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
> out of the if(bPushed) block. You paint the control only if the button
is
> down. And you don't paint (clear ) anything if the button is up.
Thats just my problem,i don't want anything to be painted when i

don't press my control,
the only thing i want to see is the form , or the image i draw on the

form
.

In my form i draw a background image in the forms paint event, and the i would like to use

my control to create hotspots almost identical as they create hotspots

on images of html pages.

I don't understand why part of the form the is'nt painted correctly if my control does'nt do any painting by itself.Even if i call the forms
invalidate, the form paint routine seems to skip the area where my control is.

Johan


> Beside I have one suggestion. If you want to paint the whole clent
rectangle
> by yourself consider setting control styles:
>
> this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | > ControlStyles.AllPaintingInWmPaint, true);
>
> Even if you have your own offscreen bitmap you should set
> ControlStyles.DoubleBuffer style in order to avoid flickering.
>
> HTH
> B\rgds
> 100
>
>



Nov 15 '05 #10

P: n/a
100
Hi Joahn,
I didn't know that you are going to use it with CF. In CF there is no
underlaying native control so there is not Handle, CreateParameters, etc
properties and methods to manimpulating the underlaying window. That's why I
told you this is platform dependent and it's not good idea to use it.
Now I'm posting you the whole source of my next suggestion, which I believe
will work for CF. You can find my comments inline.
The new things are:
1. New event in the Hotspot control class + event handler in the form class
(PaintParent).
The full version of the framework has method InvokePaint that can be
used instead. CF doesn's suported it, though, so I added this event.
2. New method in the Hotspot control class (PaintBackground)

HTH
B\rgds
100

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Drawing.Imaging;
using System.Reflection;
namespace WindowsApplication2

{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private Hotspot spot ;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//The following is not supported by CF so don't set it. It will make the
things better for not CF, though.
//Set this to remove flickering.
//SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true);
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.BackColor = System.Drawing.SystemColors.Info;
this.ClientSize = new System.Drawing.Size(304, 213);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);

}

#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_Load(object sender, System.EventArgs e)
{
spot=new Hotspot() ;
spot.Size=new Size(50,50);
spot.Location=new Point(40,40);
spot.BringToFront();
spot.Visible=true;
spot.PaintParent += new PaintEventHandler(spot_PaintParent);
this.Controls.Add(spot);
}

protected override void OnPaint(PaintEventArgs e)
{
//Draw some stuff here
base.OnPaint (e);
e.Graphics.DrawLine(Pens.Red, 0, 0, this.ClientSize.Width,
this.ClientSize.Height);
e.Graphics.DrawLine(Pens.Red, this.ClientSize.Width, 0, 0,
this.ClientSize.Height);
}

private void spot_PaintParent(object sender, PaintEventArgs e)
{
//CF dosen't support background painting
//OnPaintBackground(e);
//Use the same event handler as for Pint event
OnPaint(e);
}
}

public class Hotspot : Control
{
//Requesting parent form to draw iteself on the control's surface
public PaintEventHandler PaintParent;
private bool bPushed;
private Bitmap m_bmpOffscreen;
Brush GrayBrush;
public Hotspot()
{
bPushed = false;
//default minimal size
this.Size = new Size(21, 21);
GrayBrush=new SolidBrush(Color.Gray);
//The following is not supported by CF so don't set it. It will make the
things better for not CF, though.
//Set this to remove flickering.
//SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true);
}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )
{
base.OnPaint(e); //If you needed it it's better to call it before your
painting
PaintBackground(e);
if (bPushed)
{
e.Graphics.FillRectangle(GrayBrush,5,5,ClientSize. Width-10,
ClientSize.Height-10);
}

}

private void PaintBackground(PaintEventArgs e)
{
Graphics gxOff; //Offscreen graphics
//Beacause the form is resizable the bitmap has to be recreated everytime
the form changes its size.
if (m_bmpOffscreen == null) //Bitmap for doublebuffering
{
//CF doesn't support transforamtions so we need to create bit map for
the whole parent client.
m_bmpOffscreen = new Bitmap(this.Parent.ClientSize.Width,
this.Parent.ClientSize.Height); //I believe is better to use this
constructor
}

gxOff = Graphics.FromImage(m_bmpOffscreen);
//Setting the clip region may increase the perforamnce
gxOff.Clip = new Region(this.Bounds);
PaintEventArgs pea = new PaintEventArgs(gxOff, this.Bounds);
//Raises OnPaintParent event
OnPaintParent(pea);
gxOff.Dispose();
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0, this.Bounds,
GraphicsUnit.Pixel);

}
//Raises PaintParent event.
protected virtual void OnPaintParent(PaintEventArgs e)
{
if(PaintParent != null)
{
PaintParent(this, e);
}
}

protected override void OnMouseDown ( System.Windows.Forms.MouseEventArgs
e )
{
bPushed = true;
Invalidate();
}

protected override void OnMouseUp ( System.Windows.Forms.MouseEventArgs
e )
{
bPushed = false;
Invalidate();
}
}
}
Nov 15 '05 #11

P: n/a
100
Hi Johan,
I'm just curious. Is the problem solved.

B\rgds
100

"Sagaert Johan" <ys*********@hotmail.com> wrote in message
news:3f***********************@reader1.news.skynet .be...
Hi
Thanks for your reply , now it works just as i would like !!!!!!!!!!!

I have put the Parent.Invalidate in the controls MouseUp event ,this seems
to be enough.

Now my next problem is how to solve this issue in the Compact framework
,since CF does not have the CreateParams method...

Best regards Johan http://www.qsl.net/on5di/


"100" <10*@100.com> wrote in message
news:OX****************@TK2MSFTNGP09.phx.gbl...
A little correction. It seems like calling invalidate with
invalidateChildren=false is not enough to stop Paint event for the child
control. As a result Parent.Invalidate is called over and over again (like
infinite loop of messages).
More logic has to be put in childe's control Paint event.

The idea I came up with is to use a flag in the child's control class

public class Hotspot : Control

{
private bool mStopPaint = false;
//..... other members

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )
{
if(mStopPaint) return;
base.OnPaint(e); //If you needed it it's better to call it before
your painting

if (bPushed)
{
//..... not changed
}
else
{
mStopPaint = true;
Parent.Invalidate(this.Bounds, false); //Fires parent's
paint event
Parent.Update(); //This want return until the parent is

not
repainted. We need that in order to mStopPaint flag to work
mStopPaint = false;
}

}
//.....The rest of the class
}
HTH
B\rgds
100

"100" <10*@100.com> wrote in message
news:en**************@TK2MSFTNGP10.phx.gbl...
Hi Johan,

Now I see what your issue is. Ok, the problem is that when a control is created the framework by default sets WS_CLIPCHILDREN windows style to the underlaying window. This style cause any part of of the client area

covered
by a child control to be excluded of the invalid region. As a result all drawing in those areas are clipped.
What you can do is to reset this style. I don't know if it is good idea to
use such platform dependant features, but this solves your problem. So what
you can do is:

1. Add the following property to your main form:
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.Style &= ~0x02000000; //reset WS_CLIPCHILDREN
return createParams;
}
}

2. Now you have to restore the main form's clent area when the mouse

button
is released. You can't simply ignore OnPaint event in the child
control. This will not repaint the main form. You have to do something to fire

Paint
event in the parent form. There is my suggestion for the child control's Paint event implementation:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e ) {
base.OnPaint(e); //If you needed it it's better to call it before

your
painting
if (bPushed)
{

Graphics gxOff; //Offscreen graphics
if (m_bmpOffscreen == null) //Bitmap for doublebuffering
{
m_bmpOffscreen = new Bitmap(ClientSize.Width,

ClientSize.Height,
e.Graphics); //I believe is better to use this constructor
}
gxOff = Graphics.FromImage(m_bmpOffscreen);
//gxOff.Clear(Color.Empty); - I believe it is not necessary

sice it
doesnt do anything
gxOff.FillRectangle(GrayBrush,5,5,ClientSize.Width-10,
ClientSize.Height-10);
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
}
else
{
Parent.Invalidate(this.Bounds, false); //Fires parent's paint

event
}
}
HTH
B\rgds
100
"Sagaert Johan" <RE*******************@hotmail.com> wrote in message
news:un**************@TK2MSFTNGP09.phx.gbl...
>
>
> "100" <10*@100.com> wrote in message
> news:Ot*************@TK2MSFTNGP12.phx.gbl...
> > Hi Johan,
> >
> > 1. Dont use Color.Empty for clearing the bitmap. This won't clear
> anything.
> > You should use color instead.
> >
> > something like:
> > gxOff.Clear(this.BackColor);
> >
> > 2. Move
> > e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
> > out of the if(bPushed) block. You paint the control only if the button is
> > down. And you don't paint (clear ) anything if the button is up.
>
>
> Thats just my problem,i don't want anything to be painted when i don't > press my control,
> the only thing i want to see is the form , or the image i draw on
the form
.
>
> In my form i draw a background image in the forms paint event, and
the i > would like to use
>
> my control to create hotspots almost identical as they create
hotspots on
> images of html pages.
>
> I don't understand why part of the form the is'nt painted correctly
if my
> control does'nt do any painting by itself.Even if i call the forms
> invalidate, the form paint routine seems to skip the area where my control
> is.
>
> Johan
>
>
>
>
> > Beside I have one suggestion. If you want to paint the whole clent
> rectangle
> > by yourself consider setting control styles:
> >
> > this.SetStyle(ControlStyles.DoubleBuffer |

ControlStyles.UserPaint | > > ControlStyles.AllPaintingInWmPaint, true);
> >
> > Even if you have your own offscreen bitmap you should set
> > ControlStyles.DoubleBuffer style in order to avoid flickering.
> >
> > HTH
> > B\rgds
> > 100
> >
> >
>
>



Nov 15 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.