一応これまでのところでプログラムは動いて 絵を表示できるようにはなりましたが、いまのままでは、
- 動かせない
- 隠せない
- 止められない
- いつも白目を剥いている!!
という状態ですので、ユーザ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) ;
}
---- ダイアログプロシジャ ここまで ----
これで、一応はプログラムらしくなったでしょう。 しかし、まだいつも白目を剥いたままです。 最後に目玉を動かすコードを追加してプログラムを完成させます。
