winapi - GetDC 与 BeginPaint 性能注意事项

标签 winapi gdi+ gdi wm-paint

MSDN 和许多帖子都建议在 WM_PAINT 中使用 BeginPaint/EndPaint。我还看到很多地方表明,如果在绘画中使用双缓冲,那么在 WM_CREATE 中初始化 DC 和 mem 分配并在 WM_PAINT 中重用这些句柄更有意义。

例如,使用 BeginPaint,我经常看到:

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
MemDC = CreateCompatibleDC(hdc);
bmp = CreateCompatibleBitmap(hdc, width, height);
oldbmp = SelectObject(MemDC,bmp);
g = new Graphics(MemDC);

//do paint on bmp
//blt bmp back to hdc

EndPaint(hWnd, &ps);
DeleteObject(bmp);
g->ReleaseHDC(MemDC);
DeleteDC(MemDC);
delete g;

为了保存初始化和拆卸,是否可以这样做:

case WM_CREATE:
hdc   = GetDC(hWnd);
//create memDC and graphics object references ...
case WM_DESTROY
//delete memDC and graphics object references...
case WM_PAINT
BeginPaint(hWnd, &ps);
//use previously create mem and graphics object to paint 
EndPaint(hWnd, &ps);

因此我们只使用 EndPaint 来清除更新区域,并将绘图委托(delegate)给先前创建的对象。

最佳答案

不,这是一个非常糟糕的做法。这首先是由于设备上下文具有错误的剪切区域而出错,当用户调整窗口大小时,您无法正确绘制窗口。

第二个问题是更新区域剪切不会生效,PAINTSTRUCT.rcPaint。当更新区域只是窗口的一部分时,防止 Windows 可能自动执行的任何可能的绘制优化。

第三个问题是您不必要地占用了操作系统资源。所有 GDI 对象都分配在一个堆中,该堆由同一桌面上运行的所有进程共享。

创建 HDC 非常便宜,在需要时创建它。更不用说 PAINTSTRUCT.hdc 了,您可以将其放在盘子上,随时可以使用。

关于winapi - GetDC 与 BeginPaint 性能注意事项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12153472/

相关文章:

c++ - WinAPI - C++ - 如何完全删除/清除窗口中的所有内容?

c# - WPF相当于GDI+的ColorMatrix

c# - 在 .Net 中清除位图

.net - DotNET 应用程序中的 GDI 句柄

winapi - 如何在 Firemonkey 中获取 TCanvas DC?

c++ - GetWindowTextW 无法获取宽字符串

windows - "An unhandled non-continuable exception was thrown during process load"

c - 剪贴板内存的本地副本?

GDI+ 和 WPF 之间的 C# 转换

c++ - Win32 C++ "Old Bitmap"可以重用吗?