如何使用 bitblt 在屏幕上绘制数组制作的位图?
How do I draw an array made bitmap on screen using bitblt?
我不想使用 Moveto
和 LineTo
进行绘图,而是想使用手工制作的位图,我将用我自己创建的数组填充它,然后用它来填充屏幕.
现在,数组只是用红色填充,
但是当我画到屏幕上时,我全黑了。
这是代码:
void CCGWorkView::OnDraw(CDC* pDC)
{
CCGWorkDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
pDCToUse->FillSolidRect(&r, world.bg_color);
BITMAPINFO bminfo;
CPaintDC hdc(this);
CRect rect;
GetWindowRect(&rect);
int h = rect.bottom - rect.top,
w = rect.right - rect.left;
int *bits = new int[w * h];
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP bm = CreateCompatibleBitmap(hdc, w, h);
SelectObject(hdcMem, bm);
bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader);
bminfo.bmiHeader.biWidth = w;
bminfo.bmiHeader.biHeight = h;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
bminfo.bmiHeader.biSizeImage = 0;
bminfo.bmiHeader.biXPelsPerMeter = 1;
bminfo.bmiHeader.biYPelsPerMeter = 1;
bminfo.bmiHeader.biClrUsed = 0;
bminfo.bmiHeader.biClrImportant = 0;
for (int i = 0; i < w * h; i++) {
bits[i] = RGB(255, 0, 0);
}
SetDIBits(hdcMem, bm, 0, h, bits, &bminfo, 0);
BitBlt(hdc, rect.left, rect.top, w, h, hdcMem, rect.left, rect.top, SRCCOPY);
DeleteDC(hdcMem);
DeleteObject(bm);
delete bits;
}
您的代码中有几个问题。
首先,您不需要 CPaintDC
,因为 pDC
已传递到您的 OnDraw()
函数中。
这实际上可能导致你的黑色显示,因为新创建的 DC 有一个单像素的黑白位图 select 进入其中,当你调用 CreateCompatibleBitmap()
时,该位图也是单色的。
其次,SetDIBits()
期望 RGBQUAD
颜色 (https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-rgbquad),而不是 RGB
。
并且,正如 Constantine Georgiou 所建议的那样,您应该在删除位图之前将其从 DC 中删除,select 以避免资源泄漏,即使 MFC 已为您处理它也是如此。
这里是修改后的代码:
void CMFCApplication1View::OnDraw(CDC* pDC)
{
CMFCApplication1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
//pDCToUse->FillSolidRect(&r, world.bg_color);
BITMAPINFO bminfo;
CRect rect;
GetClientRect(&rect);
int h = rect.bottom - rect.top,
w = rect.right - rect.left;
int* bits = new int[w * h];
HDC hdcMem = CreateCompatibleDC(pDC->m_hDC);
HBITMAP bm = CreateCompatibleBitmap(pDC->m_hDC, w, h);
HGDIOBJ hOld = SelectObject(hdcMem, bm);
bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader);
bminfo.bmiHeader.biWidth = w;
bminfo.bmiHeader.biHeight = h;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
bminfo.bmiHeader.biSizeImage = 0;
bminfo.bmiHeader.biXPelsPerMeter = 1;
bminfo.bmiHeader.biYPelsPerMeter = 1;
bminfo.bmiHeader.biClrUsed = 0;
bminfo.bmiHeader.biClrImportant = 0;
RGBQUAD red = { 0, 0, 255, 0 };
for (int i = 0; i < w * h; i++) {
bits[i] = *((int*)&red);
}
SetDIBits(hdcMem, bm, 0, h, bits, &bminfo, DIB_RGB_COLORS);
BitBlt(pDC->m_hDC, rect.left, rect.top, w, h, hdcMem, rect.left, rect.top, SRCCOPY);
SelectObject(hdcMem, hOld);
DeleteDC(hdcMem);
DeleteObject(bm);
delete[] bits;
}
我不想使用 Moveto
和 LineTo
进行绘图,而是想使用手工制作的位图,我将用我自己创建的数组填充它,然后用它来填充屏幕.
现在,数组只是用红色填充, 但是当我画到屏幕上时,我全黑了。
这是代码:
void CCGWorkView::OnDraw(CDC* pDC)
{
CCGWorkDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
pDCToUse->FillSolidRect(&r, world.bg_color);
BITMAPINFO bminfo;
CPaintDC hdc(this);
CRect rect;
GetWindowRect(&rect);
int h = rect.bottom - rect.top,
w = rect.right - rect.left;
int *bits = new int[w * h];
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP bm = CreateCompatibleBitmap(hdc, w, h);
SelectObject(hdcMem, bm);
bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader);
bminfo.bmiHeader.biWidth = w;
bminfo.bmiHeader.biHeight = h;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
bminfo.bmiHeader.biSizeImage = 0;
bminfo.bmiHeader.biXPelsPerMeter = 1;
bminfo.bmiHeader.biYPelsPerMeter = 1;
bminfo.bmiHeader.biClrUsed = 0;
bminfo.bmiHeader.biClrImportant = 0;
for (int i = 0; i < w * h; i++) {
bits[i] = RGB(255, 0, 0);
}
SetDIBits(hdcMem, bm, 0, h, bits, &bminfo, 0);
BitBlt(hdc, rect.left, rect.top, w, h, hdcMem, rect.left, rect.top, SRCCOPY);
DeleteDC(hdcMem);
DeleteObject(bm);
delete bits;
}
您的代码中有几个问题。
首先,您不需要 CPaintDC
,因为 pDC
已传递到您的 OnDraw()
函数中。
这实际上可能导致你的黑色显示,因为新创建的 DC 有一个单像素的黑白位图 select 进入其中,当你调用 CreateCompatibleBitmap()
时,该位图也是单色的。
其次,SetDIBits()
期望 RGBQUAD
颜色 (https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-rgbquad),而不是 RGB
。
并且,正如 Constantine Georgiou 所建议的那样,您应该在删除位图之前将其从 DC 中删除,select 以避免资源泄漏,即使 MFC 已为您处理它也是如此。
这里是修改后的代码:
void CMFCApplication1View::OnDraw(CDC* pDC)
{
CMFCApplication1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
//pDCToUse->FillSolidRect(&r, world.bg_color);
BITMAPINFO bminfo;
CRect rect;
GetClientRect(&rect);
int h = rect.bottom - rect.top,
w = rect.right - rect.left;
int* bits = new int[w * h];
HDC hdcMem = CreateCompatibleDC(pDC->m_hDC);
HBITMAP bm = CreateCompatibleBitmap(pDC->m_hDC, w, h);
HGDIOBJ hOld = SelectObject(hdcMem, bm);
bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader);
bminfo.bmiHeader.biWidth = w;
bminfo.bmiHeader.biHeight = h;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
bminfo.bmiHeader.biSizeImage = 0;
bminfo.bmiHeader.biXPelsPerMeter = 1;
bminfo.bmiHeader.biYPelsPerMeter = 1;
bminfo.bmiHeader.biClrUsed = 0;
bminfo.bmiHeader.biClrImportant = 0;
RGBQUAD red = { 0, 0, 255, 0 };
for (int i = 0; i < w * h; i++) {
bits[i] = *((int*)&red);
}
SetDIBits(hdcMem, bm, 0, h, bits, &bminfo, DIB_RGB_COLORS);
BitBlt(pDC->m_hDC, rect.left, rect.top, w, h, hdcMem, rect.left, rect.top, SRCCOPY);
SelectObject(hdcMem, hOld);
DeleteDC(hdcMem);
DeleteObject(bm);
delete[] bits;
}