学习窗体美化不错的知识====================================================================================相信大家看过许多形状怪异的窗口吧?可是在VB里,系统提供的只是一个矩形的窗体。
如何在VB里实现这种异形窗体呢?其实原理很简单。
首先,在内存中构建一个想要的图形,再通过API函数将窗体设置为此形状,最后将图片放上去就可以了。
关键在于如何构建这个想要的图形。
让我们看看下面这个图:。
这张图片中既有白色,也有其他彩色,而我们想要的颜色正是除白色以外的其它颜色。
我们可以这样想:在内存中创建一幅一样大小的空的图像,然后只把我们需要的颜色(即非白色)输入内存。
这样,就可以创建出我们想要的图形了。
以上是原理,接下来介绍几个API函数。
GetPixel:获取指定对象的某个点的颜色。
定义为:Public Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long其中hdc为图形对象的句柄,x、y为坐标。
SelectObject:向内存中的指定地点输入图形。
定义为:Public Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long其中hdc为内存中图形对象的句柄,hObject为欲输入的图像。
CreateCompatibleDC:在内存中创建一个与指定对象一样的场景(可以理解为图像)。
定义为:Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long其中hdc为指定对象的句柄。
DeleteObject:删除GDI对象(在这里用来删除用完的内存中的图形)。
记住,用完后释放资源是非常重要的!定义为:Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long其中hObject为欲删除的对象。
CreateRectRgn:在内存中创建一个矩形,返回值为矩形的句柄。
定义为:Public Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long其中X1、Y1为矩形左上角的点坐标,X2、Y2为矩形右下角的点坐标。
CombineRgn:将两个图形结合为一个图形。
定义为:Public Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long其中hDestRgn为合成后的图形句柄,hSrcRgn1、hSrcRgn2为两个欲合成的图形,nCombineMode 为合成模式(包括交集部分、并集部分、并集以外部分、不相交部分,我们需要的是并集部分)SetWindowRgn:使指定窗口形状成为指定形状。
定义为:Public Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long其中hwnd为指定窗口的句柄,hRgn为指定图形句柄,bRedraw为选择是否立即重画窗口。
SetWindowPos:为窗口指定一个新位置和状态。
定义为:Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long其中hwnd为目标窗口的句柄,hWndInsertAfter设置窗口的新位置,x、y设置了窗体的坐标,cx、cy设置了窗体的新大小,wFlags设置了窗口的状态。
还有一个需要的常数:RGN_OR,是CombineRgn函数的模式之中的并集模式,定义为:Public Const RGN_OR = 2为了方便,我将这些代码制作成了一个函数。
以下为代码+注释:Public Sub CreateImageForm(Form As Object, Imagebox As Object, strFile As String, BGColor As Long)'Form为目标窗体,Imagebox是放图片用的,strFile是源图片路径,BGColor是不需要的颜色Dim T As Integer '图形横坐标Dim R As Integer '图形纵坐标DoEvents '防止死机Imagebox.AutoSize = True '使图片框自动调整大小,大小为图片大小Imagebox.BorderStyle = 0 '使图片框无边框,防止边框占用图形位置Imagebox.Picture = LoadPicture(strFile) '将图片读入图片框。
图片框是用来更好的控制窗体大小Form.Width = Imagebox.WidthForm.Height = Imagebox.Height '这两行将窗体大小调整为图片框大小Imagebox.Visible = False '图片框不是让用户看的Form.Picture = Imagebox.Picture '图片框没有了,窗体就应该显示图形Form.ScaleMode = 3 '设置度量用的单位FW = Form.ScaleWidthFH = Form.ScaleHeight '将窗体内部大小赋值给变量,方便读取Dim DC As Long '内存中图形句柄Dim BMP As Long '不知道是什么句柄Dim rgn As Long '临时用的矩形的句柄Dim rgnTotal As Long '欲得到的图形句柄Dim SX As Long '搜索用的变量DC = CreateCompatibleDC(Form.hdc) '创建一个与目标窗体一样大的内存图形空间BMP = SelectObject(DC, LoadPicture(strFile)) '将图形放入刚刚创建的空间中rgnTotal = CreateRectRgn(0, 0, 0, 0) '初始化目标图形For T = 0 To FW '逐行搜索R = 0: Do '搜索前横坐标归零While GetPixel(DC, T, R) = BGColor And R <= FH '当找到需要留下的点后退出搜索R = R + 1WendSX = R '记录下此行所需部分开始的点坐标While GetPixel(DC, T, R) <> BGColor And R <= FH '当找到需要要除去的点后退出搜索 R = R + 1WendIf SX <= R - 1 Then '此时R-1为此行所需部分结束的点坐标rgn = CreateRectRgn(T, SX, T + 1, R) '创建这一行中刚才搜索到的矩形CombineRgn rgnTotal, rgnTotal, rgn, RGN_OR '将刚才创建的矩形并入目标图形中 DeleteObject rgn '销毁临时用的小矩形,以释放系统资源(重要)End IfLoop Until R >= FH '此行结束后进入下一个搜索循环Next TSetWindowRgn Form.hwnd, rgnTotal, True '将目标窗体形状设置为已经创建好的图形SetWindowPos Form.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE + SWP_SHOWWINDOW'将目标窗体设置在所有窗口的最顶层,且不能移动、不能改变大小End Sub最后,还需要注意:有时图片里在需要的部分中也会出现背景颜色(比如说一幅白花的图,背景为白色),此时直接用本函数会造成需要的图片不能完整出现。
怎么办呢?这是你需要准备一张底图。
所谓底图,即只有两种颜色(最好是这样),一种是背景,一种是需要的图的部分。
如上面例子的图的背景图为:。
可以用PS快速地做好背景图。
程序中的操作有所更改,使用函数时用的图应该是背景图,然后在窗体的代码中加一句:Me.Picture = LoadPicture("******") '其中"******"为原图片好,完成了。
PS:囧……写了我半天……再PS:某A等不玩程序的同志们,看了此文莫PIA……。