用VC++實現自繪按鈕控制 (轉)

worldblog發表於2007-12-15
用VC++實現自繪按鈕控制 (轉)[@more@]用VC++實現自繪按鈕控制

以其豐富一致的圖形介面,簡單靈便的操
作,被廣大使用者所接受。對話方塊就是其中一個非常重要的介面形式,
並且Windows為其應用的開發者提供了相當豐富的介面資源,許多
控制可以方便地加入對話方塊中。但當我們需要編寫一個商業應用,需
要一個更友好的圖形使用者介面時,就會發現資源的貧乏。
Visual C++提供了一個CBitmap Button類在一定程式上緩解了
增加新資源的要求。但當我們要求在程式中能動態地改變圖形時,我
們就不得不考慮放棄CBitmapButton類,而坐下來自己做一點工作了。
一個可行的辦法就是過載CButton類(即按鈕控制)。這樣對這塊區域
的大小、位置和ID號都可以透過AppStadio方便地製作。當然這樣作最
大的好處還是在於充分利用C++的特性把繪製控制的程式碼封裝了起來
,既避免了重複性開發,又使程式變得更簡潔,增強了程式碼的可讀性

現在我們就透過建立一個名叫CColorButton的類來學習這種方法
。雖然這是一個功能非常簡單的類,透過成員ChangeColor可
改變其顏色,滑鼠點中時則高亮邊框表示選中。但利用這種思路我們
只需新增幾個資料成員和過載一個函式就可以方便地實現你所需要的
功能。
在建立這個類之前,我們必須先了解WM_DRAWITEM訊息。當按鈕
、組合框、列表框或選單的某一視覺狀況發生變化時,就會傳送
一條WM_DRAWITEM訊息給這些控制的擁有者視窗。這個訊息的wParam
指出這個控制的 id 號,而IParam則是一個指向DRAWITEMSTRUCT結構
的指標,該結構存放有關要繪製的項的資訊以及繪製所需的型別。DR
AWITEM?STRUCT結構具有如下格式。
typedef struct tagDRAWITEM?STRUCT{
UINT CtlType; // 控制型別
UINT CtlID;// 控制的ID號
UNIT itemID;//選單項的
UINT itemAction;// 說明需要的繪圖操作
UINT itemState; // 指明繪圖後的可見狀態
HWND hwndItem; // 控制的視窗控制程式碼
HDC hDC; // 相關的裝置環境
RECT rcItem;//被畫控制的邊框
D itemData;// 指定與選單項相聯絡的應用程式定義的
32位值
}DRAWITEMSTRUCT;
其中itemAction 和 itemState決定了需要的繪圖操作。itemAct
ion 說明需要的繪圖操作,可為下列值中的一個或多個;
值 含 義
ODA_DRAWENTIRE 需要重來全部控制時
ODA_FOCUS 獲得或失去輸入焦點
ODA_ 選擇狀態改變
itemState指明當前繪圖動作發生之後,項的可見狀態。下面是狀
態標誌:
值 含 義
ODS_CHECKD 只用於選單中
ODS_DISABLE 該項被遮蔽
ODS_FOCUS 該項具有輸入焦點
ODS_GRAYED 只用於選單中
ODS_SELECT 該項處於被選中狀態
(上) □成都 曾志
用VC++實現自繪按鈕控制
利用VC++會發現,當按鈕控制接收到WM-DRMAWITEM訊息時
會呼叫Cbotton類的DrawItem函式。因此我們要做的就是利用C++的
多型性透過過載CButton類的Drawitem函式來響應MW-DRAWITEM訊息。
下面我們就實際構造一個CCol?orButton類。
class ccolorButton:public CButton
{ private:
COLORREF m-color:
public:
CColorButton():CButton(),m-color(0){}; //構
造函式
void ChangeColor(COLORREF color); //改變顏色
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct
);//過載的函式
};
//過載的虛擬函式
void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawIt
emtruct)

CDC dc;
dc.Attach(lpDrawItemStruct->hDC); //得到繪製的設
備環境CDC
VERIFY( lpDrawItemStruct->CtlType==ODT-BUTTON);
if (lpDrawItemStruct->itemAction & ODA-DRAWENTIRE)

