+3

Sử dụng method SendMessage để Click button nằm ngoài app.

Trong bài báo này tôi muốn giới thiệu tới các bạn cách sử dụng method SendMessage để gửi lệnh click đến một button nằm trên application khác. Kĩ thuật này cũng rất có khả năng edit và thao tác với những control khác như là label, textfield v.v... Để minh họa cho kĩ thuật trên, chúng ta sẽ viết một ví dụ nho nhỏ cho việc send message click button "=" trên application Calculator của Windown.

1. Xác định button và chức năng của button cần thực hiện.

Trên application Calculator, khi chúng ta ấn "2+2=", ta sẽ nhận được kết qủa hiện thị là 4. Sau đó mỗi khi click "=", kết qủa sẽ được tăng lên 2. Chúng ta sẽ tạo application để tự động click button "=". Chúng ta có thể xác định việc send message thành công hay không thông qua kết qủa hiện thị trên màn hình.

2. Xác định mã id của button "=".

Run windows Calculator, chạy Visual studio. Trong tool menu, click "Spy++".

alt

Click vào icon "Find Window"

alt

"Find Window" dialog sẽ được bật lên. Sau đó click vào "Finder Tool" icon.

alt

Kéo con trỏ từ "Finder Tool" icon đến button "=" và thả chuột. "Find Window" dialog sẽ cung cấp thông tin về window handle và một vài thông tin khác của button "=". Click "OK", "Window Properties" window sẽ hiện ra gồm các tab: General, Styles, Windows, Class và Process.

alt

Xác định gía trị của "Control Id" ở đây gía trị của nó là "00000079". Gía trị này là kiểu hexadecimal value. Khi sử dụng các function của Windows API, controls thường được xác định bởi control id.

3. write the application

Chúng ta cần sử dụng thư viện trong namespaces "System.Diagnostics" và "System.Runtime.InteropServices" .

const int WM_COMMAND = 0x0111;
// Command id của action Click
const int BN_CLICKED = 0;
// Control Id của button "="
const int ButtonId = 0x79;
//Path run exe của window Calculator
const string fn = @"C:\Windows\system32\calc.exe";
//Import method Get Dialog Item handle.
[DllImport("user32.dll")]
static extern IntPtr GetDlgItem(IntPtr hWnd, int nIDDlgItem);
//Import method SendMessage của window Api.
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

Xác định process module chạy application Calculator và Window Handle Id của nó.

IntPtr handle = IntPtr.Zero;
Process[] localAll = Process.GetProcesses();
foreach (Process p in localAll)
{
if (p.MainWindowHandle != IntPtr.Zero)
{
ProcessModule pm = GetModule(p);
if (pm != null && p.MainModule.FileName == fn)
handle = p.MainWindowHandle;
}
}
if (handle == IntPtr.Zero)
{
Console.WriteLine("Not found");
return;
}

Để click button "=", chúng ta sử dụng lệnh send message BN_CLICKED notification message đến Calculator window. Chúng ta cần sử dụng cả button id và window handle Id của button. Xác định Handle của button qua method GetDlgItem:

IntPtr hWndButton = GetDlgItem(handle, ButtonId);

Chúng ta sẽ send WM_COMMAND message. Hai parameter khác chúng ta cần xác định là wParam và lParam. Gía trị của chúng phụ thuộc vào việc chúng ta sử dụng loại message id nào. Trong trường hợp của WM_COMMAND message, wParam có nửa đầu chứa control id của button và nửa sau chứa command id ở đây là BN_CLICKED và lParam chính là Handle của button "=".

int wParam = (BN_CLICKED << 16) | (ButtonId & 0xffff);
SendMessage(handle, WM_COMMAND, wParam, hWndButton);

Để test app, run Calculator và click "2+2=". Sau đó chạy appplication. Mỗi khi chạy, kết qủa hiện thị trên Calculator sẽ tăng thêm 2.

Ví dụ trên đây hữu dụng khi các bạn có nhu cầu viết một application auto test hoặc chạy gầm application của một bên thứ 3.

Các bạn có thể download source code tại đây


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí