GDI¡¢OnPaint¡¢AutoScroll

N

NewSun

I draw a grid on a panel.And panel1' property AutoScroll is set true.When
HScroollBar is Scroolling,the grid is error.
I have rewritten the mathod of WndProc.But the effect is unexpected.
How can i do? Thx a lot.
Main codes go here:
class frm
private MyApp.Panel panel1;
this.panel1.Paint += new
System.Windows.Forms.PaintEventHandler(this.OnPaint);

private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs e)
{

Graphics grPaint = e.Graphics;

grPaint.Flush(System.Drawing.Drawing2D.FlushIntention.Sync);

SolidBrush brushWhite = new SolidBrush(Color.White);
Pen blackpen = new Pen(Color.Black,2);

// Clear the screen
grPaint.FillRectangle(brushWhite, e.ClipRectangle);

// Draw the grid
grPaint.DrawString("testsdsdsadssadadafsewr3wqr32r", new
Font("Arial",12), new SolidBrush(Color.Black),_RECTSIZE_,10);
grPaint.DrawString("testsdsdsadssadadafsewr3wqr32r", new
Font("Arial",12), new SolidBrush(Color.Black),_RECTSIZE_,30);

for(int i=0;i<iCols;i++)
{
for(int j=0;j<iRows;j++)
{
grPaint.DrawRectangle(blackpen, 5 * _RECTSIZE_ + (i* _RECTSIZE_), 3 *
_RECTSIZE_ + (j*_RECTSIZE_),_RECTSIZE_,_RECTSIZE_);
}
}
brushWhite.Dispose();
blackpen.Dispose();
}
class Panel :System.Windows.Forms.Panel
{

[System.Security.Permissions.PermissionSet(System.Security.Permissions.Secur
ityAction.Demand, Name="FullTrust")]
protected override void WndProc(ref Message m)
{
if(m.Msg == 0x0114)
{
Invalidate();
}
else if(m.Msg == 0x0115)
{
Invalidate();
}
else if(m.Msg == 0x020A)
{
Invalidate();
}
else
{

}
base.WndProc(ref m);
}
}
 
M

Morten Wennevik

I think you will want to handle the panel1.autoscrollposition in your
OnPaint code to find out where upper left of the grid will start. Beware
that the position will be negative as you move the panel "to the right and
upwards" when scrolling left and down.

I'm not sure what you try to do with WndProc, but if it is scrolling with
keys, you can do that much easier by using the forms OnKeyDown event and
use panel1.AutoScrollPosition = // new position or +/-= increment (beware
of boundaries errors)
 
N

NewSun

Thank Morten Wennevik.
I'm a beginner for .net.
I rewirte OnKeyDown method,but it doen't work. My code goes here:

public int iX = 0 ,iY = 0 ;
protected override void OnKeyDown(KeyEventArgs e)
{
iX = this.AutoScrollPosition.X;
iY = this.AutoScrollPosition.Y;
base.OnKeyDown(e);
MessageBox.Show(iX.ToString());
}
 
M

Morten Wennevik

What are you trying to accomplish?

If you want the arrow keys to scroll you can use something like this

protected override void OnKeyDown(KeyEventArgs e)
{
// xStep and yStep is the amount to scroll left-right/up-down each time
the key is hit
int xStep = 10;
int yStep = 10;
// Check all keys pressed
// The AutoScrollPosition is actually negative or 0, but when you set the
autoscrollposition
// it has to be positive, so we set // AutoScrollPosition = new Point(-
AutoScrollPosition.X, -AutoScrollPosition.Y);
switch(e.KeyCode)
{
case Keys.Right:
AutoScrollPosition = new Point(-AutoScrollPosition.X + xStep, -
AutoScrollPosition.Y);
break;
case Keys.Left:
AutoScrollPosition = new Point(-AutoScrollPosition.X - xStep, -
AutoScrollPosition.Y);
break;
case Keys.Up:
AutoScrollPosition = new Point(-AutoScrollPosition.X, -
AutoScrollPosition.Y - yStep);
break;
case Keys.Down:
AutoScrollPosition = new Point(-AutoScrollPosition.X, -
AutoScrollPosition.Y + yStep);
break;
default:
break;
}
// You can use a label control to show the current autoscrollposition.
// Set top and left position each time you scroll or the label will move
with the window
label1.Top = 0;
label1.Left = 0;
label1.Text = AutoScrollPosition.ToString();
}
 
