IE風メニューバーを作る 3
IE風メニューバーを作ります。キーボードナビゲーションというものを実装します。
最終更新:2017/12/05
初版:2017/12/05
#include "user32.as" #include "kernel32.as" #include "hscallbk.as" #uselib "" #func _MsgHookProc "" int,int,int setcallbk MsgHookProc, _MsgHookProc,*OnMsgHookProc //メッセージフックプロシージャー登録 setcallbk KbdHookProc, _MsgHookProc,*OnKbdHookProc //キーボードフックプロシージャー登録 #define RBS_TOOLTIPS 0x00000100 #define RBS_VARHEIGHT 0x00000200 #define RBS_BANDBORDERS 0x00000400 #define RBS_FIXEDORDER 0x00000800 #define RBS_REGISTERDROP 0x00001000 #define RBS_AUTOSIZE 0x00002000 #define RBS_VERTICALGRIPPER 0x00004000 #define RBS_DBLCLKTOGGLE 0x00008000 #define TBSTYLE_ALTDRAG 0x00000400 #define TBSTYLE_AUTOSIZE 0x00000010 #define TBSTYLE_BUTTON 0x00000000 #define TBSTYLE_CHECK 0x00000002 #define TBSTYLE_CHECKGROUP 0x00000006 #define TBSTYLE_CUSTOMERASE 0x00002000 #define TBSTYLE_DROPDOWN 0x00000008 #define TBSTYLE_EX_DRAWDDARROWS 0x00000001 #define TBSTYLE_EX_HIDECLIPPEDBUTTONS 0x00000010 #define TBSTYLE_EX_MIXEDBUTTONS 0x00000008 #define TBSTYLE_FLAT 0x00000800 #define TBSTYLE_GROUP 0x00000004 #define TBSTYLE_LIST 0x00001000 #define TBSTYLE_NOPREFIX 0x00000020 #define TBSTYLE_REGISTERDROP 0x00004000 #define TBSTYLE_SEP 0x00000001 #define TBSTYLE_TOOLTIPS 0x00000100 #define TBSTYLE_TRANSPARENT 0x00008000 #define TBSTYLE_WRAPABLE 0x00000200 #define CCS_ADJUSTABLE 0x00000020 #define CCS_BOTTOM 0x00000003 #define CCS_LEFT 0x00000081 #define CCS_NODIVIDER 0x00000040 #define CCS_NOMOVEX 0x00000082 #define CCS_NOMOVEY 0x00000002 #define CCS_NOPARENTALIGN 0x00000008 #define CCS_NORESIZE 0x00000004 #define CCS_RIGHT 0x00000083 #define CCS_TOP 0x00000001 #define CCS_VERT 0x00000080 #define RBBIM_STYLE 0x00000001 #define RBBIM_COLORS 0x00000002 #define RBBIM_TEXT 0x00000004 #define RBBIM_IMAGE 0x00000008 #define RBBIM_CHILD 0x00000010 #define RBBIM_CHILDSIZE 0x00000020 #define RBBIM_SIZE 0x00000040 #define RBBIM_BACKGROUND 0x00000080 #define RBBIM_ID 0x00000100 #define RBBIM_IDEALSIZE 0x00000200 #define RBBIM_LPARAM 0x00000400 #define RBBIM_HEADERSIZE 0x00000800 #define RBBIM_CHEVRONLOCATION 0x00001000 #define RBBIM_CHEVRONSTATE 0x00002000 #define RBBS_BREAK 0x00000001 #define RBBS_FIXEDSIZE 0x00000002 #define RBBS_CHILDEDGE 0x00000004 #define RBBS_HIDDEN 0x00000008 #define RBBS_NOVERT 0x00000010 #define RBBS_FIXEDBMP 0x00000020 #define RBBS_VARIABLEHEIGHT 0x00000040 #define RBBS_GRIPPERALWAYS 0x00000080 #define RBBS_NOGRIPPER 0x00000100 #define RBBS_USECHEVRON 0x00000200 #define RBBS_HIDETITLE 0x00000400 #define RBBS_TOPALIGN 0x00000800 #define WS_CLIPCHILDREN 0x02000000 #define WS_CLIPSIBLINGS 0x04000000 #define WS_VISIBLE 0x10000000 #define WS_CHILD 0x40000000 #define RB_INSERTBAND 0x0401 #define TB_CHECKBUTTON 0x0402 #define TB_ADDBUTTONS 0x0414 #define TB_BUTTONSTRUCTSIZE 0x041E #define TB_GETRECT 0x0433 #define TB_SETHOTITEM 0x0448 #define TB_MAPACCELERATOR 0x044E #define TB_GETMAXSIZE 0x0453 #define TB_SETEXTENDEDSTYLE 0x0454 #define I_IMAGENONE -2 #define TBSTATE_ENABLED 0x04 #define BTNS_DROPDOWN 0x08 #define BTNS_AUTOSIZE 0x10 #define WM_NOTIFY 0x004E #define WM_KEYDOWN 0x0100 #define WM_MENUSELECT 0x011F #define WM_MOUSEMOVE 0x0200 #define WM_MY_SHOWMENU 0x8000 + 1 #define VK_MENU 0x0012 #define VK_LEFT 0x0025 #define VK_RIGHT 0x0027 #define VK_DOWN 0x0028 #define TBN_DROPDOWN -710 #define TBN_HOTITEMCHANGE -713 #define KEYEVENTF_KEYUP 0x0002 #define TPM_NOANIMATION 0x4000 #define REBARBANDINFO_SIZE 22 #define MF_POPUP 0x00000010 #define MF_INSERT 0x00000000 #define MF_SEPARATOR 0x00000800 #define WH_MSGFILTER -1 #define WH_KEYBOARD 2 #define HC_ACTION 0 #define MSGF_MENU 2 #define ctype LOWORD(%1) (%1&0xFFFF) #define ctype HIWORD(%1) ((%1>>16)&0xFFFF) #define ctype MAKELPARAM(%1,%2) (%1&0xFFFF)|(%2<<16) #enum IDM_NEW = 100 #enum IDM_OPEN #enum IDM_EXIT #enum IDM_UNDO #enum IDM_OPTION #enum IDM_ABOUT #enum IDM_SUBMENUITEM onexit *exit oncmd gosub *l_OnNotify, WM_NOTIFY oncmd gosub *l_OnMenuSelect, WM_MENUSELECT oncmd gosub *l_OnMyShowMenu, WM_MY_SHOWMENU //メニュー項目を作成 hMenu(4) = CreatePopupMenu() AppendMenu hMenu(4), MF_INSERT, IDM_SUBMENUITEM, "サブメニュー項目(&S)" hMenu(3) = CreatePopupMenu() AppendMenu hMenu(3), MF_INSERT, IDM_ABOUT, "バージョン情報(&A)" hMenu(2) = CreatePopupMenu() AppendMenu hMenu(2), MF_POPUP, hMenu(4), "サブメニュー(&S)" //サブメニューを持つ項目を追加してみた AppendMenu hMenu(2), MF_INSERT, IDM_OPTION, "オプション(&O)" hMenu(1) = CreatePopupMenu() AppendMenu hMenu(1), MF_INSERT, IDM_UNDO, "元に戻す(&U)\tCtrl+Z" hMenu(0) = CreatePopupMenu() AppendMenu hMenu(0), MF_INSERT, IDM_NEW, "新規作成(&N)\tCtrl+N" AppendMenu hMenu(0), MF_INSERT, IDM_OPEN, "開く(&O)\tCtrl+O" AppendMenu hMenu(0), MF_SEPARATOR, 0, 0 AppendMenu hMenu(0), MF_INSERT, IDM_EXIT, "終了(&X)\tAlt+F4" hMainMenu = CreateMenu() //トップレベルメニュー AppendMenu hMainMenu, MF_POPUP, hMenu(0), "file" AppendMenu hMainMenu, MF_POPUP, hMenu(1), "edit" AppendMenu hMainMenu, MF_POPUP, hMenu(2), "tool" AppendMenu hMainMenu, MF_POPUP, hMenu(3), "help" //IE風メニューバーを作成 winobj "ToolbarWindow32", "", 0, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_CUSTOMERASE | TBSTYLE_LIST | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP,200, 20, 0, 0 hToolBar = objinfo_hwnd(stat) sendmsg hToolBar, TB_BUTTONSTRUCTSIZE, 20, 0 sendmsg hToolBar, TB_SETEXTENDEDSTYLE, 0, 0 MenuName = "ファイル(&F)", "編集(&E)", "ツール(&T)", "ヘルプ(&H)" //メニューの名前 MenuHnd = hMenu(0), hMenu(1), hMenu(2), hMenu(3) //メニューのハンドル //ボタン追加 foreach MenuName TBB = I_IMAGENONE, cnt, ((BTNS_DROPDOWN|BTNS_AUTOSIZE) << 8) | TBSTATE_ENABLED, 0, varptr(MenuName(cnt)) sendmsg hToolBar, TB_ADDBUTTONS, 1, varptr(TBB) loop //レバーコントロールを作成 winobj "ReBarWindow32", "", 0, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_BANDBORDERS | RBS_VARHEIGHT, 0, 20, 0, 0 hReBar = objinfo_hwnd(stat) dim RBBI, REBARBANDINFO_SIZE RBBI(0) = REBARBANDINFO_SIZE*4 //cbSize RBBI(1) = RBBIM_STYLE | RBBIM_SIZE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_ID //fMask RBBI(2) = RBBS_BREAK | RBBS_GRIPPERALWAYS //fStyle RBBI(8) = hToolBar //hwndChild RBBI(10) = 26 //cyMinChild sendmsg hReBar, RB_INSERTBAND, -1, varptr(RBBI) //バンド追加 hKbdHook = SetWindowsHookEx(WH_KEYBOARD, varptr(KbdHookProc), 0, GetCurrentThreadId()) //キーボードフックインストール nm_mousemoveCount = 0 nm_menuid = -1 stop *exit EndMenu //メニューを閉じる UnhookWindowsHookEx hKbdHook //フック削除 DestroyMenu hMainMenu //トップレベルメニューを削除 end *OnMsgHookProc if bm_show{ //メニューが表示されている時のみ処理 if (callbkarg(0)==MSGF_MENU){ dupptr mhp_pMsg, callbkarg(2), 7*4 //MSG構造体を取り出す。 MenuHookProc mhp_pMsg(0), mhp_pMsg(1), mhp_pMsg(2), mhp_pMsg(3) //メニューフックプロシージャーに処理を渡す。 } } return CallNextHookEx( hm_MsgHook, callbkarg(0), callbkarg(1), callbkarg(2) ) *OnKbdHookProc if (callbkarg(0)==HC_ACTION){ nIndex=0 //アクセラレーター文字に対応したボタンIDを取得する。 SendMessage hToolbar(0), TB_MAPACCELERATOR, callbkarg(1), varptr(nIndex) if ((stat) && (nm_menuid!=nIndex)){ getkey k,18 if k{ //Altキーが一緒に押されてたら処理 bm_ac = 1 bm_ckey = 1 bm_show = 1 nm_menuid=nIndex SendMessage hToolbar(0), TB_SETHOTITEM, nIndex, 0 return 1 } } } return CallNextHookEx( hKbdHook, callbkarg(0), callbkarg(1), callbkarg(2) ) *l_OnNotify return OnNotify(ginfo(24), iparam, wparam , lparam) *l_OnMenuSelect return OnMenuSelect(ginfo(24), iparam, wparam , lparam) *l_OnMyShowMenu return OnMyShowMenu(ginfo(24), iparam, wparam , lparam) #defcfunc OnNotify int msg_wndid, int msg_msg, int msg_wp, int msg_lp //OnNotify 処理用関数 dupptr Nmhdr, msg_lp, 4*3 if ((Nmhdr(0) == hToolBar) && (Nmhdr(2) == TBN_DROPDOWN)){ //ツールバーボタンが押された dupptr nmtoolbar, msg_lp, 44 PostMessage hwnd, WM_MY_SHOWMENU, nmtoolbar(3), 0 //WM_MY_SHOWMENUメッセージを発行してメニューを表示。 } if ((Nmhdr(0) == hToolBar) && (Nmhdr(2) == TBN_HOTITEMCHANGE)){ //ツールバーのホットアイテムが変更された dupptr nmtbhotitem, msg_lp, 24 if ((bm_show) && (nmtbhotitem(4)>=0) && (((nm_menuid!=nmtbhotitem(4)) && (bm_chg)) || (bm_ac))){ EndMenu //メニューを閉じる PostMessage hwnd, WM_MY_SHOWMENU, nmtbhotitem(4), TPM_NOANIMATION //WM_MY_SHOWMENUメッセージを発行してメニューを表示。 } return 1 } return 0 #defcfunc OnMenuSelect int msg_wndid, int msg_msg, int msg_wp, int msg_lp //OnMenuSelect 処理用関数 if bm_show{ bm_haveSubmenu = HIWORD(msg_wp)&MF_POPUP //サブメニューを持つメニューアイテムか判定。 } return 0 #defcfunc OnMyShowMenu int msg_wndid, int msg_msg, int msg_wp, int msg_lp //OnMyShowMenu 処理用関数 //wParam に表示するメニューIDが入ります。 //lParam にTrackPopupMenuExに渡すフラグを指定します。 dim rc,4 sendmsg hToolBar ,TB_GETRECT, msg_wp, varptr(rc) //ツールバーボタンの座標を取得 pt = rc(0),rc(3) ClientToScreen hToolBar, varptr(pt) sendmsg hToolBar, TB_CHECKBUTTON, msg_wp, 1 //ボタンを押した状態にする if bm_ckey{ //通常のメニューと仕様を合わせるため、キーによる操作のときは一番最初の項目をホットアイテムにする。 keybd_event VK_DOWN, 0, 0, 0 keybd_event VK_DOWN, 0, KEYEVENTF_KEYUP, 0 } bm_show = 1 //メニュー表示フラグ nm_menuid = msg_wp //表示中メニューID bm_chg = 0 //メニューが変更されたかのフラグ bm_haveSubmenu = 0 //サブメニューがあるかのフラグ bm_ckey = 0 //キーで操作したかのフラグ bm_ac = 0 //アクセラレータ文字による操作かのフラグ hm_MsgHook = SetWindowsHookEx(WH_MSGFILTER, varptr(MsgHookProc), 0, GetCurrentThreadId()) //フックインストール TrackPopupMenuEx MenuHnd(msg_wp), flag, pt(0), pt(1), hwnd, 0 //メニュー表示 UnhookWindowsHookEx hm_MsgHook //フック削除 bm_show = 0 nm_menuid = -1 bm_chg = 0 bm_haveSubmenu = 0 bm_ac = 0 hm_MsgHook = 0 sendmsg hToolBar, TB_CHECKBUTTON, msg_wp, 0 //ボタンを離した状態にする return 0 #deffunc MenuHookProc int mhp_hwnd, int mhp_msg, int mhp_wp, int mhp_lp switch mhp_msg case WM_MOUSEMOVE nm_mousemoveCount-- if nm_mousemoveCount<0:nm_mousemoveCount=0 if nm_mousemoveCount>0:return pt=LOWORD(mhp_lp), HIWORD(mhp_lp) //マウスカーソルがツールバーの中にあるときだけ処理する。 Rect=0,0,0,0:size=0,0 GetWindowRect hToolbar, varptr(Rect) SendMessage hToolbar, TB_GETMAXSIZE, 0, varptr(size) //ツールバーのサイズ取得 Rect(2)=Rect(0)+size(0),Rect(1)+size(1) PtInRect varptr(Rect), pt(0), pt(1) //マウスカーソルがツールバーのボタンの上にあるかを判定 if stat==0:return ScreenToClient hToolbar, varptr(pt) bm_chg=1 SendMessage hToolbar, mhp_msg, mhp_wp, MAKELPARAM(pt(0), pt(1)) //転送 bm_chg=0 swbreak case WM_KEYDOWN switch mhp_wp case VK_LEFT if (nm_menuid)<=0:nm_menuid=length(MenuHnd) nm_mousemoveCount = 4 bm_chg =1 bm_ckey =1 SendMessage hToolbar(0), TB_SETHOTITEM, nm_menuid-1, 0 swbreak case VK_RIGHT if bm_haveSubmenu:return if nm_menuid>=(length(MenuHnd)-1):nm_menuid=-1 nm_mousemoveCount = 4 bm_chg =1 bm_ckey =1 SendMessage hToolbar(0), TB_SETHOTITEM, nm_menuid+1, 0 swbreak swend swbreak swend return 0
(C)2019 inonote / 無断転載禁止