成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

學習C#消息:循序漸進

開發 后端
本文介紹了什么是C#消息,C#消息驅動的過程以及C#消息的封裝等內容,希望對大家有所幫助。

一、C#消息概述

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#的消息封裝原理。

實現鼠標左鍵按下的消息的響應(WM_LBUTTONDOWN)  

  1. this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown1);   
  2.  this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown2);   
  3.  
  4.  private void Form1_MouseDown1(object sender, System.Windows.Forms.MouseEventArgs e)   
  5.  {   
  6.      if(e.Button==System.Windows.Forms.MouseButtons.Left)   
  7.    System.Windows.Forms.MessageBox.Show("消息被Form1_MouseDown1函數響應");   
  8.  }   
  9.  
  10.  private void Form1_MouseDown2(object sender, System.Windows.Forms.MouseEventArgs e)   
  11.  {   
  12.   if(e.Button==System.Windows.Forms.MouseButtons.Left)   
  13.    System.Windows.Forms.MessageBox.Show("消息被Form1_MouseDown2函數響應");   
  14.  }  

上面this.MouseDown是C#中的一個事件。它的定義如下:

  1. public event MouseEventHandler MouseDown;  

而MouseEventHandler的定義為:

  1. public delegate void MouseEventHandler( object sender,MouseEventArgs e);  

實際上,上面定義了一個委托類型MouseEventHandler。委托了啟用了其它編程語言中的函數指針的解決方案。與C++的函數指針不同,委托是完全面向對象的,同時封裝了對象實例和方法。本質上,委托把一個實例和該實例上的方法函數封裝成一個可調用的實體,它是面對對象的、安全的。

我們可以把

  1. this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown1);  

這條語句看成向this.MouseDown添加一個函數指針。

事件是對象發送的消息,以發送信號通知操作的發生。引發(觸發)事件的對象叫做事件發送方。捕獲事件并對事件作出響應的對象叫做事件接收方。在事件通訊中,事件發送方類并不知道哪個對象或方法將接收到(處理)它引發的事件。所需要的是在發送方和接收方之間存在一個媒介(類似指針的機制)。.NET框架定義了一個特殊的類型(Delegate委托),該類型提供函數指針的功能。這樣,委托就等效于一個類型安全的函數指針或一個回調函數。

前面我們向this.MouseDown事件添加了兩個委托。

  1. this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown1);   
  2. this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown2);  

結果,我們的兩個函數Form1_MouseDown1、Form1_MouseDown2在我們單擊鼠標左鍵的時候都會被調用,而且調用的順序和我們添加委托的順序一致。

WM_LBUTTONDOWN消息首先被Application類從應用程序消息隊列中取出,然后分發到相應的窗體。窗體使用MouseDown事件中的函數指針調用已經添加的響應函數。所以C#中的事件字段實質上是一個函數指針列表,用來維護一些消息到達時的響應函數的地址。    

三、結論

C#消息的工作流程:

C#消息被Application類從應用程序消息隊列中取出,然后分發到消息對應的窗體,窗體對象的***個響應函數是對象中的protected override void WndProc(ref System.Windows.Forms.Message e)方法。

它再根據消息的類型調用默認的消息響應函數(如OnMouseDown),默認的響應函數然后根據對象的事件字段(如this.MouseDown )中的函數指針列表,調用用戶所加入的響應函數(如Form1_MouseDown1和Form1_MouseDown2),而且調用順序和用戶添加順序一致。

四、再回首Application類

Application類有一個AddMessageFilter的靜態方法,通過它我們可以添加消息篩選器,以便在向目標傳遞Windows消息時,檢視這些消息。

