如何:创建非矩形 Windows 窗体
更新:2007 年 11 月
以前,创建非矩形窗体是一个既费时又费人力的过程,其中涉及到 API 调用和大量的编程工作。现在,这已经不成问题了。
说明: |
---|
此过程涉及到大量的相关硬件的图形处理,因此,根据现有的内存和图形卡,计算机的执行也有所不同。当应用程序涉及到自定义绘图时,在为用户部署该应用程序之前,应始终在不同的显示视频卡上进行测试,以确保良好的性能。 |
创建非矩形窗体的过程有两个要素:创建成形的窗体,并编写某些编程逻辑的代码以允许移动和关闭窗体。第二个步骤是必要的,因为自定义形状的窗体没有标题栏,并且它本身不具有任何功能,例如在屏幕中移动窗体以及关闭窗体的能力。因此,编写重现这些功能的代码是非常必要的。有关创建非矩形形状的两个窗体和控件的更多信息,请参见 如何:创建特定形状的 Windows 窗体。
创建非矩形窗体的过程包含三个步骤:
创建一个作为窗体图面的位图。(一种有效的方式是,您可以从矩形中“裁剪掉”所需的窗体形状。)
创建 Windows 应用程序项目,将其属性设置为移除标题栏并使用位图作为窗体背景。
输入重新创建标题栏所提供功能的代码,例如移动和关闭窗体。
说明: |
---|
显示的对话框和菜单命令可能会与“帮助”中的描述不同,具体取决于您的当前设置或版本。若要更改设置,请在“工具”菜单上选择“导入和导出设置”。有关更多信息,请参见 Visual Studio 设置。 |
创建特定形状的窗体
创建一个非矩形的单色位图,其背景则使用另一种颜色。使用您喜欢的任何绘图程序。所绘制的形状最终将成为您的窗体,因此请确保该形状足够大,以满足使用的需求。
说明: 请选择便于记忆的背景色,例如蓝色,因为这对于后面的操作是非常重要的。
在 Visual Studio 中创建一个新的 Windows 应用程序项目。有关更多信息,请参见如何:创建 Windows 应用程序项目。
在“属性”窗口中:
将 FormBorderStyle 属性设置为 None。
此属性从窗体中移除标题栏。(它同时移除标题栏所提供的功能,包括关闭和移动窗体的能力。不过,以下代码中解决了这种不足。)
将窗体的 BackgroundImage 属性设置为先前创建的位图文件。不必将文件添加到项目系统中;这将在指定该文件作为背景图像时自动完成。
此属性将该位图图像设置为窗体的背景。(当与以下指定的 TransparencyKey 属性前后使用时,此属性将定义窗体的形状。)
将 TransparencyKey 属性设置为位图文件的背景色。
此属性告诉应用程序窗体中的哪些部分需要设置为透明。
说明: 如果监视器的颜色深度设置大于 24 位,则不管 TransparencyKey 属性是如何设置的,窗体的非透明部分都会产生显示问题。若要避免出现这种问题,请确保“显示”控制面板中的监视器颜色深度的设置小于 24 位。当开发具有这种透明功能的应用程序时,请牢记应使您的用户意识到此问题。
编写关闭窗体的代码
将一个 Button 控件添加到窗体中。有关更多信息,请参见 如何:向 Windows 窗体添加控件。
添加代码,使用户可通过调用 Close 方法关闭该窗体。
下面的示例显示如何添加一个按钮,单击该按钮将关闭窗体。
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Me.Close() End Sub
private void button1_Click(object sender, System.EventArgs e) { this.Close(); }
C# 说明: 请确保添加启用事件处理程序的代码。使用以下示例中的代码,它类似于以下内容:
this.Button1.Click += new System.EventHandler(this.button1_Click);
编写移动窗体的代码(可选)
创建一个在拖动窗体时使窗体移动的过程。输入类似于下文显示的代码来创建新的 Point 对象。这将作为计算如何移动窗体时的变量。isMouseDown 字段用于跟踪用户是否按下了鼠标按钮。该窗体应只在用户按下鼠标按钮时才移动。
Private mouseOffset As Point Private isMouseDown As Boolean = False
private Point mouseOffset; private bool isMouseDown = false;
为窗体的 MouseDown 事件创建一个事件处理程序。在处理程序中添加代码,使用户可以在窗体上的任意位置单击以拖动窗体。有关创建事件处理程序的详细信息,请参见 如何:使用设计器创建事件处理程序。
输入类似于下文显示的代码,以根据鼠标指针的当前位置,将坐标分配给 mouseOffset 变量。在以下代码中,请注意偏移位置是使用有关边框大小 (FrameBorderSize.Width) 和标题栏高度 (CaptionHeight) 的系统信息进行计算的。在测试偏移位置时必须考虑这些因素,因为某些测量结果是使用工作区得出的,而另一些测量结果是使用屏幕坐标得出的。因此,偏移位置等于边框宽度加上标题高度,再加上窗体工作区的偏移位置。
Private Sub Form1_MouseDown(ByVal sender As Object, _ ByVal e As MouseEventArgs) Handles MyBase.MouseDown Dim xOffset As Integer Dim yOffset As Integer If e.Button = MouseButtons.Left Then xOffset = -e.X - SystemInformation.FrameBorderSize.Width yOffset = -e.Y - SystemInformation.CaptionHeight - _ SystemInformation.FrameBorderSize.Height mouseOffset = New Point(xOffset, yOffset) isMouseDown = True End If End Sub
private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { int xOffset; int yOffset; if (e.Button == MouseButtons.Left) { xOffset = -e.X - SystemInformation.FrameBorderSize.Width; yOffset = -e.Y - SystemInformation.CaptionHeight - SystemInformation.FrameBorderSize.Height; mouseOffset = new Point(xOffset, yOffset); isMouseDown = true; } }
C# 说明: 请确保添加启用事件处理程序的代码。使用以下示例中的代码,它类似于以下内容:
this.MouseDown += new System.Windows.Forms.MouseEventHandler (this.Form1_MouseDown);
为窗体的 MouseMove 事件创建一个事件处理程序。
输入类似以下内容的代码。单击鼠标左键并且拖动鼠标时,窗体的 Location 属性将设置为新的位置。
Private Sub Form1_MouseMove(ByVal sender As Object, _ ByVal e As MouseEventArgs) Handles MyBase.MouseMove If isMouseDown Then Dim mousePos As Point = Control.MousePosition mousePos.Offset(mouseOffset.X, mouseOffset.Y) Location = mousePos End If End Sub
private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { if (isMouseDown) { Point mousePos = Control.MousePosition; mousePos.Offset(mouseOffset.X, mouseOffset.Y); Location = mousePos; } }
C# 说明: 请确保添加启用事件处理程序的代码。使用以下示例中的代码,它类似于以下内容:
this.MouseMove += new System.Windows.Forms.MouseEventHandler (this.Form1_MouseMove);
为窗体的 MouseUp 事件创建一个事件处理程序。输入类似以下内容的代码。
Private Sub Form1_MouseUp(ByVal sender As Object, _ ByVal e As MouseEventArgs) Handles MyBase.MouseUp ' Changes the isMouseDown field so that the form does ' not move unless the user is pressing the left mouse button. If e.Button = MouseButtons.Left Then isMouseDown = False End If End Sub
private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { // Changes the isMouseDown field so that the form does // not move unless the user is pressing the left mouse button. if (e.Button == MouseButtons.Left) { isMouseDown = false; } }