wParam - みる会図書館


検索対象: 月刊 C MAGAZINE 1992年11月号
14件見つかりました。

1. 月刊 C MAGAZINE 1992年11月号

ログラムは , メニューを持たなかったのて、 , NULL を与えていた。 WM COMMAND メッセージ これて、 , ウインドウとメニューが関連づ けられたわけだ。後は , 実際にメニューが 選択されたときの処理をウインドウブロシ ージャに付け加えるだけだ。 ” HelloMenu' と指定している。ちなみに 12 : / * ー 16 : { List これまて、のプ He A 用へッダファイル HelloA 用へッダファイル 日 e110A. H 2 : 3 : 4 : 5 : 6 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 14 : 17 : 19 : 20 : 22 : 23 : 24 : 25 : 26 : 28 : 30 : 32 : 33 : 34 : 36 : 38 : 39 : 40 : 41 : 42 : 43 : 44 : 45 : 46 : 48 : 49 : 50 : 51 : 52 : 53 : 54 : 55 : 56 : 58 : 59 : (C) BohYoh Shibata, 1992 case WM COMMAND if (wParam IDM ABOUT) 7 : #define IDM-ABOUT 100 「 HelIo Wo 日 d 」終了確認つき Ver. 2 1 : / * ニ HeIIoA. C " He110 響 , world" と表示 (Abount つき ) 15 : BOOL FAR PASCAL About(HWND hwnd, WORD message, A b 0 u t プロシージャ 10 : HANDLE hlnst; #include ” hel 10a. h ” く windows. h 〉 #include (C) BohYoh Shibata, 1992 有効なメニューを選択したときに送られ るのが , WM COMMAND メッセージて、あ る。このさき , サプメニューて、ある wPara m に , メニュー ID が格納されている。 、、 About... クメニューのメニュ—ID は ,IDM ABOUT て、あるから , wParam がその値を 持っときのみ , なんらかの応答を行えばよ さて , このメニューが選択されたとき , プログラムは , アバウト機能を実現するた めにダイアログボ、ツクスを表示しなければ ならない。次にダイアログボックスの説明 Step2 ダイアログボックス に移ろう。 ジボックスと同様に , ポップアップウイン ダイアログボックスは , 前章のメッセー テンプレート ダイアログボックス ドウの形式を持つ。 70 C MAGAZINE 1992 11 ァイルに記述しなければならない。ダイア アログボックステンプレートをリソースフ ースファイルに記述したのと同様に , ダイ メニュー作成時に , メニュー構造をリソ WORD wParam, LONG 1 Param) switch (message) { case WM_INITDIALOG return (TRUE) ; case WM_COMMAND : if (wparam = IDOK Ⅱ wParam = IDCANCEL) { ウインドウブロシージャ return (FALSE) : break ; return (TRUE) ; EndDialog(hwnd, TRUE) : long FAR PASCAL WndProc (HWND hwnd, WORD mes sage, WORD wParam, LONG lParam) HDC hdc; PA INTSTRUCT ps ; RECT rect; switch (message) { case WM_PA I NT ・ GetCl ientRect(hwnd, &rect) ; hdc = BeginPaint(hwnd, &ps) ; if (wParam = IDM_ABOUT) { case WM_COMMAND : return ( の ; EndPaint(hwnd, &ps) : DT_SINGLELINE ー DT_CENTER ー DT—VCENTER) : ー 1 , &rect, DrawText(hdc, ” HeI 10 , World! ” return ( の : PostQuitMessage(O) ; case WM_DESTROY : break; return ( の : FreeProcI ns tance ( 1 pProcAtmt) ; DialogBox(hInst, "AboutBox ” , hwnd, lpProcAbout) : FARPROC 1 pProcAbout = MakeProc I ns tance (About, hl ns t) ;

2. 月刊 C MAGAZINE 1992年11月号

