|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
update graphics between debugger steppingeach step. My OnPaint handler ultimately updates the screen with: pe.Graphics.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); So I tried writing the following, and calling it from the watch window and/or debug window: internal void BlitNow() { using (Graphics g = CreateGraphics()) { g.FillRectangle(Brushes.Red, new Rectangle(0, 0, 500, 500)); g.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); g.Flush(); } } Doesn't do a thing. Why? Tried entering this in the watch window: g = CreateGraphics() Inspect g, VisibleClipBounds is {X = 0.0 Y = 0.0 Width = 339.0 Height = 537.0} g.FillRectangle(Brushes.Green, g.VisibleClipBounds) g.Flush() Nothing happens. I think at this point my entire control should be green. Where is .NET buffering my output and what method do I call to force .NET to show me immediately? I am not using the DoubleBuffered or OptimizedDoubleBuffering control style flags, since I manage my own off-screen buffer. Ben Voigt wrote:
Show quote > Ok, while troubleshooting painting code, I am trying to see my canvas I don't know if it's relevant to the issue you're encountering, but... one > after each step. My OnPaint handler ultimately updates the screen > with: pe.Graphics.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, > -scrollOffset.Y); > So I tried writing the following, and calling it from the watch window > and/or debug window: > internal void BlitNow() > { > using (Graphics g = CreateGraphics()) > { > g.FillRectangle(Brushes.Red, new Rectangle(0, 0, 500, 500)); > g.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); > g.Flush(); > } > } > > Doesn't do a thing. Why? Tried entering this in the watch window: > g = CreateGraphics() > > Inspect g, VisibleClipBounds is {X = 0.0 Y = 0.0 Width = 339.0 Height > = 537.0} > g.FillRectangle(Brushes.Green, g.VisibleClipBounds) > g.Flush() > > Nothing happens. I think at this point my entire control should be > green. Where is .NET buffering my output and what method do I call to > force .NET to show me immediately? I am not using the DoubleBuffered > or OptimizedDoubleBuffering control style flags, since I manage my own > off-screen buffer. very useful technique for debugging paint routines is to run your application on a VPC on your workstation and use remote debugging to debug it. This works best on a dual monitor system with the VPC maximized on one monitor and visual studio maximized on the other. That way your application and the debugger are running on different desktops and the debugger coming into focus doesn't actually invalidate your application's window(s). -cd
Show quote
"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam> I have dual monitors, so the form is not covered by the debugger, so it's wrote in message news:uFrpjyXzGHA.1536@TK2MSFTNGP02.phx.gbl... > Ben Voigt wrote: >> Ok, while troubleshooting painting code, I am trying to see my canvas >> after each step. My OnPaint handler ultimately updates the screen >> with: pe.Graphics.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, >> -scrollOffset.Y); >> So I tried writing the following, and calling it from the watch window >> and/or debug window: >> internal void BlitNow() >> { >> using (Graphics g = CreateGraphics()) >> { >> g.FillRectangle(Brushes.Red, new Rectangle(0, 0, 500, 500)); >> g.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); >> g.Flush(); >> } >> } >> >> Doesn't do a thing. Why? Tried entering this in the watch window: >> g = CreateGraphics() >> >> Inspect g, VisibleClipBounds is {X = 0.0 Y = 0.0 Width = 339.0 Height >> = 537.0} >> g.FillRectangle(Brushes.Green, g.VisibleClipBounds) >> g.Flush() >> >> Nothing happens. I think at this point my entire control should be >> green. Where is .NET buffering my output and what method do I call to >> force .NET to show me immediately? I am not using the DoubleBuffered >> or OptimizedDoubleBuffering control style flags, since I manage my own >> off-screen buffer. > > I don't know if it's relevant to the issue you're encountering, but... one > very useful technique for debugging paint routines is to run your > application on a VPC on your workstation and use remote debugging to debug > it. This works best on a dual monitor system with the VPC maximized on one > monitor and visual studio maximized on the other. That way your > application and the debugger are running on different desktops and the > debugger coming into focus doesn't actually invalidate your application's > window(s). not being invalidated. Show quote > > -cd > > Hi Ben,
I am not sure if I understand you completely. Based on my understanding, you use debugger to set a breakpoint in the paint handler of the form/control. When you want to single step through each code statement in the paint handler, you want to see the actual visual painting effect of each code statement. If I have misunderstood you, please feel free to tell me, thanks. Yes, this is a by design behavior. Below is the detailed information regarding what happens: The painting handler code executes in the main GUI thread of .Net winform. If you use debugger to set a breakpoint in the paint handler, the main GUI thread is break by the debugger. Once the WM_PAINT message is sent to your paint handler, the breakpoint is hit, which the debugger is notified with the breakpoint. At this point, all the graphics/control UI that is drawn by the executed code is displayed on the screen. However, the debugger code will suspend the GUI thread and bring the IDE/debugger to the front, this operation will immediately erase all the graphics/control UI the paint handler just draws. These operations are all too fast, so you may not see the graphics/control UI. While you are single stepping through each code statement of the paint handler, you will find the winform window as a white rectangle without any graphics on it. This is the same reason. When Windows recognize that you want to display the winform, it will dispatch WM_PAINT message to winform's Painting handler, who takes the responsibility to paint the graphics/control UI. However, at this time, the Painting handler's main GUI is still being suspended by debugger, so we can not execute all the code in the painting handler, the UI remains as a white rectangle. So you can only see the .Net winform painting effect without breaking the Painting handler. With debugging the Painting handler, you can only verify the logic of your code with single stepping, the visual effect can only be visible with running at full speed. Do you fail to see the g.FillRectangle filled rectangle on the screen without breaking in debugger? Based on my review, it seems that you use CreateGraphics() to create a new Graphics object for painting. Normally, we should use the Graphics object provided by the paint handler. For example, the code snippet below works well on my side: protected override void OnPaint(PaintEventArgs e) { e.Graphics.FillRectangle(Brushes.Green, e.Graphics.VisibleClipBounds); base.OnPaint (e); } If you still need help, please feel free to feedback more information and I will work with you. Thanks. Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. ""Jeffrey Tan[MSFT]"" <je***@online.microsoft.com> wrote in message
news:nDxa9aYzGHA.396@TK2MSFTNGXA01.phx.gbl... And/or subfunctions called by the paint handler.> Hi Ben, > > I am not sure if I understand you completely. Based on my understanding, > you use debugger to set a breakpoint in the paint handler of the > form/control. When you want to single step through each code statement in > the paint handler, you want to see the actual visual painting effect of Since I've allocated a memory bitmap, there is no visual effect of each > each code statement. If I have misunderstood you, please feel free to tell > me, thanks. statement. My paint handler ends by flipping the offscreen canvas to the screen with: pe.Graphics.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); So I tried to write a method BlitNow and call it from watch window or immediate window to see the offscreen buffer being built up. internal void BlitNow() { using (Graphics g = CreateGraphics()) { g.FillRectangle(Brushes.Red, new Rectangle(0, 0, 500, 500)); g.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); g.Flush(); } } I also tried g.Flush(FlushIntention.Flush). Still nothing. All my drawing code works on a Graphics for the bmpCanvas, so pe.Graphics isn't in scope. In addition, some updates to bmpCanvas are performed during OnLayout. So I used CreateGraphics() in BlitNow. I considered that without calling Flush and/or Dispose on the Graphics associated with bmpCanvas, the DrawImageUnscaled command might not work (because graphics commands could be buffered and thus not apparent on bmpCanvas, and Win32 API won't let you SelectObject a bitmap into two DCs at once). But I would still expect the rectangle to appear... it didn't, even for cases when bmpCanvas.Height < 500 and Control.Height > 500, when no matter what image was in the bitmap it could not have obscured the entire rectangle. Also, immediately after recreating bmpCanvas, before creating a Graphics object for it, I got the same behavior (probably was 100% transparent, but should have drawn with no errors leaving me with the rectangle). Show quote > > Yes, this is a by design behavior. Below is the detailed information > regarding what happens: > The painting handler code executes in the main GUI thread of .Net winform. > If you use debugger to set a breakpoint in the paint handler, the main GUI > thread is break by the debugger. > Once the WM_PAINT message is sent to your paint handler, the breakpoint is > hit, which the debugger is notified with the breakpoint. At this point, > all > the graphics/control UI that is drawn by the executed code is displayed on > the screen. However, the debugger code will suspend the GUI thread and > bring the IDE/debugger to the front, this operation will immediately erase > all the graphics/control UI the paint handler just draws. These operations > are all too fast, so you may not see the graphics/control UI. > > While you are single stepping through each code statement of the paint > handler, you will find the winform window as a white rectangle without any > graphics on it. This is the same reason. When Windows recognize that you > want to display the winform, it will dispatch WM_PAINT message to > winform's > Painting handler, who takes the responsibility to paint the > graphics/control UI. However, at this time, the Painting handler's main > GUI > is still being suspended by debugger, so we can not execute all the code > in > the painting handler, the UI remains as a white rectangle. > > So you can only see the .Net winform painting effect without breaking the > Painting handler. With debugging the Painting handler, you can only verify > the logic of your code with single stepping, the visual effect can only be > visible with running at full speed. > > Do you fail to see the g.FillRectangle filled rectangle on the screen > without breaking in debugger? Based on my review, it seems that you use > CreateGraphics() to create a new Graphics object for painting. Normally, > we > should use the Graphics object provided by the paint handler. For example, > the code snippet below works well on my side: > > protected override void OnPaint(PaintEventArgs e) > { > e.Graphics.FillRectangle(Brushes.Green, e.Graphics.VisibleClipBounds); > base.OnPaint (e); > } > > If you still need help, please feel free to feedback more information and > I > will work with you. Thanks. > > Best regards, > Jeffrey Tan > Microsoft Online Community Support > ================================================== > Get notification to my posts through email? Please refer to > http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif > ications. > > Note: The MSDN Managed Newsgroup support offering is for non-urgent issues > where an initial response from the community or a Microsoft Support > Engineer within 1 business day is acceptable. Please note that each follow > up response may take approximately 2 business days as the support > professional working with you may need further investigation to reach the > most efficient resolution. The offering is not appropriate for situations > that require urgent, real-time or phone-based interactions or complex > project analysis and dump analysis issues. Issues of this nature are best > handled working with a dedicated Microsoft Support Engineer by contacting > Microsoft Customer Support Services (CSS) at > http://msdn.microsoft.com/subscriptions/support/default.aspx. > ================================================== > This posting is provided "AS IS" with no warranties, and confers no > rights. > Hi Ben,
Thanks for your feedback! Can you be specific about what effect you want to achieve? Can you provide detailed description regarding this? I suspect that you have some misunderstanding over the code snippet below: internal void BlitNow() { using (Graphics g = CreateGraphics()) { g.FillRectangle(Brushes.Red, new Rectangle(0, 0, 500, 500)); g.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); g.Flush(); } } In the code, CreateGraphics() method is a member method of Control class, which will create a Graphics object for the control.(Graphics object encapsulates a GDI+ drawing surface). So, all the following g.FillRectangle, g.DrawImageUnscaled will take effect over this control surface, not over bmpCanvas surface. Graphics object *g* has no relation with bmpCanvas memory bitmap. Regarding g.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y), GDI+ will read the memory bitmap bmpCanvas and write to the surface *g* represents. So the result is drawn to the control surface, not bmpCanvas. Is this the logic you want to complete? If I still have misunderstood your key point, pleasse feel free to create a little sample project with detailed steps to demonstrate what you want to achieve and what the actual problem is. Thanks. Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. ""Jeffrey Tan[MSFT]"" <je***@online.microsoft.com> wrote in message
Show quote news:0AFMuh%23zGHA.400@TK2MSFTNGXA01.phx.gbl... That's my intention.> Hi Ben, > > Thanks for your feedback! > > Can you be specific about what effect you want to achieve? Can you provide > detailed description regarding this? > > I suspect that you have some misunderstanding over the code snippet below: > internal void BlitNow() > { > using (Graphics g = CreateGraphics()) > { > g.FillRectangle(Brushes.Red, new Rectangle(0, 0, 500, 500)); > g.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); > g.Flush(); > } > } > > In the code, CreateGraphics() method is a member method of Control class, > which will create a Graphics object for the control.(Graphics object > encapsulates a GDI+ drawing surface). So, all the following > g.FillRectangle, g.DrawImageUnscaled will take effect over this control > surface, not over bmpCanvas surface. Graphics object *g* has no relation > with bmpCanvas memory bitmap. > > Regarding > g.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y), > GDI+ will read the memory bitmap bmpCanvas and write to the surface *g* > represents. So the result is drawn to the control surface, not bmpCanvas. > I have declared a new OnPaint, such that a user can subclass my control and > Is this the logic you want to complete? override OnPaint, or else wire up the Paint event handler, but I provide some simple default painting code otherwise: new public event PaintEventHandler Paint; new protected virtual void OnPaint(PaintEventArgs subpe) { if (Paint != null) { Paint(this, subpe); } else { LinearGradientBrush background = new LinearGradientBrush(new Point(0, 0), new Point(size), Color.Gray, Color.LightGray); subpe.Graphics.FillRectangle(background, subpe.ClipRectangle); } } I have created a Graphics for bmpCanvas: using (Graphics subg = Graphics.FromImage(bmpCanvas)) And passed subg to my subclass's OnPaint: PaintEventArgs subpe = new PaintEventArgs(subg, shiftedClip); if (invalid != null) { subg.Clip = invalid; //global::System.Diagnostics.Debug.WriteLine("invalid bounded by " + invalid.GetBounds(pe.Graphics).ToString()); } OnPaint(subpe); And copied some part of the resulting image to the screen: pe.Graphics.DrawImageUnscaled(bmpCanvas, -scrollOffset.X, -scrollOffset.Y); I'm trying to debug code in my OnLayout method (e.g. called by OnFontChanged) that paints into the offscreen buffer bmpCanvas, by using the immediate window to call BlitNow as I step through the code. Actually OnLayout substitutes bmpCanvas with another larger/smaller bitmap, whose size is based on content, not window area). But I rearranged things so that this substitution takes place before the draw and blit code; the new bmpCanvas is the Bitmap I'm trying to observe. This does not show me any progression of states as I build up the offscreen bitmap. I considered that perhaps the Graphics for bmpCanvas isn't flushed, or perhaps the limitation of SelectObject -- one DC per HBITMAP -- prevents DrawImageUnscaled from using a Bitmap while I have a Graphics object for it. So I added the FillRectangle line, which covers an area larger than bmpCanvas but smaller than my control, so I ought to see it regardless of what bmpCanvas contains. But FillRectangle doesn't even show anything. I've not set the DoubleBuffer or OptimizedDoubleBuffer control bits. I've flushed that Graphics g = CreateGraphics. Where else could my bits be getting held up so I can't see them onscreen? I've not overridden CreateGraphics (yet). Show quote > > If I still have misunderstood your key point, pleasse feel free to create > a > little sample project with detailed steps to demonstrate what you want to > achieve and what the actual problem is. > > Thanks. > > Best regards, > Jeffrey Tan > Microsoft Online Community Support > ================================================== > Get notification to my posts through email? Please refer to > http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif > ications. > > Note: The MSDN Managed Newsgroup support offering is for non-urgent issues > where an initial response from the community or a Microsoft Support > Engineer within 1 business day is acceptable. Please note that each follow > up response may take approximately 2 business days as the support > professional working with you may need further investigation to reach the > most efficient resolution. The offering is not appropriate for situations > that require urgent, real-time or phone-based interactions or complex > project analysis and dump analysis issues. Issues of this nature are best > handled working with a dedicated Microsoft Support Engineer by contacting > Microsoft Customer Support Services (CSS) at > http://msdn.microsoft.com/subscriptions/support/default.aspx. > ================================================== > This posting is provided "AS IS" with no warranties, and confers no > rights. > Hi Ben,
Thanks for your feedback! Yes, I understand your purpose better now. Based on my understanding, there are many places in your code that draw onto the memory bmpCanvas. Then you want to see the final effect of bmpCanvas, so you draw the bmpCanvas onto the control surface in OnPaint method. However, there are too much context information in your application, and without reproducing this problem it is hard for us to find out the root cause. Is it possible for you to create a little sample project to demonstrate this problem? This will be helpful and efficient for us to find out the root cause. With the current information, my recommendation is: 1. Do not draw the bmpCanvas to control surface, but use bmpCanvas.Save() method to save the memory bitmap to the disk file. Then you may view it from disk to verify the visual effect for testing purpose. 2. I'm not sure why you have to call BlitNow from Watch window. I recommend you embed the BlitNow code in the OnLayout method, this will help us to isolate other IDE issue. Anyway, a sample reproduce project is still the most efficient way to demonstrate the problem, I will wait for your sample project to give it a deeper review and understanding. Thanks. Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Other interesting topics
|
|||||||||||||||||||||||