BITMAP图像不会从文件"INVALID HANDLE"加载

-3 winapi bitmap

这是基本的,因此只需要一个来自绘图函数的代码片段,因为它具有必要的信息

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();
    }
Run Code Online (Sandbox Code Playgroud)

获取上一个错误显示错误6,这是一个无效的文件句柄.消息框显示,这意味着图像从未加载和失败,因此其后的代码不是主要关注点.

我正在尝试加载位图并将其放在我创建的Win32窗口上.

不需要其他代码,因为没有任何具体的任何其他代码可以导致整体可能的答案.告诉我如何才能成功加载图像.

Rem*_*eau 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!
}
Run Code Online (Sandbox Code Playgroud)

LoadImage()失败的原因是因为您未LR_LOADFROMFILE按照LoadImage()文档指定标志,而不是正确请求图像大小:

lpszName [in]
...
如果hinst参数为NULL并且fuLoad参数省略了LR_LOADFROMFILE值,则lpszName指定要加载的OEM映像.OEM映像标识符在Winuser.h中定义,并具有以下前缀.
...
如果fuLoad参数包含LR_LOADFROMFILE值,则lpszName是包含独立资源(图标,光标或位图文件)的文件的名称.因此,将hinst设置为NULL.

...

cxDesired [in]
...
... 如果此参数为零且未使用LR_DEFAULTSIZE,则该函数使用实际资源宽度.

...

cyDesired [中]
...
... 如果这个参数是零,不使用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);
Run Code Online (Sandbox Code Playgroud)

解决之后,代码还有其他问题.

您正在CreateCompatibleDC()使用未初始化的 HDC变量进行调用,而不是检查CreateCompatibleDC()失败的结果.你的电话GetDC()是在错误的地方,需要将其移到上方CreateCompatibleDC().而你泄漏HDCGetDC()返回,你需要调用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);
}
Run Code Online (Sandbox Code Playgroud)

话虽如此,PAINTSTRUCT变量意味着您的代码正在WM_PAINT消息处理程序中使用.如果这是真的,你应该使用BeginPaint()而不是GetDC()让目标HDC绘制:

case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    draw(hdc);
    EndPaint(hwnd, &ps);
    break;
};
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

否则,如果你在外面使用你的代码WM_PAINT,那么代码几乎没用,因为它UpdateWindow()会触发一次擦除你的绘图的重新绘制.在窗口上持续图纸必须使用来完成WM_PAINT(除非您使用UpdateLayeredWindow()一个WS_EX_LAYERED窗口).

  • 不,这并不明显,因为你隐藏了路径和文件名的细节.**绝对路径**不受CWD的影响.如果加载使用**绝对路径**以错误2(`ERROR_FILE_NOT_FOUND`)或3(`ERROR_PATH_NOT_FOUND`)失败,那么您没有使用简单明了的有效路径.如果您认为我错了,请随意显示您正在使用的实际路径,请停止隐藏它. (2认同)