为什么从WM中使用DrawImageUnscaled会导致闪烁
我目前正在构建一个派生自System.Windows.Forms.ContainerControl
的控件,该控件具有我需要绘制自己的边框区域。 由于没有OnPaintNonClientArea
覆盖,我自己像这样构建它(处理其他消息,如WM_NCCALCSIZE
, WM_NCHITTEST
等,为简洁起见而删除):
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 > 0 && Height > 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);
}
在OnPaintNonClientArea
,我做了:
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);
}
保持OnPaintNonClientArea
不变,这将消除闪烁:
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);
}
那么,为什么DrawImageUnscaled
会导致这种闪烁? 在绘制缓冲区之前,它似乎使用白色笔刷清除它的工作区域。 我没有找到澄清这个问题的文档中的任何内容。 如果它仅仅是控件周围的一个小边框就没有太大关系,但NC区域内会显示文本,因此该区域清晰可见,因此闪烁真的可见并且令人讨厌。
相关问题:我是否正确地使用本地GDI内容,还是存在潜在的问题,我目前没有看到? 另外,在创建ncBitmap
,我使用的是控件的宽度和高度,但GDI +是分辨率无关的,那里可能有任何问题吗?
为了避免在UserControl中出现闪烁现象,我使用了BufferedGraphics类。
MSDN
这是一个选择吗?
链接地址: http://www.djcxy.com/p/50303.html上一篇: Why does DrawImageUnscaled cause flickering when used from WM
下一篇: Custom control under modaldialog not repainting when moving dialog