[DllImport("User32.Dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("User32.Dll")] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("User32.Dll")] public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam); //调用类似以下: SendMessage(ParenthWnd, WM_KEYDOWN, (IntPtr)31, "0"); SendMessage(ParenthWnd, WM_KEYUP, (IntPtr)31, "0");
const int WM_KEYDOWN = 0x100; const int WM_KEYUP = 0x101;
不活动窗体,肯定用到API 通过FindWindow和PostMessage
很多游戏会监视的,发现find sendkey等,就自动关闭了
用C#调用WIN32API,先FindWindow函数获取指定窗口的句柄,然后用PostMessage发送消息! SendMessage是同步处理的,也就是说如果窗口没有响应消息,该方法不会返回,而PostMessage是发送消息后,就返回的。对应定义如下: using System.Runtime.InteropServices;
[DllImport("User32.Dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("User32.Dll")] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("User32.Dll")] public static extern int PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam); //调用类似以下: PostMessage(ParenthWnd, WM_KEYDOWN, (IntPtr)31, "0"); PostMessage(ParenthWnd, WM_KEYUP, (IntPtr)31, "0");
然后用
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)
发送消息,这个API的用法可以查查,很简单
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);找到句柄,然后用 [DllImport("user32.dll", EntryPoint = "PostMessage", SetLastError = true)]
private extern static bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
或SendMessage好像有些游戏的输入框句柄是找不到的,使用Spy++都不行,像永恒,不知为什么。
C#中调用Windows API的要点
Windows API——Sendmessage中的消息值
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("User32.Dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("User32.Dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam); //调用类似以下:
SendMessage(ParenthWnd, WM_KEYDOWN, (IntPtr)31, "0");
SendMessage(ParenthWnd, WM_KEYUP, (IntPtr)31, "0");
const int WM_KEYUP = 0x101;
通过FindWindow和PostMessage
SendMessage是同步处理的,也就是说如果窗口没有响应消息,该方法不会返回,而PostMessage是发送消息后,就返回的。对应定义如下: using System.Runtime.InteropServices;
[DllImport("User32.Dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("User32.Dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("User32.Dll")]
public static extern int PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam); //调用类似以下:
PostMessage(ParenthWnd, WM_KEYDOWN, (IntPtr)31, "0");
PostMessage(ParenthWnd, WM_KEYUP, (IntPtr)31, "0");
还有,这句
PostMessage(ParenthWnd, WM_KEYDOWN, (IntPtr)31, "0");
后面两个参数分别代表什么呀,会不会是我的参数本身有问题呢?
我同样用的计算器做的测试.
[DllImport("user32.dll", EntryPoint = "RedrawWindow")]
public static extern int RedrawWindow(int hWnd, IntPtr prect, IntPtr hrgnUpdate, uint flags);
public const int WM_SETTEXT = 0xC;//消息常量
StringBuilder sbstr = new StringBuilder(setstr, 100);
int sms = SendMessage(id, WM_SETTEXT, 100, sbstr);
RedrawWindow(0, IntPtr.Zero, IntPtr.Zero, 4 | 1 | 128);//重绘窗体
int aa = PostMessage(ParenthWnd, WM_KEYDOWN, (IntPtr)32, "1");
int bb = PostMessage(ParenthWnd, WM_KEYUP, (IntPtr)32, "1");
返回值aa,bb都是1
因为postmessage该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式。
IntPtr ParenthWnd = FindWindow(null, "计算器"); //查找计算器的句柄
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
int aa = SendMessage(ParenthWnd, WM_KEYDOWN, (IntPtr)31, "0");
int bb = SendMessage(ParenthWnd, WM_KEYUP, (IntPtr)31, "0");
其中aa,bb的返回值都是0.
请再帮忙看看,谢谢.
[DllImport("user32.dll")]
public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr HWnd, uint Msg, int WParam, int LParam);public const int WM_KEYDOWN = 0x0100;
public const int WM_KEYUP = 0x0101;private void button2_Click(object sender, EventArgs e)
{
IntPtr HWnd = FindWindow(null, "计算器");
SetForegroundWindow(HWnd); SendMessage(HWnd, WM_KEYDOWN, (int)Keys.Space, 0);
SendMessage(HWnd, WM_KEYUP, (int)Keys.Space, 0);
}
IntPtr HWnd = FindWindow(null, "计算器");
SetForegroundWindow(HWnd); SendMessage(HWnd, WM_KEYDOWN, (int)Keys.D4, 0);
SendMessage(HWnd, WM_KEYUP, (int)Keys.D4, 0);
原意要在计算器上模拟按下数字4键,但结果好像是发过些消息去了,但按键的模拟却没有达到,计算器不能成功显示数字4
public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);private void button1_Click(object sender, EventArgs e)
{
IntPtr HWnd = FindWindow(null, "计算器");
MessageBox.Show(HWnd.ToString());
IntPtr HWnd2 = FindWindowEx(HWnd, IntPtr.Zero, "Edit", null);
MessageBox.Show(HWnd2.ToString()); SetForegroundWindow(HWnd);
SetForegroundWindow(HWnd2);
SendKeys.Send("{C}");
SendKeys.Send("{6}");
SendKeys.Send("{+}");
SendKeys.Send("{6}");
SendKeys.Send("{=}");
// 计算器应该显示12
}
这是Windows的消息运行机制所决定的,Windows的驱动方式是事件驱动,事件发生后先转化成消息,送入应用程序的消息队列。非焦点窗口对接收的消息有不同于与焦点窗口的处理方式,有些消息直接忽略。通过SetForegroundWindow可以设置焦点窗口。如果非焦点窗口能够直接响应,那么SetForegroundWindow,SetFocus等类似函数就没必要存在了。