tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re^2: メニューハンドルの取得方法
投稿日: 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 が最適でしょうね。
>
>
> >  (このアプリが独自のメニュー実装になっているからか・・・)
> そのアプリが、別ウィンドウに所属するメニューを、
> ポップアップメニューとして表示しているとか…?

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。