第20章 リストボックス・その他の扱い方 その3


今回は、各段階のダイアローグプロシージャ内での 具体的処理方法について解説します。

まず、WM_INITDIALOGメッセージを捕まえたときの処理です。 ここでは、initDlgという自作の関数内でやっている処理に ついて解説します。

int initDlg(HWND hDlgWnd) { int i; SetWindowText(GetDlgItem(hDlgWnd, IDC_EDIT1), (LPCTSTR)edit_str); SetScrollRange(GetDlgItem(hDlgWnd, IDC_SCROLL1), SB_CTL, ScrMin, ScrMax, TRUE); ShowScroll(hDlgWnd); for ( i = 0; i <= 4; i++ ) SendMessage(GetDlgItem(hDlgWnd, IDC_LIST1), LB_INSERTSTRING, (WPARAM)i, (LPARAM)liststr[i]); SendMessage(GetDlgItem(hDlgWnd, IDC_LIST1), LB_SETCURSEL, (WPARAM)ListNo, 0L); for ( i = 0; i <= 3; i++ ) SendMessage(GetDlgItem(hDlgWnd, IDC_COMBO1), CB_INSERTSTRING, (WPARAM)i, (LPARAM)combostr[i]); SendMessage(GetDlgItem(hDlgWnd, IDC_COMBO1), CB_SETCURSEL, (WPARAM)ComboNo, 0L); return 0; }

この関数の中身をそのまま、ダイアローグプロシージャに書いても同じこと ですが、長ったらしくなるので関数にまとめただけです。 SetWindowText関数については第15章ではSetDlgItemText 関数を使いました。どちらを使っても結果は同じです。 エジットボックスに表示する文字列ですね。

次のSetScrollRange関数はスクロールバーの範囲です。

void SetScrollRange(hwnd, fnBar, nMin, nMax, fRedraw) HWND hwnd; /* スクロール バーを持つウィンドウのハンドル */ int fnBar; /* スクロール バー フラグ */ int nMin; /* スクロール位置の最小値 */ int nMax; /* スクロール位置の最大値 */ BOOL fRedraw; /* 再描画フラグ */

スクロールバーフラグは範囲を指定するときはSB_CTLにします。 再描画フラグは位置の変更を反映して再描画するかどうかを 指定します。普通は再描画をするのでTRUEですね。

次に自作関数のShowScrollを呼んでいます。(後で解説)

次におなじみのSendMessage関数を使ってリストボックスに 文字列を挿入しています。

SendMessage(LISTBOXのウィンドウハンドル, LB_INSERTSTRING, (WPARAM)何番目か, (LPARAM)文字列);

という感じで使います。ここでは2番目の引数をLB_INSERTSTRINGにしていますが LB_ADDSTRINGを使って

SendMessage(hwndCtl, LB_ADDSTRING, 0L, (LPARAM)文字列);

というようにも書けます。ただし気を付けることがあります。 このように書いた場合、リソースエジタで文字列の順番をソート するように指定(VC++4.Xの場合デフォルトではソートになっている) した場合、文字列の順番が勝手に変わってしまいます。(後でもう少し解説)

次に初期状態でリストボックスのどの文字列が選択された状態にするかを指定します。

SendMessage(hwndCtl, LB_SETCURSEL, (WPARAM)何番目か, 0L);

ここで、3番目の引数を見て下さい。これは現に表示されているリスト ボックスの上から何番目か(一番上が0)を指定します。 もし、LB_ADDSTRINGで文字列をリストボックスに加えて、なおかつ 文字列をソートする設定になっていると困ったことが起こります。 つまり、自分では2番目の文字列を指定したつもりが、ソートが起こり 2番目の文字列が意図したものと違うものになっている可能性があるからです。 言葉で説明するとわかりにくいのですが、実際に経験するとピンときます。

コンボボックスについても同じように初期設定を行います。

さて、次はOKボタンが押されて、ダイアログボックスに入力された 情報を収集する方法です。ここでは、getDlgという自作関数にまとめましたが ダイアログプローシージャに直接書いても同じです。

int getDlg(HWND hDlgWnd) { GetWindowText(GetDlgItem(hDlgWnd, IDC_EDIT1), edit_str, sizeof(edit_str)); ScrPos = GetScrollPos(GetDlgItem(hDlgWnd, IDC_SCROLL1), SB_CTL); ListNo = (int)(DWORD)SendMessage(GetDlgItem(hDlgWnd, IDC_LIST1), LB_GETCURSEL, 0L, 0L); ComboNo = (int)(DWORD)SendMessage(GetDlgItem(hDlgWnd, IDC_COMBO1), CB_GETCURSEL, 0L, 0L); return 0; }

