Call to Graphics.DrawString thows invalid argument on call to System.Drawing.Graphics.CheckErrorStatus
-
Hi, I’m having a problem whit a call to Graphics.DrawString (C# 2005 Express .Net Framework 2.0). The program draws some images, gradients and text to a bitmap, that is copied to a PictureBox in a form, it is done this way because of the time to render de bitmap is relatively high, and I don’t want the user to see id been drawn on the screen. This process iterates on a timer tick event changing the text and colors. The first time it renders correctly. The next timer tick event is fired it calls the DrawString to the bitmap and I get a “Invalid Argument Exception” in a call to “System.Drawing.Graphics.CheckErrorStatus(Int32 status)” I verified the parameters to DrawString call, and all are apparently correct (no nulls, all types correct, and no missing data?). Any Ideas what’s wrong? :confused::( Here is the stack Trace in System.Drawing.Graphics.CheckErrorStatus(Int32 status) in System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format) in ArribosPartidas.Principal.Paginar() in Principal.cs:line 1259 in ArribosPartidas.Principal.timer_Tick(Object sender, EventArgs e) in Principal.cs:line 1106 in System.Windows.Forms.Timer.OnTick(EventArgs e) in System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m) in System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) in System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) in System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) in System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) in System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) in System.Windows.Forms.Application.Run(Form mainForm) in ArribosPartidas.Program.Main() in Program.cs:line 17"
-
Hi, I’m having a problem whit a call to Graphics.DrawString (C# 2005 Express .Net Framework 2.0). The program draws some images, gradients and text to a bitmap, that is copied to a PictureBox in a form, it is done this way because of the time to render de bitmap is relatively high, and I don’t want the user to see id been drawn on the screen. This process iterates on a timer tick event changing the text and colors. The first time it renders correctly. The next timer tick event is fired it calls the DrawString to the bitmap and I get a “Invalid Argument Exception” in a call to “System.Drawing.Graphics.CheckErrorStatus(Int32 status)” I verified the parameters to DrawString call, and all are apparently correct (no nulls, all types correct, and no missing data?). Any Ideas what’s wrong? :confused::( Here is the stack Trace in System.Drawing.Graphics.CheckErrorStatus(Int32 status) in System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format) in ArribosPartidas.Principal.Paginar() in Principal.cs:line 1259 in ArribosPartidas.Principal.timer_Tick(Object sender, EventArgs e) in Principal.cs:line 1106 in System.Windows.Forms.Timer.OnTick(EventArgs e) in System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m) in System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) in System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) in System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) in System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) in System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) in System.Windows.Forms.Application.Run(Form mainForm) in ArribosPartidas.Program.Main() in Program.cs:line 17"
Did you Dipose all of your graphics objects (Graphics, Brushes, Pens, Bitmaps you're reusing, Fonts, ...) in the last pass?
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007 -
Did you Dipose all of your graphics objects (Graphics, Brushes, Pens, Bitmaps you're reusing, Fonts, ...) in the last pass?
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007 -
I disposed fonts and brushes, I recreate them because it may vary from one text to another I’m keeping reference to the bitmaps and context.
You hold open a Graphics context?? Don't. On every pass, if you create a Graphics object, you also MUST dispose it when you're done drawing the current frame. If you're getting the Graphics object from the Paint event args (Graphics g = e.Graphics, or something similar), then you do NOT dispose the graphics object. You didn't create it, so you don't dispose of it.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007 -
You hold open a Graphics context?? Don't. On every pass, if you create a Graphics object, you also MUST dispose it when you're done drawing the current frame. If you're getting the Graphics object from the Paint event args (Graphics g = e.Graphics, or something similar), then you do NOT dispose the graphics object. You didn't create it, so you don't dispose of it.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007 -
Hi, I now dispose the context after each frame is rendered. But still get the same error.
Let's see the code where this blows up. What line does it die on? Did the previous timer event finish? What I mean is that the timer fires once, you start drawing on the image, the timer fires again, but you haven't finished drawing on the previous tick, so when you go to create another Graphics object to draw the next frame, it collides with the last one.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007 -
Let's see the code where this blows up. What line does it die on? Did the previous timer event finish? What I mean is that the timer fires once, you start drawing on the image, the timer fires again, but you haven't finished drawing on the previous tick, so when you go to create another Graphics object to draw the next frame, it collides with the last one.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007I run it in debug mode, and the frame rendering finish long beefore the second timer event. Here is a resume of all the code, is quite large one to post completely. private class Principal:Form { //.... declarations , constructor, Othes Methods, etc. //waht is important for the case private Bitmap offScreenBmp; private Graphics offScreenDC; private Bitmap FondoLimpioBmp; private bool DrawingToBuffer; private viod BackImg() //this is been called once at form_load (for now). { DrawingToBuffer = true; FondoLimpioBmp = new Bitmap(BackIngPath); //BackIngPath is string containing path and file name of backgound image. FondoLimpioBmp = new Bitmap(BackIngPath); Graphics FondoLimpioDC = Graphics.FromImage(FondoLimpioBmp ); //Draw Some Gradients here to FondoLimpioDC, no problems here //PicBack is a PicuteBox in the form. offScreenBmp = new Bitmap(PicBack.Width, PicBack.Height); offScreenDC = Graphics.FromImage(offScreenBmp); offScreenDC.Clear(Color.Transparent); offScreenDC.DrawImage(this.BackgroundImage,new Point(0,0)); offScreenDC.SmoothingMode = SmoothingMode.AntiAlias; offScreenDC.DrawImage(FondoLimpioBmp , 0, 0); FondoLimpioDC.dispose(); offScreenDC.Dispose(); //Add this after yuor comment. DrawingToBuffer = false; } private void Paginar() /// this is called from Timer_Tick event { if (!DrawingToBuffer){ //flag para prevenir 2 instancias al mismo tiempo // Here gos code to read data from database.... DrawingToBuffer = true; offScreenDC = Graphics.FromImage(offScreenBmp); offScreenDC.Clear(Color.Transparent); offScreenDC.DrawImage(FondoLimpioBmp, 0, 0); offScreenDC.SmoothingMode = SmoothingMode.AntiAlias; StringFormat sf = new StringFormat(); Brush tBrush = Brushes.Black; sf.LineAlignment = StringAlignment.Center; Font tFont = new Font("Arial", 17F, FontStyle.Bold); string itemToShow; int Y1, Y2, Y3, Y4; RectangleF txtRect; for(int i = 0; i < 10; i++) { Y1 = (sepHeigth * i) + (rowHeigth * i); Y2 = (sepHeigth * (i + 1)) + (rowHeigth * i); Y3 = Y2; Y4 = (sepHeigth * (i + 1)) + (rowHeigth * (i + 1)); sf.Alignment = StringAlignment.Center; txtRect = new RectangleF(TitleSrv.Left, Y3, TitleSrv.Width, rowHeigth); itemToShow = LSRVLbl[i].Text; sf.FormatFlags = StringFormatFlags.NoClip; //*********************************************************
-
I run it in debug mode, and the frame rendering finish long beefore the second timer event. Here is a resume of all the code, is quite large one to post completely. private class Principal:Form { //.... declarations , constructor, Othes Methods, etc. //waht is important for the case private Bitmap offScreenBmp; private Graphics offScreenDC; private Bitmap FondoLimpioBmp; private bool DrawingToBuffer; private viod BackImg() //this is been called once at form_load (for now). { DrawingToBuffer = true; FondoLimpioBmp = new Bitmap(BackIngPath); //BackIngPath is string containing path and file name of backgound image. FondoLimpioBmp = new Bitmap(BackIngPath); Graphics FondoLimpioDC = Graphics.FromImage(FondoLimpioBmp ); //Draw Some Gradients here to FondoLimpioDC, no problems here //PicBack is a PicuteBox in the form. offScreenBmp = new Bitmap(PicBack.Width, PicBack.Height); offScreenDC = Graphics.FromImage(offScreenBmp); offScreenDC.Clear(Color.Transparent); offScreenDC.DrawImage(this.BackgroundImage,new Point(0,0)); offScreenDC.SmoothingMode = SmoothingMode.AntiAlias; offScreenDC.DrawImage(FondoLimpioBmp , 0, 0); FondoLimpioDC.dispose(); offScreenDC.Dispose(); //Add this after yuor comment. DrawingToBuffer = false; } private void Paginar() /// this is called from Timer_Tick event { if (!DrawingToBuffer){ //flag para prevenir 2 instancias al mismo tiempo // Here gos code to read data from database.... DrawingToBuffer = true; offScreenDC = Graphics.FromImage(offScreenBmp); offScreenDC.Clear(Color.Transparent); offScreenDC.DrawImage(FondoLimpioBmp, 0, 0); offScreenDC.SmoothingMode = SmoothingMode.AntiAlias; StringFormat sf = new StringFormat(); Brush tBrush = Brushes.Black; sf.LineAlignment = StringAlignment.Center; Font tFont = new Font("Arial", 17F, FontStyle.Bold); string itemToShow; int Y1, Y2, Y3, Y4; RectangleF txtRect; for(int i = 0; i < 10; i++) { Y1 = (sepHeigth * i) + (rowHeigth * i); Y2 = (sepHeigth * (i + 1)) + (rowHeigth * i); Y3 = Y2; Y4 = (sepHeigth * (i + 1)) + (rowHeigth * (i + 1)); sf.Alignment = StringAlignment.Center; txtRect = new RectangleF(TitleSrv.Left, Y3, TitleSrv.Width, rowHeigth); itemToShow = LSRVLbl[i].Text; sf.FormatFlags = StringFormatFlags.NoClip; //*********************************************************
DoomedOne wrote:
if (!DrawingToBuffer){ //flag para prevenir 2 instancias al mismo tiempo // Here gos code to read data from database.... DrawingToBuffer = true;
You are trying to have a mutex so only one instance of this code can execute the drawing actions, but: 1) having a separate test, then set of a variable is not reliable 2) if as your comment indicate you do a database access in between, it is doomed to fail. So give it a try with DrawingToBuffer=true before you do DB access, and better yet use a real non-reentrance defense (such as disabling the timer while inside paginar). :)
Luc Pattyn [My Articles] [Forum Guidelines]
-
DoomedOne wrote:
if (!DrawingToBuffer){ //flag para prevenir 2 instancias al mismo tiempo // Here gos code to read data from database.... DrawingToBuffer = true;
You are trying to have a mutex so only one instance of this code can execute the drawing actions, but: 1) having a separate test, then set of a variable is not reliable 2) if as your comment indicate you do a database access in between, it is doomed to fail. So give it a try with DrawingToBuffer=true before you do DB access, and better yet use a real non-reentrance defense (such as disabling the timer while inside paginar). :)
Luc Pattyn [My Articles] [Forum Guidelines]
Hi, I’ve tired that too, disabling the timer as first sentence in the Timer_tick event and enabling it again at the end, after the frame has been rendered, and don't work. The problem do not looks like a collision between 2 running threads trying run the same paint code, is more like something is missing to clean up, or set, between calls to de "Paginar" code.
-
Hi, I’m having a problem whit a call to Graphics.DrawString (C# 2005 Express .Net Framework 2.0). The program draws some images, gradients and text to a bitmap, that is copied to a PictureBox in a form, it is done this way because of the time to render de bitmap is relatively high, and I don’t want the user to see id been drawn on the screen. This process iterates on a timer tick event changing the text and colors. The first time it renders correctly. The next timer tick event is fired it calls the DrawString to the bitmap and I get a “Invalid Argument Exception” in a call to “System.Drawing.Graphics.CheckErrorStatus(Int32 status)” I verified the parameters to DrawString call, and all are apparently correct (no nulls, all types correct, and no missing data?). Any Ideas what’s wrong? :confused::( Here is the stack Trace in System.Drawing.Graphics.CheckErrorStatus(Int32 status) in System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format) in ArribosPartidas.Principal.Paginar() in Principal.cs:line 1259 in ArribosPartidas.Principal.timer_Tick(Object sender, EventArgs e) in Principal.cs:line 1106 in System.Windows.Forms.Timer.OnTick(EventArgs e) in System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m) in System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) in System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) in System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) in System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) in System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) in System.Windows.Forms.Application.Run(Form mainForm) in ArribosPartidas.Program.Main() in Program.cs:line 17"