タイトル | : Re^2: メニューハンドルの取得方法 |
記事No | : 15688 |
投稿日 | : 2013/06/04(Tue) 12:04 |
投稿者 | : genesis |
VBレスキューさま、魔界の仮面弁士さま、 早速のご返事をありがとうございます。言葉足らずの点が多く、 申し訳ございません。
ターゲットはIE6なのですが、そのウィンドウの中で別の アプリケーションが呼び出されて表示されています(一種の リッチクライアントソフトウェアか)。 その中に項目数3のメニューバー(IEのメニューバーとは別物) があって、項目を押すとプルダウンメニューが展開されること から、メニュー操作を実現したいと考えております。その メニューはショートカットキーが無く、座標を与えてマウスで クリックすることが必要となるため、GetMenuItemRect()を 使おうと考えております。 なお上記のメニューバーは、spy++で、所定のウィンドウハンドル (hwndmnb)によりハイライトさせることができております。
以下コードを示します。メモ帳では所望の結果が得られた のですが、ターゲットに対してはメニューハンドルが0(エラー 番号は0)で、ターゲットのメニューバーのメニューハンドルが GetMenu()では取得できていないと推測しております。
Sub func()
Dim classname(0 To 6) As String, i As Integer Dim wtitle As String, hwnd As Long, hmenu As Long, hsubmenu0 As Long Dim str As String, mcount As Long
classname(0) = "IEFrame" classname(1) = "Shell DocObject View" classname(2) = "Internet Explorer_Server" '第2階層hwndは1つ classname(3) = vbNullString '可変のため。第3階層hwndは1つ classname(4) = vbNullString '可変のため。第4階層hwndは1つ classname(5) = "MnbWin" '第5階層hwndは1つ
wtitle = InputBox("ウィンドウタイトル名を入力")
hwnd = 0 If InStr(wtitle, " - Microsoft Internet Explorer") > 0 Then 'ターゲットの場合 For i = 0 To 5 Step 1 If i = 0 Then hwnd = FindWindowEx(hwnd, 0, classname(i), wtitle) Else 'i=5の時のhwndがhwndmnbに相当。 hwnd = FindWindowEx(hwnd, 0, classname(i), vbNullString) End If If hwnd <> 0 Then hmenu = GetMenu(hwnd) If hmenu = 0 Then str = "Error No:" & CStr(Err.LastDllError) Else mcount = GetMenuItemCount(hmenu) str = "HMENU=" & Hex(hmenu) & " 項目数=" & mcount End If hsubmenu0 = GetSubMenu(hmenu, 0) '0番目のサブメニュー If hsubmenu0 = 0 Then str = str & vbCrLf & "Error No:" & CStr(Err.LastDllError) Else mcount = GetMenuItemCount(hsubmenu0) str = str & vbCrLf & "HSUBMENU0=" & Hex(hsubmenu0) & " 項目数=" & mcount End If MsgBox i & " hwnd=" & Hex(hwnd) & vbCrLf & str End If Next i ElseIf InStr(wtitle, " - メモ帳") > 0 Then hwnd = FindWindowEx(hwnd, 0, vbNullString, wtitle) If hwnd > 0 Then hmenu = GetMenu(hwnd) If hmenu = 0 Then str = "Error No:" & CStr(Err.LastDllError) Else mcount = GetMenuItemCount(hmenu) str = "HMENU=" & Hex(hmenu) & " 項目数=" & mcount str = str & MyGetMenuItemString(hmenu, 3) 'メニューバーの3番目の項目名 End If hsubmenu0 = GetSubMenu(hmenu, 0) '0番目のサブメニュー If hsubmenu0 = 0 Then str = str & vbCrLf & "Error No:" & CStr(Err.LastDllError) Else mcount = GetMenuItemCount(hsubmenu0) str = str & vbCrLf & "HSUBMENU0=" & Hex(hsubmenu0) & " 項目数=" & mcount str = str & MyGetMenuItemString(hsubmenu0, 8) 'メニューバーの0番目のサブメニューの8番目の項目名 End If MsgBox i & " hwnd=" & Hex(hwnd) & vbCrLf & str End If End If
End Sub
''※MyGetMenuItemString()は、自作関数でGetMenuItemInfo()を用いている
上記による調査結果 i=0(第0階層) HEMNU取得OKだが項目数=0。それの0番目SUBMENU取得NGでエラー番号0 i=1(第1階層) HMENU取得NGでエラー番号0。それの〃NGでエラー番号1401 i=2(第2階層) HMENU取得NGでエラー番号0。それの〃NGでエラー番号1401 i=3(第3階層) HEMNU取得OKだが項目数=-1。それの〃NGでエラー番号1401 i=4(第4階層) HMENU取得NGでエラー番号0。それの〃NGでエラー番号1401 i=5(第5階層) HMENU取得NGでエラー番号0。それの〃NGでエラー番号1401 ※第5階層がメニューバーに相当。
やはりメニューバー風の「見せかけ」で、独自の実装なのでしょうか…
> > OS:WindowsXP > ということは、権限周りの問題や、64bitアプリとの通信問題は > 除外して考えてよさそうですね。 > > > > そのメニューバーのウィンドウハンドルhwndmnbは、spy++等で > > 得られていますが、GetMenu(hwndmnb)では0が戻ってきてしまい > > メニューハンドルが取得できません。 > Spy++ で得た HWND を GetMenu に渡している…ということでしょうか。 > (取得したいのは、ポップアップメニューではないのですよね?) > > Option Explicit > Private Declare Function GetMenu Lib "user32" (ByVal hWnd As OLE_HANDLE) As OLE_HANDLE > Private Sub Command1_Click() > Dim target As OLE_HANDLE > target = CLng(Text1.Text) 'Spy++で調べたウィンドウハンドルを入れておく > Text2.Text = CStr(GetMenu(target)) > Text3.Text = CStr(Err.LastDllError) > End Sub > > > 戻り値に 0 が返却されたときに、Err.LastDllError は何を返しますか? > > On Error Resume Next 等で、エラーを握りつぶしており、 > 実際には別の場所に問題を抱えていた…ということはありませんか? > > > > (浅知恵ですが、プロセスとかスレッドが保有するメニューを知るような方法 > > が無いか、とか…) > メニューはウィンドウに所属するので、本来はGetMenu が最適でしょうね。 > > > > (このアプリが独自のメニュー実装になっているからか・・・) > そのアプリが、別ウィンドウに所属するメニューを、 > ポップアップメニューとして表示しているとか…?
|