пользовательский интерфейс — консольное приложение c ++ win32, добавляющее & quot; выберите файл & quot; диалоговое окно с использованием Windows API

Я пытаюсь добавить в проект диалоговое окно выбора файла, которое теперь может принимать только имя файла, введенное пользователем.

Я провел некоторый поиск, и кажется, что Windows API с функцией GetOpenFileName — самый простой способ сделать это. Тем не менее, когда я копирую&Вставьте пример кода, будь то с MSDN или других сайтов, я получил некоторые ошибки сборки.

Я использую Visual Studio 2017. И пример кода, который я использовал, взят из http://www.cplusplus.com/forum/windows/169960/:

#include <iostream>

#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>

int main()
{
char filename[ MAX_PATH ];

OPENFILENAME ofn;
ZeroMemory( &filename, sizeof( filename ) );
ZeroMemory( &ofn,      sizeof( ofn ) );
ofn.lStructSize  = sizeof( ofn );
ofn.hwndOwner    = NULL;  // If you have a window to center over, put its HANDLE here
ofn.lpstrFilter  = "Text Files\0*.txt\0Any File\0*.*\0";
ofn.lpstrFile    = filename;
ofn.nMaxFile     = MAX_PATH;
ofn.lpstrTitle   = "Select a File, yo!";
ofn.Flags        = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;

if (GetOpenFileNameA( &ofn ))
{
std::cout << "You chose the file \"" << filename << "\"\n";
}
else
{
// All this stuff below is to tell you exactly how you messed up above.
// Once you've got that fixed, you can often (not always!) reduce it to a 'user cancelled' assumption.
switch (CommDlgExtendedError())
{
case CDERR_DIALOGFAILURE   : std::cout << "CDERR_DIALOGFAILURE\n";   break;
case CDERR_FINDRESFAILURE  : std::cout << "CDERR_FINDRESFAILURE\n";  break;
case CDERR_INITIALIZATION  : std::cout << "CDERR_INITIALIZATION\n";  break;
case CDERR_LOADRESFAILURE  : std::cout << "CDERR_LOADRESFAILURE\n";  break;
case CDERR_LOADSTRFAILURE  : std::cout << "CDERR_LOADSTRFAILURE\n";  break;
case CDERR_LOCKRESFAILURE  : std::cout << "CDERR_LOCKRESFAILURE\n";  break;
case CDERR_MEMALLOCFAILURE : std::cout << "CDERR_MEMALLOCFAILURE\n"; break;
case CDERR_MEMLOCKFAILURE  : std::cout << "CDERR_MEMLOCKFAILURE\n";  break;
case CDERR_NOHINSTANCE     : std::cout << "CDERR_NOHINSTANCE\n";     break;
case CDERR_NOHOOK          : std::cout << "CDERR_NOHOOK\n";          break;
case CDERR_NOTEMPLATE      : std::cout << "CDERR_NOTEMPLATE\n";      break;
case CDERR_STRUCTSIZE      : std::cout << "CDERR_STRUCTSIZE\n";      break;
case FNERR_BUFFERTOOSMALL  : std::cout << "FNERR_BUFFERTOOSMALL\n";  break;
case FNERR_INVALIDFILENAME : std::cout << "FNERR_INVALIDFILENAME\n"; break;
case FNERR_SUBCLASSFAILURE : std::cout << "FNERR_SUBCLASSFAILURE\n"; break;
default                    : std::cout << "You cancelled.\n";
}
}
}

Когда я копирую&вставить против, он показывает следующее:

Severity    Code    Description Project File    Line    Suppression State
Error   C2440   '=': cannot convert from 'char [260]' to 'LPWSTR'   ConsoleApplication1 c:\users\xfan0\documents\visual studio 2017\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp    18
Severity    Code    Description Project File    Line    Suppression State
Error   C2440   '=': cannot convert from 'const char [19]' to 'LPCWSTR' ConsoleApplication1 c:\users\xfan0\documents\visual studio 2017\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp    20
Severity    Code    Description Project File    Line    Suppression State
Error   C2664   'BOOL GetOpenFileNameA(LPOPENFILENAMEA)': cannot convert argument 1 from 'OPENFILENAME *' to 'LPOPENFILENAMEA'  ConsoleApplication1 c:\users\xfan0\documents\visual studio 2017\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp    23

