C# 發送、接收和處理自定義的WINDOWS消息
轉載地址:http://blog.chinaunix.net/uid-24427209-id-2608350.html
為了程序啟動后自動執行主函數,在Form1_Load中直接執行啟動函數,可能造成沒有反應。當然,在Form1_Load中加入較長時間(比如2秒)的定時器,在定時器函數中關閉定時器(僅需要執行一次),再執行主函數會好些,但是我們不知道初始話的精確時間,這樣的方法也存在危險。
我們知道WINDOWS應用程序是靠消息驅動的,最好的方法就是在Form1_Load中發送消息,自己截獲消息后,才開始執行比較安全。下面分3步說明相關的方法步驟。
一、創建一個 C# 項目,並選擇 Windows 應用程序,名稱默認WindowsFormsApplication1
為了簡單,所有項目都按默認值處理。
二、添加處理Windows 消息的方法,即重載 DefWndProc方法
點選菜單[視圖]->[對象瀏覽器],打開對象瀏覽窗口(有的可能在[其他窗口]),在其中找到自己應用程序名WindowsFormsApplication1(一般在最下部),展開它並選中基類型Form,這時在右邊的窗口列出所有Form類的成員函數,你也可以更改本窗口上邊的[對象瀏覽器設置],從中勾選更多選項,以便出現更多的函數,如圖所示:
protected override void DefWndProc(ref System.Windows.Forms.Message m)
我們選中DefWndProc(ref System.Windows.Forms.Message),此時在下面窗口會顯示完整的函數protected override void DefWndProc(ref System.Windows.Forms.Message m),我們右擊這行說明字符串,點選復制將其復制下來。轉到窗口Form1.cs,粘貼到Form1類里面,注意前面的override關鍵字,適當修改就可以處理自定義消息了。
protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case USER+1:
//string message = string.Format("收到自己消息的參數:{0},{1}", m.WParam, m.LParam);
//處理啟動 函數MessageBox.Show(message);//顯示一個消息框
StartProcess();
break;
default:
base.DefWndProc(ref m);//一定要調用基類函數,以便系統處理其它消息。
break;
}
}
三、引入發送消息的函數
我們需要PostMessage發送自定義消息,所以用如下語句引用它:
[DllImport("user32.dll")]
public static extern void PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
自定義消息號一般開始於0x0400,也定義一個常量 public const int USER = 0x0400;
這樣就可以在Form1_Load中發送消息,以便自動開始執行程序。
private void Form1_Load(object sender, EventArgs e)
{
//Thread.Sleep(100); //等待100毫秒
PostMessage(this.Handle, USER + 1, 168, 51898);
}
四 引用關鍵字的命名空間
對於上面的關鍵字DllImport,字符要正確,大小寫也要正確,此時是黑色字體,還不認識,那就需要引用它的命名空間,方法如下,使用鼠標右擊關鍵字DllImport,——解析——點選using System.Runtime.InteropServices ,即將所用的命名空間using System.Runtime.InteropServices;加入到項目中,關鍵字DllImport的字體變成綠色。
五 完整代碼如下:
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.Threading;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public const int USER = 0x0400;//用戶自定義消息的開始數值
[DllImport("user32.dll")]
public static extern void PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Thread.Sleep(100); //等待100毫秒
PostMessage(this.Handle, USER + 1, 168, 51898);
}
private void StartProcess()
{
MessageBox.Show("具備條件,可以正常運行了!");
}
protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case USER+1:
//string message = string.Format("收到自己消息的參數:{0},{1}", m.WParam, m.LParam);
StartProcess();
break;
default:
base.DefWndProc(ref m);//一定要調用基類函數,以便系統處理其它消息。
break;
}
}
}
}
六 有關的圖片
1.建立項目的圖片
2.彈出對象瀏覽器的圖片
3.選擇基類型Form的圖片說明
4.對象瀏覽器設置的圖片說明
5.加入重載方法DefWndProc的圖片說明
==更多可以參考網上內容==
==1==
c# Windows消息列表
http://www.beijibear.com/index.php?aid=139
==2==
「C#:windows消息大全-詳細-有解釋」
http://www.mox.cc/018e4d33b5bc0402-ddec43ad9d5cedd0.htm
==3==
c# Windows消息處理過程探究
http://blog.csdn.net/jjjfox/article/details/7360378
一、消息概述
Windows下應用程序的執行是通過消息驅動的。消息是整個應用程序的工作引擎,我們需要理解掌握編程語言是如何封裝消息的原理。
1 什么是消息(Message)
消息就是通知和命令。在.NET框架類庫中的System.Windows.Forms命名空間中微軟采用面對對象的方式重新定義了Message。新的消息(Message)結構的公共部分屬性基本與早期的一樣,不過它是面對對象的。
公共屬性:
HWnd 獲取或設定消息的處理函數
Msg 獲取或設定消息的ID號
Lparam 指定消息的LParam字段
Wparam 指定消息的WParam字段
Result 指定為響應消息處理函數而向OS系統返回的值
2 消息驅動的過程
所有的外部事件,如鍵盤輸入、鼠標移動、按動鼠標都由OS系統轉換成相應的消息發送到應用程序的消息隊列。每個應用程序都有一段相應的程序代碼來檢索、分發這些消息到對應的窗體,然后由窗體的處理函數來處理。
二、C#中的消息的封裝
C#對消息重新進行了面對對象的封裝,在C#中消息被封裝成了事件。
System.Windows.Forms.Application類具有用於啟動和停止應用程序和線程以及處理Windows消息的方法。
調用Run以啟動當前線程上的應用程序消息循環,並可以選擇使其窗體可見。
調用Exit或ExitThread來停止消息循環。
C#中用Application類來處理消息的接收和發送的。消息的循環是由它負責的。
從本質上來講,每個窗體一般都對應一個窗體過程處理函數。那么,C#的一個Form實例(相當於一個窗體)收到消息后是如何處理消息的?其實,這個問題的分析也就是展示了C#的消息封裝原理。
三、C#中消息的工作流程:
1、 Application類有一個AddMessageFilter的靜態方法,通過它我們可以添加消息篩選器,以便在向目標傳遞Windows消息時,檢視這些消息。
使用消息篩選器來防止引發特定事件,或在將某事件傳遞給事件處理程序之前使用消息篩選器對其執行特殊操作。
我們必須提供IMessageFilter接口的一個實現,然后才可以使用消息篩選器。
2、 C#中的消息被Application類從應用程序消息隊列中取出,如果有消息篩選器,先執行消息篩選, 然后分發到消息對應的窗體。
1)窗體對象的第一個響應函數是窗口過程函數,即對象中的protected override void WndProc(ref System.Windows.Forms.Message e)方法。
2)再根據消息的類型調用默認的消息響應函數(如OnMouseDown)
3)再根據用戶自定義的事件處理函數,按訂閱順序分別執行(如Form1_MouseDown1)。
四、示例:
namespace WindowsApplication27
{
partial class Form1
{
///
/// 必需的設計器變量。
///
private System.ComponentModel.IContainer components = null;
///
/// 清理所有正在使用的資源。
///
/// 如果應釋放托管資源,為 true;否則為 false。
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗體設計器生成的代碼
///
/// 設計器支持所需的方法 - 不要
/// 使用代碼編輯器修改此方法的內容。
///
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 266);
this.Name = "Form1";
this.Text = "Form1";
//這里訂閱了事件
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication27
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Application.AddMessageFilter((new msgFilter()));
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show("3");
}
protected override void OnMouseDown(MouseEventArgs e)
{
MessageBox.Show("2");
base.OnMouseDown(e);
}
protected override void WndProc(ref Message m)
{
//MouseDown Msg Id
if (m.Msg==0x0201)
MessageBox.Show("1");
base.WndProc(ref m);
}
}
public class msgFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x0201)
MessageBox.Show("0");
return false;
}
}
static class Program
{
///
/// 應用程序的主入口點。
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}