Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Detecting creation is easy. Just override <a href="http://docwiki.embarcadero.com/VCL/en/Graphics.TCanvas.CreateHandle" rel="nofollow noreferrer"><code>CreateHandle</code></a> in a descendant <code>TControlCanvas</code> and put yours in place of the default one <a href="https://stackoverflow.com/questions/1615984/delphi-gdi-when-is-a-device-context-created-destroyed/1618742#1618742">as Jeroen's answer demonstrates</a>. Detecting destruction is harder.</p> <p>One way to avoid the issue is to check whether the TGpGraphics handle is equal to the paint-box's handle, so, rather than detect the moment when the device context is freed, you simply check before you need to know.</p> <pre><code>if not Assigned(FGraphics) or (FGraphics.GetHDC &lt;&gt; PaintBox1.Canvas.Handle) then begin FGraphics.Free; FGraphics := TGpGraphics.Create(PaintBox1.Canvas.Handle); end; </code></pre> <p>This probably isn't reliable, though; handle values are liable to be re-used, so although the HDC value might be the same between two checks, there's no guarantee that it still refers to the same OS device-context object.</p> <hr> <p>The <code>TCanvas</code> base class never clears its own <code>Handle</code> property, so anything that invalidates the canvas must occur externally. <a href="http://docwiki.embarcadero.com/VCL/en/Controls.TControlCanvas" rel="nofollow noreferrer"><code>TControlCanvas</code></a> clears its <code>Handle</code> property when its <code>Control</code> property gets re-assigned, but that usually only happens when the control is created since <code>TControlCanvas</code> instances are rarely shared. However, <code>TControlCanvas</code> instances work from a pool of device-context handles kept in <code>CanvasList</code>. Whenever one of them needs a DC (in <code>TControlCanvas.CreateHandle</code>), it calls <code>FreeDeviceContext</code> to make room in the canvas cache for the handle it's about to create. That function calls the (non-virtual) <code>FreeHandle</code> method. The cache size is 4 (see <code>CanvasListCacheSize</code>), so if you have several descendants of <code>TCustomControl</code> or <code>TGraphicControl</code> in your program, chances are high that you'll get cache misses whenever more than four of them need to be repainted at once.</p> <p><a href="http://docwiki.embarcadero.com/VCL/en/Controls.TControlCanvas.FreeHandle" rel="nofollow noreferrer"><code>TControlCanvas.FreeHandle</code></a> is not virtual, and it doesn't call any virtual methods. Although you could make a descendant of that class and give it virtual methods, the rest of the VCL is going to continue calling the non-virtual methods, oblivious to any of your additions.</p> <hr> <p>Instead of trying to detect when a device context is released, you might be better off using a different TGpGraphics constructor. Use <a href="http://msdn.microsoft.com/en-us/library/ms536162.aspx" rel="nofollow noreferrer">the one that takes a window handle</a> instead of a DC handle, for instance. Window-handle destruction is much easier to detect. For a one-off solution, assign your own method to the <a href="http://docwiki.embarcadero.com/VCL/en/Controls.TControl.WindowProc" rel="nofollow noreferrer"><code>TPaintBox.WindowProc</code></a> property and watch for <a href="http://msdn.microsoft.com/en-us/library/ms632620.aspx" rel="nofollow noreferrer"><code>wm_Destroy</code></a> messages. If you're doing this often, then make a descendant class and override <a href="http://docwiki.embarcadero.com/VCL/en/Controls.TWinControl.DestroyWnd" rel="nofollow noreferrer"><code>DestroyWnd</code></a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload