创建 GDI 矩形图像

Create a GDI Rectangle image

本文关键字:图像 GDI 创建      更新时间:2023-10-16

我一定是做错了什么或错过了什么,因为我实际上只想将矩形渲染成位图,以便我可以在其上创建WindowEx()。 有谁知道我错过了什么?

HDC hdc = GetDC(hWnd);
// Create Pen and brush for the rectangle
HPEN pn = CreatePen(style, stroke, pen);
HBRUSH br = CreateSolidBrush(brush);
// Create a compatible bitmap and DC from the window DC with the correct dimensions
HDC bm_hdc = CreateCompatibleDC(hdc);
HBITMAP hImage = CreateCompatibleBitmap(bm_hdc, sz.x, sz.y);
// Select the bitmap, pen, brush into the DC
HGDIOBJ bm_obj = SelectObject(bm_hdc, hImage);
HGDIOBJ pn_obj = SelectObject(bm_hdc, pn);
HGDIOBJ br_obj = SelectObject(bm_hdc, br);
// Draw the rectangle into the compatible DC with the bitmap selected
::Rectangle(bm_hdc, xPos, yPos, xPos + xSize, yPos + ySize);
// Restore the old selections
SelectObject(bm_hdc, br_obj);
SelectObject(bm_hdc, pn_obj);
SelectObject(bm_hdc, bm_obj);
// Delete the not needed DC, pen and brush
DeleteDC(bm_hdc);
DeleteObject(br);
DeleteObject(pn);
ReleaseDC(hWnd, hdc);
// Create the window and send a message to set the static image
HWND win = CreateWindow(TEXT("STATIC"), NULL, WS_CHILD | SS_BITMAP | WS_VISIBLE, pos.x, pos.y, sz.x, sz.y, hWnd, NULL, hInst, NULL)));
HGDIOBJ obj = (HGDIOBJ)SendMessage(win, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hImage);
// Delete the old image
if (obj)
    DeleteObject(hImage);

哼...... 但这行不通... 我得到的只是一个完全黑色的区域,而不是我绘制的矩形。 知道为什么吗? 是否需要在设备上下文之间创建另一个 DC 和 BitBlt()?

感谢大家的帮助,但我实际上已经自己解决了它,这也是一个愚蠢的错误...... 考虑这条线...:-

::Rectangle(bm_hdc, xPos, yPos, xPos + xSize, yPos + ySize);

乍一看没有错,对吧? 错! 如果您查看我的代码,我会创建一个所需大小的兼容位图来包含我的矩形,并尝试将矩形呈现到此位图(已选择到 DC 中)。

但。。。 我在位图中的哪个位置渲染? xPos 和 yPos 是矩形的窗口位置,但我没有渲染到窗口 DC,不是吗?!? 哎呀! 没错,xPos 和 yPos 都应该是 0,因为我正在渲染到正确大小的位图中,并且当显示窗口时,xPos 和 yPos 应该包含屏幕坐标!

哇。。。 多么愚蠢的错误,感谢从窗口而不是从兼容的 DC 在 HDC 上的好位置。 我确实知道内存DC具有1位深度,但仍然犯了经典的错误。 谢谢大家。

尝试将此行HBITMAP hImage = CreateCompatibleBitmap(bm_hdc, sz.x, sz.y);更改为:

HBITMAP hImage = CreateCompatibleBitmap(hdc, sz.x, sz.y);

保罗·瓦特(Paul Watt)为GDI和图像构图撰写了出色的文章MsImage32.dll

我参考这篇文章是因为它解决了你的问题,以下是相关的引用和代码片段:

默认情况下,内存 DC 使用单色 1x1 像素位图进行初始化。

避免常见错误

在我们离我向您展示开始运行所需的代码太远之前,我想确保您安全地握住这把新剪刀。不要将内存 DC 与调用 CreateCompatibleBitmap 一起使用。

...
// You may be tempted to do this; DON'T:
HDC     hMemDC = ::CreateCompatibleDC(hDC);
                                     // DON'T DO THIS
                                     //       |
                                     //       V
HBITMAP hBmp   = ::CreateCompatibleBitmap(hMemDC, width, height);
...
// TIP: Try to use the same DC to create
//      the Bitmap which you used to create the memory DC.

还记得关于内存 DC 如何默认使用单色 1x1 像素位图初始化的部分吗?!

至于成员Raymond Chen的言论,我相信他也是对的,但是既然你说你的实际代码是不同的,这是我唯一能看到的错误。

希望这有所帮助。

此致敬意。