GetOpenFileName在64位失败,但在32Bit中工作?

时间:2011-02-13 05:46:33

标签: windows winapi 64-bit openfiledialog

我有以下代码,我用来使用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)。我将其更改为默认值并且神奇地工作了。请查看下面的答案及其评论以获取更多信息。

5 个答案:

答案 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以获取错误代码。除此之外,我将使用

将结构的所有成员初始化为0
ZeroMemory(&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

http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel._application.getopenfilename.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