异形窗口程序设计技巧 为了制作出丰富多彩的界面，窗口已不再局限于矩形形状，许多场合，如多媒体播放器或者部分游戏程序,都比较直观的显示为一具体的物体形状。在VB中,实现这样的界面效果很难，但我们可借助于Windows API 函数来制作出一些别具风格的异形窗口。 一、异形窗口的形成方法 1.巧妙安排控件 这种方法实际上是正常的程序编制,只是把控件安排在特殊的位置,比如整个窗口内只有一个按钮,或者把许多控件安排在一个范围内,取消标题栏,这样的程序提供给用户的便是一种特殊的界面。
2.用图形对界面装饰
这里所说的不是简单的在窗口内进行图形或图片装饰,而是通过一些巧妙的图形绘制,使整个窗口本身形成特殊的效果，比如在窗体的底部及右侧分别用两种不同的颜色绘制出彩色条，这样窗体本身就变成一个立方体,具有很强的立体效果。
3.剪切原窗口
VB本身并不具有特殊形状窗口的建立方法,但Windows的API 函数具有这样的功能,其中的区域操作不仅可以对窗体中的其它控件区域进行剪切等处理,而且可以对窗体本身进行操作,这样即可按要求对原常规的矩形窗口进行适当修整,从而形成千奇百怪的异形窗口。
二、窗口剪切的方法
可用SetWindowRgn函数来剪切窗口,其共有三个参数,第一个指定被剪切的对象的句柄,比如图形框等,如果指定为Form即对应用程序窗口本身进行处理 ；第二个参数指明剪切的形状,即指定的几何图形特征,此参数也必须由相应的API函数提供说明 ；第三个参数是一布尔变量,一般可设置为真(True)。
在API 中有多个几何图形的说明函数,常见的有：
CreateRectRgn :建立矩形区域,其参数分别为矩形的左上角坐标及右下角坐标。
CreateRoundRectRgn:建立圆角矩形区域,其参数分别为左上角及右下角坐标,还有圆角直径等,当圆角直径接近或超过矩形的长度时,将呈现为圆或椭圆形。
CreateEllipticRgn :建立椭圆矩形区域,参数分别为横向与纵向直径的起点和终点。
CreatePolygonRgn :建立多边形区域。
要建立一个特殊形状窗口,需要使用区域设置函数Set
WindowRgn和一个几何图形说明函数,比如建立一个圆形窗口的命令为:
SetWindowRgn Form1.hWnd,CreateEllipticRgn(10,0,200,200),True
利用此方法得到特殊形状的窗口,程序运行之后将只显示为剪切后的窗口,但其不可见部分仍然属于应用程序窗口范围之内。
窗口被剪切后其大小和形状固定,最大化之后仍只显示为其原来的尺寸,只是屏幕位置发生变化。
剪切的尺寸可以小于或大于原窗口的尺寸,但最终显示结果只是原窗体范围之内的区域。
三、控制异形窗口的方法
大部分的异形窗口必须取消标题栏,相应的标题栏所具有的功能也随之丧失,比如移动、最大化或最小化等，所以在这样的应用程序中必须加入窗口的控制功能,这里推荐使用Windows的API函数SendMessage向窗口发出控制命令,它有四个参数：第一个参数为窗口句柄hwnd,第二个参数为
WM_SYSCOMMAND(&H112),第三个参数为发出的命令,第四个参数恒为0&。
常用的系统命令有:
SC_MOVE: &HF010 移动窗口
SC_MINMIZE: &HF020 最小化窗口
SC_MAXIMIZE: &HF030 最大化窗口
SC_CLOSE: &HF060 关闭窗口
SC_RESTORE:&HF120 恢复窗口到原来状态
在无标题栏窗口中,安排适当的按钮或菜单并使用上述的函数向窗口发出控制命令,即可方便地使窗口发生相应的变化。
四、异形窗口鼠标拖动的实现
当对无标题栏窗口进行鼠标拖动时,其鼠标在窗口中的坐标始终不变,如果能够在鼠标移动过程中,通过改变窗口在桌面上的坐标,而始终保持鼠标的相对坐标不变,即可实现鼠标的拖动效果。
在具体程序设计时,先在MouseDown()事件中记录鼠标位置，在MouseMove() 事件中根据鼠标的移动距离实时修改窗体Form的Top及Left值,即可准确无误的实现窗口的鼠标拖动操作。
在实际程序设计时,窗口中可能有多种控件,若想使鼠标拖动窗口中的任何位置都可实现窗口移动,必须对窗口中的所有控件进行上述的鼠标位置记录与移动处理,即在MouseDown()与MouseMove()事件中加入文末所附的程序代码。
异形窗口界面在具体的程序编制中有很多特殊性,比如在Windows 95中当程序最小化时只在任务栏或桌面上显示该程序的标题栏,用VB编制的程序即使已经置为无标题栏,最小化时仍然显示其标题栏,进行剪切后的窗口最小化时,将对其标题栏进行剪切,使标题栏不完整,所以必须正确地对窗口的当前状态进行判断,当处于最小化状态时恢复原窗口大小,才能进行剪切。
五、实 例
下面是一个有趣的异形窗口程序,它的功能是显示当前时钟,其外形就像一个椭圆的电子表，编制过程如下：
新建工程,在窗体中放置三个命令按钮Command(1～3),分别用于移动、最小化窗口及退出程序,再在中央放置一个标签Lable1,用于显示当前日期和时间,置Form1 的BorderStyle属性为none即无标题栏,再放置一个时间控件Timer1,然后把所附的代码加到相应的事件之中。
运行程序之后,即在椭圆的窗体内显示当前日期和时间,通过按钮可分别控制移动和最小化等,最小化之后将在标题栏内显示当前日期和时间。此程序支持鼠标拖动,用鼠标拖动窗口的任一部分都可使窗口随鼠标移动。
附：源程序
’API函数说明
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"(ByVal hwnd As Long,ByVal wMsg As Long,ByVal wParam As Long,lParam As Any) As Long
Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long,ByVal hRgn As Long,ByVal bRedraw As Boolean) As Long
Private Declare Function CreateEllipticRgn Lib "gdi32" (ByVal x1 As Long,ByVal y1 As Long,ByVal x2 As Long,ByVal y2 As Long) As Long
’定义变量
Dim x1,x2,y1,y2,cx,cy,dx,dy,i,num
’移动窗口
Private Sub Command1_Click()
i = SendMessage(Form1.hwnd,&H112,&HF010,0&)
End Sub
’最小化窗口
Private Sub Command2_Click()
i = SendMessage(Form1.hwnd,&H112,&HF020,0&)
End Sub
’结束程序
Private Sub Command3_Click()
End
End Sub
’调入代码,实现窗口剪切等功能
Private Sub Form_Load()
Form1.AutoRedraw = True
Form1.ScaleMode = 3
x1 = 0
x2 = Form1.ScaleWidth
y1 = 0
y2 = Form1.ScaleHeight
SetWindowRgn Form1.hwnd,CreateEllipticRgn(x1,y1,x2,y2),True
cx = Form1.ScaleWidth / 2
cy = Form1.ScaleHeight / 2
num = Form1.ScaleHeight / Form1.ScaleWidth
Form1.ForeColor = RGB(200,30,50)
Form1.DrawWidth = 2
Form1.Circle (cx,cy),Form1.ScaleWidth / 2 - 2,RGB(55,220,255),,,num
Timer1.Enabled = True
Timer1.Interval = 10
Label1.BackColor = 0
Label1.ForeColor = &HFF00&
End Sub
’鼠标拖动窗口
Private Sub form_MouseMove(Button As Integer,Shift As Integer,X As Single,Y As Single)
Dim mx,my
leftDown = (Button And vbLeftButton) > 0
rightDown = (Button And vbRightButton) > 0
If (leftDown Or rightDown) Then
mx = X - dx
my = Y - dy
Form1.Left = Form1.Left + mx
Form1.Top = Form1.Top + my
Form1.CurrentX = 10
Form1.CurrentY = 10
End If
End Sub
’记录当前鼠标位置
Private Sub Form_MouseDown(Button As Integer,Shift As Integer,X As Single,Y As Single)
dx = X
dy = Y
End Sub
’实时显示时间并判断当前窗口的状态
Private Sub Timer1_Timer()
Label1.Caption = Now
If Form1.WindowState = 1 Then
SetWindowRgn Form1.hwnd,CreateRectRgn(0,0,x2,y2)，True
Form1.Caption = Now
Else
SetWindowRgn Form1.hwnd,CreateEllipticRgn(x1,y1,x2,y2),True
End If
End Sub
(杨 扬)