ョンは停止し , ほかのアプリケーションに 制御が移される。 さて , メッセージループの本体 , すなわ ち GetMessage が WM QUIT 以外のメッセ ージを受け取った場合の処理を考えよう。 キーボードメッセージの変換 まず TransIateMessage て、ある。 Transla teMessage の概略を Table 15 に示す。 Tran slateMessage は , このプログラムにおいて は , 意味を持たない。コラムⅦを参照して いただきたい 形式 void PostQuitMessage(int nExitCode) , PostQuitMessage TabIe 17 PostQuitMessage の概要 する。 プログラマの定義した WndProc 関数 ) に転送 を , ウインドウブロシージャ ( この場合は , essage によって変換を行った ) メッセーシ 取った ( さらに , 必要に応じて TranslateM DispatchMessage は , GetMessage て、受け している。 DispatchMessage の概略は , Table 16 に示 が , DispatchMessage の呼び出して、ある。 メッセージを変換した後に実行しているの TranslateMessage によって , キーボ、一ド メッセージの転送 奇妙なことだが , WinMain 関数中のメッ セージループは , 受け取ったメッセージを 転送するだけて、ある。メッセージに対して , 直接応答して , 何らかの処理を行うわけて、 Ste 8 ウインドウブロシージャ ウインドウブロシージャ はないのだ。 wParam, LONG lParam) ・ hwnd, WORD message, WORD long FAR PASCAL WndProc(HWND よい ) 。 りて、はなく , プログラマが自由に定義して 持つ ( もちろん , 関数名や引数名はこのかぎ ウインドウブロシージャは以下の形式を ることが多い は WndProc や WinProc といった名前を与え 呼ばれており , C 言語のプログラム作成時に これは , 一般にウインドウブロシージャと を行うのが , メッセージハンドラて、ある。 られてくるメッセージに対して反応し処理 ことがわかった。ウインドウに対して送 WinMain 関数は , 実質的には , 何もしな 解説アプリケーションが実行を終了しようとしていることを Windows に通知する ( 具体的には , WM QU 灯メッセージをアプリケーションキューにポストする ( その際のサプメッセージ wpa 「 am には nExitCodeh\ 格納される )。通常は , WM DESTROY メッセージへの応答として使用する。 DefWindowP 「 oc TabIe 18 DefWindowProc の概要 戻り値なし 形式 解説 LONG DefWindowP 「 oc(HWND hWnd, WORD wMsg, WORD wParam, DWORD lParam) , す。 行う。ウインドウブロシージャで処理しないウインドウメッセージは , DefWindowProc 関数に渡 Windows のメッセージのうち , アプリケーションで処理しないメッセージのテフォルトの処理を 各 API 関数と同様に , ウインドウブロシー ジャ関数も FAR PASCAL の属性を持て いる。 さてウインドウブ。シージャの 4 個の引数 が , MSG 構造体の最初の 4 個のメン , ヾと対応 していることに気づかれただろうか ? 最初の引数は , メッセージを受け取た ウインドウの , 、ンドルて、ある。この場合は , WinMain 関数て℃ reateWindow が返した , ンドルて、ある。第 2 引数 message がメッセー ジて、ある。第 3 引数 wparam および第 4 引数 1 Param には , サプメッセージ , すなわちウ インドウメッセージに対する追加情報が渡 される。 これらに格納される内容は , 各メッセー ジによって異なる。 メッセージへの応答 さて , WndProc は , ウインドウブロシー ジャに送られたすべてのメッセージを受け 取る。ウインドウブロシージャは , 受け取 ったメッセージに対して , 以下のいすれか を実行する。 ( a ) メッセージに対して応答するために , 何 らかの処理を行う ( b ) メッセージに対して , 既定の ( あらかじ め定義されている ) 処理を行う これらにふたつについて , 詳しく解説し (a) こて、取り上げている nothing. exe は , 「何 も行わないプログラム」て、あるから , ウィ ンドウブロシージャは簡単だ。 ( a ) に該当 するメッセージは , WM DESTROY だけ て、ある。 if (message = = WM DESTROY) { PostQuitMessage ( 0 ) ・ return ( 0 ) ・ WM DESTROY は , ウインドウの破棄処 理を行っていることを示すメッセージて、 ある。 戻り値メッセージ処理の結果。ただしその意味はメッセージにより異なる。 58 C MAGAZINE 1992 11

3. 月刊 C MAGAZINE 1992年11月号

特集 ープログラミンク ダイアログボックスプロシージャを作成す る。これは , ウインドウブロシージャとよ く似た関数て、ある。 この関数て、は , ・ダイアログボックス作成時のコントロー ルの初期化 ・コントロールからのメッセージの処理 ・ダイアログボックスの終了 の三つの処理のみを行う。 したがって , ダイアログボックスに送ら れる一部のメッセージを処理するために ダイアログボ、ツクスプロシージャを記述し なければならない このプログラムて、は , ダイアログボック スプロシージャは About という関数として実 現しており , その関数頭部は , BOOL FAR PASCAL About (HWND hwnd, WORD message, WORD wParam, LONG lParam) となっている。一見してすぐわかるように ダイアログボックスには , 通常のウインド ウブロシージャと同じ引数を受け取る。た だし , 関数が戻すのは , LONG て、なく BOO L て、ある。 さて , ウインドウブロシージャと異なる 占を説明しよう。 ・既定の処理 通常のウインドウブロシージャは , 自分 の処理しないメッセージは , すべて De ハ indowProc を呼び出すことにより既定の 処理を行うが , ダイアログボックスは , その必要はない。メッセージを処理した 場合は TRUE, 処理しなかった場合には FALSE を返すだけて、よい ・ウインドウ作成時のメッセージ 通常のウインドウブロシージャには , W M CREATE メッセージが送られるのに対 し , WM INITDIALOG が送られる。な お , WM PAINT や WM DESTROY など を処理する必要もない , こて , ダイアログボックスプロシージ ャが処理を行っているのは , WM COMM AND メッセージだけてある。サプメッセー 特集 MS-Windows プログラミング基礎学 73 "Hellow, WO 日 d " と表示 ( About / 終了確認つき ) HelloDX. C 2 : ” Hellow , World ”と表示 (About/ 終了確認つき ) 3 : (C) BohYoh Shibata, 1992 4 : 6 : 7 : #include く windows.h> ” hellodx. h ” 8 : #include 10 : HANDLE hlnst; ” Hel 10 World ”・ 11 : char szAppName ロ = 12 : 13 : / * ー 14 : 終了確認関数 16 : int ConfirmTerm(HWND hwnd) 19 : } 20 : A b 0 u t プロシージャ 22 : 23 : 24 : BOOL FAR PASCAL About(HWND hwnd, WORD message, WORD wparam, LONG lParam) switch (message) ( 26 : case WM—INITDIALOG . return (TRUE) ; 28 : 29 : cas e WM_COMMAND : 30 : if (wparam = IDOK Ⅱ wparam = IDCANCEL) { EndDialog(hwnd, TRUE) ; 32 : return (TRUE) ; 33 : 34 : break : 35 : 36 : re turn (FALSE) : 39 : ウインドウブロシージャ 41 : 42 : 43 : long FAR PASCAL WndProc(HWND hwnd, WORD message, WORD wparam, LONG lParam) 44 : { HDC hdc; 45 : PAINTSTRUCT. ps : 46 : RECT rect : FARPROC IpProcAbout; 48 : 49 : switch (message) { 50 : case WM_PAINT : 51 : hdc = BeginPaint(hwnd, &ps) ; 52 : GetCI ientRect(hwnd, &rect) ; 53 : DrawText(hdc, " He110 , World!Yn ” ー 1 , &rect, 54 : DT_SINGLELINE ー DT_CENTER ー DT_VCENTER) ; 55 : EndPaint(hwnd, &ps) ; 56 : return ( の ; 58 : case WM_COMMAND : 59 : switch (wParam) { 60 : case IDM_ABOUT : 61 : lpProcAbout = MakeProcInstance(About, hlnst) ; DialogBox(hInst, "AboutBox", hwnd, lpProcAbout) : 63 : FreeProcI ns tance ( 1 pProcAbou t) : 64 : return ( 0 ) ; 65 : case IDM_EXIT : 66 : SendMessage(hwnd, WM—CLOSE, 0 , (L) : re turn ( の : 68 : 71 : 74 : return (MessageBox(hwnd, " 終了しますか ? ” , szAppName. MB—YESNO)) : break : case WM-QUERYENDSESSION ・ return ( (ConfirmTerm(hwnd) case WM—CLOSE ・ ニ IDYES) ? IL : OL);

4. 月刊 C MAGAZINE 1992年11月号

Fig. 7 Window とメッセージの概路 キーボード Fig. 8 MSG 構造体の定義 typedef struct tagMSG { hwnd; HWND WORD message; WOR D WParam : LONG 1 Param ; DWORD time; POI NT pt; } MSG; / / メッセージが送られるウインドウのハンドル / / メッセージ識別子 / / ワードバラメータ / / ロングパラメータ / / メッセージがキューにポストされた時刻 / / メッセージがポストされたときのマウスの座標 マウス タイマ Windows Fig. 9 PO 爪 T 構造体の定義 typedef s truct tagP01 NT ( / / X 座標 int / / Y 座標 i nt ) POINT; アプリケーション アプリケーション るのか , マウスの情報て、あるのかはわから よ ! ) や WM DESTROY( ウインドウが破壊 ージループの解説に移れるようになった。 ない ( わざと選択的に待っこともて、きるが , される ! ) のように , WM て、始まる名前が while 文の条件式中の GetMessage が , メ あまり一般的て、はない ) 。 ッセージを受け取る関数だ ( 概要を Table 与えられている。 Windows て、は , そのような情報をメッセ 14 に示す ) 。 GetMessage は , 受け取ったメ 続くメンバ , wParam および IParam は , ージという概念て、考える。キーポードやマ サプメッセージ , すなわちウインドウメッ ッセージが , アプリケーションを終了する ウスの操作などは , メッセージの形に変換 必要があることを指示する WM QUIT て、あ セージに対する追加情報が格納される。 され , Windows システムに送られる。その れば , アプリケーションを終了すべきて、あ こに格納される内容は , 各メッセージによ メッセージは , アプリケーションに読み出 ることを示す FALSE を返す 0FALSE は 0 と って異なる。たとえば , 文字入力を表す W され , そのメッセージに対して何らかの処 して定義されているのて、 , while ループは , M CHAR メッセージの場合 , 入力された文 理を行うというのがⅥⅱ ndows プログラムの 字の ASCII コードがサプメッセージて、ある w 繰り返しを終了する。 基本的な構造てある。 Windows とメッセー これがメッセージループの骨格だ。 Param に格納される。 ジの関係の概略を Fig. 7 に示す。 while (GetMessage(&msg, NULL' 0 , 0 ) ) { 最後のふたつのメンバは , メッセージ発 TranslateMessage (&msg) ・ 生時の状況を示すものて、ある。メンバ time メッセージを表す MSG 構造体 DispatchMessage(&msg) ・ には , メッセージがメッセージキューに入 れられた時間が , メンバ pt には , その時点て、 第 2 引数は , アプリケーションに属するす Windows の動作の根本となるのがメッセ のマウス座標が格納される。なお , 座標を べてのウインドウのメッセージを得るため ージて、あることがわかったが , そのメッセ 表す POINT 構造体は , Fig. 9 に示すように ージは , プログラム上て、はどのように表現 に NULL を指定している。第 3 引数 , 第 4 引 定義されている。 されるのだろうか。メッセージは , Fig. 8 のよ 数は受け取るメッセージの範囲を制限する うに定義される MSG 構造体として表される。 メッセージループ。。 ためのものて、あるが , 通常はすべてのメッセ ージを受け取るのて、 , 両方とも 0 を指定する。 MSG 構造体の各メンバを見ていこう。 これて、 , 先ほど名前だけ紹介した GetMessage が受け取ったのが , WM QU 最初のメンノ *hwnd は , メッセージの送り ' メッセ 先て、あるウインドウを表す。 TabIe 14 GetMessage の概要 2 番目のメンバ message は , メッセージ識 GetMessage 別子て、あり , どのようなイベントが発生し * IpMsg, HWND hWnd, WORD wMsgFilterMin• 形式 BOOL GetMessage(LPMSG たのかをアプリケーションに知らせる。 WORD wMsgFilterMax) : れは , ウインドウメッセージと呼ばれるも 解説 アプリケーションキューからメッセージを受け取り , ゆ Msg の指す LPMSG 構造体テータに , メ ッセージを格納する。 のて、 , <windows. h> には , すべてのウイン hWnd には , メッセージを受け取るウインドウの識別八ンドル ( アプリケーションに属するすべ ドウメッセージが定義されている。ウイン てのウインドウのメッセージを得るには NUL し ) を指定する。 戻り値 メッセージが WM QU げであれば 0 ( FALSE ) を , そうでなければ非ゼロの値を返す。 ドウメッセージには , WM PAINT ( ウイン 関連項目 PeekMessage, WaitMessage ドウの描画内容が破損したのて、 , 再描画せ 56 C MAGAZINE 1 2 11

5. 月刊 C MAGAZINE 1992年11月号

特集 ープログラミンク mdParam という名前があるが , これは , 複て、記述する。 これだけの機能を持つプログラムが数十 数の前置子を組み合わせている。 sz が ASC 行程度て、記述て、きるのて、あるから , List 2 の さて , ハンガリアン記法に関しては , 賛 IZ 文字列 ( コラムⅡ参照 ) て、あること , lp が否両論がある。しかし , プログラムは , その見かけからはちょっと 想像て、きない強力なパワーを持っといって ( その ASCIZ 文字列への )far ポインタて、ある iCounter ことを示している。 CmdParam の部分が名という名前が与えられると , 整数て、表現す も過言て、はないだろう。 前の本体部て、あり , 各単語の先頭を大文字るカウンタて、あることが一目瞭然て、あると とはいえ , Windows プログラミングの初 心者には , このプログラムを理解するのも 何もしない Windows プログラム 困難て、ある。ひとつずつ解説していく にする。 List Nothing. C 何もしないプログラム 3 : 4 : (C) BohYoh Shibata, 1992 5 : 6 : 7 : #include く windows. h 〉 8 : ウインドウブロシージャ 10 : 11 : 12 : long FAR PASCAL WndProc (HWND hwnd, WORD mes sage, WORD wParam, LONG 1 Param) 13 : { if (message = = WM_DESTROY ) { 14 : PostQui tMessage( の : 15 : return ( の ; 17 : return (DefWindowProc(hwnd, message, wParam, IParam)) : 18 : 19 : } 20 : 22 : メイン関数 23 : 24 : int PASCAL WinMain(HANDLE hlnstance, HANDLE hPrevInstance, 25 : LPSTR lpszCmdParam, int nCmdShow) szAppName[] = "DON0thing ・ 27 : Char 28 : HWND hwnd; 29 : MSG msg; 30 : WN DCLASS wndclass; 31 : if ( !hPrevInstance) { 32 : ニ CS_HREDRAW ー CS_VREDRAW ; 33 : wndclass. style 34 : wndc 1 as s. 1 pfnWndProc = WndProc; 35 : wndclass. cbClsExtra 36 : wndclass. cbWndExtra wndclass. hlnstance = hlnstance; 38 : wndclass. hlcon = LoadIcon( NULL, IDI_APPLICATION) ; 39 : wndclass. hCursor = LoadCursor(NULL, IDC ARROW) : 40 : wndclass. hbrBackground ニ GetStock0bject(WHITE_BRUSH) : 41 : wndc 1 as s. 1 pszMenuName = NULL; 42 : wndclass. IpszCIassName = szAppName; 43 : RegisterClass (&wndclass) : 44 : 45 : 46 : 47 : 48 : 49 : 50 : 51 : 52 : 53 : 54 : 55 : 56 : 57 : 58 : 59 : 62 : 63 : 64 : Windows プログラミング の規則と慣習 まず , 各種の表記法など , Windows プロ グラミングの本質とはいい難い , 周辺的な 事項から始めよう。 / / コメント 〃コメントは , C て、はなく C 十十のコメン トて、ある。 / / から , その行末まて、をコメント と見なす。 MS, Quick, Turbo, BorIand などの新しいバージョンて、は , C 言語て、もこ のコメントを採用しており , Windows プロ グラミングの開発時には利用してもよいだ 0 ただし , 一般には , 〃コメントを利用す るだけて , そのプログラムは C て、はなく , C 十十 のプログラムとなってしまうのて、 , Windo ws 以外の C プログラムて、は利用すべきて、な hwnd = CreateWindow(szAppName, ” DO Nothing. WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hl ns tance, NULL) ; ShowWindow(hwnd, nCmdShow) : UpdateWindow(hwnd) ; while (GetMessage(&msg, NULL, 0 , の ) { TransIateMessage(&msg) : DispatchMessage(&msg) ; return (msg. wParam) ; / / Windo 響クラス名 / / Window キャプション 〃 Window スタイル / / 初期 x 座標 / / 初期 y 座標 / / 初期 x サイズ / / 初期 y サイズ / / 親 Window ハンドル / / Window メニューハンドル / / プログラムインスタンスハンドル 〃作成パラメータ ハンガリアン記法 プログラムをざっと見渡すと , まず , 変 数名がやたらと長いことに気づくはずて、あ る。一般に Windows のプログラムにおいて は , ハンガリアン記法という命名法を利用 するという慣習がある。これは , 識別子の 先頭に , その型情報を前置子として付け加 えるものて、ある。 Windows プログラミング て、多用する前置子を TabIe 1 に示す。 たとえは第ⅱ nMain 関数の第 3 引数に IpszC 特集 MS-Windows プログラミング基礎学 47

6. 月刊 C MAGAZINE 1992年11月号

Li st 7 x て、ある。 MessageBox(hwnd, ' 終了しますか ? " " [ 確認 ] " , MB YESNO) MessageBox の概要を Table 23 に示す。 メッセージボックスは , ユーザに対して確 訒を促すなどの , 単純な応答を必要とする ロ・じ、 ときに便利なウインドウて、ある。 < windows. h> て、定義されている Messag eBox スタイルの識別子の一覧を Table 24 に 示す。 , こては , メッセージボ、ツクスが返した のが IDYES て、あるとき ( すなわちューザが [ は い ] のボタンを押したとき ) のみ DestroyW ind 。 w 関数を呼び出して , ウインドウの破棄 を行っていることがわかるだろう。 11 : / * ー 終了確認関数 12 : 13 : 14 : int Conf i rmTerm (HWND hwnd ) 15 : ( return (MessageBox(hwnd, " 終了しますか ? " 19 : / * ー ウインドウブロシージャ 20 : 21 : 22 : long FAR PASCAL WndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam) 23 : { hdc; HDC 24 : PAINTSTRUCT ps ; 25 : RECT 26 : rect ; switch (message) { 28 : case WM_PAINT ・ 29 : hdc = BeginPaint(hwnd, &ps) ; 30 : GetCl ientRect(hwnd, &rect) ; 31 : DrawText(hdc, "Hel 10 , World!}n" ー 1 , &rect, 32 : DT_SINGLELINE ー DT_CENTER ー DT—VCENTER) ; 33 : EndPaint(hwnd, &ps) ; 34 : return ( の ; 35 : 36 : case WM—QUERYENDSESSION : return ( (ConfirmTerm(hwnd) = IDYES) ? lL : (L) ; 38 : 39 : 40 : case WM_CLOSE : if (ConfirmTerm(hwnd) = = IDYES) 41 : DestroyWindow(hwnd) ; 42 : return ( の : 43 : 44 : 45 : case WM_DESTROY : PostQuitMessage( の : 46 : return ( の ; 47 : 48 : return (DefWindowProc(hwnd, message, wParam, lParam)) ; 49 : 50 : } 51 : 52 : / * ー メイン関数 53 : 54 : 55 : int PASCAL WinMain(HANDLE hlnstance, HANDLE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) 56 : 57 : { hwnd ; 58 : HWND 59 : MSG msg; WNDCLASS wndclass : 60 : 61 : if ( !hPrevInstance) { 62 : wndclass. style 63 : wndclass. lpfnWndProc 64 : wndclass. cbClsExtra 65 : 66 : wndclass. cbWndExtra wndclass. hlnstance 68 : wndclass. hlcon wndclass. hCursor 69 : wndc 1 as s. hbrBackground 70 : wndclass. lpszMenuName wndclass. lpszClassName 72 : RegisterCIass(&wndclass) ; 73 : 74 : hwnd ニ CreateWindow(szAppName, ” Hel 10 World ! ” WS OVERLAPPEDWINDOW, 76 : CW_USEDEFAULT, CW_USEDEFAULT, 77 : CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hlnstance, NULL) ; 80 : ShowWindow(hwnd, nCmdShow) ; UpdateWindow(hwnd) ; 82 : 83 : while (GetMessage(&msg, NULL, 0 , の ) { 84 : TranslateMessage(&msg) ; DispatchMessage(&msg) : 86 : return (msg. wparam) ; 88 : , szAppName, MB_YESNO)) : Windows の終了 he110C1. exe はまだ完璧て、ない。試しに he 110C1. exe を起動したままの状態て、 , プログ ラムマネージャをクローズして , Windows の終了を試みていただきたい。 he110C1. exe は実行を終了してしまう。 この he110C1. exe の場合は , 勝手に終了し てもなんの支障もないが , たとえば工ディ タを考えよう。 Windows を終了させようと したときは , 工デイタ側て、 , 「文書を保存し ていません。保存しますか ? 」などの確認が 必要て、あろう。 さて Windows を終了しようとすると ,W indows は , すべてのウインドウブロシージ ャに対して , WM QUERYENDSESSION というメッセージを送るのて、ある。したが って , Windows の終了とともにアプリケー ションを終了させたくないのて、あれば , のメッセージに対しても応答しなければな らない WM QUERYENDSSIN に対しても , 正 しく応答するプログラムを List 7 に示す。こ のプログラム he110C2. exe は , ユーザが hell 0C2 を終了しようとするときだけて、なく , W indows を終了しようとする際にも , 終了の 確認を行う。 66 C MAGAZINE 1992 11 = CS_HREDRAW ー CS_VREDRAW : = WndProc ; = hlnstance; ニ LoadIcon(NULL, IDI—APPLICATION) ; = LoadCursor(NULL, IDC—ARROW) ; ニ NULL; szAppName ;

7. 月刊 C MAGAZINE 1992年11月号

List 4 34 : / * ー ときや , アプリケーションが GetMessag た , UpdateWindow 関数が呼び出された ペイントを要求するときに送られる。ま プリケーションのウインドウの一部の再 Windows またはアプリケーションが , ア WM PAIN T WM PAINT の概要を示そう。 ージて、ある。 再描画が必要て、あることを知らせるメッセ 域の一部または全部が無効になっており , て、ある。 WM PAINT は , クライアント領 たに処理するメッセージが , WM PAINT return (DefW i ndowProc (hwnd, mes sage, wParam, メイン関数 1Param)) : e 関数か , PeekMessage 関数を使ってこの メッセージを取得したときにも , Dispat chMessage 関数によって送られる。 Windows によって送られ てくる場合 クライアント領域が無効になる場合は , このようなときに WM PAINT が送られ たとき て裏に隠れた後 , ウインドウを表に出し ・ほかのウインドウが上に重ねて表示され 後 , ウインドウ表示に戻したとき ・アプリケーションを一旦アイコン化した とき ・ユーザがウインドウの大きさを変更した いろいろと考えられるのて、例をあげよう。 てくる。 インドウを表示しただけて、は , クライアノ と呼び出したことを覚えているだろう。ウ UpdateWindow (hwnd) ・ すかさず ( ! ) UpdateWindow 関数を , 最初に Window を作成・表示したときに 生成する場合 アプリケーションか自ら 62 C MAGAZINE 1992 11 ればならないのて、ある。 を生成し , 該当するウインドウに送らなけ とによって , 自ら WM PAINT メッセージ そこて、 , UpdateWindow 関数を呼び出すこ ト領域は無効て、あり , 有効にはならない Fig. 31 : 32 : ) 33 : 35 : 36 : 37 : 38 : 39 : { 40 : 41 : 42 : 43 : 44 : 45 : 46 : 48 : 49 : 50 : 52 : 53 : 54 : 55 : 56 : 58 : 59 : 60 : 61 : 62 : 63 : 64 : 66 : 67 : 68 : 69 : 70 : 71 : 72 : } 1 1 int PASCAL WinMain(HANDLE hlnstance, HANDLE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) static char szAppName[] ” He110Wolrd ”・ RegisterClass(&wndclass) ; wndclass. lpszClassName wndc 1 ass. 1 pszMenuName wndc las s. hbrBackground wndclass. hCursor wndclass.hlcon wndclass. hlnstance wndclass. cbWndExtra wndclass. cbClsExtra wndclass. lpfnWndProc wndclass. style if ( !hPrevInstance) { wndclass; WNDCLASS msg; MSG HWND hwnd; = LoadIcon(NULL, IDI—APPLICATION) ; = hlnstance; WndProc; ニ CS_HREDRAW ー CS_VREDRAW; = GetStock0bject(WHITE_BRUSH) ; ニ LoadCursor(NULL, IDC_ARROW) : szAppName ; = NULL; NULL, NULL, hlnstance, NULL) ; CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, WS_OVERLAPPEDWINDOW, hwnd = CreateWindow(szAppName, ” Hel 10 World ! " return (msg. wParam) : DispatchMessage(&msg) ; TranslateMessage(&msg) ; while (GetMessage(&msg, NULL, 0 , の ) { UpdateWindow(hwnd) ; ShowWindow(hwnd, nCmdShow) ; hello. exe の実行例 オプション ( 0 ) プログラムマネージャ ウインドウ M ヘルプ ( H ) \ 平旦 dQ Ⅵ ' 准裕 Vo 盟 . H 訓 0. WorId ! \'Vs 工 0 Ⅵ

8. 月刊 C MAGAZINE 1992年11月号

特集 ープログラミンク マは , この名前を持っ関数を必ず作成しな 様変更などを考えると , 呼び出される側の 関数を前に , 呼び出す側の関数を後ろに配 ければならない。しかも , 引数の形式も ma 起動する時計の数の制限 置して定義する , P 001 風の記述が好まし in とは異なり , Windows< は , タイマを一種の入力デバ int PASCAL WinMain イスとして扱う。同時に利用てきるタイマ (HANDLE hlnstance, は , 最大 16 個なのて , 時計 ( やタイマを利用 HANDLE hPrevlnstance, するアプリケーション ) を 16 個より多く起動 することはてきない。時計を数多く起動す LPSTR lpszCmdParam, ると , どうなるかは , 実際に試してみれば int nCmdShow) ・ わかるだろう。 の形式て、定義する必要がある ( もちろん , 引 数名は変更してもよい ) 。 さて , WinMain 関数に対して , Window s の環境が与える hlnstance は , そのプログラ WinMain 関数の引数と 旨師のプログラムは , まず main ムの背番号 , たとえば、、 5 番クといった番号 通常の C ロⅱロ インスタンス 関数を実行する。しかし 'List 2 のプログラ て、あるが , プログラマが , 具体的にその値 最初のふたつの引数は , HANDLE 型の引 ムには main 関数は見あたらない。 Window を知る必要はない ただ、、 hlnstance 番〃て、 数て、ある。これらは , インスタンスハンド s のプログラムて、は , main て、はなく WinMa あると考えればよい in 関数が実行される。したがって , プログラ ルを与えるものて、ある。インスタンスハン 次の hPrevInstance の説明に入る前に , W ドルは , Windows 上て、実行されているアプ indows のアプリケーション起動原理の一部 コフーム W ⅲ dows プログラムにおける リケーションを識別するためのものて、ある を解説しなければならない。ある程度 Wind 関数プロトタイプの必要性 ( 「インスタンス」については後述 ) 。各アプ ows を使えばわかることだが , Windows て、 リケーションに対して , 決してほかと重複 は同一のプログラムを複数個起動すること 一般に ANSIC て、は , 関数プロトタイプを することのない背番号 = インスタンスハン がて、きる。 Windows に付属するアクセサリ ー。与えたほうが安全というだけてあり , 宣ロ " を義務づけているわけて、はない。しかし , ドルが割り当てられていると考えれば , わ て、ある「時計」を何個も立ち上げて遊んだこ Windows プログラミングて、は , 「必須」とい かりやすいだろう。実際に HANDLE 型 とはないだろうか ( コラムⅣ参照 ) 。 っても過言て、はない。その理由は , 大部分 は , く windows. h> 中て、 , さて , Windows て、は , メモリ節約などの の関数が FAR や PASCAL などの特殊な属性 目的て、 , 同一のアプリケーションを複数個 typedef WORD HANDLE , を持つからだ。関数プロトタイプを与えな いと , 呼び出す側の関数は通常の C 関数とし 起動した場合 , そのプログラムのコード部 と , WORD 型 ( すなわち unsigned int 型 ) に て呼びだそうとするのて、 , 致命的な状況に 与えられた別名て、あり , その実体は数値な ( プログラム部て、ありデータ部て、はない ) が おちいることになる。 重複しないようにロードされる。たとえば , のて、ある。 Table 3 基本型 Fig. 2 WinMain 関数を先頭に配置した場合のプログラム 型名 フ 5 p3 WinMain 関数の形式と 引数 WinMain 関数の形式 等価な基本型 int unsigned Char unsigned int unsigned long cha 「 NEAR * cha 「 NEAR * char FAR * BYTE NEAR * BYTE FAR * int NEAR * int FAR * WORD NEAR * WORD FAR * long NEAR * long FAR * DWORD NEAR * DWORD FAR * void FAR * BOOL BYTE WORD DWORD PSTR N PSTR LPSTR PBYTE LPBYTE PINT LPINT PWORD LPWORD PLONG LPLONG PDWORD LPDWORD LPVOID #include く windows. h> long FAR PASCAL WndProc(HWND hwnd, WORD message, WORD wparam, LONG lParam) ; int PASCAL WinMain(HANDLE hlnstance, HANDLE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) / * WinMain 関数の定義 * / long FAR PASCAL WndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam) / * WndProc 関数の定義 * / 特集 MS-Windows プログラミング基礎学 49

9. 月刊 C MAGAZINE 1992年11月号

List 1 6 ジ wParam には , ダイアログテンプレートて、 指定したコントロール ID が格納されてい る。そのメッセージが IDOK もしくは IDCA NCEL の場合は , EndDialogBox を呼び出す ことにより , ダイアログボ、ツクスを終了す 77 : 78 : 80 : 82 : 83 : 84 : 86 : 87 : / * ー メイン関数 88 : 89 : 90 : int PASCAL WinMain(HANDLE hlnstance, HANDLE hPrevlnstance, LPSTR lpszCmdParam, int nCmdShow) 92 : { hwnd ; HWND 93 : MSG 94 : msg; wndclass : WNDCLASS 95 : 96 : hlnst = hlnstance; if ( !hPrevInstance) { 98 : wndclass. style 99 : wndclass. lpfnWndProc 100 : wndclass. cbClsExtra 101 : wndclass. cbWndExtra 102 : wndclass. hlnstance 103 : wndclass. hlcon 104 : wndclass. hCursor 105 : wndclass. hbrBackground 106 : wndc 1 as s. 1 ps zMenuName 107 : wndclass. lpszClassName 108 : RegisterCIass(&wndclass) ; 109 : 110 : hwnd = CreateWindow(szAppName, ” Hel 10 World ! ” 111 : WS OV ERLAPPEDWI NDOW, 112 : CW_USEDEFAULT, CW_USEDEFAULT, 113 : CW USEDEFAULT, CW_USEDEFAULT, 114 : NUiL, NULL, hlnstance, NULL) ; 115 : 116 : ShowWindow(hwnd, nCmdShow) ; 117 : UpdateWindow(hwnd) ; 118 : 119 : while (GetMessage(&msg, NULL, 0 , の ) { 120 : TransIateMessage(&msg) ; 121 : DispatchMessage(&msg) ; 122 : 123 : return (msg. wparam) : 124 : ー 125 : ) = IDYES) if (ConfirmTerm(hwnd) DestroyWindow(hwnd) ; return ( の ; cas e WM_DE STROY : PostQuitMessage( の : return ( の : return (DefWindowProc(hwnd, message, lParam) ) : ダイアログボックス プロシージャの工クスポート ダイアログボックスプロシージャは , ウ インドウブロシージャと同様に , Windows から呼び出される関数て、ある。したがって , モジュール定義ファイルの EXPORTS に登 録しなければならない。モジュール定義フ ァイルを List 13 に示す。 もう少し凝った プログラム = CS_HREDRAW ー CS_VREDRAW ; ニ WndProc ; = hlnstance; = LoadIcon( NULL, IDI—APPLICATION) : ニ LoadCursor(NULL, IDC—ARROW) : ニ GetStockObject(WHITE_BRUSH) : ” Hel loMenu ” szAppName ; Step3 helloa. exe に手を加え , もう少し凝ったプ ログラムて、ある hellodx を , List 14—List 16 に示す ( モジュール定義ファイルは , 付録 ディスクに収録 ) 。 Fig. 17,Fig. 18 の実行例を見ていただけ れば , どのように手を加えたかご理解いた だけるて、あろう。 こて、のメニュー構造は , Fig. 19 のよう になっており , さらに he110C2. c と同様に プログラム終了時には確認を行うものとす return ( 0 ) ; こて、行っていることがわかるだろうか。 アプリケーションを終了させなければなら ないのて、 , WM CLOSE というメッセージ を発生させ , 自分自身に送っているのて、あ る。したがって , ウインドウブロシーシャ が , 次に呼び出されるときは , WMCLSO このプログラムて、は , 、、 FiIe ' ' メニューの下 E メッセージを受け取ることになり , そこて、 に、、 Exit" メニューがある。このメニューは , ーて、 終了処理に取りかかるわけて、ある。 アプリケーション終了のためのメニュ このように , あるメッセージに対して , あり , IDM EXIT というメニュ—ID を割り ほかのメッセージと同様な処理を行わせる 当てている。その処理の部分を見てみよう。 メニューテンプレートにおいて , 、、 Edit 〃の 必要があるときは , そのメッセージを自分 case IDM E 刈 T 項は , 自身に対して送るというテクニックが頻繁 SendMessage (hwnd, WM CLOSE' に使われる。必ず覚えておかねばならない と定義している。 GRAYED を指定すること によって , メニューは無効化され , テキス トの表示もグレイ ( 淡色 ) になる。 Step4 プログラムの解説 Exit メニュー 誌面の残りに余裕がないのて、 , 重要な点 のみを , かいつまんて、解説しよう。 グレイメニュー '&Edit ” , IDM EDIT, MENUITEM GRAYED 74 C MAGAZINE 1992 11

10. 月刊 C MAGAZINE 1992年11月号

NULL, NULL, ShowWindow(hwnd, nCmdShow) ; UpdateWindow(hwnd) ; whi le (GetMessage(&msg, NULL, 0 , TransIateMessage(&msg) ; DispatchMessage(&msg) ; return (msg. wParam) ; DialogBox TabIe 25 DialogBox の概要 LiSt 61 : 62 : 64 : 65 : / * ー 66 : 68 : 69 : 71 : 72 : 73 : 74 : 75 : 76 : 77 : ニ CS HREDRAW ー CS_VREDRAW; 79 : 80 : 82 : 83 : 84 : 85 : 86 : 88 : 89 : 90 : 92 : 93 : 94 : 95 : 96 : 98 : 99 : 100 : 101 : 102 : 103 : 104 : 1 2 return (DefW i ndowproc (hwnd, メイン関数 message, wParam, lParam)) ; 特集 ープログラミンク は , ダイアログボ、ツクスのスタイルを指定 STYLE WS CAPTION ー WS SYSMENU 縦方向は高さの 8 分の 1 を単位とした値て、あ 向はシステムフォントの文字幅の 4 分の 1 , int PASCAL WinMain(HANDLE hlnstance, HANDLE hPrevInstance, LPSTR 1 ps zCmdParam, int nCmdShow) ” He110 Wolrd ”・ static char szAppName ロ する。 こには , ウインドウスタイル (Tab HWND hwnd; MSG msg; WNDCLASS wndclass ; hlnst = hlnstance; if ( !hPrevInstance) { wndclass. style wndclass. lpfnWndProc wndclass. cbClsExtra wndclass. cbWndExtra wndclass. hlnstance wndclass. hlcon wndclass. IpszMenuName wndc 1 as s. hbrBackground wndc las s. hCursor = WndProc ; = hlnstance; ニ LoadIcon( NULL, IDI APPLICATION) ; = LoadCursor(NULL, IDC-ARROW) ; = GetStockObject(WHITE BRUSH) ; ” Hel loMenu ” ; wndclass. lpszClassName : szAppName; RegisterCIass(&wndclass) : hwnd = CreateWindow(szAppName, ” Hel 10 World ! ” WS OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hlnstance, NULL) ; の ) { 形式 解説 int DiaIogBox(HANDLE hlnstance, LPSTR lpTempIateName, HWND hWndParent, FARPROC lpDialogFunc) : ゆ Tem ate に指定されたダイアログボックステンプレートに定義されたサイズ , スタイル , コン トロールを持つモードっきダイアログボックスを作成する。 hWndParent は , ダイアログボック スを所有するアプリケーションのウインドウを示す。ゆ DialogFunc パラメータが指す関数は , ダ イアログボックスが受け取るすべてのメッセージを処理する。 戻り値ダイアログホックスを終了させるために使われた EndDialog 関数の nResu はの値を返す ログボックスは , ェデイタ上て、作成するこ ともて、きるし , 各種のダイアログボックス 工デイタによる作成も可能だ ( 後者の使用法 などについては , マニュアルなどを参照し ていただきたい ) 。 最初の行は , AboutBox DIALOG 22 , 17 , 144 , 72 て、 , ダイアログボックスの名前を AboutBo x と指定している。 DIALOG の後の数値は , ダイアログボックスの左上隅の x 座標 , 同 y 座標 ( 親ウインドウのクライアント領域の左 上隅を ( 0 , 0 ) としたときの座標 ) , 幅 , 高さ て、ある。 なお , この単位はドットてはなく , 横方 le 11 参照 ) を指定する。 指定しなかった場合は , WS POPUP ー WS BORDER ー WS SYSMENU が自動 的に設定される。 CAPTION ” About Hello-WorId' は , タイトルバーに表示するキャプション ー 1 , 0 , 14 , 144 , 8 ー 1 , 0 , 5 , 144 , 8 BEGIN を指定する。 CTEXT "Hello, World!" CTEXT ” Microsoft Windows 特集 MS-Windows プログラミング基礎学 71 だが , ここて、は詳細な解説は省略する。 ロールに対するキー操作などのために必要 最後の WS GROUP は本来 , 複数のコント 場所と大きさを指定する。 続く 4 個のパラメータは , コントロールの OK を返すように指定している。 こて、ブッシュボタンを押した場合は , ID ジを送らないのて、 , ー 1 としている。また , して送る ID て、ある。テキストは , メッセー 2 番目のパラメータは , 親ウインドウに対 ボタンを指定するものだ PUSHBUTTON は ,デフォルトのブッシュ ボ、ツクスの横方向中央に表示される。 DEF 指定するのて、 , 、、 Microsoft Windows" は , CTEXT は , センタリングしたテキストを EFPUSHBUTTON のふたつがある。 ロールを記述する。 こて、は , CTEXT, D テキスト , アイコン , ボタンなどのコント ログボックスの具体的な内容だ。各行には , BEGIN と END て、囲まれた部分が , ダイア END 旧 OK , 53 , 50 , 32 , 14 , WS GROUP DEFPUSHBUTTON ” OK ー 1 , 0 , 30 , 144 , 8 CTEXT ” Version 3.0 '