Severity    Code    Description Project File    Line    Suppression State
Error (active)  E0167   argument of type "OPENFILENAME *" is incompatible with parameter of type "LPOPENFILENAMEA"  ConsoleApplication1 c:\Users\XFAN0\Documents\Visual Studio 2017\Projects\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cpp    23

Пытался найти это, но мне не повезло 🙁

0

Решение

Microsoft обычно рекомендует использовать их макросы «общего текста», чтобы ваши строковые литералы выглядели так:

ofn.lpstrFilter = _T("Text Files\0*.txt\0Any File\0*.*\0");
ofn.lpstrTitle = _T("Select a File, yo!");

Таким образом, вы можете создавать узкие или широкие символьные строки (последние, определяя UNICODE а также _UNICODE). _T будет отображаться в ничто для узкосимвольной сборки и L для построения широких символов, так что вы автоматически получаете правильный тип строки для того, как вы строите.

Чтобы использовать это, вы включаете <tchar.h>,

Например:

#include <iostream>
#include <tchar.h>

#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>

int main()
{
char filename[ MAX_PATH ];

OPENFILENAME ofn;
ZeroMemory( &filename, sizeof( filename ) );
ZeroMemory( &ofn,      sizeof( ofn ) );
ofn.lStructSize  = sizeof( ofn );
ofn.hwndOwner    = NULL;  // If you have a window to center over, put its HANDLE here
ofn.lpstrFilter  = _T("Text Files\0*.txt\0Any File\0*.*\0");
ofn.lpstrFile    = filename;
ofn.nMaxFile     = MAX_PATH;
ofn.lpstrTitle   = _T("Select a File, yo!");
ofn.Flags        = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;

if (GetOpenFileName( &ofn ))
{
std::cout << "You chose the file \"" << filename << "\"\n";
}
else
{
// All this stuff below is to tell you exactly how you messed up above.
// Once you've got that fixed, you can often (not always!) reduce it to a 'user cancelled' assumption.
switch (CommDlgExtendedError())
{
case CDERR_DIALOGFAILURE   : std::cout << "CDERR_DIALOGFAILURE\n";   break;
case CDERR_FINDRESFAILURE  : std::cout << "CDERR_FINDRESFAILURE\n";  break;
case CDERR_INITIALIZATION  : std::cout << "CDERR_INITIALIZATION\n";  break;
case CDERR_LOADRESFAILURE  : std::cout << "CDERR_LOADRESFAILURE\n";  break;
case CDERR_LOADSTRFAILURE  : std::cout << "CDERR_LOADSTRFAILURE\n";  break;
case CDERR_LOCKRESFAILURE  : std::cout << "CDERR_LOCKRESFAILURE\n";  break;
case CDERR_MEMALLOCFAILURE : std::cout << "CDERR_MEMALLOCFAILURE\n"; break;
case CDERR_MEMLOCKFAILURE  : std::cout << "CDERR_MEMLOCKFAILURE\n";  break;
case CDERR_NOHINSTANCE     : std::cout << "CDERR_NOHINSTANCE\n";     break;
case CDERR_NOHOOK          : std::cout << "CDERR_NOHOOK\n";          break;
case CDERR_NOTEMPLATE      : std::cout << "CDERR_NOTEMPLATE\n";      break;
case CDERR_STRUCTSIZE      : std::cout << "CDERR_STRUCTSIZE\n";      break;
case FNERR_BUFFERTOOSMALL  : std::cout << "FNERR_BUFFERTOOSMALL\n";  break;
case FNERR_INVALIDFILENAME : std::cout << "FNERR_INVALIDFILENAME\n"; break;
case FNERR_SUBCLASSFAILURE : std::cout << "FNERR_SUBCLASSFAILURE\n"; break;
default                    : std::cout << "You cancelled.\n";
}
}
}

Чтобы получить «сохранить» имя файла, просто измените GetOpenFilename в GetSaveFilename, Есть несколько различий в флагах, которые вы, вероятно, передаете в OPENFILENAME — например, это довольно распространенная передача OFN_FILEMUSTEXIST когда вы открываете файл, но вы почти никогда не хотите, когда вы сохраняете файл.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]