GetOpenFileName не работает в 64-битной, но работает в 32-битной? - PullRequest
4 голосов
/ 13 февраля 2011

У меня есть следующий код, который я использую, чтобы открыть диалог открытия файла с помощью 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 байт.

ОБНОВЛЕНИЕ: В моих настройках проекта в разделе «Генерация кода» «Выравнивание элементов Struct» установлено на 4 байта (/ Zp4). Я изменил это на дефолт, и это волшебным образом сработало. Ищите ответы и их комментарии ниже для получения дополнительной информации.

Ответы [ 5 ]

5 голосов
/ 13 февраля 2011

Вы не инициализируете 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, поскольку вы не включали его в первую очередь!

EDIT

Вы заявляете в комментарии, что это не работает. Звонить по номеру CommDlgExtendedError - это хорошая идея, и она должна сказать вам, почему она не работает.

Вы также можете попытаться запустить минимально возможную GetOpenFileName, а именно:

char Filestring[MAX_PATH] = "\0";
OPENFILENAME opf={0};
opf.lStructSize = sizeof(OPENFILENAME);
opf.lpstrFile = Filestring;
opf.nMaxFile = MAX_PATH;
GetOpenFileName(&opf);
3 голосов
/ 24 февраля 2011

У меня та же проблема и частичное решение: + простой следующий простой пример (предложенный abobe) не работал в режиме x64.+ Я изменил опцию complie "struct Alignment" с 1byte / Zp1 на default, что решило эту проблему (путем введения других !!!)

char Filestring [MAX_PATH] = "\ 0";OPENFILENAME opf = {0};opf.lStructSize = sizeof (OPENFILENAME);opf.lpstrFile = Filestring;opf.nMaxFile = MAX_PATH;GetOpenFileName (& БКП);

2 голосов
/ 13 февраля 2011

Чтобы узнать больше, вы должны позвонить CommDlgExtendedError , чтобы получить код ошибки, что пошло не так.Помимо этого, я бы инициализировал все члены структуры в 0 с помощью

ZeroMemory(&opf, sizeof(opf));

Поскольку диалог открытия файла в действительности является COM-компонентом, возможно, стоит проверить, отличается ли ваше состояние квартиры потока под 64-битным,

if( RPC_E_CHANGED_MODE == CoInitialize(NULL) )
   ASSERT(FALSE); // MTA Apartment found
CoUnitialize()

Ваш, Алоис Краус

1 голос
/ 01 декабря 2014

Мне удалось обойти эту проблему, правильно настроив упаковку перед тем, как включить файл заголовка.Таким образом, для этой единственной функции мы использовали 16-байтовое выравнивание по умолчанию, но не нужно было изменять выравнивание упаковки для остальной части нашей программы:

#ifdef _WIN64
  #pragma pack( push )
  #pragma pack( 16 ) 
  #include "Commdlg.h"
  #pragma pack( pop )
#else
  #include "Commdlg.h"
#endif   // _WIN64
1 голос
/ 03 августа 2011

В качестве примечания в Microsoft Office 2010 64-bit мы отказались и использовали внутренние оболочки, поскольку структура превратилась в 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 должны начать рассматривать другие варианты, так как поддержка будущих версий для нескольких клиентов и платформ может быть просто ... безумной!

...