2010-05-04 108 views
0

我已經實現了我的自定義按鈕繼承自CButton並使用uxtheme.dll(DrawThemeBackground與BP_PUSHBUTTON)繪製它。使用uxtheme.dll自定義繪製按鈕

一切工作正常,但我有兩個狀態(普通和按下),熱狀態是相同的。這意味着當用戶將光標放在按鈕上時,無論按鈕狀態如何(按下或不按下),它都會被畫出。

這對用戶來說有點令人困惑,我想改變按鈕在Pressed & Hot狀態下的繪製方式。有人知道一種方式嗎?

我也想過定製整個繪圖,但按鈕使用漸變,邊框,陰影等。因此,要自己繪製所有東西並不容易。有沒有辦法找到DLL的源代碼或知道如何做到這一點?

在此先感謝。

哈維爾

注:我想我可能能才達到我想要使用CMFCButton並重寫OnDraw的方法來做。讓控件在OnDrawBorder上繪製按鈕,然後自己繪製內部按鈕。但是我需要知道按下時控件如何繪製內部按鈕。這是一個漸變,我無法猜測它是如何完成的。有人有線索嗎?

回答

1

我終於想出瞭如何實現我想要做的事情。確實很容易。

我使用兩次調用DrawThemeBackground。第一個是PBS_PRESSED,第二個是PBS_HOT。然後我做一個ExcludeClipRect以避免在按鈕的中心上畫圖。

事情是這樣的:

 DrawThemeBackground( hTheme, 
           pCustomDraw->hdc, 
           BP_PUSHBUTTON, 
           PBS_PRESSED, 
           &pCustomDraw->rc, 
           NULL); 

     CDC *pDC = CDC::FromHandle(pCustomDraw->hdc); 

     CRect rectClient; 
     GetClientRect(rectClient); 
     CRect rectInternal = rectClient; 

     rectInternal.DeflateRect(4,4); 
     pDC->SelectClipRgn(NULL); 
     pDC->ExcludeClipRect(&rectInternal); 

     DrawThemeBackground( hTheme, 
           pCustomDraw->hdc, 
           BP_PUSHBUTTON, 
           PBS_HOT, 
           &pCustomDraw->rc, 
           NULL); 

     pDC->SelectClipRgn(NULL); 

當然,這並不是全部的代碼,但我認爲這是足以讓我的觀點。

謝謝。

1

在回答你的第二個問題,如果你從CMFCButton而不是CButton派生可以覆蓋OnDraw()OnDrawText()而不是通常的DrawItem()。這樣就會繪製默認的按鈕背景,然後執行您的繪圖代碼。

+0

請看看我在原始問題中的註釋。並感謝您的幫助。 – 2010-05-05 08:35:35

1

我知道真正解決這個問題的唯一方法是使用'自定義繪製',而不是'所有者繪製'。自定義繪圖與Windows 2000一起提供,但只有通過comctrl32 6.0(所以Windows XP以上版本)的按鈕控件才能使用,並沒有非常明確的文檔記載,並且MFC不會支持它。

無論如何,關於自定義繪製的好處在於它可以讓你在繪製過程中的各個點上掛鉤,而不像所有者繪製,這使得你處理整個事情。在NM_CUSTOMDRAW通知消息中查看MSDN。

對於問題的其他部分,檢測'熱'狀態,最簡單的方法是使用WM_MOUSEMOVE消息和TrackMouseEvent()函數來跟蹤鼠標是否在按鈕上。

不幸的是,這是一個模糊的答案:你需要演示一個使用自定義繪製按鈕的代碼數量太多,無法輸入到這些答案框中!我有一個演示這種技術的項目,使用自定義繪製按鈕(回退到老版本的Windows版本的所有者繪製),向按鈕添加一個小箭頭。您可以通過獲取

Windows_UI_source.zip

打開它看看源代碼,看看在「DropArrowButton」級。重要的是OnCustomDraw()處理程序及其幫助程序函數DrawControl():它們在各種按鈕繪製階段被調用,並使用UxTheme來適當地繪製控件。

+0

我看了一下你的代碼,但我沒有看到如何解決我的問題。您最終以PBS_HOT狀態調用DrawThemeBackground並繪製帶有金色邊框(熱狀態)的正常(未按下)按鈕。我需要一種方法來繪製帶有金色邊框(熱狀態)的按下(PBS_PRESSED)狀態。無論如何非常感謝你。 – 2010-05-12 05:57:09

+0

我的錯誤:我誤解了你的問題。我不認爲有什麼辦法可以讓DrawThemeBackground()完成你想要的任何事情:我可以建議的所有方法都是按下背景,然後將alpha混合到「熱」狀態矩形中。如果你總是這樣做的「熱」矩形,你應該可以得到一個可以通過的效果。 – DavidK 2010-05-12 06:16:34

+0

這與我所做的相似。事實上,如果沒有使用AlphaBlend,效果相當不錯(如果有人抱怨,我會試一試!)。不幸的是,當我看到您的評論時,我已經接受了我的回答,我無法取消我的接受。否則我會接受你的回答。謝謝。 – 2010-05-12 06:39:00