DOBON.NET DOBON.NETプログラミング掲示板過去ログ

他ウィンドウのボタンをSendMessageで押したいのですが・・・

環境/言語:[WinXP Pro SP2,VB.NET 2002,.NET Framework 1.1]
分類:[.NET]

はじめまして。いつも参考にさせていただいております。
早速ですが、質問をさせて頂きます。

VB.NETで作成したプログラムから、windowメッセージを使用して
他のウィンドウにあるボタンを押下したのですがうまくいきません。

実現するためにはそのボタン(コントロール)のハンドルを取得して、WM_LBUTTONDOWN→WM_LBUTTONUPすればよいのかと思っているのですが、
うまく押すことができません。

ご存知の方いらっしゃればお教え下さい。
よろしくお願いします。
------------------------------------------------------

Public Const CONTROLID As Integer = 1
Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Public Declare Function GetDlgItem Lib "user32.dll" Alias "GetDlgItem" ( _
ByVal hDlg As Integer, ByVal nIDDlgItem As Integer) As Integer
Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As Integer) As Integer
Public Const WM_LBUTTONDOWN As Short = &H201
Public Const WM_LBUTTONUP As Short = &H202

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim nCallWnd As Integer = FindWindow("WindowsForms10.app1", "Form1")
Dim nAcceptBtn As Integer = GetDlgItem(nCallWnd, CONTROLID)
Call SendMessage(nAcceptBtn, WM_LBUTTONDOWN, 0, 0)
Call SendMessage(nAcceptBtn, WM_LBUTTONUP, 0, 0)
End Sub
こんにちは。

> VB.NETで作成したプログラムから、windowメッセージを使用して
> 他のウィンドウにあるボタンを押下したのですがうまくいきません。
> Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
> ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As Integer) As Integer

まず、SendMessageではなくPostMessageを使用してください。
それから、WM_LBUTTONDOWN及びWM_LBUTTONUPの場合
lParamはByRefではなくByValでなくてはいけません。
ant 軍団さん、ご返信ありがとうございます。

> まず、SendMessageではなくPostMessageを使用してください。
> それから、WM_LBUTTONDOWN及びWM_LBUTTONUPの場合
> lParamはByRefではなくByValでなくてはいけません。

上記のように修正しましたら、ちゃんとボタンを押下できるようになりました。
ありがとうございました!

ただ、正常に動作する理由がよく理解できていないのですが、よろしければ教えてもらえませんでしょうか。

疑問点としては2つです。
@SendMessageのまま、lParamをyValに変更しただけでも押下できるようになったのですが、PostMessageを使用した方がよいのでしょうか。

AWM_LBUTTONDOWN及びWM_LBUTTONUPはなぜlParamをByValにする必要があったのでしょうか。#ちなみに、WM_COPYDATAの時はByRefにしないとうまくいきませんでした。

ご存知の方いらっしゃればお教え下さい。
> @SendMessageのまま、lParamをyValに変更しただけでも押下できるようになったのですが、PostMessageを使用した方がよいのでしょうか。

SendMessageで行うと、その処理が終わるまで制御が
返ってこないことになります。通常はPostMessageを
使うと思います。

> AWM_LBUTTONDOWN及びWM_LBUTTONUPはなぜlParamをByValにする必要があったのでしょうか。#ちなみに、WM_COPYDATAの時はByRefにしないとうまくいきませんでした。

lParamに指定する値はメッセージによって異なります。
WM_COPYDATAの場合はCOPYDATASTRUCT構造体のポインタを要求
しているので、参照を渡すように指示してあとはマーシャラーに
任せます。WM_LBUTTONDOWNの場合はカーソルの位置の
値自身を要求しているので、値渡しをするためにByValにします。
詳しくは、MSDNを参照ください。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/mouseinputreference/mouseinputmessages/wm_lbuttondown.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/dataexchange/datacopy/datacopyreference/datacopymessages/wm_copydata.asp
ant 軍団さん、ご返信ありがとうございます。

>>@SendMessageのまま、lParamをyValに変更しただけでも押下できるようになったのですが、PostMessageを使用した方がよいのでしょうか。
>
> SendMessageで行うと、その処理が終わるまで制御が
> 返ってこないことになります。通常はPostMessageを
> 使うと思います。

なるほど。
キーを送信するときなどはPostMessageを使ったほうがベターってことですね。

>>AWM_LBUTTONDOWN及びWM_LBUTTONUPはなぜlParamをByValにする必要があったのでしょうか。#ちなみに、WM_COPYDATAの時はByRefにしないとうまくいきませんでした。
>
> lParamに指定する値はメッセージによって異なります。
> WM_COPYDATAの場合はCOPYDATASTRUCT構造体のポインタを要求
> しているので、参照を渡すように指示してあとはマーシャラーに
> 任せます。WM_LBUTTONDOWNの場合はカーソルの位置の
> 値自身を要求しているので、値渡しをするためにByValにします。
> 詳しくは、MSDNを参照ください。
>
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/mouseinputreference/mouseinputmessages/wm_lbuttondown.asp
>
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/dataexchange/datacopy/datacopyreference/datacopymessages/wm_copydata.asp

なるほどー!
頭の中のもやもやが解けました!!
簡単そうに見えて、奥が深いですね。

解説どうもありがとうございました。
#「解決済み」にさせて頂きます。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板