第18章 リストボックス・その他の扱い方 その1


今回は、ダイアログボックスのコントロールでまだ 取り扱っていなかった、リストボックス、コンボボックス、 スクロールバーなどについて解説します。

実は、ダイアログボックスのコントロールの取り扱い方には 2種類あります。それは、マクロを使う方法と、使わない方法です。 以前のボタン類や、エジットボックスでもマクロを使わなかったので 今回もマクロを使わずに解説します。マクロについては、後の章で 解説する予定です。

まずは、次のようなダイアログボックスを作ってみて下さい。

左上から、エジットボックス、コンボボックス、リストボックスです。

中段左から、スクロールバー、テキストです。 スタティックテキストにはくぼみを付けてみました。VC++4.X ですと、プロパティの所の「スタイル」の「くぼみ」欄をチェックするだけです。

下段はプッシュボタンです。

念のため、リソース・スクリプトを表示しておきます。 各コントロールの位置や、大きさを表す数値は例題と違っていてかまいません。

///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDIALOG DIALOG DISCARDABLE 0, 0, 187, 93 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "ダイアログボックスのテスト" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,13,66,50,14 PUSHBUTTON "キャンセル",IDCANCEL,71,65,50,14 EDITTEXT IDC_EDIT1,7,7,47,16,ES_AUTOHSCROLL LISTBOX IDC_LIST1,118,7,62,46,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBO1,63,7,51,47,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP LTEXT "",IDC_STATIC1,81,35,24,15,SS_SUNKEN SCROLLBAR IDC_SCROLL1,13,39,54,7 END

さて、メニューも次のように作りましょう。

///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&Q)", IDM_END END POPUP "ヘルプ(&H)" BEGIN MENUITEM "About(&A)", IDM_ABOUT END MENUITEM "ダイアログボックス(&D)", IDM_DLG END

これで、どんなプログラムを作ろうとしているのかというと ダイアログボックスで、いろいろ入力した事項をクライアント 領域に表示するといった簡単なものです。

そこで、メニューに少し注目して下さい。"終了(&q)"などのように 今まで、解説しなかったものが付け加わっています。 これは、できあがったメニューを見てもらえば一目瞭然です。 メニュー項目の後ろに(F)とか(H)とかが付け加えられていますね。 これは、メニューの所をクリックしなくてもALT(GRPH)キーを 押すことにより、キーボードからもメニューを操作できるようにするものです。 ショートカットキーとか、アクセラレーターキーと呼ばれるものです。

今回は、ヘッダーファイルはすべて、リソースエジタに任せて、 自分では作りません。リソース・スクリプトもエジタ任せで 自分では手を入れません。従ってソースファイルにはresource.hを インクルードしなくてはいけません。

VC++以外の人は、先に挙げたリソーススクリプトに

#include <windows.h> #include "dialog01.h" //自作のヘッダーファイル

を記述しておいて下さい。またソースファイルには 自作のヘッダーファイルをインクルードしておいて下さい。
では、さっそくプログラムを見ていきましょう。

// dialog01.cpp #include <windows.h> #include "resource.h" #define ScrMax 100 //スクロールつまみの最大値 #define ScrMin 0 //最小値 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE, LPCSTR); BOOL InitInstance(HINSTANCE, LPCSTR, int); //リストボックス LPCTSTR liststr[] = {"粂井康孝", "粂井ひとみ", "粂井櫻都", "粂井志麻", "マイケル"}; //コンボボックス LPCTSTR combostr[] = {"東京", "北海道", "大阪", "名古屋"}; int initDlg(HWND); int getDlg(HWND); int ShowScroll(HWND); int ShowStatic(HWND); int ShowText(HWND); int SetWinCenter(HWND); char edit_str[256]; int ScrPos=0, ListNo=0, ComboNo=0; int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; char szClassName[] = "dialog01"; //ウィンドウクラス if (!hPrevInst) { if (!InitApp(hCurInst, szClassName)) return FALSE; } if (!InitInstance(hCurInst, szClassName, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }

まず、コンボボックスやら、リストボックスに表示する 文字列をグローバル変数にしておいてどこからでもみれるように しておきました。また、選択された項目番号などもグローバル変数に しておきました。

WinMain関数はいつもと変わり映えしませんね。

//ウィンドウ・クラスの登録 BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; //インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; return (RegisterClass(&wc)); }

ここも、いつもと殆ど同じです。メニュー名を入れ忘れないで下さい。

//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, LPCSTR szClassName, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, (LPCTSTR)"ダイアログボックス", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

あー、ここも同じですね。 次からが大事です。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; HINSTANCE hIns; switch (msg) { case WM_CREATE: SetWinCenter(hWnd); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0L); break; case IDM_ABOUT: MessageBox(hWnd, (LPCTSTR)"ダイアログボックス Ver1.00", (LPCTSTR)"About", MB_OK | MB_ICONINFORMATION); break; case IDM_DLG: hIns = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); DialogBox(hIns, "MYDIALOG", hWnd, (DLGPROC)DlgProc); InvalidateRect(hWnd, NULL, TRUE); break; } break; case WM_PAINT: ShowText(hWnd); break; case WM_CLOSE: id = MessageBox(hWnd, (LPCTSTR)"終了しても良いですか", (LPCTSTR)"終了確認", MB_OKCANCEL | MB_ICONQUESTION); if (id == IDOK) DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; }

親ウィンドウが作られようとしているときに、SetWinCenter関数 (自作)を呼んでウィンドウを画面の真ん中に移動させています。 SetWinCenter関数の中身については 第16章で解説しました。

メニューが選択されたときの説明は不要ですね。

ただ、IDM_DLGメッセージを捕まえたとき、 DialogBox関数を呼び出した後で、InvalidateRect関数を 呼んでいることに注意して下さい。 これは、第10章で解説してあります。 ダイアログボックスが終了したらすぐにクライアント領域を 書き直さなくてはいけません。それで更新リージョンに 長方形を加えています。さらに、最後の引数をTRUEにしてあります。 これは、背景も書き直すという意味です。背景を書き直すことにより 今まで表示されていたものが完全に消されます。どういうことかというと この引数がFALSEにしておくと、新しく表示する文字列が前回より 短いとき、以前の文字列の後ろの方が残ってしまうのを防ぐためです。 自分でいろいろやってみると意味がすぐに分かります。

WM_PAINTのところで、ダイアログボックスから得た情報を ShowText関数(自作)でクライアント領域に書き込みます。
さて、次はいよいよダイアログ・プロシージャです。 と、思ったらもう紙面がありません。続きはまた次回!

肝心なところでやめるなんて、こりゃ詐欺だ!

はい。すいません。次回はきっちり最後まで解説します。

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

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