Hatena::ブログ(Diary)

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

2009-12-27

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

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

引き続き、あぷりをいじるメモです。

ラジオボタンチェックボックスあたりです。

ラジオボタンの状態を知る(BM_GETCHECK)

ラジオボタンに限らず、チェックボックスも同様なんですが

一応、分けて書きますね。


・(&HF0)BM_GETCHECK…ラジオorチェックボックスのチェック状態を知る

SendMessageの

 第3引数:未使用

 第4引数:未使用

 返り値 :0…(&H00)BST_UNCHECKED 'チェックされてない

      1…(&H01)BST_CHECKED 'チェックされてる

      2…(&H02)BST_INDETERMINATE 'グレー状態(選択できない状態ですね)

      ※BST_INDETERMINATEは、3状態可能な場合のみ


ラジオボタンの状態確認

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 BM_GETCHECK = &HF0

    Sub Main()
        Dim hwnd As Integer
        hwnd = FindWindow("SciCalc", "電卓") '親ハンドルを取得

        Dim title() As String = {"16 進", "10 進", "8 進", "2 進"}
        Dim hwnd2(3) As Integer
        hwnd2(0) = FindWindowEx(hwnd, 0, "Button", title(0))
        hwnd2(1) = FindWindowEx(hwnd, 0, "Button", title(1))
        hwnd2(2) = FindWindowEx(hwnd, 0, "Button", title(2))
        hwnd2(3) = FindWindowEx(hwnd, 0, "Button", title(3))

        Dim Ret As Integer
        For i As Integer = 0 To hwnd2.Length - 1
            Ret = SendMessage(hwnd2(i), BM_GETCHECK, 0, 0)
            Console.WriteLine(Ret & ":" & title(i))
        Next
    End Sub

End Module

実行すると、ラジオボタンがついているとこだけ1になりますね。


ここで問題が…

BM_GETCHECKで状態が見れるのだからBM_SETCHECKでチェックをつけれるのかな?

と、思ってしまいがちですがそういうわけでもないもたいですよ??

というわけで、やってみる。

ラジオボタンを切り替える(BM_SETCHECK)

・(&HF1)BM_SETCHECK…ラジオorチェックボックスのチェック状態を変更する

SendMessageの

 第3引数ラジオボタン/チェックボックスの状態を指定。

      0…(&H00)BST_UNCHECKED 'チェックされてない

      1…(&H01)BST_CHECKED 'チェックされてる

      2…(&H02)BST_INDETERMINATE 'グレー状態(選択できない状態ですね)

      ※BST_INDETERMINATEは、3状態可能な場合のみ

 第4引数:未使用

 返り値 :0


では、電卓関数電卓モードに切り替えて…

10進数の16は、16進数に切り替えるといくつになるの?

ってのをやってみますか。

f:id:maeyan:20091227184858j:image

これが16進をクリックすると

f:id:maeyan:20091227184932j:image

こうなるはず。


じゃ、さっそく上の画像の状態で16 進をクリックするコードを実行してみます。

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 BM_SETCHECK = &HF1
    Public Const BST_CHECKED = &H1

    Sub Main()
        Dim hwnd1 As Integer, hwnd2 As Integer
        hwnd1 = FindWindow("SciCalc", "電卓")
        hwnd2 = FindWindowEx(hwnd1, 0, "Button", "16 進")

        SendMessage(hwnd2, BM_SETCHECK, BST_CHECKED, 0)
    End Sub

End Module

結果は、こうなりました。

f:id:maeyan:20091227185817j:image

16進のとこにチェックがついたのはいいけど...

10進のとこにもついてるままじゃんか 汗

ラジオボタンにあるまじき状態になってますね 汗

表示している値をみても10進数の時のままですね。。


もしかして…

GETCHECKで値を調べてループさせていき、チェックがあればチェックを

はずしチェックを付けたいとこに来たらチェックをつけて、さらに

クリックでもすればいいの??

って、思ったけど…実際のところラジオボタンクリックしてるんだから

クリックすればいいんじゃ??

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

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 BM_CLICK = &HF5

    Sub Main()
        Dim hwnd1 As Integer, hwnd2 As Integer
        hwnd1 = FindWindow("SciCalc", "電卓")
        hwnd2 = FindWindowEx(hwnd1, 0, "Button", "16 進")

        SendMessage(hwnd2, BM_CLICK, 0, 0)
    End Sub

End Module

これなら、うまくいきました。


チェックボックスの状態を知る(BM_GETCHECK)

基本的ラジオボタンと同じなんで項目を分ける必要はないんだけどさ・・・

