#pragma twice

KAB-studio > プログラミング > #pragma twice > 095 Version 5.30 ファイルダイアログを使おう!

#pragma twice 095 Version 5.30 ファイルダイアログを使おう!

前のページへ 表紙・目次へ 次のページへ

 Version 5.30
ファイルダイアログを使おう!

コントロール編も終わったし、次はなに?
まず今回はファイルダイアログっていうの。復習も兼ねて……

void CFileTestDlg::OnBtnShow() 
{
    m_cDataLstBox.ResetContent();

    std::ifstream cIFStrm;
    cIFStrm.open( "Data.txt" );
    if( cIFStrm.fail() )
    {
        MessageError( IDS_E_NOFILE );
        return;
    }

    int i;
    CString cDestStr;
    while( 1 )
    {
        cIFStrm
            >> i;
        if( cIFStrm.eof() )
        {
            break;
        }

        if( cIFStrm.fail() )
        {
            MessageError( IDS_E_NONINT );
            return;
        }
        cDestStr.Format( "%d", i );
        m_cDataLstBox.AddString( cDestStr );
    }
}

bool CFileTestDlg::MessageError(unsigned int p_puiID)
{
    const unsigned int iIDOffset = 1000;
    CString cStr;
    cStr.LoadString( p_puiID );
    CString cStrCap;
    cStrCap.LoadString( p_puiID + iIDOffset );
    MessageBox
        ( cStr, cStrCap
        , MB_OK | MB_ICONEXCLAMATION );
    return true;
}

表示ボタンを押したときのメンバ関数と、エラー表示用のメンバ関数だね
この中でファイル名を "Data.txt" って書き込んでるでしょ。でもホント
は使う側が自由に変えられるようにするから
それを選ぶんでファイルダイアログなんだ!
そう、【参照】ボタンを押したらファイルダイアログが出て、それで選ん
だファイルが【ファイル】コンボボックスに書き込まれるようにします
……聞いてるだけだとなんか難しそうなんだけど
簡単簡単! まずは【参照】ボタンのハンドラ関数作って
メンバ関数のことだよね。右クリックで……
詳しくは Ver 4.01 ( No.051 )を参照にね
そんなの見なくてもできるもん。 CFileTestDlg::OnBtnBrowse() ができ
たよ
ファイルダイアログは MFC だと CFileDialog を使えば表示できます。と
りあえず使ってみましょう

void CFileTestDlg::OnBtnBrowse() 
{
    CFileDialog cFileDlg( TRUE );
    int iRes
        = cFileDlg.DoModal();
    if( iRes == IDCANCEL )
    {
        return;
    }

    CString cPathStr = cFileDlg.GetPathName();
    TRACE( "%s\n", cPathStr );
}

んじゃビルドして実行……おおっ、ファイルダイアログが出た! ホント
に簡単ねー
とりあえず何かファイル選んでみて【開く】押してみて
ほい。あ、そのファイルのが出た

C:\WINDOWS\1stboot.bmp

おお!
じゃ、1行ずつ見ていこうか。まずは CFileDialog 型の変数を作ります
コンストラクタっていう関数呼んで、 TRUE 渡してるんだよね
この TRUE は【開く】ダイアログにするフラグ。これを FALSE にすると
ダイアログのタイトルが【名前を付けて保存】になった! つまり、開く
ダイアログも保存ダイアログも同じってこと?
そゆこと。これが TRUE か FALSE かってことだけで決まるから
簡単って言えば簡単ね。次の DoModal() ってどっかで見たことあるね
 DoModal() はダイアログを実際に表示させるメンバ関数。 FileTest.cpp
で〈てすと〉ダイアログを表示するとこでも呼んでるよ

    int nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO: ダイアログが <OK> で消された時のコードを
        //       記述してください。
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: ダイアログが <キャンセル> で消された時のコードを
        //       記述してください。
    }

そうそうそう! これ呼ばないとダイアログ出ないんだよね。で、その戻
り値で【OK】ボタンか【キャンセル】ボタンかって分かるんだよね。あ、
ファイルダイアログの方も同じことしてるんだ!
そう、 DoModal() の戻り値が IDOK なら【開く】ボタンが、 IDCANCEL
なら【キャンセル】ボタンが押されたってこと
ファイルダイアログの方は IDCANCEL だとすぐ終わらせるってふうにして
るんだね。〈てすと〉ダイアログのと、っつーか MFC のとスタイル違う
僕はこっちの方が見やすいと思うんだよね。 IDCANCEL の場合には特にす
ることないからとっとと return させて、 IDOK の方が大事だからそっちを
普通に書くってスタイル
あんま変わらないと思うけど……
これは if が1重だからね。何度も何度もチェックするようになると、ネ
ストがどんどん深くなって
タブが増えて右の方に来ちゃうね。それは見にくそう
ま、今回くらいならそんなに変わらないけどね
で、 IDCANCEL じゃないなら CFileDialog::GetPathName() を呼んで……
これはファイル名返すメンバ関数なんだね
ドライブからファイル名まで全部ね。こういうのを〈フルパス〉って言い
ます
ふるぱす?
さっきの例だと 1stboot.bmp はファイル名、 C:\WINDOWS\1stboot.bmp が
フルパス。フルパスはドライブも含めてのだから、ばっちりどこのどのファ
イルか言えるからね
そっか、 1stboot.bmp だけだと、同じ名前のファイルがいろんなフォル
ダにあったらどれか分かんなくなっちゃうんだもんね
そゆこと。そのフルパスを CString で受け取って、 TRACE() で表示
うん、実際に簡単ねー
じゃ、もちっと凝ってみようか。開いたフォルダってどこだった?
なんか自動的にマイドキュメントになってたけど
それを指定しましょう

