using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.IO; namespace findWindowTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } // Find Window // 查找窗体 // @para1: 窗体的类名 例如对话框类是"#32770" // @para2: 窗体的标题 例如打开记事本 标题是"无标题 - 记事本" 注意 - 号两侧的空格 // return: 窗体的句柄 [DllImport("User32.dll", EntryPoint = "FindWindow")] public static extern IntPtr FindWindow(string className, string windowName); // Find Window Ex // 查找窗体的子窗体 // @para1: 父窗体的句柄 如果为null,则函数以桌面窗口为父窗口,查找桌面窗口的所有子窗口 // @para2: 子窗体的句柄 如果为null,从@para1的直接子窗口的第一个开始查找 // @para3: 子窗体的类名 为""表示所有类 // @para4: 子窗体的标题 为""表示要查找的窗体无标题 如空白的textBox控件 // return: 子窗体的句柄 [DllImport("user32.dll", EntryPoint = "FindWindowEx")] private static extern IntPtr FindWindowEx( IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); // SendMessage // 向窗体发送消息 // @para1: 窗体句柄 // @para2: 消息类型 // @para3: 附加的消息信息 // @para4: 附加的消息信息 [DllImport("User32.dll", EntryPoint = "SendMessage")] private static extern int SendMessage( IntPtr hWnd, int Msg, IntPtr wParam, string lParam); // 消息类型(部分) const int WM_GETTEXT = 0x000D; // 获得窗体文本 如获得对话框标题 const int WM_SETTEXT = 0x000C; // 设置窗体文本 如设置文本框内容 const int WM_CLICK = 0x00F5; // 发送点击消息如调用该窗体(按钮)的"button1_Click();" // 本程序针对指定的另一程序窗体因此声名了如下变量 IntPtr Wnd = new IntPtr(0);// 一卡通注册程序主窗体 IntPtr sWnd = new IntPtr(0);// GroupBox控件 此为“一卡通注册程序”主窗体的子窗体 IntPtr txt = new IntPtr(0);// 文本框 IntPtr btn1 = new IntPtr(0);// 查询按钮 IntPtr btn2 = new IntPtr(0);// 注册按钮 这三个窗体又为“GroupBox控件”的子窗体 //IntPtr popW = new IntPtr(0);// 弹出对话框 //IntPtr popB = new IntPtr(0);// 弹出对话框确定按钮 // 文件操作 private String filename = string.Empty; private StreamReader reader = null; // 从“打开文件”对话框打开txt文件 同时获得需要的窗口句柄 private void button2_Click(object sender, EventArgs e) { label2.Text = ""; openFileDialog1.DefaultExt = "txt"; openFileDialog1.Filter = "文本文件|*.txt"; openFileDialog1.RestoreDirectory = true; openFileDialog1.FilterIndex = 1; if (openFileDialog1.ShowDialog() == DialogResult.OK) { filename = openFileDialog1.FileName; } // 获得窗口句柄 Wnd = FindWindowEx((IntPtr)0, (IntPtr)0, null, "读者一卡通注册");// 一个注册程序的窗体 sWnd = FindWindowEx(Wnd, (IntPtr)0, null, "条件"); // 窗体上的一个GroupBox控件 txt = FindWindowEx(sWnd, (IntPtr)0, null, ""); // GroupBox内的textBox控件 btn1 = FindWindowEx(sWnd, (IntPtr)0, null, "查询"); // GroupBox内的查询按钮 btn2 = FindWindowEx(sWnd, (IntPtr)0, null, "注册"); // GroupBox内的注册按钮 } // 重复地把文件内读取的行 // 将该行发送给注册程序窗体上的文本框中 // 并“点击”查询按钮和注册按钮 // 直到文件读取完毕 private void button3_Click(object sender, EventArgs e) { //计数 int count = 0; //读取文件 if (filename == string.Empty) { button2.Focus(); return; } reader = new StreamReader(filename); if (reader.EndOfStream) { return; } string str = string.Empty; do { //读取学号 保存在变量str中 str = reader.ReadLine(); //设置学号 SendMessage(txt, WM_SETTEXT, (IntPtr)0, str); //点击查询按钮 SendMessage(btn1, WM_CLICK, (IntPtr)0, ""); //点击注册按钮 SendMessage(btn2, WM_CLICK, (IntPtr)0, ""); count++; } while(!reader.EndOfStream); reader.Close(); filename = string.Empty; label1.Text = "注册人数:"; label2.Text = Convert.ToString(count); } } }
//*********
在项目中有这样的需求,在主窗体隐藏时或者主进程运行时对其它窗体的控件或者事件进行控制,而且其它窗体是处于活动状态,而主窗体或者主进程是隐藏在后面的。这个时候使用句柄和消息来处理就比较好解决这些问题了,当然了也可以使用其它方法。比如将其它窗体在主窗体中申明并且定义,使之和主窗体一样一直存在于内存中,在各个窗体中申明公共方法,在主进程需要调用时直接调用即可,但是这样耗费了大量的系统资源。现在使用消息来解决这个问题。下面提供一个小程序,在主窗体中通过句柄和消息来控制子窗体中Label上文字变化和颜色,代码如下:
Windowns的API类
using System;
using System.Runtime.InteropServices;
namespace TestHwnd
{
public class Win32API
{
[DllImport("user32.dll ", CharSet = CharSet.Unicode)]
public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, string wParam, string lParam);
}
}
主窗体程序(发送消息):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace TestHwnd
{
public partial class Main : Form
{
//定义了一个子窗体的句柄
public IntPtr hwndfrmTest;
public Main()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
if(hwndfrmTest!=(IntPtr)0)
{
if(DateTime.Now.Second % 3 == 0)
{
Win32API.PostMessage(hwndfrmTest, 0x60, "", "");
}
if(DateTime.Now.Second % 5 == 0)
{
Win32API.PostMessage(hwndfrmTest, 0x61, "", "");
}
}
}
void Button2Click(object sender, EventArgs e)
{
frmTest frm=new frmTest();
frm.Show(this);
}
}
子窗体程序(接收消息)
using System;
using System.Drawing;
using System.Windows.Forms;
namespace TestHwnd
{
/// <summary>
/// Description of frmTest.
/// </summary>
public partial class frmTest : Form
{
Main main;
public frmTest()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
void FrmTest_Load( object sender, EventArgs e)
{
main = this.Owner as Main;
//初始化该窗体的句柄
main.hwndfrmTest = this.Handle;
}
/// 重写窗体的消息处理函数DefWndProc,从中加入自己定义消息 MYMESSAGE 的检测的处理入口
protected override void DefWndProc( ref Message m)
{
switch (m.Msg)
{
case 0x60:
{
label1.ForeColor=Color.Red;
label1.Text = DateTime.Now. ToString() + "-" + "测试成功。。。。,呵呵,变红了";
}
break;
case 0x61:
{
label1.ForeColor=Color.Blue;
label1.Text = DateTime.Now. ToString() + "-" + "测试成功。。。。,呵呵,变蓝了";
}
break;
default:
base. DefWndProc( ref m);
break;
}
}
void Button1Click( object sender, EventArgs e)
{
main.hwndfrmTest = (IntPtr) ( 0);
this. Close();
}
}
}