質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.47%

  • C++

    4526questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    297questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

GetOpenFileNameの実行が変

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,053

BeatStar

score 1366

C/C++ ( Windows API実装 ) でやっています。

今までは 書籍についていたコンパイラ MinGW でやっていました。

今は Dialog.dll という自分用のダイアログを表示したりするDLLを作成しようとしています。

書籍についていたコンパイラから 比較的最新の MinGW ( minimalでない方 ) を 使ってコンパイルしたからなのか、

GetOpenFileName関数がうまくいきません。

DLLの方ではなく、実行ファイルの方にやっても同じでした。

GUIのひな形(?) に

// GetOpenFileName関数を使って "ファイルを開く"ダイアログ を表示し、ファイルパス取得する。
/*
          HWND hWnd             := 親ウィンドウハンドル
          int  DefaultIndex     := 初期のインデックス
    const char *DefaultDir      := 初期ディレクトリ
    const char *DefaultFileName := 初期ファイル名
          char *result          := 戻り値。ファイルパスが格納される。
*/
int ShowOpenFile( HWND hWnd, int DefaultIndex, const char *DefaultDir, const char *DefaultFileName, char *result ){
     OPENFILENAME ofn;

     string filter;

     char temp[MAX_PATH+1];

     int tempIndex;

     if( DefaultIndex <= 0 ){
         tempIndex = OF_INDEX_ALL;
     }else{
            tempIndex = DefaultIndex;
     }

     // これをやらないと失敗する
     memset( &ofn, 0, sizeof(OPENFILENAME) );


     ofn.lpstrFilter = TEXT("画像ファイル (*.gif, *.jpg, *.jpeg, *.png, *.bmp)\0*.gif;*.jpg;*.jpeg;*.png;*.bmp\0")
                      // 中略
                       TEXT("BATファイル (*.bat)\0*.bat\0")
                       TEXT("PHPファイル (*.php)\0*.php\0")
                       TEXT("PYファイル (*.py)\0*.py\0")
                       TEXT("コンパイル済みPythonファイル (*.py)\0.pyc\0")
                       TEXT("RBファイル (*.rb)\0*.rb\0")
                       TEXT("RERLファイル (*.pl)\0*.pl\0")
                       TEXT("Cファイル (*.c)\0*.c\0")
                       TEXT("CCファイル (*.cc)\0*.cc\0")
                       TEXT("CPPファイル (*.cpp)\0*.cpp\0")
                       TEXT("Oファイル (*.o)\0*.o\0")
                       TEXT("OBJファイル (*.obj)\0*.obj\0")
                       TEXT("LIBファイル (*.lib)\0*.lib\0")
                       TEXT("ヘッダファイル (*.h,*.hpp)\0*.h;*.hpp\0")

                       // 圧縮ファイル関係
                       TEXT("ZIPファイル (*.zip)\0*.zip\0")
                       TEXT("RARファイル (*.rar)\0*.rar\0")
                       TEXT("LZHファイル (*.lzh)\0*.lzh\0")
                       TEXT("ISOファイル (*.iso)\0*.iso\0")

                       // OFFICE製品
                       TEXT("DOCファイル (*.doc)\0*.doc\0")
                       TEXT("DOCXファイル (*.docx)\0*.docx\0")
                       TEXT("XLSファイル (*.xls)\0*.xls\0")
                       TEXT("XLSXファイル (*.xlsx)\0*.xlsx\0")
                       TEXT("PPTファイル (*.ppt)\0*.ppt\0")
                       TEXT("PPTXファイル (*.pptx)\0*.pptx\0")

                       // リソースファイル
                       TEXT("ANIファイル (*.ani)\0*.ani\0")
                       TEXT("CURファイル (*.cur)\0*.cur\0")
                       TEXT("ICOファイル (*.ico)\0*.ico\0")
                       TEXT("TTFファイル (*.ttf)\0*.ttf\0")
                       TEXT("OTFファイル (*.otf)\0*.otf\0")

                       // リソースファイル
                       TEXT("ショートカットファイル (*.lnk)\0*.lnk\0")
                       TEXT("インターネットショートカットファイル (*.url)\0*.url\0")

                       // すべてのファイル
                       TEXT("全てのファイル(*.*)\0*.*\0\0");


     ofn.lStructSize = sizeof(OPENFILENAME);
     ofn.hwndOwner = hWnd;
     ofn.nFilterIndex = tempIndex; // 最初に指定するインデックス
     ofn.lpstrInitialDir = DefaultDir;
     ofn.lpstrFile = temp; // 戻り値用
     ofn.nMaxFile = MAX_PATH+1; // 戻り値の最大の長さ
     ofn.Flags = OFN_FILEMUSTEXIST; // フラグ

     if( GetOpenFileName( &ofn ) != 0 ){
            strcpy( result, temp );
            return 0;
     }else{
            DWORD r = CommDlgExtendedError();
            if( r == 0 ){
                        return -1; // "キャンセル"された
            }else if( r == CDERR_DIALOGFAILURE ){
                        return -2; // 無効なウィンドウハンドルが指定された等でダイアログ生成失敗
            }else if( r == CDERR_FINDRESFAILURE ){
                        return -3; // リソースが見つからなかった
            }else if( r == CDERR_INITIALIZATION ){
                        return -4; // メモリ不足等によりダイアログ初期化失敗
            }else if( r == CDERR_LOADRESFAILURE ){
                        return -5; // リソースのロード失敗
            }else if( r == CDERR_LOADSTRFAILURE ){
                        return -6; // 指定した文字列のロード失敗
            }else if( r == CDERR_LOCKRESFAILURE ){
                        return -7; // 指定したリソースのロック失敗
            }else if( r == CDERR_MEMALLOCFAILURE ){
                        return -8; // 内部の構造体用のメモリ割り当てに失敗
            }else if( r == CDERR_MEMLOCKFAILURE ){
                        return -9; // ハンドルに関連付けられているメモリをロック失敗
            }else if( r == CDERR_REGISTERMSGFAIL ){
                        return -10; // コモンダイアログボックス関数が呼び出した RegisterWindowMessage 関数が、エラーコードを返した
            }else if( r == CDERR_STRUCTSIZE ){
                        return -11; // 該当するコモンダイアログボックス用の初期化構造体の lStructSize メンバが無効
            }else if( r == FNERR_BUFFERTOOSMALL ){
                        return -12; // 構造体の lpstrFile メンバが指すバッファが小さすぎて、ユーザーが指定したファイル名を格納できない
                        // lpstrFile バッファの最初の 2 バイトは、名前全体を受け取るために必要なサイズを TCHAR 単位で格納します。
            }else if( r == FNERR_INVALIDFILENAME ){
                         return -13; // ファイル名が無効
            }else if( r == FNERR_SUBCLASSFAILURE ){
                         return -14; // メモリ不足のため、リストボックスのサブクラス化失敗
            }else{
                         return -15; // それ以外
            }
     }
}

