0

プロジェクトにファイル選択ダイアログボックスを追加しようとしていますが、これはユーザーがファイル名を入力するだけです。C++ win32 console app Windows APIを使用してファイルを選択ダイアログボックスを追加する

私はいくつかの検索を行い、GetOpenFileName関数を使用したWindows APIがこれを行う最も簡単な方法だと思われます。しかし、私が&をコピーしてMSDNか他のウェブサイトからのサンプルコードを貼り付けると、ビルドエラーが発生します。

私は、Visual Studio 2017を使用していますが、私が使用したコード例はhttp://www.cplusplus.com/forum/windows/169960/からです:

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 

はしてみました:

#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"; 
    } 
    } 
} 

私が対に&ペーストをコピーし、それは以下を示しそれを検索しても私の運が見つかりませんでした:(

+0

ビルドのデフォルトはワイド文字列ですが、MBCS文字列を使用しています。 Windows APIを呼び出すときにワイド文字列を使用するようにコードを変更するか、プロジェクトの設定を変更することができます(プロジェクトプロパティ - >一般 - >文字セット - >複数バイト文字セットを使用する)。 –

+0

ここで取得したコード例では、MBCSのバージョン(GetOpenFileNameAなど)を明示的に呼び出していますが、一貫して実行していません(たとえば、OPENFILENAMEがOPENFILENAMEEWではなくOPENFILENAMEWにデフォルト設定されています)。現代のWindowsプログラムでは、ワイド文字列のAPIを使用することをお勧めします。 MBCSの機能は主に下位互換性のためであり、制限があります。 –

+0

Cool。実際に私はその設定を試みましたが、別の例を試してみたところ、Lolは動作しませんでした。 –

答えて

1

マイクロソフトが主張する方法は、一般的なテキストマクロを使用することです。リングリテラルは次のようになります。

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"; 
    } 
    } 
} 

だけGetOpenFilenameGetSaveFilenameに変更し、代わりに "保存" のファイル名を取得します。あなたがOPENFILENAMEで渡す可能性が高いフラグにはいくつかの違いがあります。たとえば、ファイルを開くときにはOFN_FILEMUSTEXISTを渡すのが一般的ですが、ファイルを保存しているときはほとんど望めません。

+0

ファイルダイアログを保存するには、 "OPENFILENAME"のような簡単な方法がありますか? –

+0

@XiaofengFan:[GetSaveFilename](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646928.aspx) –

+0

勉強できる例はありますか?私はMSDNからのそのドキュメントをチェックしたが、与えられた例は他のものの一部のようであった。だから私は与えられた例を理解できませんでした(この段階で)。実際にGetSaveFileNameを使用している実行可能な例がありがたいです。 –

関連する問題