这是基本的,因此只需要一个来自绘图功能的代码片段,因为它具有必要的信息
void draw()
{
RECT rect;
GetClientRect(hwnd, &rect);
HBITMAP FRAME1ANIMDASH = NULL;
FRAME1ANIMDASH = (HBITMAP) LoadImage(NULL, "Hidden but correct pathname that won't be shown here", 0, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_CREATEDIBSECTION);
if(FRAME1ANIMDASH == NULL)
{
MessageBox(NULL, "CANNOT LOAD", "CANNOT LOAD", MB_OK);
}
HDC device;
PAINTSTRUCT ps;
BITMAP bm;
GetObject(FRAME1ANIMDASH,sizeof(BITMAP),&bm);
HDC hdcdevice=CreateCompatibleDC(device);
SelectObject(hdcdevice,FRAME1ANIMDASH);
BitBlt(device,0,0,0,0,hdcdevice,0,0,SRCCOPY);
UpdateWindow(hwnd);
device=GetDC(hwnd);
DeleteDC(hdcdevice);
DeleteObject((HBITMAP) FRAME1ANIMDASH);
DWORD lastError = GetLastError();
cout << GetLastError();
}
获取上一个错误显示错误6,这是一个无效的文件句柄。消息框显示,这意味着图像从未加载和失败,所以其后的代码不是主要关注点。
我正在尝试加载位图并将其放在我创建的Win32窗口上。
不需要其他代码,因为没有任何其他代码可以导致整体可能的答案。告诉我如何才能成功加载图像。
答案 0 :(得分:5)
你打电话给GetLastError()
太晚了。此时错误代码毫无意义,因为它可能会被您调用的任何其他函数覆盖。在GetLastError()
失败后,您必须立即致电LoadImage()
:
HBITMAP FRAME1ANIMDASH = (HBITMAP) LoadImage(...);
if (FRAME1ANIMDASH == NULL)
{
DWORD lastError = GetLastError();
cout << "CANNOT LOAD IMAGE, ERROR " << lastError;
MessageBox(NULL, "CANNOT LOAD IMAGE", "CANNOT LOAD IMAGE", MB_OK);
return; // <-- add this, too!
}
LoadImage()
失败的原因是因为您未按照LoadImage()
documentation指定LR_LOADFROMFILE
标记,而没有正确请求图像大小:
lpszName [in]
...
如果hinst参数为NULL并且fuLoad参数省略了LR_LOADFROMFILE值,则lpszName指定要加载的OEM映像。 OEM映像标识符在Winuser.h中定义并具有以下前缀。
...
如果fuLoad参数包含LR_LOADFROMFILE值,则lpszName是包含独立资源(图标,光标或位图文件)的文件名。因此,将hinst设置为NULL。...
cxDesired [in]
...
... 如果此参数为零且未使用LR_DEFAULTSIZE,则该函数使用实际资源宽度。
...
cyDesired [in]
...
... 如果此参数为零且未使用LR_DEFAULTSIZE,则该函数使用实际资源高度。...
fuLoad [in]
...
LR_DEFAULTSIZE
... 如果未指定此标志且cxDesired和cyDesired设置为零,则该函数使用实际资源大小。
...... LR_LOADFROMFILE
...从lpszName 指定的文件(图标,光标或位图文件)加载独立图像。
所以看起来应该更像这样:
HBITMAP FRAME1ANIMDASH = (HBITMAP) LoadImage(NULL, "pathname", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
修复后,代码还有其他问题。
您正在使用未初始化的 CreateCompatibleDC()
变量来调用HDC
,而不是检查CreateCompatibleDC()
的失败结果。您对GetDC()
的来电位置错误,需要将其移至CreateCompatibleDC()
以上。而且,如果您HDC
返回GetDC()
,则需要致电ReleaseDC()
以释放它。
您还告诉BitBlt()
复制一个0x0的像素矩形,而不是使用BITMAP
结构中的位图的真实尺寸,甚至是您使用的RECT
窗口从GetClientRect()
检索。
尝试更像这样的东西:
void draw()
{
HBITMAP FRAME1ANIMDASH = (HBITMAP) LoadImage(NULL, "pathname", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
if (FRAME1ANIMDASH == NULL)
{
DWORD lastError = GetLastError();
cout << "CANNOT LOAD IMAGE, ERROR " << lastError;
MessageBox(NULL, "CANNOT LOAD IMAGE", "CANNOT LOAD IMAGE", MB_OK);
return;
}
HDC hdcWnd = GetDC(hwnd);
if (hdcWnd === NULL)
{
DeleteObject(FRAME1ANIMDASH);
cout << "CANNOT GET WINDOW DC";
MessageBox(NULL, "CANNOT GET WINDOW DC", "CANNOT GET DC", MB_OK);
return;
}
HDC hdcMem = CreateCompatibleDC(hdcWnd);
if (hdcMem == NULL)
{
ReleaseDC(hwnd, hdcWnd);
DeleteObject(FRAME1ANIMDASH);
cout << "CANNOT CREATE COMPATIBLE DC";
MessageBox(NULL, "CANNOT CREATE COMPATIBLE DC", "CANNOT CREATE DC", MB_OK);
return;
}
BITMAP bm;
GetObject(FRAME1ANIMDASH, sizeof(BITMAP), &bm);
HBITMAP oldBm = (HBITMAP) SelectObject(hdcMem, FRAME1ANIMDASH);
BitBlt(hdcWnd, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBm);
DeleteDC(hdcMem);
ReleaseDC(hwnd, hdcWnd);
DeleteObject(FRAME1ANIMDASH);
UpdateWindow(hwnd);
}
话虽如此,PAINTSTRUCT
变量意味着您的代码正在WM_PAINT
消息处理程序中使用。如果确实如此,您应该使用BeginPaint()
代替GetDC()
来获取目标HDC
:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
draw(hdc);
EndPaint(hwnd, &ps);
break;
};
void draw(HDC hdcTarget)
{
HBITMAP FRAME1ANIMDASH = (HBITMAP) LoadImage(NULL, "pathname", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
if (FRAME1ANIMDASH == NULL)
{
DWORD lastError = GetLastError();
cout << "CANNOT LOAD IMAGE, ERROR " << lastError;
// DO NOT use MessageBox() in a WM_PAINT handler,
// You will trigger an endless re-paint loop!
return;
}
HDC hdcMem = CreateCompatibleDC(hdcTarget);
if (hdcMem == NULL)
{
DeleteObject(FRAME1ANIMDASH);
cout << "CANNOT CREATE COMPATIBLE DC";
return;
}
BITMAP bm;
GetObject(FRAME1ANIMDASH, sizeof(BITMAP), &bm);
HBITMAP oldBm = (HBITMAP) SelectObject(hdcMem, FRAME1ANIMDASH);
BitBlt(hdcWnd, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBm);
DeleteDC(hdcMem);
DeleteObject(FRAME1ANIMDASH);
}
否则,如果您使用WM_PAINT
之外的代码,则代码几乎无用,因为UpdateWindow()
将触发重绘以消除您的绘图。必须使用WM_PAINT
完成窗口上的持久性绘图(除非您使用UpdateLayeredWindow()
并使用WS_EX_LAYERED
窗口。)