飘渺李煜 發表於 2026-4-13 12:00:00

基于.NET的Windows窗体编程之WinForms事件简介

<p>在实际开发中,程序的核心是处理数据,它将收集到的数据进行加工处理等计算,再将结果呈现到软件页面上。所以系统不仅向用户展示数据,还会从用户收集数据,以实现双向交互(接收-处理-反馈)的闭环。程序与用户的交互,离不开事件的帮助,事件就像是程序与用户之间的桥梁,实现双方的完美对接。今天我们以一些简单的小例子,简述基于.NET的Windows窗体编程中事件的相关内容,仅供学习分享使用,如有不足之处,还请指正。</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202603/1068941-20260329003445816-806777847.png"></p>
<p>&nbsp;</p>
<h1>概述</h1>
<p>&nbsp;</p>
<p>事件是在代码中可以响应或“处理”的操作。 事件通常由用户操作(如单击鼠标或按键)触发,但它们也可以由程序代码或系统生成。事件驱动的应用程序运行代码以响应事件。 每个窗体和控件都会公开一组预定义的事件,可以响应这些事件。 如果引发其中一个事件并且存在关联的事件处理程序,则调用处理程序并运行代码以完成相应的功能。</p>
<p>委托是 .NET 中通常用于生成事件处理机制的类。 委托大致等同于函数指针,但与函数指针不同的是,委托是面向对象的、类型安全的和保险的。 此外,函数指针仅包含对特定函数的引用,委托包含对对象的引用,以及对对象中的一个或多个方法的引用。事件模型使用<em> </em>委托 将事件绑定到用于处理事件的方法,关于事件模型,主要有以下几点需要注意:</p>
<ol>
<li>委托允许其他类通过指定处理程序方法来注册事件通知。 当发生事件时,委托会调用绑定的方法。</li>
<li>委托可绑定到单个方法或多个方法,后者又称为多路广播。 为事件创建委托时,通常会创建多播事件。多播委托维护绑定到它的方法的调用列表。</li>
<li>当应用程序触发事件时,控件通过调用该事件的委托来引发该事件。 委托依次调用绑定的方法。</li>
<li>委托还允许将多个事件绑定到同一个方法上,从而允许多对一通知。例如,按钮单击事件和菜单命令单击事件都可以调用相同的委托,然后调用单个方法以相同的方式处理这些单独的事件。</li>
<li>用于委托的绑定机制是动态的:委托可以在运行时与任何其签名与事件处理程序的签名匹配的方法绑定。 使用此功能,可以根据条件设置或更改绑定方法,并动态将事件处理程序附加到控件。</li>
</ol>
<p>&nbsp;</p>
<h1>事件分类</h1>
<p>&nbsp;</p>
<p>控件通过基类 Control提供 60 多个事件。 其中包括 Paint 导致绘制控件的事件、与显示窗口相关的事件(如 Resize 和 Layout 事件)以及低级别鼠标和键盘事件。 某些低级别事件由Control合成为语义事件,例如Click和DoubleClick。 大多数事件属于以下类别:</p>
<ul>
<li>鼠标事件,鼠标输入是用户与 Windows 窗体应用程序交互的主要方式。 所有控件都提供与鼠标相关的基本事件:<br>
<ul>
<li>MouseClick,鼠标单击事件,可以获取鼠标更多点击信息</li>
<li>MouseDoubleClick,鼠标双击事件,双击由用户操作系统的鼠标设置决定。 用户可以设置两次单击鼠标按钮之间的时间以便将这两次单击认为是双击而不是两次单击。</li>
<li>MouseDown,鼠标按下事件</li>
<li>MouseEnter,鼠标指针进入控件时触发事件</li>
<li>MouseHover,鼠标放上去事件</li>
<li>MouseLeave,鼠标离开事件</li>
<li>MouseMove,鼠标移动事件</li>
<li>MouseUp,鼠标弹起事件</li>
<li>MouseWheel,鼠标滚动事件</li>
<li>Click,鼠标单击事件,它仅表示鼠标点击了控件,从而触发此事件,如果需要更多鼠标信息,请使用MouseClick事件。</li>
</ul>
</li>
<li>键盘事件,如果控件响应用户输入(如&nbsp;TextBox&nbsp;或&nbsp;Button&nbsp;控件),则会为控件引发相应的输入事件。 控件需要聚焦才能接收键盘事件。 某些控件(如&nbsp;Label&nbsp;控件)无法聚焦且无法接收键盘事件。 下面是键盘事件的列表:<br>
<ul>
<li>KeyDown,键盘上的键被按下时触发此事件。</li>
<li>KeyPress,当控件具有焦点时按下字符、空格或反空间键时发生。它在KeyDown之后触发,可以用来阻止字符的输入。</li>
<li>KeyUp,键盘上的键按下弹起时触发此事件。</li>
</ul>
</li>
<li>属性更改事件,Windows 窗体对于包含更改事件的属性,遵循&nbsp;<em>PropertyNameChanged</em> 模式。 Windows 窗体提供的数据绑定引擎可识别此模式并与之很好地集成。 如果属性名称为FirstName,则属性更改事件具有如下命名格式:<br>
<ul>
<li>将属性命名为:&nbsp;<code>FirstName</code>。</li>
<li>使用模式&nbsp;<code>PropertyNameChanged</code>为属性创建事件:&nbsp;<code>FirstNameChanged</code>。</li>
<li>使用模式&nbsp;<code>OnPropertyNameChanged</code>创建私有或受保护的方法:&nbsp;<code>OnFirstNameChanged</code>。</li>
<li>如果修改了<code>FirstName</code>属性集的后备值,则将调用<code>OnFirstNameChanged</code>方法。 该方法&nbsp;<code>OnFirstNameChanged</code>&nbsp;引发&nbsp;<code>FirstNameChanged</code>&nbsp;事件。</li>
</ul>
</li>
<li>常见的属性变更事件,主要有以下几种:
<ul>
<li>BackColorChanged &nbsp; &nbsp;当 BackColor 属性的值发生更改时触发。</li>
<li>BackgroundImageChanged &nbsp; &nbsp;当 BackgroundImage 属性的值发生更改时触发。</li>
<li>BindingContextChanged &nbsp; &nbsp;当 BindingContext 属性的值发生更改时触发。</li>
<li>DockChanged &nbsp; &nbsp;当 Dock 属性的值发生更改时触发。</li>
<li>EnabledChanged &nbsp; &nbsp;在 Enabled 属性值更改后发生。</li>
<li>FontChanged &nbsp; &nbsp;当 Font 属性值更改时发生。</li>
<li>ForeColorChanged &nbsp; &nbsp;当 ForeColor 属性值更改时发生。</li>
<li>LocationChanged &nbsp; &nbsp;在 Location 属性值更改后发生。</li>
<li>SizeChanged &nbsp; &nbsp;当 Size 属性值更改时发生。</li>
<li>VisibleChanged &nbsp; &nbsp;当 Visible 属性值更改时发生。</li>
</ul>
</li>
<li>其他事件,控件还会根据控件的状态或其他与控件的交互引发事件。 例如, HelpRequested 如果控件具有焦点,并且用户按下&nbsp;<kbd>F1</kbd>&nbsp;键,则会引发该事件。 如果用户在窗体上按下上下文相关的&nbsp;<strong>帮助</strong> 按钮,然后按控件上的帮助光标,也会引发此事件。另一个示例是,当控件更改、移动或调整大小时,会引发&nbsp;Paint&nbsp;事件。 此事件为开发人员提供了绘制控件和更改其外观的机会。</li>
</ul>
<p>关于事件,还有以下两点补充说明:</p>
<ol>
<li>每次双击控件时都会引发Click事件。 例如,如果控件具有的Click&nbsp;和&nbsp;DoubleClick 事件的事件处理程序,则双击窗体并调用这两种方法时,将引发DoubleClick和Click事件。 如果双击某个控件,并且该控件不支持该 DoubleClick 事件,则可能会引发 Click&nbsp;事件两次。</li>
<li>在用户按下键盘键时发生两个事件,在用户释放键盘键时发生一个事件。KeyDown&nbsp;事件发生一次。KeyPress&nbsp;事件,当用户按住同一个密钥时,可能会多次发生该事件。当用户释放密钥时,KeyUp&nbsp;事件发生一次。</li>
</ol>
<p>&nbsp;</p>
<h1>窗体的事件顺序</h1>
<p>&nbsp;</p>
<p>了解Windows 窗体应用程序中事件被引发的顺序,有助于依次处理每个事件。 当出现需要谨慎处理事件的情况时(例如,在重绘窗体的某些部件时),有必要了解运行时引发事件的确切顺序。&nbsp;</p>
<p>Form&nbsp;和&nbsp;Control&nbsp;类公开了一组与应用程序启动和关闭相关的事件。 Windows 窗体应用程序启动时,主窗体的启动事件将按照以下顺序引发:</p>
<ul>
<li>Control.HandleCreated,在为控件创建句柄时触发此事件。</li>
<li>Control.BindingContextChanged,当&nbsp;BindingContext&nbsp;属性的值更改时发生。</li>
<li>Form.Load,在第一次显示窗体前发生。</li>
<li>Control.VisibleChanged,当&nbsp;Visible&nbsp;属性值更改时发生。</li>
<li>Form.Activated,当使用代码激活或用户激活窗体时发生。</li>
<li>Form.Shown,只要窗体是首次显示就发生。</li>
</ul>
<p>应用程序关闭时,主窗体的关闭事件将按照以下顺序引发:</p>
<ul>
<li>Form.Closing,当窗体关闭时发生。此事件已过时,请采用 FormClosing&nbsp;事件。</li>
<li>Form.FormClosing,当窗体关闭时发生。</li>
<li>Form.Closed,关闭窗体时发生。此事件已过时,请采用 FormClosed事件。</li>
<li>Form.FormClosed,关闭窗体时发生。</li>
<li>Form.Deactivate,当窗体失去焦点并不再是活动窗体时发生。</li>
</ul>
<p>在主窗体关闭事件后,将引发Application类的ApplicationExit事件。</p>
<p>&nbsp;</p>
<h1>窗体中的坐标</h1>
<p>&nbsp;</p>
<p>Windows 窗体的坐标系基于设备坐标,在 Windows 窗体中绘制时的基本度量单位是设备单位(通常为像素)。 屏幕上的点由 x 坐标和 y 坐标对描述,x 坐标向右增加,y 坐标从上到下增加。 原点相对于屏幕的位置会有所不同,具体取决于是指定屏幕还是客户端坐标。</p>
<ul>
<li>屏幕坐标:Windows 窗体应用程序以屏幕坐标指定窗口在屏幕上的位置。 对于屏幕坐标,原点为屏幕左上角。 窗口的整个位置通常由一个&nbsp;Rectangle&nbsp;结构描述,该结构包含两个点的屏幕坐标,用于定义窗口的左上角和右下角。</li>
<li>客户端坐标:Windows 窗体应用程序使用客户端坐标指定窗体或控件中点的位置。 客户端坐标的原点是控件或窗体的客户区左上角。 客户端坐标可确保应用程序可以在窗体或控件中绘图时使用一致的坐标值,而不管窗体或控件在屏幕上的位置如何。</li>
</ul>
<p>客户区的尺寸也由一个包含该区域客户端坐标的&nbsp;Rectangle&nbsp;结构进行描述。 在所有情况下,矩形的左上角坐标包含在客户区中,而右下角坐标则不包括在内。 图形操作不包括工作区的右边缘和下边缘。 例如,FillRectangle&nbsp;方法将填充到指定矩形的右边缘和下边缘,但不包括这些边缘。</p>
<p>有时,可能需要从屏幕坐标映射到客户端坐标。 可以使用&nbsp;PointToClient&nbsp;类中提供的&nbsp;PointToScreen&nbsp;和&nbsp;Control&nbsp;方法轻松实现此目的。 例如,MousePosition&nbsp;的&nbsp;Control&nbsp;属性是以屏幕坐标表示的,但可能需要将其转换为客户端坐标。</p>
<p>&nbsp;</p>
<h1>事件示例</h1>
<p>&nbsp;</p>
<p>在Windows窗体编程中,最常用的就是Button(按钮)控件,它允许用户通过单击来执行某项操作。&nbsp;<span style="font-family: &quot;PingFang SC&quot;, 宋体"><code>Button</code> 控件可以同时显示文本和图像。 单击该按钮时,看上去它像是被按下并释放。每当用户单击按钮时,&nbsp;就会调用Click事件处理程序, 我们可以在 Click 事件处理程序中放置代码以执行您选择的任何操作。</span></p>
<p><span style="font-family: &quot;PingFang SC&quot;, 宋体">Button按钮关键属性与事件:</span></p>
<ul>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">Name,按钮控件的唯一标识,它在一个Form窗体中具有唯一性。</span></li>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">Text,用于设置按钮上显示的文本内容,如果文本超过按钮的宽度,它将换行到下一行。 但是,如果控件不能容纳其整体高度,则会将其剪裁。</span></li>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">TextAlign,按钮上文本的对齐方式。</span></li>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">Image,可以为控件设置图标。</span></li>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">ImageAlign,按钮上图像的对齐方式。</span></li>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">Click事件,又称为“点击”事件,通过Click事件可以在单击按钮时运行一些代码。如果用户尝试双击Button控件,将单独处理每次单击;也就是说,该控件不支持双击事件。</span></li>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">TextImageRelation,文本图像的相对位置,它的值类型是一个枚举类型,共有5个值,Overlay(默认重叠),ImageBeforeText(左图右字),TextBeforeImage(左字右图),ImageAboveText(上图下字),TextAboveImage(上字下图)。</span></li>
</ul>
<p><span style="font-family: &quot;PingFang SC&quot;, 宋体">为Button按钮添加Click事件,具体步骤如下:</span></p>
<p><span style="font-family: &quot;PingFang SC&quot;, 宋体">1. 在Form窗体中添加一个按钮控件,并命名为btnOk,设置Text属性为OK,如下所示:</span></p>
<p><span style="font-family: &quot;PingFang SC&quot;, 宋体"><img src="https://img2024.cnblogs.com/blog/1068941/202604/1068941-20260412220840523-2083997973.png"></span></p>
<p><span style="font-family: PingFang SC, 宋体">2. 在属性窗口切换到事件Tab页(⚡️),在Click事件右侧的框中双击,VisualStudio设计器,会自动生成btnOk_Click</span><span style="font-family: &quot;PingFang SC&quot;, 宋体">事件处理方法,如下图所示:</span></p>
<p><span style="font-family: PingFang SC, 宋体"><img src="https://img2024.cnblogs.com/blog/1068941/202604/1068941-20260412221232838-198126381.png"></span></p>
<p><span style="font-family: &quot;PingFang SC&quot;, 宋体">3. 切换到Form窗体对应的类文件,便可以看到自动生成的事件处理方法,它包含两个参数:</span></p>
<ul>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">object sender,它表示用户点击的控件本身,在这里表示btnOk按钮。</span></li>
<li><span style="font-family: &quot;PingFang SC&quot;, 宋体">EventArgs e,它表示点击事件包括的参数数据。</span></li>
</ul>
<p><span style="font-family: &quot;PingFang SC&quot;, 宋体">默认btnOk_Click方法是空的,可以在其中编写需要被执行的代码,如:弹出一个对话框,提示点击了按钮,如下所示:</span></p>
<pre class="language-csharp highlighter-hljs"><code>namespace Okcoder.WinForm.Demo
{
    public partial class FrmEvent: Form
    {
      public FrmEvent()
      {
            InitializeComponent();
      }

      private void btnOk_Click(object sender, EventArgs e)
      {
            //点击事件被执行的代码
            MessageBox.Show("你点击了OK按钮");
      }
    }
}</code></pre>
<p>通过Visual Studio调试运行程序,当点击按钮时,弹出一个带有“你点击了OK按钮”字样的对话框,如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202604/1068941-20260412222527779-1696969619.png"></p>
<p>说明:Button控件还会生成许多其他事件,例如MouseEnter,MouseDown和MouseUp事件。 如果打算为这些相关事件添加事件处理程序,请确保其作不会冲突。同时我们还可以设置Form窗体的AcceptButton或CancelButton为指定的按钮控件,它允许用户即使在按钮没有焦点时也可以通过按下 Enter 或 ESC 键来单击按钮。&nbsp;</p>
<p>以上就是《基于.NET的Windows窗体编程之WinForms事件简介》的全部内容,旨在抛砖引玉,一起学习,共同进步。</p>

</div>
<div id="MySignature" role="contentinfo">
    <div id="AllanboltSignature">

    <p style="border-top: #e0e0e0 1px dashed; border-right: #e0e0e0 1px dashed; border-bottom: #e0e0e0 1px dashed; border-left: #e0e0e0 1px dashed; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 30px; font-family: 微软雅黑; font-size: 12px" id="PSignature">
<br>

   <img alt="" src="https://images.cnblogs.com/cnblogs_com/hsiang/1154298/o_115f1cd8.jpg" width="80px" height="80px">
   
    作者:老码识途
    <br>
    出处:http://www.cnblogs.com/hsiang/
    <br>
    本文版权归作者和博客园共有,写文不易,支持原创,欢迎转载【点赞】,转载请保留此段声明,且在文章页面明显位置给出原文连接,谢谢。
    <br>关注个人公众号,定时同步更新技术及职场文章
<br><br>
   </p>
</div><br><br>
来源:https://www.cnblogs.com/hsiang/p/19837736
頁: [1]
查看完整版本: 基于.NET的Windows窗体编程之WinForms事件简介