您的位置:首页 > 其它

.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 的消息机制 的方式

一、.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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