Operaとかはメニューの階層が深いのでなんとかカスタマイズできないかってことで、他アプリのメニュー操作を調査してみました。
調査もかねてメニューカスタマイズツールを作ってみました。
直接メニューをいじるソフトなんで当面は非公開ですが、自己責任でもし使ってみたい人がいたらメール下さい(WM6用です)。
カスタマイズしても設定を保存できないのであくまで調査・解析用です。
さて、なんか便利そうなアプリは作れるかな。アイデアあったら教えて下さい(^^;;;
何ができるかって言うと、起動中のアプリケーション名を選択(またはクラス名を指定)して
(1)左右メニューの名称とID一覧を取得できます。
(2)メニュー名とIDを指定してメニューの追加ができます。
(3)メニュー名を指定してメニューの削除ができます。
(4)メニュー名を置換できます。
(5)チェックの反転ができます。(ON→OFF / OFF→ON)
他アプリのメニュー取得、まる2日がかりでものすごい大変でした(^^;
メニューの取得の方法の大まかな流れです。
(1)SHFindMenuBarでメニューハンドルを取得する
Dim hMenu As IntPtr = SHFindMenuBar(hWnd)
(2)メニューにTB_GETBUTTONメッセージを投げて左右のメニュー情報を取得する
左:SendMessage(hMenu, TB_GETBUTTON, 0, TBBUTTON構造体ポインタ)
右:SendMessage(hMenu, TB_GETBUTTON, 1, TBBUTTON構造体ポインタ)
サブメニューハンドルが取れる
hSubMenu = TBBUTTONのdwData
(3)GetMenuItemInfoで各メニューを取得する
GetMenuItemInfo(hSubMenu, uItem, fByPosition, MENUITEMINFO構造体ポインタ)
戻ってきたMENUITEMINFOより、IDやメニュー名、サブメニューハンドルが取得できる
流れ的にはこれだけで、自分のメニューを取る分には問題なかったんですが、他のアプリにSendMessageでポインタを渡してあげても受け付けてくれない。
CreateFileMappingとMapViewOfFileで他アプリと共有できるメモリを割当てて、それをポインタとして割当ててあげないとだめでした。
(2)の場合こんな感じ
Dim tbb As New TBBUTTON
Dim hFileMapping As IntPtr = CreateFileMapping(&HFFFFFFFF, IntPtr.Zero, PAGE_READWRITE, 0, Marshal.SizeOf(tbb), IntPtr.Zero)
Dim memTBtn As IntPtr = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0)
SendMessage(hMenu, TB_GETBUTTON, 0, memTBtn.ToInt32)
tbb = Marshal.PtrToStructure(memTBtn, GetType(TBBUTTON))
UnmapViewOfFile(memTBtn)
CloseHandle(hFileMapping)
ソフトキーの名称をとるのにまた一苦労。TBBUTTONのiStringに文字列のハンドルが帰ってくるんですが、これがまた他プロセスのポインタなのでそのまま使えない。
他アプリのウインドウハンドルでプロセスIDを取得して・・・↓な感じです(^^;
Dim intRdCnt As Integer
Dim memStr As IntPtr = LocalAlloc(LMEM_FIXED Or LMEM_ZEROINIT, 256)
GetWindowThreadProcessId(hWnd, intPID)
Dim hProc As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, intPID)
ReadProcessMemory(hProc, tbb.iString, memStr, 256, intRdCnt)
dim iString as String = Marshal.PtrToStringUni(memStr)
LocalFree(memStr)
CloseHandle(hProc)
iStringにソフトキー名が入ります。
ソフトキー名を取ることはできたけど、ソフトキー名を変更するのはいろいろやってみたけど断念です。
TB_DELETEBUTTONでソフトキーメニューを削除して、TB_ADDBUTTONSで再度追加をしてみたけど追加されない…