使用消息篩選器來防止引發特定事件,或在將某事件傳遞給事件處理程序之前使用消息篩選器對其執行特殊操作。我們必須提供IMessageFilter接口的一個實現,然后才可以使用消息篩選器。以下的示范代碼將演示在消息發往窗體前我們如何攔截它。我們攔截的同樣是WM_LBUTTONDOWN消息。

  1. using System;   
  2. using System.Drawing;   
  3. using System.Collections;   
  4. using System.ComponentModel;   
  5. using System.Windows.Forms;   
  6. using System.Data;   
  7.  
  8. namespace MessageMech3   
  9. {   
  10.     //實現消息過濾器接口   
  11.    public class CLButtonDownFilter : IMessageFilter   
  12.    {   
  13.       public bool PreFilterMessage(ref Message m)   
  14.       {   
  15.          if (m.Msg==0x0201)// WM_LBUTTONDOWN   
  16.          {   
  17.             System.Windows.Forms.MessageBox.Show("App中鼠標左鍵按下");   
  18.             //返回值為true, 表示消息已被處理,不要再往后傳遞,因此消息被截獲   
  19.             //返回值為false,表示消息未被處理,需要再往后傳遞,因此消息未被截獲   
  20.             return true;   
  21.          }   
  22.          return false;   
  23.       }   
  24.    }   
  25.  
  26.  
  27.    /// < summary>   
  28.    /// Summary description for WinForm.   
  29.    /// < /summary>   
  30.    public class WinForm : System.Windows.Forms.Form   
  31.    {   
  32.       /// < summary>   
  33.       /// Required designer variable.   
  34.       /// < /summary>   
  35.       private System.Windows.Forms.Label label1;   
  36.       private System.ComponentModel.Container components = null;   
  37.  
  38.       public WinForm()   
  39.       {   
  40.          //   
  41.          // Required for Windows Form Designer support   
  42.          //   
  43.          InitializeComponent();   
  44.  
  45.          //   
  46.          // TODO: Add any constructor code after InitializeComponent call   
  47.          //   
  48.          //安裝自己的過濾器   
  49.          CLButtonDownFilter MyFilter=new CLButtonDownFilter();   
  50.          System.Windows.Forms.Application.AddMessageFilter(MyFilter);   
  51.       }   
  52.  
  53.       /// < summary>   
  54.       /// Clean up any resources being used.   
  55.       /// < /summary>   
  56.       protected override void Dispose (bool disposing)   
  57.       {   
  58.          if (disposing)   
  59.          {   
  60.             if (components != null)   
  61.             {   
  62.                components.Dispose();   
  63.             }   
  64.          }   
  65.          base.Dispose(disposing);   
  66.       }   
  67.  
  68.       #region Windows Form Designer generated code   
  69.       /// < summary>   
  70.       /// Required method for Designer support - do not modify   
  71.       /// the contents of this method with the code editor.   
  72.       /// < /summary>   
  73.       private void InitializeComponent()   
  74.       {   
  75.          this.label1 = new System.Windows.Forms.Label();   
  76.          this.SuspendLayout();   
  77.          //    
  78.          // label1   
  79.          //    
  80.          this.label1.BackColor = System.Drawing.Color.Transparent;   
  81.          this.label1.Dock = System.Windows.Forms.DockStyle.Top;   
  82.          this.label1.ForeColor = System.Drawing.Color.DarkViolet;   
  83.          this.label1.Name = "label1";   
  84.          this.label1.Size = new System.Drawing.Size(440, 32);   
  85.          this.label1.TabIndex = 0;   
  86.          this.label1.Text = "演示如何在App對象中處理消息,請點鼠標左鍵";   
  87.          this.label1.TextAlign = System.Drawing.ContentAlignment.BottomCenter;   
  88.          //    
  89.          // Form1   
  90.          //    
  91.          this.AutoScaleBaseSize = new System.Drawing.Size(7, 22);   
  92.          this.BackColor = System.Drawing.Color.WhiteSmoke;   
  93.          this.ClientSize = new System.Drawing.Size(440, 273);   
  94.          this.Controls.AddRange(new System.Windows.Forms.Control[] {this.label1});   
  95.          this.Font = new System.Drawing.Font("華文行楷", 15F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(134)));   
  96.          this.Name = "WinForm";   
  97.          this.Text = "WinForm";   
  98.  
  99.          //消息響應函數的調用順序和添加委托的順序一致   
  100.          //即:以下命令將先調用Form1_MouseDown1再調用Form1_MouseDown2   
  101.  
  102.          //通過委托添加自己的鼠標按鍵消息響應函數1   
  103.          this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown1);   
  104.          //通過委托添加自己的鼠標按鍵消息響應函數2   
  105.          this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown2);   
  106.  
  107.          this.ResumeLayout(false);   
  108.       }   
  109.       #endregion   
  110.  
  111.       /// < summary>   
  112.       /// 應用程序的主入口點。   
  113.       /// < /summary>   
  114.       [STAThread]   
  115.       static void Main()    
  116.       {   
  117.          Application.Run(new WinForm()); //啟動當前Form線程上的應用程序消息循環   
  118.       }   
  119.  
  120.       //要點1   
  121.       // 通過C#提供的事件接口添加自己的鼠標按鍵事件的響應函數   
  122.       //   
  123.       private void Form1_MouseDown1(object sender, System.Windows.Forms.MouseEventArgs e)   
  124.       {   
  125.           if(e.Button==System.Windows.Forms.MouseButtons.Left)   
  126.             System.Windows.Forms.MessageBox.Show("消息被Form1_MouseDown1函數響應");   
  127.  
  128.       }   
  129.       private void Form1_MouseDown2(object sender, System.Windows.Forms.MouseEventArgs e)   
  130.       {   
  131.          if(e.Button==System.Windows.Forms.MouseButtons.Left)   
  132.             System.Windows.Forms.MessageBox.Show("消息被Form1_MouseDown2函數響應");   
  133.  
  134.       }   
  135.       //要點2   
  136.       //通過覆蓋基類的事件引發函數攔截消息   
  137.       //   
  138.       protected override  void OnMouseDown( MouseEventArgs e)   
  139.       {   
  140.          if(e.Button==System.Windows.Forms.MouseButtons.Left)   
  141.             System.Windows.Forms.MessageBox.Show("消息被OnMouseDown函數響應");   
  142.  
  143.          //如果需要截獲消息,可將base.OnMouseDown(e);語句注釋掉   
  144.          base.OnMouseDown(e);   
  145.       }   
  146.       //要點3   
  147.       //通過覆蓋基類的窗體函數攔截消息   
  148.       //   
  149.       protected override void WndProc(ref System.Windows.Forms.Message e)   
  150.       {   
  151.          //如果需要截獲消息,   
  152.          //if(e.Msg==0x0201)// WM_LBUTTONDOWN   
  153.          //   System.Windows.Forms.MessageBox.Show("消息被WndProc函數響應");   
  154.          //else   
  155.          //   base.WndProc(ref e);   
  156.  
  157.          //不需要截獲消息則為   
  158.          if(e.Msg==0x0201)// WM_LBUTTONDOWN   
  159.             System.Windows.Forms.MessageBox.Show("消息被WndProc函數響應");   
  160.          base.WndProc(ref e);   
  161.       }   
  162.  
  163.    }   
  164. }  

