.NET用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序[转]
2011-04-14 12:15
429 查看
首页,要说明几个概念:
Win32 平台是 消息驱动模式
.Net 框架是 事件驱动模式
标题所指的 “控制外部程序”,外部程序
是指与本程序无内在相关性的另外一个程序
基于上面提到的,对于.NET的winform程序,在默认情况下(即未对接收消息的事件做自定义处理
,说白了:就是没有 重写/覆写(override)窗体(Form)的DefWndProc
事件),.Net 的 winform 程序,是不响应所接收到的自定义消息的。
我们这里要讨论的内容,就分为两种情况:
C#/.NET的程序,控制外部的 win32程序(win16不做考虑)
C#/.NET的程序,控制外部的 .NET程序
从标题,大家也看到, C# 对外部程序的控制, 我们也分为两种情况来讨论:
.NET 平台自带的 SendKeys 和 Process 结合的方式
完全利用 Windows API 的消息机制 的方式
为了看清效果,将 Form 的 TopMost 设为 true
Code
private
void
button1_Click(
object
sender, EventArgs e )
{
//
启动notepad.exe 记事本程序,并在d:/下创建 或 打开 text_test.txt文件
System.Diagnostics.Process txt
=
System.Diagnostics.Process.Start (
@"
notepad.exe
"
,
@"
d:/text_test.txt
"
);
txt.StartInfo.WindowStyle
=
ProcessWindowStyle.Normal;
//
等待一秒,以便目标程序notepad.exe输入状态就绪
txt.WaitForInputIdle (
1000
);
//
如果目标程序 notepad.exe 没有停止响应,则继续
if
( txt.Responding )
{
//
开始写入内容
SendKeys.SendWait (
"
-----下面的内容是外部程序自动写入-----/r/n
"
);
SendKeys.SendWait (
this
.textBox1.Text );
//
将文本框内的内容写入
SendKeys.SendWait (
"
{Enter}{Enter}
"
);
//
写入2个回车
SendKeys.SendWait (
"
文档创建时间:
"
);
SendKeys.SendWait (
"
{F5}
"
);
//
发送F5按键
SendKeys.SendWait (
"
{Enter}
"
);
//
发送回车键
SendKeys.SendWait (
"
^s
"
);
//
发送 Ctrl + s 键
SendKeys.SendWait (
"
%{F4}
"
);
//
发送 Alt + F4 键
MessageBox.Show (
"
文件已经保存成功!
"
);
}
}
注: SendKeys 发送的按键的接收窗体,必须是当前的活动窗体
API 中我们要用到的函数有 FindWindow
, FindWindowEx
, SendMessage
, SetForegroundWindow
对于API的引用方法,大家去看 API 手册,我这里提供一个VB自带的API查询程序
要使用API,需要引入命名空间
Code
using
System.Runtime.InteropServices;
下面的API引用部分的代码,放入 class 内部
Code
[DllImport (
"
user32.dll
"
, EntryPoint
=
"
FindWindow
"
, SetLastError
=
true
)]
private
static
extern
IntPtr FindWindow(
string
lpClassName,
string
lpWindowName );
[DllImport (
"
user32.dll
"
, EntryPoint
=
"
FindWindowEx
"
, SetLastError
=
true
)]
private
static
extern
IntPtr FindWindowEx( IntPtr hwndParent,
uint
hwndChildAfter,
string
lpszClass,
string
lpszWindow );
[DllImport (
"
user32.dll
"
, EntryPoint
=
"
SendMessage
"
, SetLastError
=
true
, CharSet
=
CharSet.Auto )]
private
static
extern
int
SendMessage( IntPtr hwnd,
uint
wMsg,
int
wParam,
int
lParam );
[DllImport (
"
user32.dll
"
, EntryPoint
=
"
SetForegroundWindow
"
, SetLastError
=
true
)]
private
static
extern
void
SetForegroundWindow( IntPtr hwnd );
Code
private
void
button1_Click(
object
sender, EventArgs e )
{
const
uint
BM_CLICK
=
0xF5
;
//
鼠标点击的消息,对于各种消息的数值,大家还是得去API手册
IntPtr hwndCalc
=
FindWindow (
null
,
"
计算器
"
);
//
查找计算器的句柄
if
( hwndCalc
!=
IntPtr.Zero )
{
IntPtr hwndThree
=
FindWindowEx ( hwndCalc,
0
,
null
,
"
3
"
);
//
获取按钮3 的句柄
IntPtr hwndPlus
=
FindWindowEx ( hwndCalc,
0
,
null
,
"
+
"
);
//
获取按钮 + 的句柄
IntPtr hwndTwo
=
FindWindowEx ( hwndCalc,
0
,
null
,
"
2
"
);
//
获取按钮2 的句柄
IntPtr hwndEqual
=
FindWindowEx ( hwndCalc,
0
,
null
,
"
=
"
);
//
获取按钮= 的句柄
SetForegroundWindow ( hwndCalc );
//
将计算器设为当前活动窗口
System.Threading.Thread.Sleep (
2000
);
//
暂停2秒让你看到效果
SendMessage ( hwndThree, BM_CLICK,
0
,
0
);
System.Threading.Thread.Sleep (
2000
);
//
暂停2秒让你看到效果
SendMessage ( hwndPlus, BM_CLICK,
0
,
0
);
System.Threading.Thread.Sleep (
2000
);
//
暂停2秒让你看到效果
SendMessage ( hwndTwo, BM_CLICK,
0
,
0
);
System.Threading.Thread.Sleep (
2000
);
//
暂停2秒让你看到效果
SendMessage ( hwndEqual, BM_CLICK,
0
,
0
);
System.Threading.Thread.Sleep (
2000
);
MessageBox.Show (
"
你看到结果了吗?
"
);
}
else
{
MessageBox.Show (
"
没有启动 [计算器]
"
);
}
}
VB.NET调用
Win32 平台是 消息驱动模式
.Net 框架是 事件驱动模式
标题所指的 “控制外部程序”,外部程序
是指与本程序无内在相关性的另外一个程序
基于上面提到的,对于.NET的winform程序,在默认情况下(即未对接收消息的事件做自定义处理
,说白了:就是没有 重写/覆写(override)窗体(Form)的DefWndProc
事件),.Net 的 winform 程序,是不响应所接收到的自定义消息的。
我们这里要讨论的内容,就分为两种情况:
C#/.NET的程序,控制外部的 win32程序(win16不做考虑)
C#/.NET的程序,控制外部的 .NET程序
从标题,大家也看到, C# 对外部程序的控制, 我们也分为两种情况来讨论:
.NET 平台自带的 SendKeys 和 Process 结合的方式
完全利用 Windows API 的消息机制 的方式
一、.NET平台自带的 Process 和 SendKeys 结合的方式
本例子,用 C# 的一个Winform程序,创建一个指定路径的文本文件,写入某些内容后,并保存。为了看清效果,将 Form 的 TopMost 设为 true
Code
private
void
button1_Click(
object
sender, EventArgs e )
{
//
启动notepad.exe 记事本程序,并在d:/下创建 或 打开 text_test.txt文件
System.Diagnostics.Process txt
=
System.Diagnostics.Process.Start (
@"
notepad.exe
"
,
@"
d:/text_test.txt
"
);
txt.StartInfo.WindowStyle
=
ProcessWindowStyle.Normal;
//
等待一秒,以便目标程序notepad.exe输入状态就绪
txt.WaitForInputIdle (
1000
);
//
如果目标程序 notepad.exe 没有停止响应,则继续
if
( txt.Responding )
{
//
开始写入内容
SendKeys.SendWait (
"
-----下面的内容是外部程序自动写入-----/r/n
"
);
SendKeys.SendWait (
this
.textBox1.Text );
//
将文本框内的内容写入
SendKeys.SendWait (
"
{Enter}{Enter}
"
);
//
写入2个回车
SendKeys.SendWait (
"
文档创建时间:
"
);
SendKeys.SendWait (
"
{F5}
"
);
//
发送F5按键
SendKeys.SendWait (
"
{Enter}
"
);
//
发送回车键
SendKeys.SendWait (
"
^s
"
);
//
发送 Ctrl + s 键
SendKeys.SendWait (
"
%{F4}
"
);
//
发送 Alt + F4 键
MessageBox.Show (
"
文件已经保存成功!
"
);
}
}
注: SendKeys 发送的按键的接收窗体,必须是当前的活动窗体
二、C# 利用 Windows API 控制 外部的 win32 程序
我们这里,用控制 “计算器”程序,算一个 3 + 2 = 5 的算式来做示例。API 中我们要用到的函数有 FindWindow
, FindWindowEx
, SendMessage
, SetForegroundWindow
对于API的引用方法,大家去看 API 手册,我这里提供一个VB自带的API查询程序
要使用API,需要引入命名空间
Code
using
System.Runtime.InteropServices;
下面的API引用部分的代码,放入 class 内部
Code
[DllImport (
"
user32.dll
"
, EntryPoint
=
"
FindWindow
"
, SetLastError
=
true
)]
private
static
extern
IntPtr FindWindow(
string
lpClassName,
string
lpWindowName );
[DllImport (
"
user32.dll
"
, EntryPoint
=
"
FindWindowEx
"
, SetLastError
=
true
)]
private
static
extern
IntPtr FindWindowEx( IntPtr hwndParent,
uint
hwndChildAfter,
string
lpszClass,
string
lpszWindow );
[DllImport (
"
user32.dll
"
, EntryPoint
=
"
SendMessage
"
, SetLastError
=
true
, CharSet
=
CharSet.Auto )]
private
static
extern
int
SendMessage( IntPtr hwnd,
uint
wMsg,
int
wParam,
int
lParam );
[DllImport (
"
user32.dll
"
, EntryPoint
=
"
SetForegroundWindow
"
, SetLastError
=
true
)]
private
static
extern
void
SetForegroundWindow( IntPtr hwnd );
Code
private
void
button1_Click(
object
sender, EventArgs e )
{
const
uint
BM_CLICK
=
0xF5
;
//
鼠标点击的消息,对于各种消息的数值,大家还是得去API手册
IntPtr hwndCalc
=
FindWindow (
null
,
"
计算器
"
);
//
查找计算器的句柄
if
( hwndCalc
!=
IntPtr.Zero )
{
IntPtr hwndThree
=
FindWindowEx ( hwndCalc,
0
,
null
,
"
3
"
);
//
获取按钮3 的句柄
IntPtr hwndPlus
=
FindWindowEx ( hwndCalc,
0
,
null
,
"
+
"
);
//
获取按钮 + 的句柄
IntPtr hwndTwo
=
FindWindowEx ( hwndCalc,
0
,
null
,
"
2
"
);
//
获取按钮2 的句柄
IntPtr hwndEqual
=
FindWindowEx ( hwndCalc,
0
,
null
,
"
=
"
);
//
获取按钮= 的句柄
SetForegroundWindow ( hwndCalc );
//
将计算器设为当前活动窗口
System.Threading.Thread.Sleep (
2000
);
//
暂停2秒让你看到效果
SendMessage ( hwndThree, BM_CLICK,
0
,
0
);
System.Threading.Thread.Sleep (
2000
);
//
暂停2秒让你看到效果
SendMessage ( hwndPlus, BM_CLICK,
0
,
0
);
System.Threading.Thread.Sleep (
2000
);
//
暂停2秒让你看到效果
SendMessage ( hwndTwo, BM_CLICK,
0
,
0
);
System.Threading.Thread.Sleep (
2000
);
//
暂停2秒让你看到效果
SendMessage ( hwndEqual, BM_CLICK,
0
,
0
);
System.Threading.Thread.Sleep (
2000
);
MessageBox.Show (
"
你看到结果了吗?
"
);
}
else
{
MessageBox.Show (
"
没有启动 [计算器]
"
);
}
}
VB.NET调用
<System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="FindWindowA")> _ Public Shared Function _ FindWindowA(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer End Function -------------------- Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim hWnd As Integer = FindwindowA(vbNullString, "frm2.2") End Sub
相关文章推荐
- C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序[转]
- C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序
- C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序[转]
- C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序[转]
- C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序
- C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序[转]
- C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序
- C#用 SendKyes 结合 Process 或 API之SendMessage(PostMessage) 等控制外部程序
- 【转】[C#.NET][VB.NET] 用 Win32 API 控制 外部應用程式選單
- C# SendMessage等控制外部程序
- .Net启动外部程序 .
- C# API Keybd_event + mouse_event 利用API程序控制按下某键
- 用外部程序添加的UTF-8编码的Web窗体在ASP.NET中显示乱码的问题的解决
- Window API 之 PostMessage (消息投递)
- c# 使用Process调用外部程序时等待该进程结束后再执行住进程
- 我秀秀淘宝购物导航淘宝客api程序源码版(.net源码)
- ASP.NET C# 如何在程序中控制IIS服务或应用程序池重启?
- 结合JavaScript与ASP.NET Web窗体进行程序开发
- 用vb.net与acess结合实现简单的电话号码本程序(一)
- 最简单的window程序——API版本