FindWindow, FindWindowEx, SendMessage, SetForegroundWindow 使用

  1. C#/.NET的程序,控制外部的 win32程序(win16不做考虑)
  2. C#/.NET的程序,控制外部的 .NET程序

从标题,大家也看到, C# 对外部程序的控制, 我们也分为两种情况来讨论:

  1. .NET 平台自带的 SendKeys 和 Process 结合的方式
  2. 完全利用 Windows API 的消息机制 的方式

一、.NET平台自带的 Process 和 SendKeys 结合的方式

本例子,用 C# 的一个Winform程序,创建一个指定路径的文本文件,写入某些内容后,并保存。

为了看清效果,将 Form 的 TopMost 设为 true

  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,需要引入命名空间

using System.Runtime.InteropServices;

下面的API引用部分的代码,放入 class 内部

[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 );

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 ("没有启动 [计算器]");
    }
}

你可能感兴趣的:(Win,32,api,string,null,winform,button,user)