void CFileTestDlg::OnBtnBrowse() 
{
    CFileDialog cFileDlg( TRUE );
    cFileDlg.m_ofn.lpstrInitialDir = "C:\\Windows\\";
// あとは同じ。

うわ簡単! m_ofn ってメンバ変数の……
の、 lpstrInitialDir ってメンバ変数に〈最初に表示するフォルダのパ
スを示す文字列ポインタ〉を格納すればいいってこと
こういうメンバ変数のメンバ変数ってなんか苦手……
左から順々に見ていけば大丈夫だよ。で、この m_ofn っていうのが鍵
リファレンス見ると OPENFILENAME っていうのなんだね
そう。いつものことなんだけど、ファイルダイアログの表示にはホントは
API を使います
それを MFC が便利に使いやすくしてるって例のパターンね
そ、【開く】ダイアログは GetOpenFileName() 、【保存】ダイアログは
GetSaveFileName() を呼び出します
 CFileDialog と違って別々なんだ
で、これを呼び出すときに、いろんな設定を渡すのが OPENFILENAME 
なんかすんごくメンバ変数多いんですけど……
これ、省略できないからほとんど全部設定しないと渡せないしね
げげ
で、その中の lpstrInitialDir っていうので開くフォルダを指定します
ようするに CFileDialog もこれと同じ仕組み持ってるからこれを使えば
色々できるってことね
そゆこと。最初の例みたく簡単に使うこともできるし、こういうふうに
ちょっと拡張させることもできるし
いつもみたく、この API 使ってみせたりしないの?
これまでしつこく言ってきたのは、 MFC が API をただ呼び出してるだけ
ってことを憶えて欲しかったから
それが分かっちゃえばいいの?
とりあえずね。もう少ししたら、こういう API 呼ぶのに難しい部分を教
えたりするから。さて、実際にこの最初のフォルダってどこにすればいいと
思う?
前回開いたフォルダ!
うん、そう。でもそれは〈レジストリ〉っていうのを使ってその〈前回開
いたフォルダ〉を保存しなきゃいけないから
知ってる! WriteProfileInt() とか使うんだよね
 Ver 3.19 ( No.044 ) でやったね。そのレジストリへの書き込みはもう
ちょっとあと
じゃーどのフォルダ開けばいいのかな……とりあえずそのアプリとか?
じゃ、それしてみましょう

void CFileTestDlg::OnBtnBrowse() 
{
    CFileDialog cFileDlg( TRUE );
    char chPath[MAX_PATH];
    GetModuleFileName
        ( AfxGetInstanceHandle(), chPath, MAX_PATH - 1 );
    cFileDlg.m_ofn.lpstrInitialDir = chPath;
// あとはそのまま。

えっと、まず文字配列作ってるね。 MAX_PATH ってなに?
 API で定義されてる定数値。実は、ファイルのフルパスって、この 
MAX_PATH よりも大きい文字列って使えないんです
ってことは、そんだけ深いフォルダとか、長いファイル名とかは
ダメってこと。なんで、この MAX_PATH で文字配列作るとファイルのフル
パスは絶対入るっていう
それは安心。次の GetModuleFileName() は API だね
これは今実行されてるアプリのフルパスを取得する関数
あ、そうすると FileTest.exe のフルパスが分かるんだ
それが第2引数に渡されるから、それを lpstrInitialDir に渡せばOK
なるほどねん
あ、でも〈初めて開くフォルダ〉はアプリのとこにしない方がいいかも
じゃあどこ?
マイドキュメント
なにぃ!?

/*
    Preview Next Story!
*/
まいどきゅめんとぉ!? あたしあのフォルダ嫌いなんだけど
でもプログラミング初心者がアプリのフォルダ見て理解できると思う?
う”
マイドキュメントなら保存するときファイルが散らばらなくて済むし
というわけで次回
< Version 5.31 コンボボックスとエディットボックス >
につづく!
うがーっ初心者ってムカツク!!
僕も本当は嫌だけど、フォルダ作ったことない人は山ほどいるんだから
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。