Hatena::ブログ(Diary)

×××Diary このページをアンテナに追加 RSSフィード

2009-12-27

自作あぷりからAPIで他のあぷりをいじるときのめも。(3/4)

前回の記事自作あぷりからAPIで他のあぷりをいじるときのめも。(2/4)

電卓だけだと、いじりたい物がついてなかったりするんで

他にいじってみたいものだけ集めて1つのフォームを作ってみました。

f:id:maeyan:20091228110650j:image

↑上から順にTextBox/RichEdit/ListBox/ComboBox

ListBoxには、 ListBox01,ListBox02,・・・,ListBox10が入っていて

ComboBoxには、ComboBox01,ComboBox02,・・・,ComboBox10が入ってます

各ボタンは、それぞれの値を表示するボタンです。

クラス名とツリー関係はこうなってます。

f:id:maeyan:20091228110815j:image

TextBoxに文字を送る(WB_SETTEXT)

じゃ、文字でも送ってみます。

・(&HC)WM_SETTEXT…文字列を送る

SendMessageの

 第3引数:未使用

 第4引数:送りたい文字列を指定します

 返り値 :成功すると1、失敗した場合、ウィンドウによってエラーが違いますね。

Imports System.Text
Module Module1
    Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

    Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
    (ByVal hwndParent As Integer, ByVal hwndChildAfter As Integer, _
    ByVal lpszClass As String, ByVal lpszWindow As String) As Integer

    Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
    (ByVal hWnd As Integer, ByVal MSG As Integer, _
    ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Declare Function SendMessageStr Lib "user32.dll" Alias "SendMessageA" _
    (ByVal hWnd As Integer, ByVal MSG As Integer, _
    ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer

    Public Const WM_SETTEXT = &HC
    Public Const BM_CLICK = &HF5

    Sub Main()
        Dim hwnd1 As Integer, hwnd2 As Integer, hwnd3 As Integer
        hwnd1 = FindWindow("WindowsForms10.Window.8.app.0.378734a", "test")
        hwnd2 = FindWindowEx(hwnd1, 0, "WindowsForms10.BUTTON.app.0.378734a", "表示1")
        hwnd3 = FindWindowEx(hwnd1, 0, "WindowsForms10.EDIT.app.0.378734a", "")

        'TextBoxに何か文字列を送ってみる。
        Dim Ret As Integer, sb = New StringBuilder
        sb = New StringBuilder("ほげほげ")
        Ret = SendMessageStr(hwnd3, WM_SETTEXT, 0, sb)

        '表示1をクリックしてみる
        SendMessage(hwnd2, BM_CLICK, 0, 0)
    End Sub

End Module

これで「ほげほげ」って表示されますね。

しれっと、StringBulider型の変数文字列をつっこんで

送信したんですが…String型でも送れますね。。

試しに、RichEdit欄にString型で送りつけてみる。

Module Module1
    Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

    Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
    (ByVal hwndParent As Integer, ByVal hwndChildAfter As Integer, _
    ByVal lpszClass As String, ByVal lpszWindow As String) As Integer

    Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
    (ByVal hWnd As Integer, ByVal MSG As Integer, _
    ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Declare Function SendMessageStr Lib "user32.dll" Alias "SendMessageA" _
    (ByVal hWnd As Integer, ByVal MSG As Integer, _
    ByVal wParam As Integer, ByVal lParam As String) As Integer

    Public Const WM_SETTEXT = &HC
    Public Const BM_CLICK = &HF5

    Sub Main()
        Dim hwnd1 As Integer, hwnd2 As Integer, hwnd3 As Integer
        hwnd1 = FindWindow("WindowsForms10.Window.8.app.0.378734a", "test")
        hwnd2 = FindWindowEx(hwnd1, 0, "WindowsForms10.BUTTON.app.0.378734a", "表示2")
        hwnd3 = FindWindowEx(hwnd1, 0, "WindowsForms10.RichEdit20W.app.0.378734a", "")

        'RichEDITに何か文字列を送ってみる。
        Dim Ret As Integer, str As String
        str = "ほげ" & vbCr & "ほげ"
        Ret = SendMessageStr(hwnd3, WM_SETTEXT, 0, str)

        '表示2をクリックしてみる
        SendMessage(hwnd2, BM_CLICK, 0, 0)
    End Sub

End Module

f:id:maeyan:20091228111750j:image

こんな感じでちゃんと表示されますね。



ListBoxをいじってみる

ここでやってみることは、

ListBoxのリスト内容を調べる。

目的の項目を選択状態にしてみる。

この2点に絞ります。


まず、リストにいくつアイテムが入っているのかわからないと

コードがかけたもんじゃないんで、リストの数を調べるメッセージでも

投げてみたいと思います。

リストボックス関係は、LB_系ですね。

・(&H18B)LB_GETCOUNT…リストボックスの項目するを調べる

SendMessageの

 第3引数:未使用

 第4引数:未使用

 返り値 :エラー時、LB_ERR(-1)


次に、個数がわかればFor文でくるくるまわして各アイテムを取得するだけなので

電卓の例で表示の文字列を取得した時のように各項目の長さを調べて

変数を作って受取るの繰り返しをすればよさそうですね。

使うメッセージは・・・

・(&H18A)LB_GETTEXTLEN…指定した項目の長さを取得

SendMessageの

 第3引数:どの項目の長さを知りたいか指定します

 第4引数:未使用

 返り値 :該当する項目の文字数


・(&H189)LB_GETTEXT…指定した項目の文字列を取得

SendMessageの

 第3引数:どの項目の文字列を取得するか指定します。

 第4引数文字列を受取る為の変数を指定します。

 返り値 :受け取った文字列文字数

Imports System.Text
Module Module1
  Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

  Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
  (ByVal hwndParent As Integer, ByVal hwndChildAfter As Integer, _
  ByVal lpszClass As String, ByVal lpszWindow As String) As Integer

  Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
  (ByVal hWnd As Integer, ByVal MSG As Integer, _
  ByVal wParam As Integer, ByVal lParam As Integer) As Integer

  Declare Function SendMessageStr Lib "user32.dll" Alias "SendMessageA" _
  (ByVal hWnd As Integer, ByVal MSG As Integer, _
  ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer

  Public Const LB_GETCOUNT = &H18B
  Public Const LB_GETTEXT = &H189
  Public Const LB_GETTEXTLEN = &H18A

  Sub Main()
    Dim hwnd1 As Integer, hwnd2 As Integer, hwnd3 As Integer
    hwnd1 = FindWindow("WindowsForms10.Window.8.app.0.378734a", "test")
    hwnd2 = FindWindowEx(hwnd1, 0, "WindowsForms10.BUTTON.app.0.378734a", "表示3")
    hwnd3 = FindWindowEx(hwnd1, 0, "WindowsForms10.LISTBOX.app.0.378734a", "")

    Dim Index As Integer
    Index = SendMessage(hwnd3, LB_GETCOUNT, 0, 0)

    Dim LB As String = ""
    For i As Integer = 0 To Index - 1
      Dim length As Integer
      length = SendMessage(hwnd3, LB_GETTEXTLEN, i, 0)

      Dim Ret As Integer, sb = New StringBuilder
      sb = New StringBuilder("", length)
      Ret = SendMessageStr(hwnd3, LB_GETTEXT, i, sb)
      If LB = "" Then
        LB = sb.ToString & vbCrLf
      Else
        LB = LB & sb.ToString & vbCrLf
      End If
    Next
    MsgBox(LB)
  End Sub

End Module

これはこれで各項目の値が取得できるんですが…

WM_GETTEXTの時には、SendMessageの第3引数に受取る文字列バイト数を指定して

第4引数に受取る変数を指定したのに対し、LB_GETTEXTの場合には、第3引数

どの項目を受取るのか指定するだけなんですね。。


疑問:もしかして、文字数を調べなくてよかったりするの???


試してみる。

Imports System.Text
Module Module1
  Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

  Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
  (ByVal hwndParent As Integer, ByVal hwndChildAfter As Integer, _
  ByVal lpszClass As String, ByVal lpszWindow As String) As Integer

  Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
  (ByVal hWnd As Integer, ByVal MSG As Integer, _
  ByVal wParam As Integer, ByVal lParam As Integer) As Integer

  Declare Function SendMessageStr Lib "user32.dll" Alias "SendMessageA" _
  (ByVal hWnd As Integer, ByVal MSG As Integer, _
  ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer

  Public Const LB_GETCOUNT = &H18B
  Public Const LB_GETTEXT = &H189

  Sub Main()
    Dim hwnd1 As Integer, hwnd2 As Integer, hwnd3 As Integer
    hwnd1 = FindWindow("WindowsForms10.Window.8.app.0.378734a", "test")
    hwnd2 = FindWindowEx(hwnd1, 0, "WindowsForms10.BUTTON.app.0.378734a", "表示3")
    hwnd3 = FindWindowEx(hwnd1, 0, "WindowsForms10.LISTBOX.app.0.378734a", "")

    Dim Index As Integer
    Index = SendMessage(hwnd3, LB_GETCOUNT, 0, 0)

    Dim LB As String = ""
    For i As Integer = 0 To Index - 1
      Dim Ret As Integer, sb = New StringBuilder
      sb = New StringBuilder("")
      Ret = SendMessageStr(hwnd3, LB_GETTEXT, i, sb)
      If LB = "" Then
        LB = sb.ToString & vbCrLf
      Else
        LB = LB & sb.ToString & vbCrLf
      End If
    Next
    MsgBox(LB)
  End Sub

End Module

これでもいけますね。

次に目的の項目を選択してみる…

(&H186)LB_SETCURSEL…リストボックスの項目を選択する

SendMessageの

 第3引数:選択したい項目を指定。

      -1を指定すると選択解除となる。

 第4引数:未使用。

 返り値 :エラー時、LB_ERR(-1)


ついでに、

(&H197)LB_SETTOPINDEX…指定した項目をリストの上部に表示する

SendMessageの

 第3引数:項目を指定

 第4引数:未使用。

 返り値 :エラー時、LB_ERR(-1)


Module Module1
    Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

    Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
    (ByVal hwndParent As Integer, ByVal hwndChildAfter As Integer, _
    ByVal lpszClass As String, ByVal lpszWindow As String) As Integer

    Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
    (ByVal hWnd As Integer, ByVal MSG As Integer, _
    ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Public Const LB_GETCOUNT = &H18B
    Public Const BM_CLICK = &HF5
    Public Const LB_SETCURSEL = &H186
    Public Const LB_SETTOPINDEX = &H197

    Sub Main()
        Dim hwnd1 As Integer, hwnd2 As Integer, hwnd3 As Integer
        hwnd1 = FindWindow("WindowsForms10.Window.8.app.0.378734a", "test")
        hwnd2 = FindWindowEx(hwnd1, 0, "WindowsForms10.BUTTON.app.0.378734a", "表示3")
        hwnd3 = FindWindowEx(hwnd1, 0, "WindowsForms10.LISTBOX.app.0.378734a", "")

        Dim Index As Integer
        Index = SendMessage(hwnd3, LB_GETCOUNT, 0, 0)

        For i As Integer = 0 To Index - 1
            SendMessage(hwnd3, LB_SETTOPINDEX, i, 0)
            SendMessage(hwnd3, LB_SETCURSEL, i, 0)
            SendMessage(hwnd2, BM_CLICK, 0, 0)
        Next
    End Sub

End Module

これで、リストの最初の物から順にスクロールしつつ、選択が変わっていくんだけど…

ボタンをおすことで現在選択されているリストを表示する

部分で正しく選択されなーーーーい。なぜ???


ComboBoxをいじる。

ここまでやれば、もう説明不要かと。。

リストボックスで送ったメッセージがLBだったのがCBに変わっただけですね。

CBになった際の値は、

・CB_GETCOUNT = &H146

・CB_SETCURSEL = &H14E

・CB_SETTOPINDEX = &H15C


Module Module1
    Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

    Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
    (ByVal hwndParent As Integer, ByVal hwndChildAfter As Integer, _
    ByVal lpszClass As String, ByVal lpszWindow As String) As Integer

    Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
    (ByVal hWnd As Integer, ByVal MSG As Integer, _
    ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Declare Function SendMessageStr Lib "user32.dll" Alias "SendMessageA" _
    (ByVal hWnd As Integer, ByVal MSG As Integer, _
    ByVal wParam As Integer, ByVal lParam As String) As Integer

    Public Const CB_GETCOUNT = &H146
    Public Const BM_CLICK = &HF5
    Public Const WM_SETTEXT = &HC
    Public Const CB_SETCURSEL = &H14E
    Public Const CB_SETTOPINDEX = &H15C

    Sub Main()
        Dim hwnd1 As Integer, hwnd2 As Integer, hwnd3 As Integer, hwnd4 As Integer
        hwnd1 = FindWindow("WindowsForms10.Window.8.app.0.378734a", "test")
        hwnd2 = FindWindowEx(hwnd1, 0, "WindowsForms10.BUTTON.app.0.378734a", "表示4")
        hwnd3 = FindWindowEx(hwnd1, 0, "WindowsForms10.COMBOBOX.app.0.378734a", "")
        hwnd4 = FindWindowEx(hwnd3, 0, "EDIT", "")

        Dim Index As Integer
        Index = SendMessage(hwnd3, CB_GETCOUNT, 0, 0)

        For i As Integer = 0 To Index - 1
            SendMessage(hwnd3, CB_SETTOPINDEX, i, 0)
            SendMessage(hwnd3, CB_SETCURSEL, i, 0)
            SendMessage(hwnd2, BM_CLICK, 0, 0)
        Next

        Dim Ret As Integer
        Ret = SendMessageStr(hwnd4, WM_SETTEXT, 0, "ほげほげ")
        SendMessage(hwnd2, BM_CLICK, 0, 0)
    End Sub

End Module

こちらは、クリックメッセージを送ってボタンをおした際にちゃんと表示されますね。

上記コードのうち、CB_SETTOPINDEは使わなくても問題ないみたい。

次の記事自作あぷりからAPIで他のあぷりをいじるときのめも。(4/4)

トラックバック - http://d.hatena.ne.jp/maeyan/20091227/1261936878
リンク元

はてなダイアリーの記事の更新機能、はてなダイアリープラスを停止しました