以上代碼我們首先用類CLButtonDownFilter實現了IMessageFilter接口,在WinForm初始化的時候我們安裝了消息篩選器。程序實際執行的時候,在點擊鼠標左鍵的時候,程序僅僅會彈出一個"App中鼠標左鍵按下"的消息框。因為我們在消息發往窗體前攔截了它,所以窗體將接收不到WM_LBUTTONDOWN消息。

如果我們把   

  1.     if (m.Msg==0x0201)// WM_LBUTTONDOWN   
  2. {   
  3.    System.Windows.Forms.MessageBox.Show("App中鼠標左鍵按下");   
  4.    return true;   
  5. }  

改成

  1.     if (m.Msg==0x0201)// WM_LBUTTONDOWN   
  2. {   
  3.    System.Windows.Forms.MessageBox.Show("App中鼠標左鍵按下");   
  4.    return false;   
  5. }  

那么,我們在Application類處理消息后,消息將繼續發往窗體。窗體的函數將可以處理此消息。程序執行效果是順序彈出5個消息框。

    1:< < App中鼠標左鍵按下>>

    2:< < 消息被WndProc函數響應>>

    3:< < 消息被OnMouseDown函數響應>>

    4:< < 消息被Form1_MouseDown1函數響應>>

    5:< < 消息被Form1_MouseDown2函數響應>>

