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();
}
}
}