最初のGetWindowTextは

int GetWindowText( HWND hWnd, // handle of window or control with text LPTSTR lpString, // address of buffer for text int nMaxCount // maximum number of characters to copy );

ということになっています。あれ? 以前にエジットボックスから文字列を 取得するにはGetDlgItemText関数を使わなかったかな・・

はい。その通りです。第15章では GetDlgItemText関数を使っています。このように、SDKのプログラムでは 同じことをするのに2種類以上の方法が用意されていることがよくあります。 この場合、

GetWindowText(GetDlgItem(hDlgWnd, IDC_EDIT1), edit_str, sizeof(edit_str)); GetDlgItemText(hDlgWnd, IDC_EDIT1, edit_str, sizeof(edit_str));

どちらで書いても同じ結果となります。

つぎに、選択されたリストボックスやコンボボックスの 番号の取得ですがやはり、SendMessage関数を使います。 例を見れば解説なしでも意味は分かりますね。

次は、自作のShowScroll関数です。

int ShowScroll(HWND hWnd) { if (ScrPos < ScrMin) ScrPos = ScrMin; if (ScrPos > ScrMax) ScrPos = ScrMax; SetScrollPos(GetDlgItem(hWnd, IDC_SCROLL1), SB_CTL, ScrPos, TRUE); ShowStatic(hWnd); return 0; }

この関数は、スクロールの位置をセットしてスタティクテキストに、 スクロールの位置を数値で表示させるものです。何時呼ばれているかというと スクロールバーがクリックされたときと、ダイアログボックスの初期化が 行われたときです。

int SetScrollPos( HWND hWnd, // スクロールバーのウィンドウハンドル int nBar, // スクロールバーフラグ int nPos, // スクロールつまみの位置 BOOL bRedraw // 再描画するかどうか );

この関数もあんまり説明はいらないですね。

次に、自作のShowStatic関数です。

int ShowStatic(HWND hWnd) { char str[8]; wsprintf(str, "%3d", ScrPos); SetWindowText(GetDlgItem(hWnd, IDC_STATIC1), (LPCTSTR)str); return 0; }

ここまで、読み進んでこられた方なら特に説明の必要はないですね。

次に、ウィンドウプロシージャでWM_PAINTメッセージを捕まえたときの ShowText関数(自作)です。

int ShowText(HWND hWnd) { HDC hdc; RECT rt; PAINTSTRUCT ps; char str[256]; char *str_org = "エジットボックス=%s\n" "リストボックス=%s\n" "コンボボックス=%s\n" "スクロールバー=%3d"; wsprintf(str, str_org, edit_str, liststr[ListNo], combostr[ComboNo], ScrPos); GetClientRect(hWnd, &rt); hdc = BeginPaint(hWnd, &ps); DrawText(hdc, str, -1, &rt, DT_WORDBREAK); EndPaint(hWnd, &ps); return 0; }

DrawText関連の解説はすでに、第5章で行っています。

int SetWinCenter(HWND hWnd) { HWND hDeskWnd; RECT deskrc, rc; int x, y; hDeskWnd = GetDesktopWindow(); GetWindowRect(hDeskWnd, (LPRECT)&deskrc); GetWindowRect(hWnd, (LPRECT)&rc); x = (deskrc.right - (rc.right-rc.left)) / 2; y = (deskrc.bottom - (rc.bottom-rc.top)) / 2; SetWindowPos(hWnd, HWND_TOP, x, y, (rc.right-rc.left), (rc.bottom-rc.top),SWP_SHOWWINDOW); return 0; }

この自作関数の解説は第16章を見て下さい。

あー!!長い解説でくたびれた!

解説する方もくたびれているので、これを読まれている方はさぞかしうんざり されていることでしょう。文章で解説すると非常に長くて複雑そうに見えますが 実際にプログラムを書いていくとそうでもないです。同じような構文が続くので 初めての関数でも何となく使い方がわかってしまいます。めげずに、ちょっとがんばれば すぐに理解できます。要は慣れです。

では、実行してみましょう。

実行すると左のようなウィンドウが画面の中央に現れます。(実際はもっと 大きいウィンドウです)

メニューの「ダイアログボックス」を選ぶと・・・

左のようなダイアローグボックスが現れます。スクロールつまみをいじったり、 コンボボックスから適当な文字列を選択したりして下さい。 OKボタンを押すとダイアログボックスが終了して、今選択したり 入力した内容がクライアント領域に表示されます。


[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]

Update Apr/16/1997 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。