淺談Winform事件的實現以及模擬其事件的實現(附實現源碼)


當我們初學Winform的時候被其神奇的事件功能所吸引,當點擊一個按鈕時,便會跳到我們所寫的點擊方法當中去。然而這並不符合我們對方法的理解,究竟.net在后面幫助我們實現了什么。我們怎樣模擬其事件的實現呢。下面先從ButtonClick方法說起。

1.首先查看設計器自動生成的代碼

 

 partial class Form1
    {
              #region Windows 窗體設計器生成的代碼

        /// <summary>
        /// 設計器支持所需的方法 - 不要
        /// 使用代碼編輯器修改此方法的內容。
        /// </summary>
        private void InitializeComponent()
        {
            //實例化一個按鈕
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(491, 100);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            //添加點擊事件
            this.button1.Click += new System.EventHandler(this.button1_Click);
                   }

        #endregion

        private System.Windows.Forms.Button button1;
}

 

 我們發現了對事件的添加 this.button1.Click += new System.EventHandler(this.button1_Click);

this.button1.Click中的Click是什么呢?我們F12轉到定義看一下(注意:Button繼承自Control(所有控件父類)

我們發現event,Click是一個事件,然后我們反編譯看一下(可以看到+=,-=的實現)

EventHandler轉到定義sender事件源(就是被誰引發的),e(事件數據)

到目前為止this.button1.Click添加了事件,但是我們知道了事件,button1訂閱了這個事件,但是事件如何觸發的呢?我們進行調試,在調用堆棧中觀察,如圖

我們從上而下進行逆向分析
01.System.Windows.Forms.dll!System.Windows.Forms.Control.OnClick(System.EventArgs e) + 0x62 字節,我們對
System.Windows.Forms.Control.OnClick反編譯一下,handler不為空說明事件被訂閱,執行
 private void button1_Click(object sender, EventArgs e){}

02System.Windows.Forms.dll!System.Windows.Forms.Button.OnClick(System.EventArgs e) + 0x80 字節我們對
System.Windows.Forms.Button.OnClick反編譯一下
,調用01的方法

03System.Windows.Forms.dll!System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs
mevent = {X = 36 Y = 13 Button = Left}) + 0xac 字節,我們對System.Windows.Forms.Button.OnMouseUp反編譯一下,
該方法最后調用Control.OnMouseUp方法執行鼠標彈起的事件



04System.Windows.Forms.dll!System.Windows.Forms.Control.WmMouseUp(ref System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons button, int clicks) + 0x274 字節我們對System.Windows.Forms.Control.WmMouseUp反編譯一下,這是對鼠標事件的判定,我們會驚奇的發現里面有對單擊與雙擊的判定。



 
        

在往下走便是對鼠標事件的監聽,有興趣可以繼續往下查看調用堆棧,

 
        

我們總結一下,buttonclick的觸發經過如下過程

好了到目前為止我們已經對Winform事件有了一定的了解,那我們如何借助這個思想來實現我們自己的事件處理呢?

接下來我們模擬一個場景,我們有一個文本文件,我們監聽文件,如果文本文件發生改變(相當於上面所說的鼠標監聽觸發事件),觸發事件向管理員和用戶發一條信息提示(這里的人相當於button對象,向不同人發模擬Winform不同控件的click事件)。利用剛才的Winform事件技術實現一下;

1首先定義一個事件的委托

 

  //處理文件發生變化后的委托聲明
    public delegate void MonitorEventHandler(object sender, EventArgs e);

 

2事件傳遞的事件數據

//事件數據類       繼承自EventArgs
    public class MsgEventArgs : EventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="changeTime">修改時間</param>
        /// <param name="toSend">提示信息</param>
        public MsgEventArgs(DateTime changeTime, string toSend)
        {
            this.ChangeTime = changeTime;
            this.ToSend = toSend;
        }
        //  修改時間
        public DateTime ChangeTime { get; set; }
        // 提示信息
        public string ToSend { get; set; }
    }

3 MonitorText類監控文件類(相當於上面講的鼠標監聽類)

 
        
 public class MonitorText
    {
        //定義監控文本事件
        public event MonitorEventHandler MonitorEvent;
        //上次文件更新時間用於判斷文件是否修改過
        private DateTime _lastWriteTime = File.GetLastWriteTime(@"C:\Users\HHY\Desktop\1.txt");
        public MonitorText()
        {

        }
        // 文件更新調用
        protected virtual void OnTextChange(MsgEventArgs e)
        {
            if (MonitorEvent != null)
            {
                //不為空,處理事件
                MonitorEvent(this, e);
            }
        }

        //事件監聽的方法
        public void BeginMonitor()
        {
            DateTime bCurrentTime;

            while (true)
            {
                bCurrentTime = File.GetLastWriteTime(@"C:\Users\HHY\Desktop\1.txt");
                if (bCurrentTime != _lastWriteTime)
                {
                    _lastWriteTime = bCurrentTime;
                    MsgEventArgs msg = new MsgEventArgs(bCurrentTime,"文本改變了");
                    OnTextChange(msg);
                }
//0.1秒監控一次 Thread.Sleep(1
00); } } }
 
        

4管理員類(相對於Button類)

public class Administrator
    {
      //管理員事件處理方法
        public void OnTextChange(object Sender, EventArgs e)
        {
            Console.WriteLine("尊敬的管理員:"+DateTime.Now.ToString() + ": 文件發生改變.");
        }
    }

5用戶類(相對於Button類以外的控件類)

public class User
    {
        //用戶事件處理方法
       public void OnTextChange(object Sender, EventArgs e)
       {
           Console.WriteLine("尊敬的用戶:" + DateTime.Now.ToString() + ": 文件發生改變.");
       }
    }

6程序的Main方法

  class Program
    {
        //定義監控文本對象
        static MonitorText MonitorTextEventSource;
        static void Main(string[] args)
        {
        
            MonitorTextEventSource = new MonitorText();
            //1. 啟動后台線程添加監視事件
            var thrd = new Thread(MonitorTextEventSource.BeginMonitor);
            thrd.IsBackground = true;
            thrd.Start();
            //2實例化管理員類
            Administrator ad = new Administrator();
            //3實例化用戶類
            User user = new User();
            //4訂閱事件
            MonitorTextEventSource.MonitorEvent += ad.OnTextChange;
            MonitorTextEventSource.MonitorEvent += user.OnTextChange;
            Console.ReadLine();
        }
    }

運行程序

好了到現在,我們的模擬完成了,大體將Winform事件的流程實現了一遍,由於自己本身也也是一個小白理解的不到位的地方請大家指出來,我把程序源碼放在了下面,大家可以調試運行一下。

源碼地址:http://pan.baidu.com/s/1bRelEQ












 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM