[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-------------------