我有以下代码,我用来使用Win32 API打开文件打开对话框。它在32位工作正常,但在64位(在DLL中)使用时失败。我做错了什么?
char Filestring[256];
Filter = "OBJ files\0*.obj\0\0";
char* returnstring = NULL;
OPENFILENAME opf;
opf.hwndOwner = mainHWND;
opf.lpstrFilter = Filter;
opf.lpstrCustomFilter = 0;
opf.nMaxCustFilter = 0L;
opf.nFilterIndex = 1L;
opf.lpstrFile = Filestring;
opf.lpstrFile[0] = '\0';
opf.nMaxFile = 256;
opf.lpstrFileTitle = 0;
opf.nMaxFileTitle=50;
opf.lpstrInitialDir = Path;
opf.lpstrTitle = "Open Obj File";
opf.nFileOffset = 0;
opf.nFileExtension = 0;
opf.lpstrDefExt = "*.*";
opf.lpfnHook = NULL;
opf.lCustData = 0;
opf.Flags = (OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT) & ~OFN_ALLOWMULTISELECT;
opf.lStructSize = sizeof(OPENFILENAME);
if(GetOpenFileName(&opf))
{
returnstring = opf.lpstrFile;
if (returnstring) {
result = returnstring;
}
}
编辑:失败,我的意思是打开文件对话框没有出现。代码仍然返回零而没有任何错误。
编辑2:我调用了CommDlgExtendedError()并返回1.从MSDN引用中,是否表示对话框的lStructSize无效?我检查了sizeof(OPENFILENAME)
,它返回了140个字节。
更新:在我的项目设置中,在代码生成下,“结构成员对齐”设置为4个字节(/ Zp4)。我将其更改为默认值并且神奇地工作了。请查看下面的答案及其评论以获取更多信息。
答案 0 :(得分:5)
您没有初始化lpTemplateName
,因此它包含随机堆栈噪音。这反过来会导致'hInstance`成为引用,它也包含堆栈噪声。
调用这样的函数时,首先应该将结构清零,只填写非零的字段。像这样:
OPENFILENAME opf={0};
opf.lStructSize = sizeof(OPENFILENAME);
opf.hwndOwner = mainHWND;
opf.lpstrFilter = Filter;
opf.nFilterIndex = 1L;
opf.lpstrFile = Filestring;
opf.lpstrFile[0] = '\0';
opf.nMaxFile = 256;
opf.lpstrInitialDir = Path;
opf.lpstrTitle = "Open Obj File";
opf.lpstrDefExt = "*.*";
opf.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
没有必要明确排除OFN_ALLOWMULTISELECT
,因为您没有首先将其排除在外!
修改强>
您在评论中说明这不起作用。调用CommDlgExtendedError
是一个好主意,应该告诉你它失败的原因。
你也可以尝试运行尽可能小的GetOpenFileName
:
char Filestring[MAX_PATH] = "\0";
OPENFILENAME opf={0};
opf.lStructSize = sizeof(OPENFILENAME);
opf.lpstrFile = Filestring;
opf.nMaxFile = MAX_PATH;
GetOpenFileName(&opf);
答案 1 :(得分:3)
我有同样的问题和部分解决方案: +简单的以下简单示例(建议的abobe)在x64模式下不起作用。 +我将complie选项“struct Member Alignment”从1byte / Zp1改为default,解决了这个问题(通过介绍其他人!!!)
char Filestring [MAX_PATH] =“\ 0”; OPENFILENAME opf = {0}; opf.lStructSize = sizeof(OPENFILENAME); opf.lpstrFile = Filestring; opf.nMaxFile = MAX_PATH; GetOpenFileName(安培; OPF);
答案 2 :(得分:2)
要了解更多信息,请致电CommDlgExtendedError以获取错误代码。除此之外,我将使用
将结构的所有成员初始化为0ZeroMemory(&opf, sizeof(opf));
由于文件打开对话框实际上是COM组件,因此在64位下检查线程单元状态是否不同可能是值得的。
if( RPC_E_CHANGED_MODE == CoInitialize(NULL) )
ASSERT(FALSE); // MTA Apartment found
CoUnitialize()
此致, Alois Kraus
答案 3 :(得分:1)
作为Microsoft Office 2010 64位中的一个注释,我们放弃并使用内部包装器,因为结构变为140字节,我们不确定如何更改对齐。
Application.GetOpenFilename(FileFilter,FilterIndex,Title,ButtonText,MultiSelect) 和Application.GetSaveAsFilename(InitialFilename,FileFilter,FilterIndex,Title,ButtonText)
http://msdn.microsoft.com/en-us/library/ff834966.aspx
毋庸置疑,我们认为在Excel中具有相当繁重应用程序的所有个人都应该开始考虑其他选项,因为在多个客户端和平台上维护未来版本可能只是......疯了!
答案 4 :(得分:1)
我设法通过在包含头文件之前适当地设置打包来解决这个问题。这样,出于这一功能的目的,我们使用了默认的' 16字节对齐,但不必更改我们程序其余部分的打包对齐:
#ifdef _WIN64
#pragma pack( push )
#pragma pack( 16 )
#include "Commdlg.h"
#pragma pack( pop )
#else
#include "Commdlg.h"
#endif // _WIN64