#E6E6E6 【VB 控件】FlatButton 演示平面按鈕與影像處理 作者:吳文成

(接上文)

  平面按鈕因應滑鼠事件所顯示的樣貌,比較主要的有「立體一般凸起
(周圍隆起)與「立體一般凹下」(周圍壓陷)兩種,我們要如何實現這些邊框樣式呢?如果你沒有學過繪製邊框的 Window API 函數 DrawEdge
,你大概只有選擇土法煉鋼 ( 例如使用好幾個不同顏色的 Line 控件充當[[img src=computer/FlatButton3.gif height=99 width=266 align=left]]邊線 )的煩悶方法 。DrawEdge 函數可以很方便地繪製十種不同樣式的物件邊框,如圖所示,我們需要其中的三種(包括無邊框)。大概輪廓的程式碼像是以下這樣:

Private Declare Function GetClientRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT) As Long
Private Declare Function DrawEdge Lib "user32" (ByVal hDC As Long, qrc As RECT, ByVal edge As Long, ByVal grfFlags As Long) As Long

' 依據指定形式,改變物件的邊框
Private Sub PaintEdge(ByVal newStyle)
 Dim drec As RECT

 With UserControl
  ' 取得物件的矩形大小
  GetClientRect .hWnd, drec
  .BorderStyle = 0
  .Cls

  Select Case newStyle
  Case NormalState
   ' 無邊框(滑鼠離開)
  Case MouseOverState
   ' 立體一般凸起(滑鼠經過)
   DrawEdge .hDC, drec, 4, &HF
  Case MouseDownState
   ' 立體一般凹下(滑鼠按下)
   DrawEdge .hDC, drec, 2, &HF
  Case InvalidState
   ' 無邊框(沒有動作)
  End Select

  .Refresh
 End With
End Sub


  處理完了平面按鈕的邊框樣式,我們將要遭遇到圖像處理的問題。[[img src=computer/FlatButton1.gif height=79 width=250 align=right]]基本上,原圖片加上「立體一般凸起
」的邊框就是按鈕 MouseOverState 的外觀樣貌,而另一張有白紋襯底的圖片加上「立體一般凹下」的邊框就是按鈕 MouseDownState 的外觀樣貌 , 如果是按鈕 InvalidState 時,就需要再一張特定灰階化的圖片配合無邊框樣式。這麼說來,實現四種樣貌的平面按鈕就至少需要三張不同的圖片了 。 FlatButton 控件相關的圖片屬性因此有 Picture、PictureMouseDown 與 PictureInvalidState 三項。假如每張圖片大小有 3 K,而軟體 ExtraPlayer 用了22個平面按鈕,那麼光是這些圖片就佔用了 ExtraPlayer 將近 3*3*22=198 K 的檔案大小, 對於要求軟體大小「
最佳化」的程式開發者來說,這些圖片似乎挺佔檔案空間的!其實我們可以不必用到三張圖片,就能夠來實現一個平面按鈕的不同樣貌,我們可以[[img src=computer/FlatButton4.gif height=159 width=170 align=left]]運用圖像處理技巧,由原圖片(Picture 屬性)來製作出另外兩張圖像 ( 所以 PictureMouseDown 與 PictureInvalidState 是選擇性屬性,可以不必設定,保留這兩個屬性是為了特殊需求者)

  這裡的圖像處理技巧的流程概念,如左圖所示,但是實際的處理程序與程式碼更為複雜。首先 FlatButton 控件內建有白紋襯底圖( 位於資源檔 downState.res ),使用者必須指定圖片的 MaskColor 作為除去背景的透背顏色( 預設為按鈕表面的顏色), 然後掃描(GetPixel)原圖片的所有圖點 , 再將非背景色的圖點轉繪(SetPixel)到白紋襯底圖上, 然後再加上「立體一般凹下」的邊框之後 , 就完成了按鈕 MouseDownState 的外觀樣貌 。 要完成按鈕 InvalidState 的外觀樣貌 ,在程序撰寫裡,我們必須指定預設的灰階色,然後將原圖片的非背景色的圖點,根據其與黑色的「色[[img src=computer/FlatButton5.gif height=99 width=234 align=left]]彩差異度」而轉成相應程度的灰階色,但是仔細一看,似乎不只是這樣,因為還有「浮雕式的白邊」。根據光照方向
,假如此白邊總是在非背景色之圖像的右下角,那麼我們只要多掃描與比較鄰近方向的單位圖點,即可判定是否需要繪製此白邊。這裡面還有許多的細節,例如牽涉到 StdPicture 物件,與 CreateCompatibleDC 的運用。

  描述大致輪廓的流程總是不困難,但是這個輪廓如何從無到有,以及從有到真正可執行地編寫出來,那是很困難,因為除了界定問題與解決問題的構思之外,還需要遭遇非簡化的邏輯程序問題,以及各個不同的子程序如何協調成一個整體的問題。我之所以深入地、一步一步地闡述這些構思與流程,是希望在這裡示範一個程式開發者該有的漸進步驟,唯有瞭解對於問題的界定、方案提出(包括模組化與結構化的構思)、方案測試與方案修正的步驟,程式開發的路才會越走越寬。在以後的文章裡,我還會談到這些重要的步驟,與思考策略,以及作為進階的程式開發者可能需要的知識背景。

  我將程式碼與控件列舉在文末,這樣的控件在大型的程式開發案中,方便地幫助我呈現出所需要的功能,希望它對你也是同樣實用。

範例源碼下載

控制項下載
2004/11/14