Как получить дескриптор кнопки стороннего приложения, используя C#?

Я пытаюсь создать событие нажатия в стороннем приложении. Для начала я попытался смоделировать щелчок в калькуляторе. Вот код

IntPtr hwnd = IntPtr.Zero;
IntPtr hwndChild = IntPtr.Zero;
//Get a handle for the Calculator Application main window
hwnd = FindWindow(null, "Calculator");

hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Button", "1");

//send BN_CLICKED message
SendMessage(hwndChild, BM_CLICK, IntPtr.Zero, IntPtr.Zero);

Но с помощью этого кода я не получаю ручку кнопки. Может ли кто-нибудь помочь, пожалуйста. Есть ли другой способ симулировать нажатие кнопки на стороннем приложении?

Благодарю.

4 ответа

Решение

Он начал работать, когда я заменил

public const uint BM_CLICK = 0x00F5;

с

public const uint WM_LBUTTONDOWN = 0x0201; 
public const uint WM_LBUTTONUP = 0x0202;

и использовал

SendMessage(buttonHandle, WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero); 
SendMessage(buttonHandle, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);

Ваш общий подход верен, но есть две потенциальные проблемы с вашим кодом:

  1. FindWindowEx находит только прямые потомки указанного окна. Возможно, что кнопки калькулятора расположены в окне контейнера, которое является дочерним элементом основного окна, поэтому кнопка не будет прямым дочерним элементом основного окна.

  2. Документация для BM_CLICK говорит, что он имитирует щелчок, отправляя сообщения мыши вверх и вниз, и, следовательно, вам может потребоваться активировать родительское окно перед отправкой этого сообщения

Сначала используйте SPY++, чтобы найти кнопку с ручкой.

В некоторых случаях элементы управления, которые выглядят как кнопки, могут быть графическим элементом управления. Разница в том, что графический элемент управления не будет иметь дескриптора, но элемент управления Windows будет иметь дескриптор. Если этот элемент управления имеет действительный Handle.Then использовать FindWindowEx

Также укажите родительский дескриптор окна (я думаю, что первый параметр, может быть, вы должны использовать GetWindow(), используя заголовок)

Затем отправьте сообщение клика.

Если у вас нет ручки кнопки, вы можете эмулировать щелчок мышью по координатам:

class User32
 { 
    [Flags]
    public enum MouseEventFlags
    {
        LEFTDOWN = 0x00000002,
        LEFTUP = 0x00000004,
        MIDDLEDOWN = 0x00000020,
        MIDDLEUP = 0x00000040,
        MOVE = 0x00000001,
        ABSOLUTE = 0x00008000,
        RIGHTDOWN = 0x00000008,
        RIGHTUP = 0x00000010
    }

    [DllImport("user32.dll")]
    public static extern bool SetCursorPos(int X, int Y);

    [DllImport("user32.dll")]
    public static extern void mouse_event(uint dwFlags, 
                                   uint dx, 
                                   uint dy, 
                                   uint dwData,
                                   int dwExtraInfo);

    [DllImport("user32.dll")]
    public static extern void mouse_event(uint dwFlags, 
                                   uint dx, 
                                   uint dy, 
                                   uint dwData,
                                   UIntPtr dwExtraInfo);
}

class Program
{
     static void Main()
     {
         User32.SetCursorPos(25, 153);
         User32.mouse_event((uint)User32.MouseEventFlags.LEFTDOWN, 25, 153, 0, 0);
         User32.mouse_event((uint)User32.MouseEventFlags.LEFTUP, 25, 153, 0, 0);
     }
}

Но функция SetCursorPos устанавливает положение курсора в глобальных координатах экрана, так что сначала вы должны получить возможность окна стороннего приложения.

Другие вопросы по тегам