主要有兩種方法過濾實現過濾

***種:

  1. protected override void WndProc(ref Message m)   
  2. {   
  3. if (m.Msg == 0x0201)   
  4. return;   
  5. else   
  6. base.WndProc(ref m);   
  7. }  

第二種

不重寫WndProc

  1. //實現消息過濾器接口   
  2. public class CLButtonDownFilter : IMessageFilter   
  3. {   
  4. public bool PreFilterMessage(ref Message m)   
  5. {   
  6. if (m.Msg == 0x0201)// WM_LBUTTONDOWN   
  7. {   
  8. //返回值為true, 表示消息已被處理,不要再往后傳遞,因此消息被截獲   
  9. //返回值為false,表示消息未被處理,需要再往后傳遞,因此消息未被截獲   
  10. return true;   
  11. }   
  12. return false;   
  13. }   
  14. }  

CLButtonDownFilter MyFilter = new CLButtonDownFilter();

System.Windows.Forms.Application.AddMessageFilter(MyFilter);

關于C#消息的相關知識就介紹到這里。

【編輯推薦】

  1. 總結C#語言命名規范
  2. C#反射相關知識學習
  3. 大話F#和C#:是否會重蹈C#失敗的覆轍?
  4. 總結和學習C#接口
  5. 學習C#程序有感
責任編輯:book05 來源: cnblogs
相關推薦

2009-08-07 03:47:00

2011-05-20 10:39:43

oracle

2019-06-25 09:02:44

加密加密算法密鑰

2010-12-28 16:49:05

2012-03-01 22:37:02

Linux入門

2023-03-23 08:49:39

負載均衡服務器

2011-05-24 13:47:25

程序員

2020-02-19 08:48:04

Java內存模型CPU

2018-02-05 15:30:01

MariaDB服務器主從復制

2009-10-30 14:43:24

寬帶接入網

2022-04-21 14:03:54

開發API生命周期

2010-12-31 15:28:41

Windows 7

2010-12-28 16:38:16

Windows SerWindows 部署服

2022-03-31 06:23:43

自動化響應網絡安全

2024-07-04 08:00:00

2020-07-17 10:37:08

云計算安全IT

2020-11-23 11:09:18

大數據教育云計算

2010-01-06 16:40:30

cisco交換機vla

2022-04-29 11:27:26

循序漸進!開展零信任

2013-12-03 09:57:15

下一代互聯網IPv6遷移
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕二区 | 国产精品一区视频 | 日韩在线视频一区 | 黄色大片视频 | 亚洲h色| 福利成人 | 国产成人精品一区二区三区在线 | 亚洲午夜久久久 | h片在线观看免费 | 日本特黄a级高清免费大片 特黄色一级毛片 | a级片网站| 日韩精品在线一区 | 免费av在线网站 | 99久久精品免费看国产高清 | 久久精品中文字幕 | 久久机热 | 亚洲av毛片成人精品 | 亚洲欧美国产毛片在线 | 亚洲在线一区 | 久久精品99 | 国产精品高潮呻吟久久av黑人 | www.国产精品 | 精品一区二区三区在线观看国产 | 亚洲精品片| 国产精品地址 | 不卡在线视频 | 日本午夜一区二区三区 | 在线欧美小视频 | 日韩中文字幕av | 久久国产精品免费 | 91精品国产一区二区三区 | 国产一级一级毛片 | 在线观看第一区 | 国产精品久久久久久婷婷天堂 | 久久国产精品久久久久久 | 久草福利| 奇米四色影视 | 四虎最新地址 | 国产99久久 | 成人免费日韩 | 成人久久久久 |