中心漸變的快速填充函數

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
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章