#pragma twice

KAB-studio > プログラミング > #pragma twice > 299 Version 14.32 スレッドからダイアログに表示する、の続き

#pragma twice 299 Version 14.32 スレッドからダイアログに表示する、の続き

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

 Version 14.32
スレッドからダイアログに表示する、の続き

前回はソースコードだけでした
あれだけで、しかもまだ書いちゃダメってゆーし……
うん、エディットボックスとか用意してなかったから
え、ダイアログの方になんかしなきゃいけないの?
結果とか検索中のフォルダとか表示するでしょ
そういえば……
というわけで、まずはダイアログにコントロールを追加します。
【ファイル検索】ダイアログ、つまり IDD_SEARCHDLG_DIALOG を開いて
ダイアログエディタでだよね
もちろん。そこにエディットボックスを貼り付けて、 ID は
【IDC_E_MATCH_NUM】、スタイルの【境界線】をオフ、【読み取り専用】を
オンにして
? これってなんの意味があるの?
やってみるとわかるけど、見た目がスタティックコントロールみたいにな
るでしょ
ほんとだ、文字だけみたい
でもエディットボックスだから、文字列をセットできるんです
なるほど、見た目はスタティックコントロールだけど、使い勝手は
エディットボックス、みたいな?
そういうこと。ここには検索結果、つまり一致した数をセットします
ほい
というわけで、 ClassWizard でこのエディットボックスの変数を作って
うわ、懐かしい作業を……メニューの【表示】−【ClassWizard】で、
【メンバ変数】のページで IDC_E_MATCH_NUM を選んで【変数の追加】っと
変数名は m_cMatchNumStr 、あとはそのまま【値】の【CString】で
ほいほい
次に、【検索中】ダイアログに【今検索しているフォルダ】を表示する欄
を作ります。【検索中】ダイアログ開いて
ほい
同じようにエディットボックスを貼り付けて、 ID は IDC_E_FOLDER 、
スタイルはさっきと同じ
ん、スタティックコントロールみたくなった
ただ、こっちは変数は作りません
え、どうして?
これはソースコードの説明の時に。それと、このダイアログの 
WM_INITDIALOG のイベントハンドラを作って
ダイアログが表示するときに送られるメッセージだね。メニューの
【表示】−【ClassWizard】開いて、【MFC ClassWizard】ダイアログの
【メッセージマップ】のとこで……
【オブジェクト ID】を【CSearchingDlg】にして、右の【メッセージ】で
【WM_INITDIALOG】を選んだら【関数の追加】押して【コード編集】
ん、 CSearchingDlg::OnInitDialog() できた
ここの段階で、 SearchingDlg.cpp には CSearchingDlg::OnCancel() と 
CSearchingDlg::OnInitDialog() のふたつのイベントハンドラが作られたこ
とになってると思います
うんなってる
この状態で前回のソースを見返してみて。 SearchDlgDlg.cpp のソースに
このふたつの関数があるでしょ
あ、ほんとだ
このふたつの関数の上に StartCountMatchFile() と CountMatchFile() 、
その他諸々を入れる、っていう形にしてください
それにしても長い……
って言っても、基本的にはこの前の検索と変わらないけどね。追加した機
能ひとつひとつ見ていこうか

・検索対象フォルダの表示

これはさっきの IDC_E_FOLDER に表示するんだね
そう。さっき説明したように、変数を使わず、直接ウィンドウハンドルを
使ってセットします。まず、そのための変数を用意します

// エディットボックスのウィンドウハンドル。
HWND g_hEditFolderWnd = NULL;

次に、ダイアログの表示時に IDC_E_FOLDER のウィンドウハンドルをセッ
トします

BOOL CSearchingDlg::OnInitDialog() 
{
// 略...
    // エディットボックスのウィンドウハンドルをセットします。
    g_hEditFolderWnd = ::GetDlgItem( GetSafeHwnd(), IDC_E_FOLDER );
// 略...
}

 Version 5.26 ( No.091 ) で説明した方法で取得します
本当に API つかって直接セットしてるんだね
セットするのも API を使います

int CountMatchFile
    ( const char * const p_pchFolderPath
    , const char * const p_pchFileName 
    )
{
// 略...
    // フォルダが存在するのでウィンドウタイトルをセットします。
    if( ::IsWindow( g_hEditFolderWnd ) )
    {
        // ウィンドウが存在するので表示します。
        ::SetWindowText( g_hEditFolderWnd, p_pchFolderPath );
    }
// 略...
}

