我已经阅读了很多关于尝试对 Richedit 控件进行双缓冲的问题,但没有看到对这个特定问题的任何直接答案(如果有微软官方声明的引用/链接,那就太好了)。
这是我一直用于测试的一些代码(VCL/Delphi/Borland Builder 6.0):
if(Message.Msg == WM_PAINT)
{
HDC dc = GetDC(0);
HBITMAP memBitmap = CreateCompatibleBitmap(dc,ClientRect.Right,ClientRect.Bottom);
ReleaseDC(0,dc);
HBITMAP memDC = CreateCompatibleDC(0);
HBITMAP oldBitmap = SelectObject(memDC,memBitmap);
try{
//PAINTSTRUCT ps;
//dc = BeginPaint(Handle,&ps);
dc = GetDC(Handle);
Message.WParam = (int)memDC;
inherited::WndProc(Message);
Message.WParam = 0;
//BitBlt(dc,0,0,ClientRect.Right,ClientRect.Bottom,memDC,0,0,SRCCOPY);
ReleaseDC(Handle,dc);
//EndPaint(Handle,&ps);
} __finally
{
SelectObject(memDC,oldBitmap);
DeleteDC(memDC);
DeleteObject(memBitmap);
}
return;
}
如果我在继承::WndProc() 之前调用 BeginPaint() (将消息传递给那些不知道 VCL 的控件),那么控件不会在我的内存 DC 或实际窗口 DC 上绘制任何内容。如果我改为调用 GetDC(),控件仍然不会在内存 DC 上绘制,但它会直接在窗口 DC 上绘制。我通过注释掉我的 BitBlt() 调用来确认这一点。如果没有注释掉,客户区全黑(意味着控件根本没有在内存 DC 上绘制),如果我注释掉那行,控件正确绘制(这意味着它忽略了 WParam 内存 DC 并直接进入窗口 DC)。
虽然听起来我已经回答了我自己的问题,但我真正想要的是其他人的确认(链接到 MS KB 文章或 MSDN 会很棒,所以我可以向我的老板展示:),以及实现双缓冲的其他可能的想法? 我不能使用我发现的大多数技巧,比如将控件隐藏在屏幕外或使用 WM_PRINT,因为我需要这个控件才能真正用于用户输入和滚动条,它不仅仅是用于显示的只读。
此外,该控件使用的是 RichEdit 2.0,即使我使用的是 VCL.. 它已被修改为将窗口创建为“richedit20a”类。我还确认 VCL 层根本没有弄乱绘画,所以在纯 win32 代码中应该看到同样的行为。