天天看點

多狀态按鈕 button vc c++ MFC CBitmapButton

本文使用vc6.0 MFC程式實作自定義的多狀态button。vc9.0(即vs2008)下,去掉stdafx.h檔案中的#define _WIN32_WINNT 0x0400 也可以運作(有個warning)。

由于隻是示例,并沒有注意接口,您可以自己改;自己的美工水準不行,您可以自己更改bitmap資源。

介紹了三種多狀态按鈕 :

1)三狀态按鈕 

     滑鼠在button上;滑鼠在button外;滑鼠按下button

2)六狀态按鈕

     在1)的基礎上增加了對應的獲得焦點的三種情況

3)MFC自帶的CBitmapButton類

    有四種狀态:up,down,focus,disabled。控件風格不同,狀态個數不同,具體可看msdn。

代碼可到此處下載下傳:

 http://download.csdn.net/source/986965

(一)三狀态按鈕

1)定義繼承自CButton的子類CyctBitmapButton。

2)三狀态需要三個位圖資源

    裝在和解除安裝位圖資源:

int CyctBitmapButton::Init()

{

//(視窗建立後的)初始化

m_hIn = ::LoadBitmap(::AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP_IN));

m_hOut = ::LoadBitmap(::AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP_OUT));

m_hDown = ::LoadBitmap(::AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP_DOWN));

ASSERT(m_hIn != NULL);

ASSERT(m_hOut != NULL);

ASSERT(m_hDown != NULL);

//SetButtonStyle( BS_BITMAP | GetButtonStyle() );

ModifyStyle(0,BS_BITMAP);//增加BS_BITMAP風格

SetBitmap(m_hOut);

return 0;

}

void CyctBitmapButton::OnDestroy()

{

CButton::OnDestroy();

//解除安裝Bitmap資源

#ifdef _DEBUG

ASSERT(0 != DeleteObject(m_hIn));

ASSERT(0 != DeleteObject(m_hOut));

ASSERT(0 != DeleteObject(m_hDown));

#else

DeleteObject(m_hIn);

DeleteObject(m_hOut);

DeleteObject(m_hPutdown);

#endif

}

3)初始化button

    視窗初始化後需要調用Init()函數。布爾值變量m_fIsInit確定button隻初始化一次。

void CyctBitmapButton::PreSubclassWindow()

{

//初始化

if(!m_fIsInit)

{

//AfxMessageBox(_T("CyctBitmapButton::PreSubclassWindow"));

Init();

m_fIsInit = TRUE;

}

CButton::PreSubclassWindow();

}

int CyctBitmapButton::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CButton::OnCreate(lpCreateStruct) == -1)

return -1;

//初始化

if(!m_fIsInit)

{

//AfxMessageBox(_T("CyctBitmapButton::OnCreate"));

Init();

m_fIsInit = TRUE;

}

return 0;

}

4)處理滑鼠響應函數(這是關鍵的)

 處理了四種滑鼠消息WM_MOUSEMOVE,WM_LBUTTONDOWN,WM_LBUTTONUP,WM_MOUSELEAVE:

void CyctBitmapButton::OnMouseMove(UINT nFlags, CPoint point)

{

if(m_MouseState.GetCurState() == _mouse_out)

{

SetBitmap(m_hIn);

return;

}

//當滑鼠離開時觸發WM_MOUSELEAVE事件

TRACKMOUSEEVENT tme;

tme.cbSize = sizeof(tme);

tme.dwFlags = TME_LEAVE;

tme.hwndTrack = m_hWnd;

tme.dwHoverTime = HOVER_DEFAULT;

::TrackMouseEvent(&tme);

CButton::OnMouseMove(nFlags, point);

}

void CyctBitmapButton::OnLButtonDown(UINT nFlags, CPoint point)

{

SetBitmap(m_hDown);

CButton::OnLButtonDown(nFlags, point);

}

void CyctBitmapButton::OnLButtonUp(UINT nFlags, CPoint point)

{

SetBitmap(m_hIn);

CButton::OnLButtonUp(nFlags, point);

}

LRESULT CyctBitmapButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)

{

SetBitmap(m_hOut);

return 0;

}

其中WM_MOUSELEAVE消息響應映射是手工添加的。

在頭檔案中DECLARE_MESSAGE_MAP()前添加一句:

afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);//手工添加

在對應的cpp檔案中BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之間添加一句:

ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)//手工添加

WM_MOUSELEAVE消息是由函數TrackMouseEvent産生的,當滑鼠離開button控件就會觸發此消息。

函數SetBitmap定義如下(具體的看源代碼吧):

HBITMAP CyctBitmapButton::SetBitmap(HBITMAP hBitmap)

{

//設定按鈕的位圖

ASSERT(m_hIn == hBitmap || m_hOut == hBitmap || m_hDown == hBitmap);

if(m_hIn == hBitmap)

m_MouseState.SetCurState( _mouse_in );

else if(m_hOut == hBitmap)

m_MouseState.SetCurState(_mouse_out );

else if(m_hDown == hBitmap)

m_MouseState.SetCurState( _mouse_down );

return CButton::SetBitmap(hBitmap);

}

5)如果想去掉按鈕button在獲得焦點時的虛框,重載WM_SETFOCUS消息,并且置函數體為空即可。

(二)六狀态按鈕

       與(一)類似,不再叙述。

(三)MFC自帶的CBitmapButton類

使用很簡單,在對話框類的OnInitDialog内裝載四個位圖資源即可:

//初始化CBitmapButton

m_BitmapButton.LoadBitmaps(IDB_BITMAP_UP,IDB_BITMAP_DOWN2

,IDB_BITMAP_FOCUS,IDB_BITMAP_DISABLED);

總結:多狀态按鈕主要是使用函數TrackMouseEvent函數實作的。本文隻是示例,很簡陋。你也可以下載下傳CButtonST來看看,方法基本一樣。下載下傳區有:

http://search.download.csdn.net/search/cbuttonst

繼續閱讀