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);
posted @ 2022-05-16 23:11  zh89233  阅读(217)  评论(0编辑  收藏  举报