我正在开发一个程序,它将有许多DIB位图(由CreateDIBSection
创建),并且必须使用Win API在它们上绘制大量文本。
为了绘制位图,Windows需要由CreateCompatibleDC
创建的设备上下文。
现在有两种方法:
我可以为每个位图创建一次DC,使用它进行绘制,并在释放位图时将其删除。
或者只有当我需要绘制到位图,调用绘图函数并删除DC时,我才能创建DC。
更好的方法是什么?我更喜欢第一个,因为呼叫较少 - 这将使我的代码更小,也更快一点。
但是,为每个位图保留一个长寿命的DC是不是太昂贵了?
Edit1:应用程序实际上是一个GUI工具包库,将来可以以不同且不可预测的方式使用,因此我需要一个平衡良好的决策,以最大限度地提高性能和最小化系统资源使用。
答案 0 :(得分:3)
GDI objects都是有限的。您正在与在同一会话中运行的所有其他进程竞争资源。考虑到这一点,您应该仅在需要时使用GDI资源(问题中的选项2)。
Mark Russinovich的博客文章Pushing the Limits of Windows: USER and GDI Objects – Part 2详细介绍了相关内容。总结一下要点,这里是窗口管理器对GDI资源的限制列表:
答案 1 :(得分:2)
这是一项测试,用于检查调用CreateCompatibleDC
所需的时间。我发现平均每次通话大约需要10到15微秒。与BitBlt
相比,这相对较快,特别是对于较大的图像。因此,保持存储器DC没有多大优势。
case WM_PAINT:
{
static HBITMAP hbitmap = (HBITMAP)LoadImage(0, L"path.bmp",
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
std::wostringstream oss;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
auto start = std::chrono::system_clock::now();
auto memdc = CreateCompatibleDC(hdc);
oss << L"CreateCompatibleDC: "
<< (std::chrono::system_clock::now() - start).count() / 10 << "\n";
auto oldbitmap = SelectObject(memdc, hbitmap);
start = std::chrono::system_clock::now();
BitBlt(hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, memdc, 0, 0, SRCCOPY);
oss << L"BitBlt: "
<< (std::chrono::system_clock::now() - start).count() / 10 << "\n";
SelectObject(memdc, oldbitmap);
DeleteDC(memdc);
EndPaint(hwnd, &ps);
OutputDebugString(oss.str().c_str());
break;
}
Windows 10上的结果:
24位5MB位图的结果:
CreateCompatibleDC
:17微秒左BitBlt
:2500微秒左
8bit 275kb的结果:
CreateCompatibleDC
:12微秒左BitBlt
:500微秒左