ひとつよくわからないことがあって、チェックボックスの状態がとれるものと

取れないものがあるのね。。

ただそれがいいたかっただけなんだけど。。

電卓チェックボックスは状態取得できるんだけど

VB.netチェックボックス作ってそれをいじってみようと

思ったら状態取得できなかったんですよねぇ。。

これってなんでなんだろ。。


というわけで、もはや代わり映えのないコードだけども

一応、のっけてみる。電卓の Inv or Hypチェックボックス

チェックがあれば、はずすコード

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 BM_GETCHECK = &HF0
    Public Const BM_CLICK = &HF5
    Public Const BST_CHECKED = &H1

    Sub Main()
        Dim hwnd As Integer, hwnd2(1) As Integer
        hwnd = FindWindow("SciCalc", "電卓")
        hwnd2(0) = FindWindowEx(hwnd, 0, "Button", "Inv")
        hwnd2(1) = FindWindowEx(hwnd, 0, "Button", "Hyp")

        For i As Integer = 0 To hwnd2.Length - 1
            If SendMessage(hwnd2(i), BM_GETCHECK, 0, 0) = BST_CHECKED Then _
            SendMessage(hwnd2(i), BM_CLICK, 0, 0)
        Next
    End Sub

End Module

SendMessageStr関数について・・・というよりAPI宣言について

Declare構文を使う場合とDllImport属性を使う方法の2通りがあります。

ここではDeclare構文を使っているのでDeclare構文の方だけ触れます。

Declare構文の定義は下記のようになってます。

[スコープ] Declare [文字コード] Function名 API関数名 _

Lib "DLLファイル名" [Alias "エイリアス名"] (引数) _

[As 戻り値の型]

スコープスコープの修飾子が先頭に着きます。ただし省略可能で省略した場合「Private」になります


文字コードAPI文字列を渡す時のコードを指定できます。

  Auto - 自動的識別し、変換して渡す

  Ansi - ANSIコードに変換して渡す

  Unicode - Unicodeに変換して渡す

 省略した場合Autoが指定されます。


API関数名 と Alias "エイリアス名":定義を知るまでこの2つが何者なのかよくわからなかったです。。

  API関数は、コードを書く人間が好きに名前をつけてよいところです。

  hogehogeでもよいわけです。ただし、それだとAPIのどの関数を参照していいかわからないので

  Alias "エイリアス名"でAPIに記載されている名称の関数名をここに指定します。

  Alias "エイリアス名"が省略可能になっているのは、APIに記載されている名称を

  API関数名に書くと重複となるのでAlias "エイリアス名"は、省略することができます。

なので、SendMessageStr関数とか書いているけど、これはAPIの中でこういう名称の

関数が用意されているのでなくて、SendMessageAという関数の別名として規定した

だけにすぎません。なので、ネットでSendMessageStrって何よ??って検索しても

あまりヒットしないはずです 笑


じゃ、APIに記載されている関数についてですが、最後にAとかWとかついて

いるのに気づくと思いますが(ほとんどが互換性を考慮してAかな?)

これは、ANSI用の場合関数の最後にAがつき、Unicode用の場合関数の最後に

Wがつきます。9X系では、ANSI用のみですが、NT系では、ANSI用とUnicode用の

関数が使えることになっているそうです。

関数名にAもWもついていない場合はカーネルに合わせてANSIUnicode

判断して関数を呼ぶようです。その場合9X系は、ANSI/NT系は、Unicodeになるようです。


引数戻り値の型は、API関数で必要な引数と必要に応じて戻り値の型を用意するってことですね。


結局、

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 System.Text.StringBuilder) As Integer

って、SendMessageAという関数に対し渡したい引数(lParam)が違うんで

SendMessageという名前の関数とSendMessageStrという名前の関数

便宜上作ったというだけです。はい。

Declare Function tarou 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 jirou Lib "user32.dll" Alias "SendMessageA" _
(ByVal hWnd As Integer, ByVal MSG As Integer, _
ByVal wParam As Integer, ByVal lParam As System.Text.StringBuilder) As Integer

でも、お好きな名前をどうぞ 笑


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

らぶらぶ 2018/03/07 15:39 お世話になります。

この記事のおかげで非常に助かりました。
普段Win32APIを使うことはないので,全体像も併せて
理解することができました。

この記事にあります通り,チェックボックスの制御が
できなくて困っておりましたが,下記サイトで解決
することができましたので参考としてお知らせさせて
いただきます。
https://stackoverflow.com/questions/32484520/viewing-checkedstatus-of-checkbox-in-external-application-vs-2012

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

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