[Mono-bugs] [Bug 74858][Nor] New - Issues with drawing inside PaintEventHandler
bugzilla-daemon@bugzilla.ximian.com
bugzilla-daemon@bugzilla.ximian.com
Sat, 7 May 2005 07:20:11 -0400 (EDT)
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by jakub007@go2.pl.
http://bugzilla.ximian.com/show_bug.cgi?id=74858
--- shadow/74858 2005-05-07 07:20:11.000000000 -0400
+++ shadow/74858.tmp.15350 2005-05-07 07:20:11.000000000 -0400
@@ -0,0 +1,337 @@
+Bug#: 74858
+Product: Mono: Class Libraries
+Version: 1.1
+OS:
+OS Details: Gentoo 2005.0
+Status: NEW
+Resolution:
+Severity:
+Priority: Normal
+Component: Windows.Forms
+AssignedTo: mono-bugs@ximian.com
+ReportedBy: jakub007@go2.pl
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL:
+Cc:
+Summary: Issues with drawing inside PaintEventHandler
+
+Please fill in this template when reporting a bug, unless you know what you
+are doing.
+Description of Problem:
+
+
+Steps to reproduce the problem:
+1. private System.Windows.Forms.PictureBox pictureBox1;
+2. this.pictureBox1.Paint += new PaintEventHandler(MyOnPaint);
+3. private void MyOnPaint(object sender, PaintEventArgs e)
+ {
+ // 1)e.Graphics.Clear(Color.White); crashes with Image==null exception
+ // e.Graphics.FillRectangle(Brushes.White,e.ClipRectangle); must be
+used instead
+ // 2)DrawSelf(e.Graphics,e.ClipRectangle); causes flickering
+ // 3)the code below is flicker-free, but when window is moved
+ // or menu is activated (covering part of pictureBox1), redrawing does
+not ocuur.
+ Image im = new Bitmap(e.ClipRectangle.Width,e.ClipRectangle.Height);
+ Graphics G = Graphics.FromImage(im);
+ G.Clear(Color.White);
+ DrawSomething(G,e.ClipRectangle);
+ e.Graphics.DrawImage(im,0,0);
+ }
+
+Actual Results: Drawing code which works with .NET causes exceptions or
+flickering or has issues with redrawing.
+
+
+Expected Results: Stable, flicker-free drawing
+
+
+How often does this happen? Always
+
+
+Additional Information: Mono 1.1.7
+
+----cut here-----------------
+/*
+ * Created by SharpDevelop.
+ * User: root
+ * Date: 2005-05-05
+ * Time: 02:54
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard
+Headers.
+ */
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using System.Drawing.Drawing2D;
+
+namespace KIK
+{
+ public class MainForm : System.Windows.Forms.Form
+ {
+ private System.Windows.Forms.PictureBox pictureBox1;
+ private System.Windows.Forms.MainMenu mainMenu1;
+ private System.Windows.Forms.MenuItem menuItem2;
+ private System.Windows.Forms.MenuItem menuItem1;
+ int sx = 30, sy = -30, vx = 40, vy = 30, a = 100;
+
+ public const int POLE_E = 0;
+ public const int POLE_O = 1;
+ public const int POLE_X = 2;
+ public const int SELECT = 100;
+
+ int my_moves = 0;
+ int ai_moves = 0;
+ bool active = true;
+
+ int[,,] pola = new int[3,3,3];
+
+ bool isX(int l, int x, int y) { return pola[l,x,y]%SELECT == POLE_X; }
+ bool isO(int l, int x, int y) { return pola[l,x,y]%SELECT == POLE_O; }
+ bool isEmpty(int l, int x, int y) { return pola[l,x,y]%SELECT == POLE_E; }
+ bool isSelected(int l, int x, int y) { return pola[l,x,y] > SELECT; }
+
+ bool Select(int level, int x, int y)
+ {
+ if (pola[level,x,y] < SELECT) {
+ pola[level,x,y]+=SELECT;
+ return true;
+ }
+ else return false;
+ }
+
+ void SetX(int l, int x, int y) { pola[l,x,y] = POLE_X; }
+ void SetO(int l, int x, int y) { pola[l,x,y] = POLE_X; }
+
+ int UnSelect(int level, int x, int y) {
+ if (pola[level,x,y] >= SELECT) {
+ pola[level,x,y]-=SELECT;
+ return 1;
+ }
+ else return 0;
+ }
+
+ public MainForm()
+ {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer
+support.
+ //
+ InitializeComponent();
+ this.pictureBox1.Paint += new PaintEventHandler(MyOnPaint);
+ this.menuItem2.Click += new EventHandler(doExit);
+ this.pictureBox1.MouseMove += new MouseEventHandler(MyOnMouseMove);
+ this.pictureBox1.MouseDown += new MouseEventHandler(MyOnClick);
+ Array.Clear(pola,0,27);
+ }
+
+ void EndGame(bool win)
+ {
+ if (win)
+ MessageBox.Show("Wygrales :)","Kolko i Krzyzyk");
+ else
+ MessageBox.Show("Wygrales :)","Kolko i Krzyzyk");
+ }
+
+ void MyOnMouseMove(object sender, MouseEventArgs e)
+ {
+ if (!active) return;
+ int X = e.X - sx;
+ int Y = e.Y - sy - a;
+ int level = Y>=0 ? Y/a : -1;
+ int y = (Y - level*a) / vy;
+ int x = (X - y*vx) / a;
+ int undo = 0;
+ for (int _level=0; _level<3; _level++)
+ for (int _x=0; _x<3; _x++)
+ for (int _y=0; _y<3; _y++)
+ undo+=UnSelect(_level,_x,_y);
+
+ if (level>-1 && x>-1 && y>-1 && x<3 && y<3 && level<3) {
+ if (Select(level,x,y))
+ this.pictureBox1.Invalidate();
+ }
+ else if (undo>0)
+ this.pictureBox1.Invalidate();
+ }
+
+ void MyOnClick(object sender, MouseEventArgs e)
+ {
+ if (!active) return;
+ int X = e.X - sx;
+ int Y = e.Y - sy - a;
+ int level = Y>=0 ? Y/a : -1;
+ int y = (Y - level*a) / vy;
+ int x = (X - y*vx) / a;
+ if (level>-1 && x>-1 && y>-1 && x<3 && y<3 && level<3)
+ {
+ if (isEmpty(level,x,y)) {
+ SetX(level,x,y);
+ my_moves++;
+ this.pictureBox1.Invalidate();
+ }
+ }
+ }
+
+ void drawBase(Graphics g, Pen p, int sx, int sy, int vx, int vy, int a)
+ {
+ g.DrawLine(p,sx+vx,sy+vy,sx+vx+a*3,sy+vy);
+ g.DrawLine(p,sx+vx*2,sy+2*vy,sx+vx*2+a*3,sy+2*vy);
+ g.DrawLine(p,sx+a,sy,sx+vx*3+a,sy+vy*3);
+ g.DrawLine(p,sx+2*a,sy,sx+vx*3+2*a,sy+vy*3);
+ g.DrawLine(p,sx,sy,sx+3*a,sy);
+ g.DrawLine(p,sx+3*vx,sy+3*vy,sx+3*a+3*vx,sy+3*vy);
+ g.DrawLine(p,sx,sy,sx+3*vx,sy+3*vy);
+ g.DrawLine(p,sx+3*a,sy,sx+3*vx+3*a,sy+3*vy);
+ }
+
+ void drawBox(Graphics g, int level, int x, int y)
+ {
+ GraphicsPath p = new GraphicsPath(); level++;
+ Point p1 = new Point(sx+x*a+y*vx,sy+y*vy+level*a);
+ Point p2 = new Point(sx+(x+1)*a +y*vx,sy+y*vy+level*a);
+ Point p3 = new Point(sx+(x+1)*a +(y+1)*vx,sy+(y+1)*vy+level*a);
+ Point p4 = new Point(sx+x*a+(y+1)*vx,sy+(y+1)*vy+level*a);
+ p.AddLine(p1,p2);
+ p.AddLine(p2,p3);
+ p.AddLine(p3,p4);
+ p.AddLine(p4,p1);
+ g.SmoothingMode = SmoothingMode.HighQuality;
+ level--;
+
+ switch (pola[level,x,y]%SELECT) {
+
+ case POLE_E:
+ g.DrawPath(Pens.LightGray,p);
+
+ if (pola[level,x,y]>=SELECT)
+ g.FillPath(Brushes.Green,p);
+ else
+ g.DrawPath(Pens.LightGray,p);
+ break;
+
+ case POLE_X:
+ g.DrawPath(Pens.LightGray,p);
+
+ Pen pen = new Pen(Color.Green, 6);
+ p1.Offset(vx/2+5,7);
+ p2.Offset(-5,5);
+ p3.Offset(-vx/2-5,-5);
+ p4.Offset(5,-5);
+ g.DrawLine(pen,p1,p3);
+ g.DrawLine(pen,p2,p4);
+ pen.Dispose();
+ break;
+
+ case POLE_O:
+ g.DrawPath(Pens.LightGray,p);
+
+ Pen pen2 = new Pen(Color.Red, 4);
+ p1.Offset(a*2/3,vy/3);
+ g.DrawEllipse(pen2,new Rectangle(p1.X-10, p1.Y-2, vy, vy/2));
+ pen2.Dispose();
+ break;
+ }
+ }
+
+ void drawBoxes(Graphics g)
+ {
+ for (int l=0; l<3; l++)
+ for (int x=0; x<3; x++)
+ for (int y=0; y<3; y++)
+ drawBox(g,l,x,y);
+ }
+
+ void drawLattice(Graphics g)
+ {
+ drawBase(g, Pens.LightGray, sx, sx+a*3, vx, vy, a);
+ drawBase(g, Pens.LightGray, sx, sx+a*2, vx, vy, a);
+ drawBase(g, Pens.LightGray, sx, sx+a, vx, vy, a);
+ }
+
+ public void DrawSelf(Graphics g, Rectangle r) {
+ drawBoxes(g);
+ }
+
+ private void MyOnPaint(object sender, PaintEventArgs e)
+ {
+ // 1)e.Graphics.Clear(Color.White); crashes with Image==null exception
+ // e.Graphics.FillRectangle(Brushes.White,e.ClipRectangle); must be
+used instead
+ // 2)DrawSelf(e.Graphics,e.ClipRectangle); causes flickering
+ // 3)the code below is flicker-free, but when window is moved
+ // or menu is activated, redrawing does not ocuur.
+ Image im = new Bitmap(e.ClipRectangle.Width,e.ClipRectangle.Height);
+ Graphics G = Graphics.FromImage(im);
+ G.Clear(Color.White);
+ DrawSelf(G,e.ClipRectangle);
+ e.Graphics.DrawImage(im,0,0);
+ }
+
+ private void doExit(object sender, EventArgs e)
+ {
+ Application.Exit();
+ }
+
+ [STAThread]
+ public static void Main(string[] args)
+ {
+ Application.Run(new MainForm());
+ }
+
+ #region Windows Forms Designer generated code
+ /// <summary>
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The
+Forms designer might
+ /// not be able to load this method if it was changed manually.
+ /// </summary>
+ private void InitializeComponent() {
+ this.menuItem1 = new System.Windows.Forms.MenuItem();
+ this.menuItem2 = new System.Windows.Forms.MenuItem();
+ this.mainMenu1 = new System.Windows.Forms.MainMenu();
+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ this.SuspendLayout();
+ //
+ // menuItem1
+ //
+ this.menuItem1.Index = 0;
+ this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+ this.menuItem2});
+ this.menuItem1.Text = "Program";
+ //
+ // menuItem2
+ //
+ this.menuItem2.Index = 0;
+ this.menuItem2.Text = "Zakoncz";
+ //
+ // mainMenu1
+ //
+ this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+ this.menuItem1});
+ //
+ // pictureBox1
+ //
+ this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.pictureBox1.Location = new System.Drawing.Point(0, 0);
+ this.pictureBox1.Name = "pictureBox1";
+ this.pictureBox1.Size = new System.Drawing.Size(640, 480);
+ this.pictureBox1.TabIndex = 0;
+ this.pictureBox1.TabStop = false;
+ //
+ // MainForm
+ //
+ this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+ this.ClientSize = new System.Drawing.Size(640, 440);
+ this.Controls.Add(this.pictureBox1);
+ this.Menu = this.mainMenu1;
+ this.Name = "MainForm";
+ this.Text = "MainForm";
+ this.ResumeLayout(false);
+ }
+ #endregion
+ }
+}
+------------cut here-------------------