N

NewSun

I'm sorry .I found that this method -- OnKeyDown was never called.
I just want to draw something and make it correct whenever.
Thx.

class Panel :System.Windows.Forms.Panel
{

[System.Security.Permissions.PermissionSet(System.Security.Permissions.Secur
ityAction.Demand, Name="FullTrust")]

protected override void OnKeyDown(KeyEventArgs e)
{
// xStep and yStep is the amount to scroll left-right/up-down each time
the key is hit
int xStep = 10;
int yStep = 10;
// Check all keys pressed
// The AutoScrollPosition is actually negative or 0, but when you set the
autoscrollposition
// it has to be positive, so we set // AutoScrollPosition = new Point(-
AutoScrollPosition.X, -AutoScrollPosition.Y);
switch(e.KeyCode)
{
case Keys.Right:
AutoScrollPosition = new Point(-AutoScrollPosition.X + xStep, -
AutoScrollPosition.Y);
break;
case Keys.Left:
AutoScrollPosition = new Point(-AutoScrollPosition.X - xStep, -
AutoScrollPosition.Y);
break;
case Keys.Up:
AutoScrollPosition = new Point(-AutoScrollPosition.X, -
AutoScrollPosition.Y - yStep);
break;
case Keys.Down:
AutoScrollPosition = new Point(-AutoScrollPosition.X, -
AutoScrollPosition.Y + yStep);
break;
default:
break;
}
}

class frmTest
{
this.panel1 = new MyApp.Panel();
}
 
M

Morten Wennevik

OnKeyDown is called whenever you hit a key (arrow keys in the example);

You also need to redraw OnPaint

protected override void OnPaint(PaintEventArgs e)
{
}

I forgot if setting scrollposition calls OnPaint or not, if not you will
want to Invalidate() or Invalidate(rect) at the end of OnKeyDown if you
change scroll position. Scrolling with mouse cursor or wheel will call
OnPaint.

Paint procedures where scrolling is involved can get tricky.
Remember the autoscroll coordinates are negative. You might want to do a
search on the web for examples.
__________ |-x,-y |
| |
|Window |
| Form |
| _______|
| |0,0 |
| | Screen|
|__|_______|
 
N

NewSun

All code goes here .

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace Sample
{
/// <summary>
/// Form1 µÄժҪ˵Ã÷¡£
/// </summary>
public class frmDemo : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel1;
private System.ComponentModel.IContainer components;
private int iCols = 10 ,iRows = 6;
private System.Windows.Forms.ImageList imageList1;
private System.Windows.Forms.Label label1;
const int _RECTSIZE_ = 30;
public frmDemo()
{
//
// Windows ´°ÌåÉè¼ÆÆ÷Ö§³ÖËù±ØÐèµÄ
//
InitializeComponent();

//
// TODO: ÔÚ InitializeComponent µ÷ÓúóÌí¼ÓÈκι¹Ô캯Êý´úÂë
//
}

/// <summary>
/// ÇåÀíËùÓÐÕýÔÚʹÓõÄ×ÊÔ´¡£
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows ´°ÌåÉè¼ÆÆ÷Éú³ÉµÄ´úÂë
/// <summary>
/// Éè¼ÆÆ÷Ö§³ÖËùÐèµÄ·½·¨ - ²»ÒªÊ¹ÓôúÂë±à¼­Æ÷ÐÞ¸Ä
/// ´Ë·½·¨µÄÄÚÈÝ¡£
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.panel1 = new System.Windows.Forms.Panel();
this.imageList1 = new System.Windows.Forms.ImageList(this.components);
this.label1 = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.AutoScroll = true;
this.panel1.Controls.Add(this.label1);
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(344, 328);
this.panel1.TabIndex = 0;
this.panel1.Paint += new
System.Windows.Forms.PaintEventHandler(this.panel1_OnPaint);
//
// imageList1
//
this.imageList1.ImageSize = new System.Drawing.Size(16, 16);
this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
//
// label1
//
this.label1.Location = new System.Drawing.Point(256, 304);
this.label1.Name = "label1";
this.label1.TabIndex = 0;
this.label1.Text = "label1";
//
// frmDemo
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(376, 349);
this.Controls.Add(this.panel1);
this.Name = "frmDemo";
this.Text = "Draw a grid";
this.Load += new System.EventHandler(this.frmDemo_Load);
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// Ó¦ÓóÌÐòµÄÖ÷Èë¿Úµã¡£
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new frmDemo());
}
private void panel1_OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
Graphics grPaint = e.Graphics;

