无法加载 .bmp 文件 win32 [重复]

Posted

技术标签:

【中文标题】无法加载 .bmp 文件 win32 [重复]【英文标题】:Unable to load .bmp files win32 [duplicate] 【发布时间】:2017-03-13 09:49:35 【问题描述】:

我一直想创建一个小型应用程序,用户可以在其中加载 .bmp 图像并同时加载音频文件(多线程)。但是,由于我对 win32 不是很熟悉,所以我在加载 .bmp 文件时似乎遇到了问题。编辑:似乎我的问题与“szFileName”变量没有通过 OpenFileDialog 函数接收任何数据有关。在 ID_FILE_LOADIMAGES 的情况下,即使在用户选择了某个 bmp 图像并单击“确定”之后,“szFileName”也正在测试为假。我不知道为什么会这样。

#include "resource.h"
#include <windows.h>

// Global Variables
HINSTANCE g_hInst;
LPTSTR szFileName;
HBITMAP hBitmap;
BITMAP bitmap;
RECT rect;
HDC hdc, hdcMem;
static OPENFILENAME ofn;
bool g_bhBitmap = false;

// Function Prototypes
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void InitialiseDialog(HWND hwnd)

    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hwnd;
    ofn.hInstance = NULL;
    ofn.lpstrCustomFilter = NULL;
    ofn.nMaxCustFilter = 0;
    ofn.nFilterIndex = 0;
    ofn.lpstrFile = (LPWSTR)szFileName;
    ofn.nMaxFile = 500;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = MAX_PATH;
    ofn.lpstrInitialDir = NULL;
    ofn.lpstrTitle = NULL;
    ofn.Flags = 0;
    ofn.nFileOffset = 0;
    ofn.nFileExtension = 0;
    ofn.lpstrDefExt = NULL;
    ofn.lCustData = 0L;
    ofn.lpfnHook = NULL;
    ofn.lpTemplateName = NULL;

BOOL OpenFileDialog(HWND hwnd, LPTSTR pFileName, LPTSTR pTitleName)

    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hInstance = GetModuleHandle(NULL);
    ofn.lpstrCustomFilter = NULL;
    ofn.nMaxCustFilter = 0;
    ofn.nFilterIndex = 0;

    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = pFileName;
    ofn.lpstrFileTitle = NULL;
    ofn.lpstrTitle = pTitleName;
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
    ofn.lpstrFilter = TEXT("Bitmap Files (*.bmp)\0*.bmp\0\0");

    return GetOpenFileName(&ofn);


//...Window Creation...

// Load bitmap and check for errors
bool LoadAndBlitBitmap(LPCWSTR szFileName, HDC hWinDC)

    // Load the bitmap image file
    hBitmap = (HBITMAP)::LoadImage(NULL, szFileName, 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:

            OpenFileDialog(hWnd, szFileName, L"Open a Bitmap File.");

            if (szFileName)
            
                ZeroMemory(&hBitmap, sizeof(HBITMAP));
                LoadAndBlitBitmap(szFileName, hdc);
            

            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(szFileName, hdc);
        

        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        if (hBitmap)
            DeleteObject(hBitmap);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    
    return 0;

非常感谢。

【问题讨论】:

“我似乎有问题”不是恰当的问题描述。 在我看来,实际问题是您不知道如何调试代码,或者选择不调试。请尝试纠正任何适用的情况。 “这是我目前的全部代码” - 请阅读如何创建minimal reproducible example 是的,对不起,我只是一个新的注册用户,正在寻求帮助。我只是希望有人能告诉我应该如何使用 OpenFileDialog。我也知道如何编写最少的代码,但我认为让人们看到整个事情以便在一定程度上帮助我是很重要的。不过感谢您的 cmets。 我遵循了您的指导方针并稍微增强了我的问题并删除了不必要的代码块。 【参考方案1】:

您似乎从未为文件名分配缓冲区。 不同的数据类型可以be found in this SO answer。

您的szFileName 被定义为

LPTSTR = char* 或 wchar_t* 取决于 _UNICODE

所以它是一个指针,但在您的代码示例中,您没有为此指针保留内存。

ofn.lpstrFile = (LPWSTR)szFileName;        // in WndProc
LoadAndBlitBitmap(LPCWSTR szFileName...)   // passed as CONST 
LoadImage(NULL, szFileName...)             // passed as parameter
OpenFileDialog(hWnd, szFileName, ...)      // passed as parameter
if (szFileName) ...                        // check if !NULL
LoadAndBlitBitmap(szFileName, hdc);        // passed as parameter

但是你永远不会为指针分配必要的内存......

OPENFILENAME structurelpstrFile中定义为:

用于初始化文件名​​编辑控件的文件名。 如果不需要初始化,则此缓冲区的第一个字符必须为 NULL。 当 GetOpenFileName 或 GetSaveFileName 函数成功返回时,此缓冲区包含所选文件的驱动器指示符、路径、文件名和扩展名...

如果缓冲区太小,函数返回 FALSE,CommDlgExtendedError 函数返回 FNERR_BUFFERTOOSMALL。在这种情况下,lpstrFile 缓冲区的前两个字节包含所需的大小,以字节或字符为单位。

因此,您只需为szFileName 分配一个缓冲区即可解决该问题。

这会解决你的

在 ID_FILE_LOADIMAGES 的情况下,即使在用户选择了某个 bmp 图像并单击“确定”之后,“szFileName”也会测试为假。

问题。它返回FALSE,因为您的“缓冲区”(=none)太小了。

【讨论】:

【参考方案2】:

谢谢,我已经解决了这个问题,现在我可以通过将LPTSTR szFileName; 更改为char szFileName[MAX_PATH]; 来加载位图图像 但是,我不能一次选择多个位图,有什么方法可以做到吗?一次加载多张图片?非常感谢你的帮助。

【讨论】:

【参考方案3】:

这是我的声明现在的样子,但即使使用OFN_ALLOWMULTISELECT;,它也不会让我一次加载多个图像,这正是我想要的。 :(

 char szFileName[MAX_PATH];

BOOL OpenFileDialog(HWND hwnd, LPTSTR pFileName, LPTSTR pTitleName)

    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hInstance = GetModuleHandle(NULL);
    ofn.lpstrCustomFilter = NULL;
    ofn.nMaxCustFilter = 0;
    ofn.nFilterIndex = 0;

    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = pFileName;
    ofn.lpstrFileTitle = NULL;
    ofn.lpstrTitle = pTitleName;
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ALLOWMULTISELECT;
    ofn.lpstrFilter = TEXT("Bitmap Files (*.bmp)\0*.bmp\0\0");

    if (GetOpenFileName(&ofn) != TRUE)
        return FALSE;
    else
        return TRUE;

【讨论】:

【参考方案4】:

没关系,解决了问题,原来我在其他地方有ofn.flags = 0;。所以它覆盖了ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ALLOWMULTISELECT;

【讨论】:

以上是关于无法加载 .bmp 文件 win32 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

无法加载库“gsdll32”

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

无法加载 pywin32 库 win32gui

无法加载文件或程序集 X 或其依赖项之一。不是有效的Win32应用程序。 (HRESULT:0x800700C1)

电脑开机提示:无法加载;如何解决?

Delphi:无法打开 .bmp 文件