30/09/2018, 23:05

Send a button click on another program C#

thật sự thì em không biết đặt tiêu đề tiếng Việt như thế nào cho nó phù hợp nên em mới đặt như vậy.
Chuyện là em đnag viết một cái tool nhỏ, ứng dụng của nó là khi click vào một cái button bên đây thì nó sẽ mở một cái app khác (ở đây là em mở OpenVPN) và rồi sau đó sẽ ấn một button bên app OpenVPN.
và em đang bị kẹt ở chỗ là không tài nào send được cái sự kiện click chuột qua cái app bên kia. Tức là đã bật openVPN client lên rồi, nhưng lại không có chuyện gì xảy ra sau đó .

control ID của button Disconnect trong spy++:


và đây là đoạn code của em

    private const int VM_COMMAND = 0x0111;
    private const int BN_CLICKED = 0;
    private const int ButtonId = 0xA3;
    private const string fn = @"C:Program FilesOpenVPNinopenvpn-gui.exe";
    [DllImport("user32.dll")]
    static extern IntPtr GetDlgItem(IntPtr hWnd, int nIDDlgItem);
    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

    private static ProcessModule GetModule(Process p)
    {
        ProcessModule pm = null;
        try
        {
            pm = p.MainModule;
        }
        catch
        {
            return null;
        }
        return pm;
    }

    public static void openApp()
    {
        IntPtr handle = IntPtr.Zero;
        Process[] localAll = Process.GetProcesses();
        IntPtr hWndButton = GetDlgItem(handle, ButtonId);
        foreach(Process p in localAll)
        {
            if(p.MainWindowHandle != IntPtr.Zero)
            {
                ProcessModule pm = GetModule(p);
                if(pm != null && p.MainModule.FileName == fn)
                {
                    handle = p.MainWindowHandle;
                    break;
                }
            }
        }
        if(handle == IntPtr.Zero)
        {
            MessageBox.Show("Not Found.");
            return;
        }
        int wParam = (BN_CLICKED << 16) | (ButtonId & 0xffff);
        SendMessage(handle, VM_COMMAND, wParam, hWndButton);
    }

Không biết code em sai chỗ nào và có cách nào khác ngoài dùng SendMessage k ạ ? mong cách thánh chỉ giáo.

Văn Dương viết 01:16 ngày 01/10/2018

Đây là 1 đoạn chương trình mình dung để click vào nút “Thông tin” của Unikey 4.0 RC2. Bạn có thể tham khảo

using System;
using System.Runtime.InteropServices;

namespace CSharp_SendMessage {
    class Program {

        [DllImport("user32.dll")]
            private static extern IntPtr FindWindow(string lpClassName,string lpWindowName);

            [DllImport("user32.dll")]
            private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,string lpszClass,string lpszWindow);

            [DllImport("user32.dll")]
            private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

            static void Main(string[] args) {
                IntPtr hwnd = FindWindow(null, "UniKey 4.0 RC2"); // Lấy Handle của Unikey theo tên cửa sổ
                IntPtr button = FindWindowEx(hwnd, IntPtr.Zero, null, "Thông tin"); // Lấy handle của nút "Thông tin" theo text
                SendMessage(button, 0x00F5, IntPtr.Zero, IntPtr.Zero); // Gửi tin nhắn BM_CLICK=0x005F để click
            }
        }
}

Kết quả :

Trịnh Minh Cường viết 01:08 ngày 01/10/2018

Cho mình hỏi cái 0x00F5 là giá trị gì vậy ? tại lúc đầu cứ tưởng nó là control ID cho nên cứ đi mò trong control ID

Văn Dương viết 01:12 ngày 01/10/2018

0x00F5 là giá trị của tin nhắn BM_CLICK. Gửi tin nhắn (Message) này đến button nào thì sự kiện click xảy ra nếu button đó khả dụng.

KlogX viết 01:10 ngày 01/10/2018

Hi. Cho mình hỏi chút. Mình có dùng lại ví dụ trên Unikey thì click được nhưng trên một số chương trình khác có tên class như WindowsForms10.BUTTON.app. …
Thì khi SendMessage lại không có hiện tượng gì xảy ra cả :((
Có ai gặp issue này không?

Nguyễn Quốc Thái viết 01:18 ngày 01/10/2018

Cái này là vì WinForm, WPF và UWP dùng event riêng, không dùng chung Window Message với các app viết bằng Win32 Controls nhé.

Dark.Hades viết 01:20 ngày 01/10/2018

Bạn có thể dùng thử Spy++ của visual studio xem thử event logging
(Mình cũng không chắc nó hoạt động trên mấy app C#)

KlogX viết 01:14 ngày 01/10/2018

Vậy làm thế nào bạn?

KlogX viết 01:16 ngày 01/10/2018

Mình có dùng Spy++ mò mãi mà chưa được

Nguyễn Quốc Thái viết 01:19 ngày 01/10/2018

1 cách làm mới hiện nay là dùng WinAppDriver cho Selenium, giống như dùng Selenium để làm automation testing.

GitHub

Microsoft/WinAppDriver

WinAppDriver - Windows Application Driver

Bài liên quan
0