无法加载.bmp文件win32

时间:2017-03-13 09:49:35

标签: c++ winapi bitmap

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

#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;
}

非常感谢。

4 个答案:

答案 0 :(得分:3)

似乎你永远不会为文件名分配缓冲区 不同的数据类型可以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 structure lpstrFile定义为:

  

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

     

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

所以你只需要为szFileName分配一个缓冲区来解决这个问题。

这将解决你的问题

  

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

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

答案 1 :(得分:0)

谢谢,我已经修复了问题,我现在可以通过将LPTSTR szFileName;更改为char szFileName[MAX_PATH];来加载位图图片但是,我无法一次选择多个位图,有没有办法让它成功这样我可以一次加载多个图像?非常感谢你的帮助。

答案 2 :(得分:0)

以下是我的声明现在的样子,但即使使用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;
}

答案 3 :(得分:0)

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