以前,创建非矩形窗体是一个既费时又费人力的过程,其中涉及到 API 调用和大量的编程工作。 现在,这已经不成问题了。
提示
此过程涉及到大量的相关硬件的图形处理,因此,根据现有的内存和图形卡,计算机的执行也有所不同。 当应用程序涉及到自定义绘图时,在为用户部署该应用程序之前,应始终在不同的显示视频卡上进行测试,以确保良好的性能。
创建非矩形窗体的过程有两个要素:创建成形的窗体,并编写某些编程逻辑的代码以允许移动和关闭窗体。 第二个步骤是必要的,因为自定义形状的窗体没有标题栏,并且它本身不具有任何功能,例如在屏幕中移动窗体以及关闭窗体的能力。 因此,编写重现这些功能的代码是非常必要的。 有关创建非矩形形状的两个窗体和控件的更多信息,请参见如何:创建特定形状的 Windows 窗体。
创建非矩形窗体的过程包含三个步骤:
创建一个作为窗体图面的位图。 (一种有效的方式是,您可以从矩形中“裁剪掉”所需的窗体形状。)
创建 Windows 应用程序项目,将其属性设置为移除标题栏并使用位图作为窗体背景。
输入重新创建标题栏所提供功能的代码,例如移动和关闭窗体。
提示
显示的对话框和菜单命令可能会与“帮助”中的描述不同,具体取决于您现用的设置或版本。 若要更改设置,请在“工具”菜单上选择“导入和导出设置”。 有关更多信息,请参见 使用设置。
创建特定形状的窗体
创建一个非矩形的单色位图,其背景则使用另一种颜色。 使用您喜欢的任何绘图程序。 所绘制的形状最终将成为您的窗体,因此请确保该形状足够大,以满足使用的需求。
提示
请选择便于记忆的背景色,例如蓝色,因为这对于后面的操作是非常重要的。
在 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; } }
C# 说明
请确保添加启用事件处理程序的代码。 使用以下示例中的代码,它类似于以下内容:
this.MouseUp += new System.Windows.Forms.MouseEventHandler (this.Form1_MouseUp);