无法加载多个位图 - WinAPI [重复]

Posted

技术标签:

【中文标题】无法加载多个位图 - WinAPI [重复]【英文标题】:Unable to load multiple bitmaps - WinAPI [duplicate] 【发布时间】:2017-03-14 12:07:47 【问题描述】:

所以最近我已经能够让我的应用程序允许用户从外部目录加载 .bmp 文件。应用程序加载图片很好,但如果用户突出显示多张图片,我的 LoadImage() 函数会抱怨,我认为这是因为它一次获取多个文件,所以它不知道如何正确读取它们。 (也许)。

这是我的初始化函数

void InitialiseDialog(HWND hwnd)

    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hInstance = GetModuleHandle(NULL);
    ofn.lpstrCustomFilter = NULL;
    ofn.nMaxCustFilter = 0;
    ofn.nFilterIndex = 0;
    ofn.nMaxFile = MAX_PATH;

    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = file;
    ofn.lpstrFilter = TEXT("Bitmap Files (*.bmp)\0*.bmp\0\0");
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = MAX_PATH;
    ofn.lpstrInitialDir = NULL;
    ofn.lpstrTitle = NULL;
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ALLOWMULTISELECT;
    ofn.nFileOffset = 0;
    ofn.nFileExtension = 0;
    ofn.lpstrDefExt = NULL;
    ofn.lCustData = 0L;
    ofn.lpfnHook = NULL;
    ofn.lpTemplateName = NULL;

这是我加载位图和调用事物的方式:

bool LoadAndBlitBitmap(LPCWSTR myFile, HDC hWinDC)

    // Load the bitmap image file
    hBitmap = (HBITMAP)::LoadImage(NULL, myFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

    // Verify that the image was loaded
    if (hBitmap == NULL) 
        ::MessageBox(NULL, L"LoadImage Failed", L"Error", MB_OK);
        return false;
    

    // Create a device context that is compatible with the window
    HDC hLocalDC;
    hLocalDC = ::CreateCompatibleDC(hWinDC);
    // Verify that the device context was created
    if (hLocalDC == NULL) 
        ::MessageBox(NULL, L"CreateCompatibleDC Failed", L"Error", MB_OK);
        return false;
    

    // Get the bitmap's parameters and verify the get
    BITMAP qBitmap;
    int iReturn = GetObject(reinterpret_cast<HGDIOBJ>(hBitmap), sizeof(BITMAP),
        reinterpret_cast<LPVOID>(&qBitmap));
    if (!iReturn) 
        ::MessageBox(NULL, L"GetObject Failed", L"Error", MB_OK);
        return false;
    

    // Select the loaded bitmap into the device context
    HBITMAP hOldBmp = (HBITMAP)::SelectObject(hLocalDC, hBitmap);
    if (hOldBmp == NULL) 
        ::MessageBox(NULL, L"SelectObject Failed", L"Error", MB_OK);
        return false;
    

    // Blit the dc which holds the bitmap onto the window's dc
    BOOL qRetBlit = ::BitBlt(hWinDC, 0, 0, qBitmap.bmWidth, qBitmap.bmHeight,
        hLocalDC, 0, 0, SRCCOPY);
    if (!qRetBlit) 
        ::MessageBox(NULL, L"Blit Failed", L"Error", MB_OK);
        return false;
    

    // Unitialize and deallocate resources
    ::SelectObject(hLocalDC, hOldBmp);
    ::DeleteDC(hLocalDC);
    ::DeleteObject(hBitmap);
    return true;


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

    int wmId, wmEvent;
    PAINTSTRUCT ps;

    switch (message)
    
    case WM_CREATE:
        InitialiseDialog(hWnd);
        return 0;

    case WM_COMMAND:
        wmId = LOWORD(wParam);
        wmEvent = HIWORD(wParam);

        // Parse the menu selections:
        switch (wmId)
        
        case ID_FILE_LOADIMAGES:
            if (GetOpenFileName(&ofn))
            
                g_bhBitmap = !g_bhBitmap;
            

            InvalidateRect(hWnd, NULL, TRUE);
            return 0;

            break;
        case ID_FILE_LOADAUDIO:
            DestroyWindow(hWnd);
            break;
        case ID_FILE_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);

        if (g_bhBitmap)
        
            LoadAndBlitBitmap(file, hdc); // <-- Something not right about this...? 
        

        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:

Output1(

感谢您阅读我的查询。我非常感谢您能给我的任何帮助:) 再见。

编辑:这里有一些变量定义:

// Global Variables
HINSTANCE g_hInst;
HBITMAP hBitmap;
HDC hdc;
static OPENFILENAME ofn;
bool g_bhBitmap = false;
wchar_t file[1024];

【问题讨论】:

能否使用调试器并在失败的 MessageBox 上设置断点,以便查看 myFile 的值? file 定义在哪里,它的值是什么 如果在LoadImage 失败并显示myFile 字符串后显示GetLastError 会更有用 myFile 基本上只是一个全局 wchar_t 数组,我发布了额外的信息希望对您有用。 @FearlessHobbit - 否 - 显示在消息框 myFile 和 GetLastError 中 【参考方案1】:

我的第一个建议是从标志中删除 OFN_ALLOWMULTISELECT

如果保留,则需要处理用户正确选择多个文件的情况。

来自手册:

OFN_ALLOWMULTISELECT

文件名列表框允许多选。

如果用户选择了多个文件,lpstrFile 缓冲区返回 当前目录的路径,后跟文件名 选定的文件。

nFileOffset 成员是偏移量,以字节或字符为单位,到 第一个文件名,并且不使用 nFileExtension 成员。

目录和文件名字符串是 NULL 分隔的,有一个额外的 最后一个文件名后的 NULL 字符。

当你发送给

hBitmap = (HBITMAP)::LoadImage(NULL, myFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

您实际上是在尝试将目录加载为位图。相反,您需要为每个选择单独创建精细名称,并分别加载它们。

【讨论】:

感谢您的及时回复。事情是,我需要 OFN_ALLOWMULTISELECT 因为我希望用户能够加载多个图像。如何为每个选择创建单独的文件名?我的 WinAPI 知识不是那么高级,我只是想实现这个基本功能,以便我可以对应用程序做其他事情。这个想法是制作一个使用多线程同时加载 .bmp 文件的应用程序。 strcat 是一种选择 如果不是太麻烦,你能给我举个例子吗?我真的不知道如何或把它放在哪里:(

以上是关于无法加载多个位图 - WinAPI [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Bitmap::GetHBITMAP 将位图转换为带有 alpha 的 HBITMAP?

无法从资源加载位图

错误 LNK2001:未解析的外部符号 WINAPI [重复]

winapi - 如何正确使用 LayeredWindows

无法从内存中正确加载位图

WinApi:无法读取注册表