Unable to check a checkbox using C# WinAPI

2019-09-19 10:52发布

问题:

I'm trying to check a checkbox inside a program called AviReComp and I'm unable to do it somehow. I've tried all sorts of code:

//Check the checkbox
        IntPtr SubtitlesSection = FindWindowEx(MoreOptions, IntPtr.Zero, null, "Subtitles");
        IntPtr AddSubtitlesCheckbox = FindWindowEx(SubtitlesSection, IntPtr.Zero, null, "Enable/Disable");

        SendMessage(AddSubtitlesCheckbox, BM_SETSTATE, 1, IntPtr.Zero);
        SendMessage(AddSubtitlesCheckbox, BM_SETCHECK, 1, IntPtr.Zero);
        SendMessage(AddSubtitlesCheckbox, WM_PAINT, 0, IntPtr.Zero);
        SendMessage(AddSubtitlesCheckbox, WM_LBUTTONDOWN, 1, MakeLParam(10, 10));
        SendMessage(SubtitlesSection, WM_PARENTNOTIFY, (int)MakeLParam((int)AddSubtitlesCheckbox, WM_LBUTTONDOWN), MakeLParam(26, 31));
        SendMessage(SubtitlesSection, WM_PARENTNOTIFY, (int)MakeLParam((int)AddSubtitlesCheckbox, WM_LBUTTONUP), MakeLParam(26, 31));

The checkbox is located within the Additions tab underneath the Subtitles section and is called Enable/Disable.

Am I doing something wrong?

Thanks for any help!

Edit: I now see that this code actually works and it does check the checkbox but I still have a problem since it does not change all the controls that are supposed to change when I check the checkbox manually and not inside my program. Is there a way to force the parent control to repaint itself or trigger the change event when I mark the checkbox as checked?

回答1:

try to use spy++ to make sure of the location of the Check-box if all didn't work and this has to run on vista and above I Would use Windows Automation



回答2:

When the state of a child control changes (in response to a user action), it sends some notification messages to it's parent window, and parent window by catching those messages, performs actions. Those notification messages are WM_COMMAND and WM_NOTIFY.

By monitoring messages sent to the parent window of your check box control (and checking the control by mouse), I noticed one WM_COMMAND message and two WM_NOTIFY messages. Those messages where not available when I programmatically sent a BM_SETCHECK message to the check box. So the magic revealed.

Sending WM_NOTIFY is a little difficult, because you have to allocate memory in the address space of the other process (using VirtualAllocEx, for NMHDR structure), fill the memory (using WriteProcessMemory), send the message, and then release the allocated memory.

Sending WM_COMMAND message is too much simpler. I tested it, and it worked!

    Win32.SendMessage(SubtitlesSection, Win32.Message.WM_COMMAND, 0, AddSubtitlesCheckbox);

The message is sent to the parent control of the check box, using the handle of the control as the fourth parameter. Third parameter of the function should be the control ID, and the ID changes every time. But hopefully it seems that the program checks the control handle and not the ID.