我试图将位图加载到我创建的窗口中。位图应该是窗口的背景(我想稍后在其上添加标签)。
这是我的代码:
HINSTANCE hInst;
LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX WndCls;
static WCHAR szAppName[] = L"BitmapIntro";
MSG Msg;
hInst = hInstance;
WndCls.cbSize = sizeof(WndCls);
WndCls.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
WndCls.lpfnWndProc = WindProcedure;
WndCls.cbClsExtra = 0;
WndCls.cbWndExtra = 0;
WndCls.hInstance = hInst;
WndCls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndCls.hCursor = LoadCursor(NULL, IDC_ARROW);
WndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndCls.lpszMenuName = NULL;
WndCls.lpszClassName = szAppName;
WndCls.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
RegisterClassEx(&WndCls);
CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
szAppName,
L"Bitmaps Fundamentals",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return static_cast<int>(Msg.wParam);
}
LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
HDC hDC, MemDCExercising;
PAINTSTRUCT Ps;
HBITMAP bmpExercising;
switch (Msg)
{
case WM_DESTROY:
PostQuitMessage(WM_QUIT);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &Ps);
// Load the bitmap from the resource
bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
// Create a memory device compatible with the above DC variable
MemDCExercising = CreateCompatibleDC(hDC);
// Select the new bitmap
SelectObject(MemDCExercising, bmpExercising);
// Copy the bits from the memory DC into the current dc
BitBlt(hDC, 10, 10, 450, 400, MemDCExercising, 0, 0, SRCCOPY);
// Restore the old bitmap
DeleteDC(MemDCExercising);
DeleteObject(bmpExercising);
EndPaint(hWnd, &Ps);
break;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
问题是,与窗口相比,PNG尺寸较小,因此当PNG打开时,它只占据左上角。如何让它拉伸到我的窗口大小或者至少一遍又一遍地拉到窗口?
答案 0 :(得分:2)
如何让它拉伸到我的窗口大小
使用StretchBlt()
代替BitBlt()
。
case WM_PAINT:
{
// Get the window dimensions
RECT r;
GetClientRect(hWnd, &r);
// Load the bitmap from the resource
HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
// Get the bitmap dimensions
BITMAP bmp;
GetObject(bmpExercising, sizeof(BITMAP), &bmp);
PAINTSTRUCT Ps;
HDC hDC = BeginPaint(hWnd, &Ps);
// Create a memory device compatible with the above DC variable
HDC MemDCExercising = CreateCompatibleDC(hDC);
// Select the new bitmap
HBITMAP hOldBmp = SelectObject(MemDCExercising, bmpExercising);
// Copy the bits from the memory DC into the current dc
StretchBlt(hDC, 0, 0, r.right - r.left, r.bottom - r.top, MemDCExercising, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
// Restore the old bitmap
SelectObject(MemDCExercising, hOldBmp);
// Destroy the memory device
DeleteDC(MemDCExercising);
// Destroy the bitmap
DeleteObject(bmpExercising);
EndPaint(hWnd, &Ps);
break;
}
或者至少一遍又一遍地画它直到它填满窗户?
有两种不同的方法可以解决这个问题。
启动时,使用CreatePatternBrush()
加载位图并在其周围创建HBRUSH
,然后在注册窗口类时将其分配给WNDCLASS::hbrBackground
字段。让操作系统使用位图为您绘制窗口背景。
HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
WndCls.hbrBackground = CreatePatternBrush(bmpExercising);
如果要手动绘制位图,请让绘制处理程序在几个循环中调用BitBlt()
。您知道位图的尺寸(可以使用GetObject()
和BITMAP
结构在代码中检索),并且您知道窗口的尺寸(您可以使用{{3}在代码中检索该尺寸}或GetWindowRect()
)。因此,根据需要,可以根据不同的偏移量多次绘制相同的位图。首先在左上角绘制一次,然后向右移动位图宽度像素并再次绘制,重复直到移过窗口宽度像素。然后向左移动到0并向下移动位图高度像素并再次重复整个宽度线,重复直到您移过窗口高度像素。
case WM_PAINT:
{
// Get the window dimensions
RECT r;
GetClientRect(hWnd, &r);
// Load the bitmap from the resource
HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
// Get the bitmap dimensions
BITMAP bmp;
GetObject(bmpExercising, sizeof(BITMAP), &bmp);
PAINTSTRUCT Ps;
HDC hDC = BeginPaint(hWnd, &Ps);
// Create a memory device compatible with the above DC variable
HDC MemDCExercising = CreateCompatibleDC(hDC);
// Select the new bitmap
HBITMAP hOldBmp = SelectObject(MemDCExercising, bmpExercising);
int width = r.right - r.left;
int height = r.bottom - r.top;
// Copy the bits from the memory DC into the current dc
for(int y = 0; y < height; y += bmp.bmHeight)
{
for(int x = 0; x < width; x += bmp.bmWidth)
{
BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, MemDCExercising, 0, 0, SRCCOPY);
}
}
// Restore the old bitmap
SelectObject(MemDCExercising, hOldBmp);
// Destroy the memory device
DeleteDC(MemDCExercising);
// Destroy the bitmap
DeleteObject(bmpExercising);
EndPaint(hWnd, &Ps);
break;
}
现在,说到这里,还有一些补充说明:
您不应该在绘图处理程序中加载位图。在创建窗口之前加载它一次,然后为每个绘制操作重复使用相同的HBITMAP
,直到窗口被销毁,然后释放位图。
LoadBitmap()
已被弃用,您应该使用GetClientRect()
代替,例如:
HBITMAP bmpExercising = (HBITMAP) LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP3), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
你说“位图应该是窗口的背景”,所以你应该绘制位图以响应LoadImage()
消息而不是WM_PAINT
消息。
case WM_ERASEBKGND:
{
HDC hDC = (HDC) wParam;
// draw the bitmap on hDC as needed...
return 1;
}