abd*_*doe 0 c++ winapi encoding callback
我几乎不知道如何描述这种行为,所以这可能是我无法自己找到答案的原因 - 我根本就不知道如何命名这个问题.所以,如果标题是误导性的,或者问题在某种程度上是错误的,请耐心等待,但是这里来了
我有一个类方法,我打开一个文件并获取文件名:
OPENFILENAME GuiUtils::ChooseFileDialog(HWND hwnd)
{
OPENFILENAME ofn;
char szFile[260];
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = (LPWSTR)szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
HANDLE hf;
// Display the Open dialog box.
if (GetOpenFileName(&ofn) == TRUE)
{
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL);
}
return ofn;
}
Run Code Online (Sandbox Code Playgroud)
当我继续使用我的调试器并跳回调用函数时,有些东西搞砸了:
调用类方法:
INT_PTR CALLBACK FormCreator::Callback(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_COMMAND:
if (LOWORD(wParam) == IDCHOOSEFILE)
{
GuiUtils *guiUtils = new GuiUtils();
OPENFILENAME ofn = guiUtils->ChooseFileDialog(hwnd);
ORMFactory* db = new ORMFactory(); // value in debugger changes here
AbstractORM* sqlite = db->GetORMProvider(TEXT("SQLITE"));
this->databaseFileName = (wstring)ofn.lpstrFile;
}
break;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有人可以让我知道这里有什么问题ofn.lpstrFile以及如何解决这个问题?
谢谢
您使用的是Unicode版本GetOpenFileName(),但是您为其提供了一个ANSI缓冲区来存储所选的文件名.在将lpstrFile字段分配给字段时,您将对缓冲区进行类型转换,隐藏可能会提醒您不匹配的编译器错误.
您需要将缓冲区更改char为wchar_t并删除类型转换.
但是,即使您修复了此问题,代码中也会出现其他错误.
您将填充填充OPENFILENAME到调用者,但它仍然指向ChooseFileDialog()退出时超出范围的本地缓冲区.因此,当调用者访问该lpstrFile字段时,它正在调用未定义的行为.
ChooseFileDialog()每次GetOpenFileName()成功时都会泄漏文件句柄.您没有对文件句柄执行任何操作,并且您没有关闭它.因此,您根本不应该打开文件
而且你在回调中泄漏动态的alloxated对象.
尝试更像这样的东西:
std::wstring GuiUtils::ChooseFileDialog(HWND hwnd)
{
OPENFILENAMEW ofn;
wchar_t szFile[MAX_PATH];
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = MAX_PATH;
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
HANDLE hf;
// Display the Open dialog box.
if (!GetOpenFileNameW(&ofn))
return L"";
// what is this for???
/*
hf = CreateFileW(ofn.lpstrFile,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
*/
return ofn.lpstrFile;
}
INT_PTR CALLBACK FormCreator::Callback(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_COMMAND:
if (LOWORD(wParam) == IDCHOOSEFILE)
{
GuiUtils guiUtils;
std::wstring fname = guiUtils.ChooseFileDialog(hwnd);
if (fname.empty()) break;
ORMFactory db;
AbstractORM* sqlite = db.GetORMProvider(L"SQLITE");
this->databaseFileName = fname;
}
break;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
107 次 |
| 最近记录: |