需求是這樣,有個程式界面我們需要通過自己的程式持續輸入數據,界面如圖。 可以獲得控制項的句柄而用鉤子寫入值。這裡需要用到spy++工具。在VS的工具下有個spy++工具,打開如下圖 通過這個工具可以獲得窗體的句柄,當然這裡獲得的句柄只能用於測試,因為.net開發的程式窗體每次打開句柄都會變,都需要重新 ...
需求是這樣,有個程式界面我們需要通過自己的程式持續輸入數據,界面如圖。
可以獲得控制項的句柄而用鉤子寫入值。這裡需要用到spy++工具。在VS的工具下有個spy++工具,打開如下圖
通過這個工具可以獲得窗體的句柄,當然這裡獲得的句柄只能用於測試,因為.net開發的程式窗體每次打開句柄都會變,都需要重新獲得。這個工具的用處在於找一個控制項的前一句柄控制項和後一句柄控制項。
一、引用
//尋找目標進程視窗
[DllImport("USER32.DLL")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("USER32.DLL", EntryPoint = "FindWindowEx", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, uint hwndChildAfter,string lpszClass, string lpszWindow);
//設置進程視窗到最前
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
//模擬鍵盤事件
[DllImport("USER32.DLL")]
public static extern void keybd_event(Byte bVk, Byte bScan, Int32 dwFlags, Int32 dwExtraInfo);
public delegate bool CallBack(IntPtr hwnd, int lParam);
[DllImport("USER32.DLL")]
public static extern int EnumChildWindows(IntPtr hWndParent, CallBack lpfn, int lParam);
//給CheckBox發送信息
[DllImport("USER32.DLL", EntryPoint = "SendMessage", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hwnd, UInt32 wMsg, int wParam, int lParam);
//給Text發送信息
[DllImport("USER32.DLL", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, string lParam);
[DllImport("USER32.DLL")]
public static extern IntPtr GetWindow(IntPtr hWnd, int wCmd);
二、方法
公共方法
/// <summary>
/// 查找窗體上控制項句柄
/// </summary>
/// <param name="hwnd">父窗體句柄</param>
/// <param name="lpszWindow">控制項標題(Text)</param>
/// <param name="bChild">設定是否在子窗體中查找</param>
/// <returns>控制項句柄,沒找到返回IntPtr.Zero</returns>
private static IntPtr FindWindowEx(IntPtr hwnd, string lpszWindow, bool bChild)
{
IntPtr iResult = IntPtr.Zero;
// 首先在父窗體上查找控制項
iResult = FindWindowEx(hwnd, 0, null, lpszWindow);
// 如果找到直接返回控制項句柄
if (iResult != IntPtr.Zero) return iResult;
// 如果設定了不在子窗體中查找
if (!bChild) return iResult;
// 枚舉子窗體,查找控制項句柄
int i = EnumChildWindows(
hwnd,
(h, l) =>
{
IntPtr f1 = FindWindowEx(h, 0, null, lpszWindow);
if (f1 == IntPtr.Zero)
return true;
else
{
iResult = f1;
return false;
}
},
0);
// 返回查找結果
return iResult;
}
/// <summary>
/// 輸入回車
/// </summary>
private static void PrintEnter()
{
keybd_event(Convert.ToByte(13), 0, 0, 0);
keybd_event(Convert.ToByte(13), 0, 2, 0);
}
獲得窗體句柄
IntPtr wcHandle = FindWindow(null, "窗體名稱");
if (wcHandle != IntPtr.Zero)
{
//設置游戲視窗到最前
SetForegroundWindow(wcHandle);
}
獲得有Title的控制項句柄
uint BM_GETCHECK = 0xF0;
uint BST_CHECKED = 0xF1;
IntPtr weightIntPtr = FindWindowEx(wcHandle, "輸入重量[&H]", true);
if (weightIntPtr != IntPtr.Zero)
{
//獲得Checkbox值
int i = SendMessage(weightIntPtr, BM_GETCHECK, 0, 0);
//更改CheckBox值
SendMessage(weightIntPtr, BST_CHECKED, 1, 0);
}
獲得沒Title的控制項句柄
public enum WindowSearch
{
GW_HWNDFIRST = 0, //同級別第一個
GW_HWNDLAST = 1, //同級別最後一個
GW_HWNDNEXT = 2, //同級別下一個
GW_HWNDPREV = 3, //同級別上一個
GW_OWNER = 4, //屬主視窗
GW_CHILD = 5 //子視窗}獲取與指定視窗具有指定關係的視窗的句柄
}
IntPtr waybill = GetWindow(waybillIntPtr, (int)WindowSearch.GW_HWNDNEXT);
SendMessage(waybill, WM_SETTEXT, IntPtr.Zero, waybillValue);
這裡完成了我們的需求,改變了窗體中選擇框和Text文本框的值。