一応これまでのところでプログラムは動いて 絵を表示できるようにはなりましたが、いまのままでは、
- 動かせない
- 隠せない
- 止められない
- いつも白目を剥いている!!
という状態ですので、ユーザI/Fを組み込み、 多少は操作できるようにします。とりあえずは基本パターンとして
左マウスボタン | 選択(TOPに) |
右マウスボタン | メニュー |
ドラッグ | 移動 |
をサポートします。メニューからは
移動 | Move | |
隠す | Hide | |
説明 | About | ダイアログ表示 |
終了 | Exit |
ぐらいはできるようにします。
まずはリソースにメニューとダイアログを追加します。 ダイアログで使う文字列については ストリングテーブルで別途定義しておきます。
---- romy.rc 追加分 ここから ----MENU IDM_POPUP BEGIN MENUITEM "~Move", IDM_MOVE MENUITEM "~Hide", IDM_HIDE MENUITEM "~About", IDM_ABOUT MENUITEM "E~xit", IDM_EXIT END DLGTEMPLATE IDD_ABOUT BEGIN DIALOG "", 0, 0, 0, 172, 60, , FCF_DLGBORDER BEGIN ICON ID_ROMY, -1, 2, 36, 0, 0 LTEXT "Mr.Romy watches You!", -1, 32, 44, 88, 8 LTEXT "" IDD_ROMYTTL, 2, 26, 168, 8 ENTRYFIELD "", IDD_ROMYURL, 2, 16, 168, 8, ES_RIGHT | ES_READONLY DEFPUSHBUTTON "OK", DID_OK, 40, 2, 40, 12 END END STRINGTABLE BEGIN IDS_ROMYTTL "Bitmap was taken from Romy's Page at" IDS_ROMYURL "http://village.infoweb.ne.jp/~fwje3068/" END---- romy.rc 追加分 ここまで ----
シェイプウィンドウを使う場合には、 メニューバーもシステムアイコンもありませんので、 どうしてもフローティング/コンテキストメニューを使うことになります。 コンテキストメニューを使うには、
hwndMenu = WinLoadMenu(hwndOwner, hmod, idMenu) ;
でメニューウィンドウを生成しておき、
WinPopupMenu(hwndParent, hwndOwner, hwndMenu, x, y, id, fs) ;
でメニューを表示します。
---- メニューの生成/表示 ここから ----/* * context menu */ static HWND hwndPopup = NULLHANDLE ; /* context menu */ static void contextMenu(void) { POINTL pt ; ULONG opts ; if (hwndPopup == NULLHANDLE) { hwndPopup = WinLoadMenu(hwndFrame, NULLHANDLE, IDM_POPUP) ; } if (hwndPopup == NULLHANDLE) { printf("failed to load opup menu\n") ; return ; } WinQueryPointerPos(HWND_DESKTOP, &pt) ; opts = PU_HCONSTRAIN | PU_VCONSTRAIN | PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2 ; WinPopupMenu(HWND_DESKTOP, hwndFrame, hwndPopup, pt.x, pt.y, IDM_HIDE, opts) ; }---- メニューの生成/表示 ここまで ----
この関数をフレームウィンドウプロシジャで
case WM_CONTEXTMENU : contextMenu() ; return (MRESULT) 0 ;
として呼び出せば右マウスボタン(厳密には違いますが)で メニューが表示されます。メニュー項目が選択されたなら、
WM_COMMAND
メッセージがオーナーウィンドウ (この場合にはフレームウィンドウ)に送付されます。 フレームウィンドウはWM_COMMANDの第一パラメタに格納されている メニュー項目のIDをチェックして必要な処理を行ないます。 これらの処理を追加するとフレームウィンドウプロシジャは 以下のようになります。
---- フレームウィンドウプロシジャ ここから ----/* * procFrame - sub-classed frame window procedure */ static MRESULT EXPENTRY procFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { PSWP pswp ; TRACE("frame %08x %08x %08x\n", msg, mp1, mp2) ; switch (msg) { case WM_ADJUSTWINDOWPOS : pswp = (PSWP) PVOIDFROMMP(mp1) ; WinSetWindowPos(hwndShape, pswp->hwndInsertBehind, pswp->x, pswp->y, pswp->cx, pswp->cy, pswp->fl) ; pswp->fl &= ~SWP_SHOW ; pswp->fl |= SWP_HIDE ; return (*pfnFrame) (hwnd, msg, mp1, mp2) ; case WM_SINGLESELECT : WinSetWindowPos(hwndShape, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER) ; return (MRESULT) 0 ; case WM_BEGINDRAG : WinSendMsg(hwndFrame, WM_TRACKFRAME, MPFROMSHORT(TF_MOVE | TF_SETPOINTERPOS), NULL) ; return (MRESULT) 0 ; case WM_CONTEXTMENU : TRACE("WM_CONEXTMENU\n") ; contextMenu() ; return (MRESULT) 0 ; case WM_COMMAND : switch (SHORT1FROMMP(mp1)) { case IDM_MOVE : WinSendMsg(hwndFrame, WM_TRACKFRAME, MPFROMSHORT(TF_MOVE | TF_SETPOINTERPOS), NULL) ; return (MRESULT) 0 ; case IDM_HIDE : WinShowWindow(hwnd, FALSE) ; return (MRESULT) 0 ; case IDM_ABOUT : WinDlgBox(HWND_DESKTOP, hwnd, procAbout, NULLHANDLE, IDD_ABOUT, NULL) ; return (MRESULT) 0 ; case IDM_EXIT : WinPostMsg(hwnd, WM_CLOSE, NULL, NULL) ; return (MRESULT) 0 ; } return (MRESULT) 0 ; } return (*pfnFrame) (hwnd, msg, mp1, mp2) ; }---- フレームウィンドウプロシジャ ここまで ----
あとは、説明(About)ダイアログのダイアログプロシジャを書けば 一応動作可能になります。 処理らしいものといえば、 初期化時にストリングテーブルから文字列をロードして 設定するぐらいのものです。
なお、エントリフィールドは、デフォルトでは文字列の長さが 32バイトに制限されているので、拡大しています。
---- ダイアログプロシジャ ここから ----/* * ABOUT dialog box */ static MRESULT EXPENTRY procAbout(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { HAB hab ; UCHAR buff[256] ; switch (msg) { case WM_INITDLG : hab = WinQueryAnchorBlock(hwnd) ; WinSendMsg(WinWindowFromID(hwnd, IDD_ROMYTTL), EM_SETTEXTLIMIT, MPFROMSHORT(128), NULL) ; WinSendMsg(WinWindowFromID(hwnd, IDD_ROMYURL), EM_SETTEXTLIMIT, MPFROMSHORT(128), NULL) ; WinLoadString(hab, NULLHANDLE, IDS_ROMYTTL, 256, buff) ; WinSetWindowText(WinWindowFromID(hwnd, IDD_ROMYTTL), buff) ; WinLoadString(hab, NULLHANDLE, IDS_ROMYURL, 256, buff) ; WinSetWindowText(WinWindowFromID(hwnd, IDD_ROMYURL), buff) ; return (MRESULT) 0 ; case WM_COMMAND : switch (SHORT1FROMMP(mp1)) { case DID_OK : case DID_CANCEL : WinDismissDlg(hwnd, DID_OK) ; return (MRESULT) 0 ; } } return WinDefDlgProc(hwnd, msg, mp1, mp2) ; }---- ダイアログプロシジャ ここまで ----
これで、一応はプログラムらしくなったでしょう。 しかし、まだいつも白目を剥いたままです。 最後に目玉を動かすコードを追加してプログラムを完成させます。