XP为我们开创了程序界面革命的新时代,它的界面最核心的特点之一就是“渐变”。在追求个性化亮丽界面的今天,到处可见漂亮的VB界面源码,可惜它们都还在用图片,或描点描线来生成窗体及控件。要知道,GradientFill函数正是MS为我们准备的一个“超级宝贝”,一直却被VB用户忽视了。它的灵活使用,会为我们带无穷的变幻效果,我就用它先写个例子吧。
像Photoshop中那样的水平与垂直渐变用GradientFill写,很简单,就不多写了。中心渐变,画球或点亮效果时常用,多数人要用图片实现,其实GradientFill是可以做到的。我的这个函数是基于椭图写的,它当然包括正圆,通用性更强。
写下面这段代码,还有一个目的,就是GradientFill是接受数组的,完全可以只调用一次,就完成全部填充,有些人使用它却忽略了这一特性。
Private Type GRADIENT_RECT
UpperLeft As Long
LowerRight As Long
End Type
Private Enum GradientFillFlag
GRADIENT_FILL_RECT_H = &H0&
GRADIENT_FILL_RECT_V = &H1&
GRADIENT_FILL_TRIANGLE = &H2&
End Enum
Private Type TRIVERTEX
x As Long
y As Long
Red(1) As Byte
Green(1) As Byte
Blue(1) As Byte
Alpha(1) As Byte
End Type
Private Type GRADIENT_TRIANGLE
Vertex1 As Long
Vertex2 As Long
Vertex3 As Long
End Type
Private Declare Function GradientFillTriangle Lib "msimg32" Alias "GradientFill" (ByVal hdc As Long, pVertex As TRIVERTEX, ByVal dwNumVertex As Long, pMesh As GRADIENT_TRIANGLE, ByVal dwNumMesh As Long, ByVal dwMode As Long) As Long
'若XP系统下,GradientFill函数在Gdi32中就有
'Private Declare Function GradientFillTriangle Lib "gdi32" Alias "GdiGradientFill" (ByVal hdc As Long, pVertex As TRIVERTEX, ByVal dwNumVertex As Long, pMesh As GRADIENT_TRIANGLE, ByVal dwNumMesh As Long, ByVal dwMode As Long) As Long
Public Sub DrawGradientElliptic(dhDC As Long, x1 As Long, y1 As Long, X2 As Long, Y2 As Long, _
StartColor As Long, Optional EndColor As Long = -1, Optional ByVal Alpha As Long = 192, _
Optional Inner As Boolean, Optional TriangleCount As Long = 36, Optional CenterX As Long = -1, Optional CenterY As Long = -1)
Dim Vertex() As TRIVERTEX
Dim Triangle() As GRADIENT_TRIANGLE
Dim Red(1) As Long, Green(1) As Long, Blue(1) As Long
Dim Theta As Double, m As Long, k As Long, l As Double, p As Double, t As Double, tc As Long
Dim i As Long, j As Long, a As Long, b As Long, cx As Long, cy As Long, cx0 As Long, cy0 As Long
'椭圆及圆形渐变填充
'指定一个矩形,该矩形与欲填充椭圆外切
'X1、Y1;X2、Y2 分别为矩形的左上角与右下角坐标
'StartColor起始填充色
'EndColor结束填充色,它是可选的,若小于零时忽略此参数,使用Alpha基于StartColor算出EndColor,实现高亮填充效果
'Alpha用于计算StartColor的高亮色,0-255之间,越大越亮,若设置了EndColor,则忽略此参数
'Inner为渐变方式,为True时,StartColor到EndColor(或是alpha计算出的)颜色,按从外向内渐变,False则相反
'TriangleCount为三角形数量,默认为36个
'CenterX、CenterY用于指定高光点的位置,若小于0则默认为椭圆中心点
Red(0) = StartColor And &HFF
Green(0) = (StartColor And &HFF00&) / &H100&
Blue(0) = (StartColor And &HFF0000) / &H10000
If EndColor < 0 Then
If Alpha < 0 Then Alpha = 0
Red(1) = (Red(0) * (256 - Alpha) + 255 * Alpha) / 256
Green(1) = (Green(0) * (256 - Alpha) + 255 * Alpha) / 256
Blue(1) = (Blue(0) * (256 - Alpha) + 255 * Alpha) / 256
Else
Red(1) = EndColor And &HFF
Green(1) = (EndColor And &HFF00&) / &H100&
Blue(1) = (EndColor And &HFF0000) / &H10000
End If
tc = (TriangleCount / 4) * 4
If tc < 8 Then tc = 8
a = (X2 - x1) / 2
b = (Y2 - y1) / 2
cx = x1 + a
cy = y1 + b
If CenterX >= 0 Then
cx0 = CenterX
Else
cx0 = cx
End If
If CenterY >= 0 Then
cy0 = CenterY
Else
cy0 = cy
End If
'设置所有三角形共有一个位于圆心的顶点
ReDim Vertex(tc)
With Vertex(0)
.x = cx0
.y = cy0
If Inner Then
j = 1
Else
j = 0
End If
.Red(1) = Red(j)
.Green(1) = Green(j)
.Blue(1) = Blue(j)
j = 1 - j
End With
'设置所有位于圆周上的三角形其它顶点,因三角形一个连一个,所以圆周上顶点数与三角形数是一样的
m = (a ^ 2)
l = (b / a)
k = tc / 4
Theta = (3.1415926 * 2 / tc)
For i = 1 To k
p = a * Cos((i - 1) * Theta)
t = l * Sqr(m - p ^ 2)
With Vertex(i)
.x = cx + p
.y = cy + t
.Red(1) = Red(j)
.Green(1) = Green(j)
.Blue(1) = Blue(j)
End With
With Vertex(2 * k - i + 1)
.x = cx - p
.y = cy + t
.Red(1) = Red(j)
.Green(1) = Green(j)
.Blue(1) = Blue(j)
End With
With Vertex(2 * k + i)
.x = cx - p
.y = cy - t
.Red(1) = Red(j)
.Green(1) = Green(j)
.Blue(1) = Blue(j)
End With
With Vertex(tc - i + 1)
.x = cx + p
.y = cy - t
.Red(1) = Red(j)
.Green(1) = Green(j)
.Blue(1) = Blue(j)
End With
Next
'设置每个三角形结构,为它们指定顶点
ReDim Triangle(tc - 1)
For i = 0 To tc - 1
Triangle(i).Vertex1 = 0
j = i + 1
Triangle(i).Vertex2 = j
j = i + 2
If j > tc Then j = 1
Triangle(i).Vertex3 = j
Next
GradientFillTriangle dhDC, Vertex(0), tc + 1, Triangle(0), tc, GRADIENT_FILL_TRIANGLE
End Sub