Custom control help!
-
The following code is meant to draw a grid and is a custom control (one that can be dragged from the toolbox) :
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
AutoScroll = true;} Point \_rowColumn; Point \_widthHeight; Rectangle\[,\] \_bound; public void Init(int x, int y, int width, int height) { SetAutoSizeMode(AutoSizeMode.GrowAndShrink); \_rowColumn = new Point(x, y); \_bound = new Rectangle\[x, y\]; \_widthHeight = new Point(width, height); \_drawArea = new Bitmap(Width, Height); LoadTiles(); \_loaded = true; AutoScrollMinSize = new Size(x \* width, y \* height); } void LoadTiles() { for (int x = 0; x < \_rowColumn.X; x++) { for (int y = 0; y < \_rowColumn.Y; y++) { \_bound\[x, y\] = new Rectangle(x\* \_widthHeight.X, y\*\_widthHeight.Y, \_widthHeight.X, \_widthHeight.Y); } } } Bitmap \_drawArea; bool \_loaded = false; void DrawGrid() { Graphics gfx = Graphics.FromImage(\_drawArea); gfx.Clear(Color.White); Pen pen = new Pen(Color.Black,1); foreach (Rectangle r in \_bound) { gfx.DrawRectangle(pen, r); } gfx.Dispose(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.Clear(Color.White); Matrix mx = new Matrix(1, 0, 0, 1, AutoScrollPosition.X, AutoScrollPosition.Y); e.Graphics.Transform = mx; e.Graphics.PageUnit = GraphicsUnit.Pixel; if (!\_loaded) return; DrawGrid(); Graphics gfx = e.Graphics; gfx.DrawImage(\_drawArea, -AutoScrollPosition.X, -AutoScrollPosition.Y, \_drawArea.Width, \_drawArea.Height); gfx.Dispose(); } private void UserControl1\_Paint(object sender, PaintEventArgs e) { } }
It displays everything but for some reason when I scroll the lines distort! Here is a link of what it looks like without scrollin
-
The following code is meant to draw a grid and is a custom control (one that can be dragged from the toolbox) :
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
AutoScroll = true;} Point \_rowColumn; Point \_widthHeight; Rectangle\[,\] \_bound; public void Init(int x, int y, int width, int height) { SetAutoSizeMode(AutoSizeMode.GrowAndShrink); \_rowColumn = new Point(x, y); \_bound = new Rectangle\[x, y\]; \_widthHeight = new Point(width, height); \_drawArea = new Bitmap(Width, Height); LoadTiles(); \_loaded = true; AutoScrollMinSize = new Size(x \* width, y \* height); } void LoadTiles() { for (int x = 0; x < \_rowColumn.X; x++) { for (int y = 0; y < \_rowColumn.Y; y++) { \_bound\[x, y\] = new Rectangle(x\* \_widthHeight.X, y\*\_widthHeight.Y, \_widthHeight.X, \_widthHeight.Y); } } } Bitmap \_drawArea; bool \_loaded = false; void DrawGrid() { Graphics gfx = Graphics.FromImage(\_drawArea); gfx.Clear(Color.White); Pen pen = new Pen(Color.Black,1); foreach (Rectangle r in \_bound) { gfx.DrawRectangle(pen, r); } gfx.Dispose(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.Clear(Color.White); Matrix mx = new Matrix(1, 0, 0, 1, AutoScrollPosition.X, AutoScrollPosition.Y); e.Graphics.Transform = mx; e.Graphics.PageUnit = GraphicsUnit.Pixel; if (!\_loaded) return; DrawGrid(); Graphics gfx = e.Graphics; gfx.DrawImage(\_drawArea, -AutoScrollPosition.X, -AutoScrollPosition.Y, \_drawArea.Width, \_drawArea.Height); gfx.Dispose(); } private void UserControl1\_Paint(object sender, PaintEventArgs e) { } }
It displays everything but for some reason when I scroll the lines distort! Here is a link of what it looks like without scrollin
Hi again, the problem with AutoScroll is Windows, while scrolling, will copy and move that part of the painting that it can reuse, and order your Paint handler to only paint the new stuff, the part that becomes visible by scrolling. And that interferes with your intentions. Furthermore, your code is much too complex; you are using an image, there is no need for, nor advantage in, doing that. Here is a simple example that works well; I use a specialized panel to get double-buffering, and I invalidate the (entire) panel when scrolling, forcing an all-paint, no-copy approach.
Panel p; int nHor=40; int nVert=10; int wid=20; int hei=20; public void Demo() { Form f=new Form(); f.Bounds=new Rectangle(0, 0, 500, 500); p=new UserDrawnPanel(); // or p=new Panel(); p.Bounds=new Rectangle(20, 20, 400, 400); p.AutoScroll=true; p.AutoScrollMinSize=new Size(nHor\*wid+10, nVert\*hei+10); p.BackColor=Color.White; p.Paint+=new PaintEventHandler(p\_Paint); p.Scroll+=new ScrollEventHandler(p\_Scroll); f.Controls.Add(p); f.Show(); } void p\_Scroll(object sender, ScrollEventArgs e) { log("Scroll="+e.NewValue); p.Invalidate(); } void p\_Paint(object sender, PaintEventArgs e) { Graphics g=e.Graphics; log("ClipRectangle="+e.ClipRectangle); log("AutoScrollPosition="+p.AutoScrollPosition); g.TranslateTransform(p.AutoScrollPosition.X, p.AutoScrollPosition.Y); for (int y=0; y<=nVert; y++) g.DrawLine(Pens.Black, 0, y\*hei, nHor\*wid, y\*hei); for (int x=0; x<=nHor ; x++) g.DrawLine(Pens.Black, x\*wid, 0, x\*wid, nVert\*hei); } class UserDrawnPanel : Panel { public UserDrawnPanel() { SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true); } }
BTW: you can safely ignore the log statements. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
-
Hi again, the problem with AutoScroll is Windows, while scrolling, will copy and move that part of the painting that it can reuse, and order your Paint handler to only paint the new stuff, the part that becomes visible by scrolling. And that interferes with your intentions. Furthermore, your code is much too complex; you are using an image, there is no need for, nor advantage in, doing that. Here is a simple example that works well; I use a specialized panel to get double-buffering, and I invalidate the (entire) panel when scrolling, forcing an all-paint, no-copy approach.
Panel p; int nHor=40; int nVert=10; int wid=20; int hei=20; public void Demo() { Form f=new Form(); f.Bounds=new Rectangle(0, 0, 500, 500); p=new UserDrawnPanel(); // or p=new Panel(); p.Bounds=new Rectangle(20, 20, 400, 400); p.AutoScroll=true; p.AutoScrollMinSize=new Size(nHor\*wid+10, nVert\*hei+10); p.BackColor=Color.White; p.Paint+=new PaintEventHandler(p\_Paint); p.Scroll+=new ScrollEventHandler(p\_Scroll); f.Controls.Add(p); f.Show(); } void p\_Scroll(object sender, ScrollEventArgs e) { log("Scroll="+e.NewValue); p.Invalidate(); } void p\_Paint(object sender, PaintEventArgs e) { Graphics g=e.Graphics; log("ClipRectangle="+e.ClipRectangle); log("AutoScrollPosition="+p.AutoScrollPosition); g.TranslateTransform(p.AutoScrollPosition.X, p.AutoScrollPosition.Y); for (int y=0; y<=nVert; y++) g.DrawLine(Pens.Black, 0, y\*hei, nHor\*wid, y\*hei); for (int x=0; x<=nHor ; x++) g.DrawLine(Pens.Black, x\*wid, 0, x\*wid, nVert\*hei); } class UserDrawnPanel : Panel { public UserDrawnPanel() { SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true); } }
BTW: you can safely ignore the log statements. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
Thanks again it works well :-D
-
Thanks again it works well :-D
you're welcome. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.