//重繪整個控制
CBrush brush(m-Color);
dc.FillRect(&(lpDrawItemstruct->reItem),&brush)

} if ((lpDrawItemStruct->itemstate & ODS-SELECTED
) &&
(lpDrawItemStruct->itemAction &
(ODA-SELECT | ODA-DRAWENTIRE))) { //選中了本控
制===>高亮邊框
COLORREF fc=RGB(255-GetRvalue(m-color), 255-GetG
Value(m-color), 255-GetBValue(m-color));
CBrush brush(fc);
dc.FrameRect(&(lpDrawItemStruct->rcItem),&brush
);
} if (!(lpDrawItemStruct->itemState & ODS-SELECT
ED) &&
(lpDrawItemStruct->itemAction & ODA-SELECT)){
//控制的選中狀態結束===>去掉邊框
CBrush brush(m-color);
dc.FrameRect(&lpDrawItemStruct->rcItem,&brush);
} dc.Detach();
} //用於改變顏色的成員函式
void CColorButton::ChangeColor(COLORREF color) { CR
ect rect;
m-color=color;
GetClientRect(&rect);

m-colorChangeColor(COLORREF color)color,WM-DRAWITEM
上面程式碼中資料成員m-color和來儲存按鈕的顏色。ChangeColo
r(COLORREF color)函式負責改變按鈕顏色值為color,然後透過使
控制的客戶區無效而激發WM-DRAWITEM訊息。現在這個按鈕控制類就
算搭好了。下面我們把它加入到對話方塊中來試驗一下(中)
用VC++實現自繪按鈕控制
1.首先透過AppWizard建立一個單文件的應用。
2.緊接著啟動AppStadio建立一個對話方塊。新增一個按鈕控制,
並將其ID設定為 IDC-COLORBUTTON。最後一定要記住將push Button
Properties對話方塊中的Owner Draw檢查框置上檢查標誌。
3.在AppStadio內執行ClassWiz?zand來產生CTestDialog類。然
後在CTestdialog類中加入資料成員,在CTestDialog類說明加入如下
的private型資料成員:
private:
ccolorButton m-ColorButton;
4.現在剩下的問題是到底要怎樣才能使m-ColorButton的DrawI
tem函式能響應系統發往ID值為IDC-COLORBUTTON的按鈕控制的WM-D
RAWITEM訊息。這時就要用到CWnd類的成員函式BOOL CWnd::Subcla
ssDlgItem(UINT nID,CWnd *pParent)。透過呼叫這個函式,我們
可以動態地接管從對話方塊模板產生的控制,並把它隸屬於CWnd。
即用當前的CWnd物件接管發向隸屬於pParent的ID號為nID的控制的一
切訊息。對於按鈕控制而言,它把當前的按鈕控制的位置和大小也清
成和nID對應的按鈕控制一樣。於是我們對CTestDialog的源進行
如下的編輯:
BOOL CTestDialog::OnInitDialog()
{ CDialog::OnInitDialog();
//TODO:Add extra initialization here
m-ColorButton.SubclassDlgtem(IDC-COLORBUTTON,this)
;//接管訊息
m-ColorButton.ChangeColor(RGB(255,0,0);//設定為
紅色(可設為任何顏色)
return(TRUE);

接著透過ClassWizzard在CTestDialog中加入一個響應滑鼠點選I
DC-COLORBUTTON按鈕的訊息的函式:
void CTestDialog::OnColerbutton()
{ //TODO:Add your control notification handler code
here
int r=int(((float)rand()/RAND-MAX)*255
int g=int(((float)rand()/RAND-MAX)*255
int b=int(((float)rand()/RAND-MAX)*255
m-ColorButton.ChangeColor(RGB(r,g,b));

5.最後,利用ClassWizzard為View加入一個響應WM-LBUTTONDO
WN的函式,以便啟用對話方塊。請按如下程式碼對其進行編輯。
void CTestView::OnLButton?Down(UINT nflags,POINT po
int)
{ CTestDialog dlg;
dlg.odal();

6.編譯並測試該程式。當滑鼠在落視窗中時,按下滑鼠左鍵應能
彈出一個對話方塊。在對話方塊中的紅色矩形區域內按下滑鼠左鍵就會使
其邊框變成高亮狀態,若在這塊區域內釋放左鍵則這城區域就會改變
顏色且顏色是隨機的。
只需更改DrawItem函式中的重繪程式碼,就可以得到自己的需要圖
形按鈕。 (下) □四川 曾 志

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993875/,如需轉載,請註明出處,否則將追究法律責任。

相關文章