? IsWindow() って?
これはウィンドウが存在してるかどうかチェックする API 。
CountMatchFile() って別スレッドで動いてるから、いつの間にかダイアログ
がなくなってる可能性があるから
げ、そういうのもチェックしなきゃいけないんだ……
 SetWindowText() はエディットボックスに文字列をセットする API 
さっきの Version 5.26 ( No.091 ) にも出てたのだね
具体例なら Version 5.27 ( No.092 ) の方がいいかな
で、なんで変数使ってセットしないの?
変数を使ってセットする方法だと、 MFC を使うことになります
そなの?
 CWnd::UpdateData() とか使うでしょ
そういえば、あれとかって API にはないよね……
結局が MFC が SetWindowText() とかしてるんだけどね。変数とか使って
分かりやすくしてるだけ。で、実は MFC は、マルチスレッドが苦手なんで

あ、そういえば前にそう言ってたね
 MFC の、特にウィンドウ関係はマルチスレッドを逆に複雑に使っている
から、別スレッドからの操作がうまくできないんです
げ……だから直接 API で?
そういうこと。次に説明する

・検索終了時にキャンセルダイアログを閉じる機能

も、同じように MFC の問題があるんです
げ”
基本的に、方法は同じ。ダイアログが作られるときにウィンドウハンドル
を取っておいて、検索が終わったらそれを使ってダイアログを閉じるだけ。
まずは取っておく変数

// ダイアログのウィンドウハンドル。
HWND g_hSearchingDlgWnd = NULL;

ここに、ダイアログが表示されるときにセットします

BOOL CSearchingDlg::OnInitDialog() 
{
// 略...
    // ダイアログのウィンドウハンドルをセットします。
    g_hSearchingDlgWnd = GetSafeHwnd();
// 略...
}

そして、検索終了時にこれを使ってダイアログを閉じます

void StartCountMatchFile( void *p_p )
{
// 略...
    // ダイアログを閉じます。
    if( ::IsWindow( g_hSearchingDlgWnd ) )
    {
        // ウィンドウが存在するので閉じます。
        ::SendMessage
            ( g_hSearchingDlgWnd
            , WM_COMMAND
            , MAKEWPARAM( IDCANCEL, 0 )
            , 0
            );
    }
}

あれ? ダイアログ閉じるのって EndDialog() じゃなかったっけ
 Version 8.09 ( No.151 ) でそう教えたけど、ここではダメ
これも MFC の関係?
そういうこと。 EndDialog() だと API で直接ダイアログ閉じちゃうか
ら。そうじゃなく、 MFC を通してダイアログを閉じてもらう必要があるん
です
それがこの SendMessage() ? えっと、 WM_COMMAND って……そっか、
ボタン押したとき、ってメッセージ送ってるんだ
そういうこと。これも Version 8.09 ( No.151 ) で説明したね。あの時
は受け取る時だったけど、今回は送る場合
こうやって送ると…… IDCANCEL ボタンが押されたってなるんだ
そういうこと。そうすれば MFC の方、つまり CSearchingDlg クラスで処
理してくれるから大丈夫
……って、それってかなり難しいかも……知らなきゃわかんないよ
僕も知らなかったよ
え”?
試してうまくいかなかったから調べただけ……こういうところもマルチ
スレッドの難しいところかも
ううう……
最後に

・検索結果の表示

これは前回と同じような感じ

// 一致数。
int g_iMatchNum = 0;
// 一致数を取得します。
int GetMatchNum()
{
    return g_iMatchNum;
}

という形で変数と関数を用意して

// SearchDlgDlg.h
// 略...
int GetMatchNum();

というふうにして呼べるようにして

// SearchDlgDlg.cpp
// 略 ...
void CSearchDlgDlg::OnSearchStart() 
{
    // 【検索中】ダイアログを表示します。
    CSearchingDlg cDlg;
    cDlg.DoModal();
    // 結果を出力します。
    m_cMatchNumStr.Format( "%d", GetMatchNum() );
    UpdateData( FALSE );
}

ここで出力
 CString::Format() 使って文字列に変換して、あ、 m_cMatchNumStr が
さっき変数作った IDC_E_MATCH_NUM だね
これでダイアログに一致結果が表示されるから

/*
    Preview Next Story!
*/
次回はマルチスレッド編最終回!
長かった……って感じもしないかな
マルチスレッドだけ見ると少ないからね
そういえば前半は同期オブジェクトだった……
というわけで次回
< Version 14.33 マルチスレッドのまとめ >
につづく!
もちろん  Version 15 の話や、さらにその先の話も!
つかいつまで続くのー! もう6年だよー!!
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。