0

I got a WM_COMMAND in a button event by Spy++, It looks like:

image

<000116> 001B0A02 S WM_NOTIFY idCtrl:133978 pnmh:0019F9A0
<000117> 001B0A02 R WM_NOTIFY
<000118> 001B0A02 S WM_COMMAND wNotifyCode:0000 wID:2 hwndCtl:00020B5A
<000119> 001B0A02 R WM_COMMAND
<000120> 001B0A02 S WM_NOTIFY idCtrl:133978 pnmh:0019F9BC
<000121> 001B0A02 R WM_NOTIFY

Then I tried to redo WM_COMMAND by SendMessage:

image

Nothing happened. I used the AHK script to be sure, same result.

When I used SendMessage(), Spy++ got this:

<000423> 001B0A02 S WM_COMMAND wNotifyCode:0000 wID:2 hwndCtl:00000014
<000424> 001B0A02 R WM_COMMAND

I also let the lParam = 0, then it worked but not as I expected, another Menu item opened.

<000001> 001B0A02 S WM_COMMAND wNotifyCode:0 (sent from a menu) wID:2

So how can I do this?

1
  • This is not how you automate a UI. UI Automation is done using UI Automation. Commented Aug 12, 2021 at 17:56

1 Answer 1

1

To emulate the WM_COMMAND for a button click, you need to send the ID of your button and the BN_CLICKED notification code (combined) as the wParam argument to SendMessage(), and the handle (HWND) of the button as the lParam.

If hDlg is the handle of your dialog window, and IDC_MYBUTTON is the resource ID of your button, the call would be like this:

SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_MYBUTTON, BN_CLICKED), (LPARAM)GetDlgItem(hDlg, IDC_MYBUTTON));

As it happens, the BN_CLICKED notification code has a value of 0, so the wParam value will be just the control ID; this appears to be 2 in your case – the value used by Windows for the "Cancel" button. The problem, in your code, seems to be an invalid window handle for the lParam argument.

Sign up to request clarification or add additional context in comments.

6 Comments

@Lain I notice that your first image suggests that your button is part of a control bar or dialog bar. If you can clarify exactly what that is, and how you have created it, then I can (maybe) edit my answer to be more specific to your use case.
An easier way to handle this is to send BM_CLICK to the button itself, and let it handle sending WM_COMMAND/BN_CLICKED to its parent.
@Remy Indeed! But the (possible) problem still remains if it's a control bar, about how to get the relevant HWND for the "button itself". For a dog-box, it's easy; for any of the new-style "magic" bars, it's not so trivial.
@Adrian Mole Thank you for your answer, I'm a novice so I wasted some time figuring it out. As you said, I need an HWND, which is the handle of the button. I tried to SPY++ it, but there's no such thing, the handle that SPY++ gave me (00020B5A)is the handle of the Toolbar. Then I tried to figure out what the button exactly is, I found this in SPY++ WM_DRAWITEM ID: 464210 Control type: ODT_BUTTON Item ID: 0 Item action: ODA_FOCUS Item state: ODS_FOCUS | ODS_NOFOCUSRECT Hwnd item: 0x00071552 Item RECT: 0, 0, 220, 52 Item data: 0x00000000 HDC: 0xbe015650
Does this mean that this button is not a normal button but an Owner-drawn button? I've googled it all day but got nothing useful. My purpose is to use something like AHK to redo the operation of clicking the button in the background. Could you give me some hints? Thank you for your help.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.