// メッセージボックス表示
void MsgBox( const char *text ){
     MessageBox( NULL, text, "結果", MB_OK );
}


//自作 ShowOpenFile関数 に引数を与えて表示する
void ShowDialogEx( HWND hWnd ){
     char result[MAX_PATH+1];

     int r = ShowOpenFile( hWnd, -1, NULL, NULL, result );

     if( r == 0 ){
            MsgBox( result );
     }else{
            char str[20];

            sprintf( str, "error: %d", r );
            MsgBox( str );
     }
}

// ...

// ウィンドウプロシージャ内の WM_CREATE メッセージで
   ShowDialogEx( hWnd );

としたところ、

実行結果が

"error: -13"

というメッセージボックスが出ます。

( "開く"ダイアログは表示されない。 )

以前までのコンパイラなら普通にできたような気が...

なぜなのでしょうか。

回避方法が知りたいです。

[環境等]
言語: C/C++
コンパイラ: MinGW ( g++ (i686-posix-dwarf-rev1, Built by MinGW-W64 project) 6.2.0 )

宜しくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

OPENFILENAME構造体lpstrFileメンバに設定するバッファは、あらかじめ初期化しておく必要があります。質問コードの場合、temp配列を空文字列で初期化しておけばOKです。

char temp[MAX_PATH+1] = "";

以前までのコンパイラなら普通にできたような気が... 

おそらく、偶然動いていただけです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/02 14:27

    なるほど。
    試してみます。

    キャンセル

0

"error: -13"の-13は、ShowOpenFile関数の下記コードの部分に由来するものでしょうから、ファイル名に不正な文字列を与えたのだろうと思われます。

}else if( r == FNERR_INVALIDFILENAME ){
                         return -13; // ファイル名が無効

そこで気になるのが、ShowDialogEx関数のコードの中でShowOpenFileの第3引数と第4引数がNULLになっているところです。
これらは、*DefaultDir と *DefaultFileName ですから、NULLは無効なファイル名なのではないでしょうか?

int r = ShowOpenFile( hWnd, -1, NULL, NULL, result );

ご確認ください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C++

    4526questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    297questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。