WinForm|--控件|--Button|--Click|--结合源码搞明白Click事件
前言
最近在搞C/S端的东西,突然对Button
控件的点击事件感兴趣了,
以前只是会用的阶段, 想看下源码具体是咋实现的...
源码查看地址
https://referencesource.microsoft.com/
其实如果看源码的话,微软在Github的开源项目更适合来看,
但是,我上次看WPF的源码, 费了好大劲都没本地构建(build:指本地能运行起来)成功...
(但是心里想 : 我以后就算用记事本看源码,也不构建源码了...)
直接上源码
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
namespace ConsoleApp.OnClickSample
{
/*
可以看到,涉及Button的Click事件的相关类主要有3个 : [ Control, EventHandlerList, Component ]
*/
public class ButtonZf //源代码继承自:ButtonBase, IButtonControl
{
#region File: winforms\Managed\System\WinForms\Control.cs
private static readonly object EventClick = new object();
/// <include file='doc\Control.uex' path='docs/doc[@for="Control.Click"]/*' />
/// <devdoc>
/// <para>Occurs when the control is clicked.</para>
/// </devdoc>
//[SRCategory(SR.CatAction), SRDescription(SR.ControlOnClickDescr)]
public event EventHandler Click
{
add
{
//Level...1
Events.AddHandler(EventClick, value);
}
remove
{
//Level...1
Events.RemoveHandler(EventClick, value);
}
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
//protected virtual void OnClick(EventArgs e)
/*
源代码: protected virtual void OnClick(EventArgs e)
改造后: public virtual void OnClick(EventArgs e)
其实源代码中还有一个方法"InvokeOnClick(Control toInvoke, EventArgs e)",使用"toInvoke.OnClick(e)",但是核心不在这个方法上,
并且如果增加这个方法的话,还要增加一些引用...
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void InvokeOnClick(Control toInvoke, EventArgs e)
{
if (toInvoke != null)
{
toInvoke.OnClick(e);
}
}
*/
public virtual void OnClick(EventArgs e)
{
Contract.Requires(e != null);
EventHandler handler = (EventHandler)Events[EventClick];
if (handler != null) handler(this, e);
}
#endregion
#region File: compmod\system\componentmodel\Component.cs [ Control继承自Component=>"public partial class Control : Component..." ]
private EventHandlerList events;
/// <devdoc>
/// <para>Gets the list of event handlers that are attached to this component.</para>
/// </devdoc>
protected EventHandlerList Events
{
get
{
if (events == null)
{
events = new EventHandlerList();
//events.parent = parent;
}
return events;
}
}
#endregion
}
/// <summary>
/// 将源代码类"EventHandlerList"直接复制过来
/// 地址 : https://referencesource.microsoft.com/#System/compmod/system/componentmodel/EventHandlerList.cs
/// </summary>
//[HostProtection(SharedState = true)]
public class EventHandlerList : IDisposable
{
ListEntry head;
Component parent;
/// <devdoc>
/// Creates a new event handler list.
/// </devdoc>
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
public EventHandlerList()
{
}
/// <devdoc>
/// Creates a new event handler list. The parent component is used to check the component's
/// CanRaiseEvents property.
/// </devdoc>
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
internal EventHandlerList(Component parent)
{
this.parent = parent;
}
/// <devdoc>
/// <para>Gets or sets the delegate for the specified key.</para>
/// </devdoc>
public Delegate this[object key]
{
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
get
{
ListEntry e = null;
/*
internal bool CanRaiseEventsInternal
{
get
{
return CanRaiseEvents;
}
}
*/
//if (parent == null || parent.CanRaiseEventsInternal)
//改造
if (parent == null)
{
e = Find(key);
}
if (e != null)
{
return e.handler;
}
else
{
return null;
}
}
set
{
ListEntry e = Find(key);
if (e != null)
{
e.handler = value;
}
else
{
head = new ListEntry(key, value, head);
}
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
public void AddHandler(object key, Delegate value)
{
ListEntry e = Find(key);
if (e != null)
{
e.handler = Delegate.Combine(e.handler, value);
}
else
{
head = new ListEntry(key, value, head);
}
}
/// <devdoc> allows you to add a list of events to this list </devdoc>
public void AddHandlers(EventHandlerList listToAddFrom)
{
ListEntry currentListEntry = listToAddFrom.head;
while (currentListEntry != null)
{
AddHandler(currentListEntry.key, currentListEntry.handler);
currentListEntry = currentListEntry.next;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public void Dispose()
{
head = null;
}
private ListEntry Find(object key)
{
ListEntry found = head;
while (found != null)
{
if (found.key == key)
{
break;
}
found = found.next;
}
return found;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
public void RemoveHandler(object key, Delegate value)
{
ListEntry e = Find(key);
if (e != null)
{
e.handler = Delegate.Remove(e.handler, value);
}
// else... no error for removal of non-existant delegate
//
}
private sealed class ListEntry
{
internal ListEntry next;
internal object key;
internal Delegate handler;
public ListEntry(object key, Delegate handler, ListEntry next)
{
this.next = next;
this.key = key;
this.handler = handler;
}
}
}
}
using ConsoleApp.OnClickSample;
Console.WriteLine("Hello, World!");
//自己写了重点在Click事件的Button按钮"ButtonZf"
ButtonZf onClickSample = new ButtonZf();
//注册点击事件
onClickSample.Click += (sender, e) =>
{
global::System.Console.WriteLine("已经点击了...");
var btnZf = sender as ButtonZf;
Console.ReadKey();
};
//模拟用户点击事件
onClickSample.OnClick(EventArgs.Empty);