grPaint.Flush(System.Drawing.Drawing2D.FlushIntention.Sync);

SolidBrush brushWhite = new SolidBrush(Color.White);
Pen blackpen = new Pen(Color.Black,2);

// Clear the screen
grPaint.FillRectangle(brushWhite, e.ClipRectangle);

// Draw the grid
grPaint.DrawString("This is a demo -- draw a grid.And expect that it
works well whenever.", new Font("Arial",12), new
SolidBrush(Color.Black),_RECTSIZE_,10);

for(int i=0;i<iCols;i++)
{
for(int j=0;j<iRows;j++)
{
grPaint.DrawRectangle(blackpen, 5 * _RECTSIZE_ + (i* _RECTSIZE_), 3 *
_RECTSIZE_ + (j*_RECTSIZE_),_RECTSIZE_,_RECTSIZE_);
}
}
brushWhite.Dispose();
blackpen.Dispose();

}

private void frmDemo_Load(object sender, System.EventArgs e)
{

}
}
class Panel :System.Windows.Forms.Panel
{

[System.Security.Permissions.PermissionSet(System.Security.Permissions.Secur
ityAction.Demand, Name="FullTrust")]

protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
MessageBox.Show("This method is never called.");
}
protected override void WndProc(ref Message m)
{
if(m.Msg == 0x0114)
{
}
else if(m.Msg == 0x0115)
{
}
else if(m.Msg == 0x020A)
{
}
else
{

}
base.WndProc(ref m);
}
}
}
 
N

NewSun

I don't know which event would be triggered when ScrollBar is clicked.


All code goes here . Plz try it.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace Sample
{

public class frmDemo : System.Windows.Forms.Form
{
private Sample.Panel panel1;
private System.ComponentModel.IContainer components;
private int iCols = 10 ,iRows = 6;
private System.Windows.Forms.ImageList imageList1;
private System.Windows.Forms.Label label1;
const int _RECTSIZE_ = 30;
public frmDemo()
{

InitializeComponent();

}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.panel1 = new Sample.Panel ();
this.imageList1 = new System.Windows.Forms.ImageList(this.components);
this.label1 = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.AutoScroll = true;
this.panel1.Controls.Add(this.label1);
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(344, 328);
this.panel1.TabIndex = 0;
this.panel1.Paint += new
System.Windows.Forms.PaintEventHandler(this.panel1_OnPaint);
//
// imageList1
//
this.imageList1.ImageSize = new System.Drawing.Size(16, 16);
this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
//
// label1
//
this.label1.Location = new System.Drawing.Point(256, 304);
this.label1.Name = "label1";
this.label1.TabIndex = 0;
this.label1.Text = "label1";
//
// frmDemo
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(376, 349);
this.Controls.Add(this.panel1);
this.Name = "frmDemo";
this.Text = "Draw a grid";
this.Load += new System.EventHandler(this.frmDemo_Load);
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);

}
#endregion

[STAThread]
static void Main()
{
Application.Run(new frmDemo());
}
private void panel1_OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
Graphics grPaint = e.Graphics;

grPaint.Flush(System.Drawing.Drawing2D.FlushIntention.Sync);

SolidBrush brushWhite = new SolidBrush(Color.White);
Pen blackpen = new Pen(Color.Black,2);

