我一直想创建一个小应用程序,其中用户可以同时加载.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;
}
非常感谢。
答案 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;