最近在學習按鈕的自繪.關於按鈕的自繪,主要的痛點如下:
1. 如果想要做到的效果稍微有點美觀的話,我想這幾個狀態時必須要考慮的:滑鼠移入、滑鼠按下、滑鼠彈起、滑鼠移開.然後相應對其處理即可.這裡主要討論如何捕捉這些事件:首先是滑鼠按下和滑鼠彈起事件,這兩個事件比較簡單,windows已經和我們寫好了這兩個響應訊息(我們只需重載他們即可).一個是OnLButtonUp一個是OnLButtonDown..我們可以在滑鼠按下和彈起時設定一個標誌位即可.其實我們可以再DrawItem裡面進行判斷.(這個東西可以再下面看到)其次是滑鼠進入和滑鼠移開訊息.你不要認為我們可以重載OnMouseMove和OnMouseLeave這兩個訊息即可.其實這兩類訊息比較"特殊"(因為Windows並沒有直接替我們對其處理),我們需要藉助windows的一個函數(TrackMouseEvent)來進行判斷、處理.大概的處理是這樣的:我們在OnMouseMOve響應函數裡面添加如下代碼:
//其中bHighlight是標示變數:標示滑鼠是否在按鈕上.
if ( !bHighlight )
{
bHighlight = TRUE;
TRACKMOUSEEVENT tm;
tm.cbSize = sizeof( TRACKMOUSEEVENT );
tm.dwFlags = TME_LEAVE;
tm.dwHoverTime = 0;
tm.hwndTrack = m_hWnd;
::TrackMouseEvent( &tm );
}
//按鈕重繪
InvalidateRect(NULL,TRUE);
這樣之後,我們就安裝了類似的一個滑鼠離開函數:OnMouseLeave.
現在我們來添加這個函數的訊息響應:
void CLinkButton::OnMouseLeave( WPARAM wParam,LPARAM lParam )
{
if ( bHighlight )
{
//重繪按鈕
bHighlight = FALSE;
}
//注意這個語句,如果我們不進行介面重新整理,那麼很可能介面不能處理滑鼠移開訊息.
InvalidateRect( NULL,TRUE );
}
兩種類的訊息添加好了之後我們還要做一些類似初始化的工作,讓WM_MOUSELEAVE和OnMouseLeave對應,還有,我們要使用::TrackMouseEvent兩個函數,必須要包含這樣一個聲明:
extern "C" WINUSERAPI BOOL WINAPI TrackMouseEvent(LPTRACKMOUSEEVENT lpEventTrack);.如果不是如此,編譯器是不認識TrackMouseEvent這個函數的.
關於TRACKMOUSEEVENT這個結構體的詳細情況,請參考我的另一篇部落格.
部落格地址:http://blog.csdn.net/yuanweihuayan/article/details/6831248
2. 接著是定義好幾種不同的狀態.分別對應前面四種狀態.
這裡主要是關於系統色彩的擷取.
◆ COLOR_3DHIGHLIGHT和 COLOR_GRAYTEXT兩種顏色來做到Disable.
◆ COLOR_3DSHADOW 和COLOR_3DHILIGHT兩種顏色來做到滑鼠按下狀態
這裡你可以參考GetSystemColor函數.
DWORD GetSysColor(int nIndex); |
說明 |
判斷指定windows顯示對象的顏色 |
傳回值 |
Long,指定對象的RGB顏色 |
參數表 |
參數 |
類型及說明 |
nIndex |
Long,一個常數,指出特定的windows顯示對象,如下表 |
Windows對象常數表 |
常數定義 |
Windows對象 |
常數定義 |
Windows對象 |
COLOR_ACTIVEBORDER |
使用中視窗的邊框 |
COLOR_ACTIVECAPTION |
使用中視窗的標題 |
COLOR_APPWORKSPACE |
MDI案頭的背景 |
COLOR_BACKGROUND |
windows案頭 |
COLOR_BTNFACE |
按鈕 |
COLOR_BTNHIGHLIGHT |
按鈕的3D加亮區 |
COLOR_BTNSHADOW |
按鈕的3D陰影 |
COLOR_BTNTEXT |
按鈕文字 |
COLOR_CAPTIONTEXT |
視窗標題中的文字 |
COLOR_GRAYTEXT |
灰色文字;如使用了抖動技術則為零 |
COLOR_HIGHLIGHT |
選定的項目背景 |
COLOR_HIGHLIGHTTEXT |
選定的項目文字 |
COLOR_INACTIVEBORDER |
不使用中視窗的邊框 |
COLOR_INACTIVECAPTION |
不使用中視窗的標題 |
COLOR_INACTIVECAPTIONTEXT |
不使用中視窗的文字 |
COLOR_MENU |
菜單 |
COLOR_MENUTEXT |
菜單本文 |
COLOR_SCROLLBAR |
捲軸 |
COLOR_WINDOW |
視窗背景 |
COLOR_WINDOWFRAME |
窗框 |
COLOR_WINDOWTEXT |
視窗本文 |
COLOR_3DDKSHADOW |
3D深陰影 * |
COLOR_3DFACE |
3D陰影化對象的正面顏色 * |
COLOR_3DHILIGHT |
3D加亮顏色(win95) |
COLOR_3DLIGHT |
3D陰影化對象的淺色 * |
COLOR_INFOBK |
工具提示的背景色 * |
COLOR_INFOTEXT |
工具提示的文本色 * |
|
|
*:帶 * 號的常數未獲NT 3.51的支援 |
3. 關於DrawItem的一些講解:
詳細請見:http://blog.csdn.net/yuanweihuayan/article/details/6817631
關鍵是如下結構體:DRAWITEMSTRUCT.這個裡面我們經常用到的一些成員.
itemState:表示當前的狀態:需要和ODS_開頭的宏與操作即可.
rcItem:控制項的大小.
hDC:可以通過它來擷取當前控制項的CDC.
另外就是幾個CDC常用的成員函數:
Draw3dRect:用來繪製3D按鈕.
DrawFocusRect:繪製具有焦點的矩形.
具體的用法可以參考msdn.
今天大概就總結這麼一些.等以後看到了更好的再繼續....