(转)自定义监听文本改变事件 了解事件的原理
转自:https://www.cnblogs.com/ATtuing/p/5351538.html
当我们初学Winform的时候被其神奇的事件功能所吸引,当点击一个按钮时,便会跳到我们所写的点击方法当中去。然而这并不符合我们对方法的理解,究竟.net在后面帮助我们实现了什么。我们怎样模拟其事件的实现呢。下面先从Button的Click方法说起。
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反编译一下,这是对鼠标事件的判定,我们会惊奇的发现里面有对单击与双击的判定。

在往下走便是对鼠标事件的监听,有兴趣可以继续往下查看调用堆栈,
我们总结一下,button的click的触发经过如下过程
好了到目前为止我们已经对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(100);
}
}
}
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事件的流程实现了一遍,由于自己本身也也是一个小白理解的不到位的地方请大家指出来,我把程序源码放在了下面,大家可以调试运行一下。

浙公网安备 33010602011771号