用VB.NET创建非标准窗体和控件

                                                         ■湖南 谢潇渔 撰于2008年10月31日

    某些时候,我们希望创建一个非标准的窗体和控件。我们常见的播放器软件,其主界面就是一个位图图像,不是规则的矩形。在VB6时代,要创建非矩形窗体是一件非常麻烦的事,然而在VB.NET中,我们可以利用.NET Framework的强大功能轻松创建非标准控件。我们只需要少数几行代码,甚至不需要代码即可完成。

    基本上,制作非矩形控件主要利用以下两种方法。

   一、利用窗体的TransparencyKey属性

    窗体有一个TransparencyKey属性,用于指定窗体上哪种颜色是透明的。由此,我们就可以使窗体部分透明,制作非矩形窗体。以这种方式可以绘制出图片界面的窗体,只需要在窗体的BackgroundImage属性载入窗体的背景图,再设置TransparencyKey属性,就可以轻松制作出与图片形状相同的窗体。

需要注意的是,除了位图边缘部分以外,其余部分不能有与指定的透明色相同的颜色,否则图片内部的某些部分也变成透明的了。例如图1所示的图片,笔者对其进行了处理,椭圆形内任何部分都没有白色的成分,而椭圆外为白色的,因此可以指定白色为透明色。(可以利用Photoshop的颜色替换将白色部分替换成极其浅的灰色)。

                               

    完整地创建非矩形的过程如下:

   1.创建非矩形窗体

    打开窗体的属性窗口,选中BackgroundImage属性,单击右边的省略号,弹出图2所示的对话框。选中“本地资源”,单击“导入”按钮导入一个位图图像。尔后将窗体的FormBorderStyle设置为None,以去除窗体的标题栏和边框,最后把TransparencyKey属性设置为白色,按F5运行程序,我们可以看到已经成功地制作了一个形如图1的非标准的椭圆形窗体。至此我们没有写一行代码,是不是觉得很方便?

    不过,由于FormBorderStyle属性是None,我们无法拖动窗体和关闭窗体,为此我们要编写代码弥补这些功能。请终止程序执行,继续下面的操作。

   2.撰写窗体的其他代码

    实现拖拽窗体的功能很简单,拖曳的过程中,窗体的左上角坐标实际上是鼠标当前的坐标减去拖动时初始坐标。藉此我们可以轻易地写出如下代码:

    Dim MouseOffSet As Point   '声明部分,记录鼠标初始位置

    Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown

       MouseOffSet = New Point(-e.X, -e.Y)

    End Sub

    Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove

        If e.Button = Windows.Forms.MouseButtons.Left Then '如果使用鼠标左键拖拽窗体

            Dim newPos As Point

            newPos = Control.MousePosition

           newPos.Offset(MouseOffSet.X, MouseOffSet.Y)    '当前坐标-初始坐标

            Me.Location = newPos

        End If

    End Sub

    我们通过按ESC键关闭程序,代码如下,为了使窗体响应按键,请将窗体的KeyPreview属性设置为True:

Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp

        If e.KeyCode = Keys.Escape Then Application.Exit()

    End Sub

   二、利用Region属性

    我们必须了解,控件并没有TransparencyKey属性,因此我们需要利用其他的方法实现此功能。以按钮控件为例,说明如何制作非标准的控件。

    控件通常有一个Region属性,该属性可以把控件的形状变换成图形路径,利用此属性我们可以随意控制控件的“区域”(即显示范围)。显而易见地,控件可以制作成各种各样的形状,可以是纯粹的或组合在一起的直线、椭圆、文字轮廓等。

我们可以利用GDI+提供的GraphicsPath创建一个路径,之后将其传递给控件的Region属性。这个过程应该在控件的Paint中,以便控件在绘制时显示成此形状。继续上面的程序编写,我们在第二个人的头上放置一个“问候”文字形状的按钮。

首先,请在程序的声明部分导入相应的命名空间:

Imports System.Drawing

    在合适的位置放置一个Button控件,然后将其Text属性清空,再将背景色指定为自己喜欢的颜色。之后,请在Button控件的Paint事件中插入以下代码,以便将按钮显示成文字的形状:

    Private Sub btGreet_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles btGreet.Paint

        Dim path As New Drawing2D.GraphicsPath '定义图形路径

        Dim ButtonText As String = "问候"      '按钮的文字形状

        Dim fnt As New FontFamily("微软雅黑") '字体

        Dim emSize As Single = 35              '字号

        Dim fntStyle As Integer = FontStyle.Underline Or FontStyle.Bold

        Dim txtLoc As New Point(10, 10)        '该形状相对于按钮左上角的坐标

        Dim strFormat As StringFormat = StringFormat.GenericDefault

       path.AddString(ButtonText, fnt, fntStyle, emSize, txtLoc, strFormat)

       btGreet.Region = New Region(path)

    End Sub

    为了使按钮更加美观,我们希望将鼠标移在其上时改变颜色,我们加入如下代码:

    Private Sub btGreet_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btGreet.Click

        MessageBox.Show("大家好,我是徐XX!", "问候", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    Private Sub btGreet_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) HandlesbtGreet.MouseEnter

        btGreet.BackColor = Color.Aqua

    End Sub

    Private Sub btGreet_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) HandlesbtGreet.MouseLeave

        btGreet.BackColor = Color.Yellow

    End Sub

    至此,我们已经完成了创建工作,运行一下程序,按钮已经按照我们所预期的方式显示出,如图3所示。

    利用GDI+的强大功能,我们可以将控件制作成各种基本形状,或者他们的组合,甚至可以用各种笔刷绘制出各种图案,您可以自己尝试。同样,窗体不仅可以通过位图创建非矩形形状,也可以使用Region属性绘制成各种形状。

   三、总结

    通过制作非标准控件,我们再一次体会到了.NET Framework给我们带来的新体验,它大量减少了程序代码量,提高了我们的开发效率。

此程序在Windows Vista SP1+Visual Studio 2005 SP1下调试通过。

6条评论


  1. VBNET是不是之类东西还要处理下On(Re)Paint的?ps:代码可以用Notepad2高亮下……

    回复

  2. 回复KC:.NET没有AutoRedraw属性,只能在Paint事件中重新绘制。

    回复

  3. 回复Master:这样~TKS~ps:Lieo啊,这篇的字体也忒小了吧~

    回复

发表评论

电子邮件地址不会被公开。