// Clear the screen
grPaint.FillRectangle(brushWhite, e.ClipRectangle);

// Draw the grid
grPaint.DrawString("This is a demo -- draw a grid.And expect that it
works well whenever.", new Font("Arial",12), new
SolidBrush(Color.Black),_RECTSIZE_,10);

for(int i=0;i<iCols;i++)
{
for(int j=0;j<iRows;j++)
{
grPaint.DrawRectangle(blackpen, 5 * _RECTSIZE_ + (i* _RECTSIZE_), 3 *
_RECTSIZE_ + (j*_RECTSIZE_),_RECTSIZE_,_RECTSIZE_);
}
}
brushWhite.Dispose();
blackpen.Dispose();

}

private void frmDemo_Load(object sender, System.EventArgs e)
{

}
}
class Panel :System.Windows.Forms.Panel
{

[System.Security.Permissions.PermissionSet(System.Security.Permissions.Secur
ityAction.Demand, Name="FullTrust")]

protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
MessageBox.Show("This method is never called.");
}
protected override void WndProc(ref Message m)
{
if(m.Msg == 0x0114)
{
}
else if(m.Msg == 0x0115)
{
}
else if(m.Msg == 0x020A)
{
}
else
{

}
base.WndProc(ref m);
}
}
}
 
M

Morten Wennevik

Well, I can see one problem with it. You aren't changing the start
position of the drawing. You can see this by scrolling, then cover the
window with another window and move the other window away, the text and
grid will always be in the same spot starting at window coordinate
_RECTSIZE_ * 1, 3 or 5.

I've made a few ints indicating start of the x-and y-coordinate of the
string and the grid.

int stringX = _RECTSIZE_ + panel1.AutoScrollPosition.X;
int stringY = 10 + panel1.AutoScrollPosition.Y;
grPaint.DrawString("This is a demo -- draw a grid.And expect that it works
well whenever.", new Font("Arial",12), new SolidBrush(Color.Black),
stringX, stringY);

and

int startX = 5*_RECTSIZE_ + panel1.AutoScrollPosition.X;
int startY = 3*_RECTSIZE_ + panel1.AutoScrollPosition.Y;
for(int i=0;i<iCols;i++)
{
for(int j=0;j<iRows;j++)
{
grPaint.DrawRectangle(blackpen, startX + i*_RECTSIZE_, startY +
j*_RECTSIZE_, _RECTSIZE_, _RECTSIZE_);
}
}


And here is the entire code for it


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Sample
{
public class frmDemo : System.Windows.Forms.Form
{
private Sample.Panel panel1;
private System.ComponentModel.IContainer components;
private int iCols = 10 ,iRows = 6;
private System.Windows.Forms.ImageList imageList1;
private System.Windows.Forms.Label label1;
const int _RECTSIZE_ = 30;
public frmDemo()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Initialize components
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.panel1 = new Sample.Panel ();
this.imageList1 = new System.Windows.Forms.ImageList(this.components);
this.label1 = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.AutoScroll = true;
this.panel1.Controls.Add(this.label1);
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(344, 328);
this.panel1.TabIndex = 0;
this.panel1.Paint += new
System.Windows.Forms.PaintEventHandler(this.panel1_OnPaint);
//
// imageList1
//
this.imageList1.ImageSize = new System.Drawing.Size(16, 16);
this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
//
// label1
//
this.label1.Location = new System.Drawing.Point(256, 304);
this.label1.Name = "label1";
this.label1.TabIndex = 0;
this.label1.Text = "label1";
//
// frmDemo
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(376, 349);
this.Controls.Add(this.panel1);
this.Name = "frmDemo";
this.Text = "Draw a grid";
this.Load += new System.EventHandler(this.frmDemo_Load);
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
[STAThread]
static void Main()
{
Application.Run(new frmDemo());
}

private void panel1_OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{

Graphics grPaint = e.Graphics;
grPaint.Flush(System.Drawing.Drawing2D.FlushIntention.Sync);
SolidBrush brushWhite = new SolidBrush(Color.White);
Pen blackpen = new Pen(Color.Black,2);
// Clear the screen
grPaint.FillRectangle(brushWhite, e.ClipRectangle);
// Draw the grid
// You need to adjust top left by adding the negative autoscrollposition
int stringX = _RECTSIZE_ + panel1.AutoScrollPosition.X;
int stringY = 10 + panel1.AutoScrollPosition.Y;
grPaint.DrawString("This is a demo -- draw a grid.And expect that it
works well whenever.", new Font("Arial",12), new SolidBrush(Color.Black),
stringX, stringY);
// Same with this, the starting point of the grid will change when you
scroll and can't be a fixed number.
int startX = 5*_RECTSIZE_ + panel1.AutoScrollPosition.X;
int startY = 3*_RECTSIZE_ + panel1.AutoScrollPosition.Y;
for(int i=0;i<iCols;i++)
{
for(int j=0;j<iRows;j++)
{
grPaint.DrawRectangle(blackpen, startX + i*_RECTSIZE_, startY +
j*_RECTSIZE_, _RECTSIZE_, _RECTSIZE_);
}
}
brushWhite.Dispose();
blackpen.Dispose();
}
private void frmDemo_Load(object sender, System.EventArgs e)
{
}
}
class Panel :System.Windows.Forms.Panel
{

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand,
Name="FullTrust")]
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
MessageBox.Show("This method is never called.");
}
protected override void WndProc(ref Message m)
{
if(m.Msg == 0x0114)
{
}
else if(m.Msg == 0x0115)
{
}
else if(m.Msg == 0x020A)
{
}
else
{
}
base.WndProc(ref m);
}
}
}
 
