Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does DrawImageUnscaled cause flickering when used from WM_NCPAINT?
    primarykey
    data
    text
    <p>I'm currently building a control derived from <code>System.Windows.Forms.ContainerControl</code> that has a border area I need to paint myself. Since there's no <code>OnPaintNonClientArea</code> to override, I built it myself like this (handling of other messages like <code>WM_NCCALCSIZE</code>, <code>WM_NCHITTEST</code> etc. removed for brevity):</p> <pre><code>protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_NCPAINT: IntPtr hDC = NativeApi.Methods.GetWindowDC(m.HWnd); if (hDC != IntPtr.Zero) { using (Graphics canvas = Graphics.FromHdc(hDC)) { if (Width &gt; 0 &amp;&amp; Height &gt; 0) using (PaintEventArgs e = new PaintEventArgs(canvas, new Rectangle(0, 0, Width, Height))) { OnPaintNonClientArea(e); } } NativeApi.Methods.ReleaseDC(m.HWnd, hDC); } m.Result = IntPtr.Zero; break; } base.WndProc(ref m); } </code></pre> <p>Within <code>OnPaintNonClientArea</code>, I did:</p> <pre><code>private void OnPaintNonClientArea(PaintEventArgs e) { if (_ncBuffer == null) { _ncBuffer = new Bitmap(Width, Height); } using (Graphics g = Graphics.FromImage(_ncBuffer)) { // painting occurs here ... } // this causes flickering e.Graphics.DrawImageUnscaled(_ncBuffer, 0, 0, Width, Height); } </code></pre> <p>Leaving <code>OnPaintNonClientArea</code> untouched, this removes the flicker:</p> <pre><code>protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_NCPAINT: using(Bitmap ncBitmap = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { using(Graphics ncGraphics = Graphics.FromImage(ncBitmap)) { using (PaintEventArgs e = new PaintEventArgs(ncGraphics, new Rectangle(0, 0, Width, Height))) { OnPaintNonClientArea(e); IntPtr hDCWin = NativeApi.Methods.GetWindowDC(m.HWnd); IntPtr hDCImg = ncGraphics.GetHdc(); IntPtr hBmp = ncBitmap.GetHbitmap(); IntPtr hBmpOld = NativeApi.Methods.SelectObject(hDCImg, hBmp); Padding p = GetNonClientArea(); NativeApi.Methods.ExcludeClipRect(hDCWin, p.Left, p.Top,Width- p.Right, Height-p.Bottom); NativeApi.Methods.BitBlt(hDCWin, 0, 0, Width, Height, hDCImg, 0, 0,NativeApi.TernaryRasterOperations.SRCCOPY); NativeApi.Methods.SelectObject(hDCImg, hBmpOld); NativeApi.Methods.DeleteObject(hBmp); ncGraphics.ReleaseHdc(hDCImg); NativeApi.Methods.ReleaseDC(m.HWnd, hDCWin); } } } m.Result = IntPtr.Zero; break; } base.WndProc(ref m); } </code></pre> <p>So, why does <code>DrawImageUnscaled</code> cause this flickering? It seems to erase the area it works on with a white brush before drawing the buffer. I didn't find anything in the docs that clarified this issue. It wouldn't matter too much if it were just a small border around the control, but there will be text displayed within the NC area, so the area is clearly visible and therefore the flickering is really visible and annoying.</p> <p>Related questions: Am I doing the native GDI stuff right, or are there potential problems I don't see right now? Also, when creating the <code>ncBitmap</code>, I'm using the control width and height, but GDI+ is resolution-independant, can there be any problems there?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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