N

NewSun

Would you give me a sample for event--OnKeyDown raised.Thx.
Here is my code. And i found this method is never called.

[System.Security.Permissions.PermissionSet(System.Security.Permissions.Secur
ityAction.Demand, Name="FullTrust")]
protected override void OnKeyDown(KeyEventArgs e)
{
MessageBox.Show("This method is never called.");
base.OnKeyDown(e);
}
 
M

Morten Wennevik

Ah, it appears that a panel doesn't have a KeyDown event, or any key event
whatsoever.
There may be other solutions to it, but you can capture the key event in
the main form and adjust the scrollposition for the panel.

Don't ask me why there is an adjustment of 28 here and 20 for setting
scrollmargins, because I don't know.
Check if adding a step will move the scrollbar outside it's margins, if
not, add a step, otherwise, set it to margin + 28;

private void frmDemo_KeyDown(object sender, KeyEventArgs e)
{
int step = 10;
switch(e.KeyCode)
{
case Keys.Right:
if(-(panel1.AutoScrollPosition.X - step) <=
(panel1.AutoScrollMargin.Width + 28))
panel1.AutoScrollPosition = new Point(-(panel1.AutoScrollPosition.X -
step), -panel1.AutoScrollPosition.Y);
else
panel1.AutoScrollPosition = new Point(panel1.AutoScrollMargin.Width +
28, -panel1.AutoScrollPosition.Y);
break;
case Keys.Left:
if(-(panel1.AutoScrollPosition.X + step) > 0)
panel1.AutoScrollPosition = new Point(-(panel1.AutoScrollPosition.X +
step), -panel1.AutoScrollPosition.Y);
else
panel1.AutoScrollPosition = new Point(0, -panel1.AutoScrollPosition.Y);
break;
default:
return;
}
}

You will also want to set AutoScrollMargin after InitializeComponent
The size is the width and height of what you don't see. That is, what is
outside the current view area, but can be accessed through scrolling. This
is typically the size of everything - the size of what we already see +
adjust for scrollbars covering some of it.

int width = 5*_RECTSIZE_ + iCols*_RECTSIZE_ - panel1.Width + 20;
if(width < 0)
width = 0;
int height = 3*_RECTSIZE_ + iRows*_RECTSIZE_ - panel1.Height + 20;
if(height < 0)
height = 0;
panel1.AutoScrollMargin = new Size(width, height);


And add a keyeventhandler to InitializeComponent

this.KeyDown += new
System.Windows.Forms.KeyEventHandler(this.frmDemo_KeyDown);
 
Top