WTL 自绘控件库 (CQsCheckBox)
生活随笔
收集整理的這篇文章主要介紹了
WTL 自绘控件库 (CQsCheckBox)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
概述:
CQsCheckBox基礎與 CButton,通過自繪來實現 實現check Box的效果,通過BST_CHECKED 屬性來實現。
代碼實現如下:
#pragma once; #include "QsInclude.h"#define TXTMAX 512 //支持最大字體長度 #define QS_CHK_SYSYSTEM 0x00000001 //CheckBox系統樣式 #define QS_CHK_OWNERDRAW 0x00000002 //CheckBox自繪樣式,默認為自繪樣式。class CQsCheckBox:public CWindowImpl<CQsCheckBox, CButton>,public CImageMgrCtrlBase< CQsCheckBox>,public COwnerDraw< CQsCheckBox > {typedef CWindowImpl< CQsCheckBox, CButton > theBaseClass;typedef CImageMgrCtrlBase< CQsCheckBox> theImageCtrlBaseClass;Image *m_pCurImage; //當前正在使用的圖片Image *m_pLastImage; //發生狀態改變前使用的圖片volatile int m_nCheck; //是否被選中標志volatile bool m_bMouseDown; //鼠標左鍵按下StringAlignment m_eAlignment; // CheckBox的方向Color m_enableColor; //可用狀態時字體的顏色Color m_unenableColor; //不可用狀態時字體的顏色。DWORD m_dwStyle;BOOL m_bunifyfont; public:BEGIN_MSG_MAP( CQsCheckBox )MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBKGnd )//MESSAGE_HANDLER( WM_LBUTTONDOWN, OnLButtonDown )MESSAGE_HANDLER( WM_LBUTTONUP, OnLButtonUp )MESSAGE_HANDLER( WM_MOUSELEAVE, OnMouseLeave )MESSAGE_HANDLER( WM_MOUSEMOVE, OnMouseMove )MESSAGE_HANDLER( BM_SETCHECK, OnSetCheck )MESSAGE_HANDLER( BM_GETCHECK, OnGetCheck )//REFLECTED_COMMAND_CODE_HANDLER( BN_CLICKED, OnClicked )CHAIN_MSG_MAP_ALT( COwnerDraw< CQsCheckBox >, 1 )CHAIN_MSG_MAP( theImageCtrlBaseClass )DEFAULT_REFLECTION_HANDLER()END_MSG_MAP()/***@method CQsCheckBox*@brief CQsCheckBox類構造函數* *@return */CQsCheckBox():m_bMouseDown( false ),m_pCurImage( NULL ),m_pLastImage( NULL ),m_enableColor(255, 0, 0, 0),m_unenableColor(255, 128, 128, 128),m_nCheck( 0 ){m_uFirstPos = CONTROL_CHK_FIRST;m_uLastPos = CONTROL_CHK_LAST;SetAlignment( StringAlignmentNear );m_dwStyle = QS_CHK_OWNERDRAW;m_bunifyfont = FALSE;}/***@method ~CQsCheckBox*@brief CQsCheckBox析構造函數* *@return */virtual ~CQsCheckBox(){}/***@method Create*@brief 通過Create來創建窗口* *@param HWND hWndParent parent window*@param ATL::_U_RECT rect window rect*@param LPCTSTR szWindowName the window name*@param DWORD dwStyle base window style*@param DWORD dwExStyle*@param ATL::_U_MENUorID MenuOrID*@param LPVOID lpCreateParam*@return 非NULL success return TRUE, failed return NULL*/HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,DWORD dwStyle = 0, DWORD dwExStyle = 0,ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL){return theBaseClass::Create( hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);}/***@method SetBtnUnifFont*@brief 設置CONTROL_CHK_CHECKED狀態下統一使用一種字體* *@return void*/void SetBtnUnifFont(BOOL bunifyfont){m_bunifyfont = bunifyfont;}/***@method SetAlignment*@brief 指定文本字符串相對于其布局矩形的對齊方式* *@param StringAlignment align 枚舉Center 指定文本在布局矩形中居中對齊。 Far 指定文本遠離布局矩形的原點位置對齊。在左到右布局中,遠端位置是右。在右到左布局中,遠端位置是左。 Near 指定文本靠近布局對齊。在左到右布局中,近端位置是左。在右到左布局中,近端位置是右 *@return void*/void SetAlignment( StringAlignment align ){m_eAlignment = align;}/***@method GetAlignment*@brief 得到定文本字符串相對于其布局矩形的對齊方式* *@param void*@return StringAlignment 枚舉Center 指定文本在布局矩形中居中對齊。 Far 指定文本遠離布局矩形的原點位置對齊。在左到右布局中,遠端位置是右。在右到左布局中,遠端位置是左。 Near 指定文本靠近布局對齊。在左到右布局中,近端位置是左。在右到左布局中,近端位置是右 */StringAlignment GetAlignment( void ){return m_eAlignment;}/***@method SetQSWindowsStyle*@brief 設置窗口的樣式* *@param DWORD dwstyle dwstyle 窗口的樣式*@return void*/void SetQSWindowsStyle(DWORD dwstyle){m_dwStyle = dwstyle;}/***@method SubclassWindow*@brief 類對象關聯* *@param HWND hWnd 對象句柄*@return BOOL 成功返回TRUE,失敗返回FALSE*/BOOL SubclassWindow( HWND hWnd ){//在此之前可能已經SetCheckm_nCheck = (int)::SendMessage( hWnd, BM_GETCHECK, 0, 0 );BOOL bRet = theBaseClass::SubclassWindow( hWnd );if(m_dwStyle&QS_CHK_OWNERDRAW){UINT nBS = GetButtonStyle();SetButtonStyle( nBS | BS_OWNERDRAW );}return bRet;}/***@method GetState*@brief 得到CheckBox的現在的狀態* *@param void*@return UINT 現在CheckBox的狀態*/UINT GetState( void ){LONG lStyle = GetWindowLong( GWL_STYLE );BOOL bIsDisabled = ( ( lStyle & WS_DISABLED ) != 0 ); //是否被禁止BOOL bIsChecked = ( GetCheck() == BST_CHECKED );UINT uStateFont = CONTROL_BTN_NORMAL;BOOL bIsFocused = ( ::GetFocus() == m_hWnd );//如果當前處于失效狀態if( bIsDisabled ){if( bIsChecked)//如果當前被鉤選{uStateFont = CONTROL_CHK_DISCHECKED;}else{uStateFont = CONTROL_CHK_DISUNCHECK;}}else{if( bIsChecked )//如果當前被鉤選{if(bIsFocused){uStateFont = CONTROL_CHK_FOUCS_CHECKED;}else{uStateFont = CONTROL_CHK_CHECKED;}}else{if(bIsFocused){uStateFont = CONTROL_CHK_FOUCS_UNCHECK;}else{uStateFont = CONTROL_CHK_UNCHECK;}}}return uStateFont;}/***@method GetCheckStateFont*@brief 得到CheckBox的現在的狀態* *@param void*@return UINT 現在CheckBox的狀態*/UINT GetCheckStateFont( void ){LONG lStyle = GetWindowLong( GWL_STYLE );BOOL bIsDisabled = ( ( lStyle & WS_DISABLED ) != 0 ); //是否被禁止BOOL bIsChecked = ( GetCheck() == BST_CHECKED );UINT uStateFont = CONTROL_CHK_CHECKED;BOOL bIsFocused = ( ::GetFocus() == m_hWnd );if(m_bunifyfont == TRUE){return uStateFont;}//如果當前處于失效狀態if( bIsDisabled ){if( bIsChecked)//如果當前被鉤選{uStateFont = CONTROL_CHK_DISCHECKED;}else{uStateFont = CONTROL_CHK_DISUNCHECK;}}else{if( bIsChecked )//如果當前被鉤選{if(bIsFocused){uStateFont = CONTROL_CHK_CHECKED;}else{uStateFont = CONTROL_CHK_CHECKED;}}else{if(bIsFocused){uStateFont = CONTROL_CHK_UNCHECK;}else{uStateFont = CONTROL_CHK_UNCHECK;}}}return uStateFont;}/***@method GetTextFont*@brief 根據控件的狀態獲得控件當前使用的字體* *@param void*@return HFONT 現在CheckBox的狀態字體對象*/HFONT GetTextFont( void ){return GetStateFont( GetCheckStateFont() );}/***@method SetEnableColor*@brief 設置可用時字體的顏色* *@param Color enableColor 可用時字體的顏色*@return void*/void SetEnableColor(Color enableColor){m_enableColor = enableColor;}/***@method SetUnEnableColor*@brief 設置不可用時字體的顏色* *@param Color unenableColor 不可用時字體的顏色*@return void*/void SetUnEnableColor(Color unenableColor){m_unenableColor = unenableColor;} public:/***@method GetTextImageRect*@brief 得到字體和圖片的顯示區域* *@param RECT * lpTextRect 字體所在的區域*@param RECT * lpImageRect 圖片所在的區域*@return void*/void GetTextImageRect( RECT* lpTextRect, RECT* lpImageRect ){CRect rtCtrl;GetClientRect( &rtCtrl );Image *pImg = GetCurrentImage( );HFONT hFont = GetTextFont( );HDC hDC = ::GetDC( m_hWnd );Graphics graph( hDC );Gdiplus::Font fnt( hDC, hFont );RectF rtfText( 0, 0,(REAL)rtCtrl.Width(), (REAL)rtCtrl.Height() );RectF boundText( 0.0, 0.0, 0.0, 0.0 );TCHAR szTxt[TXTMAX] = {'0'};GetWindowText( szTxt, TXTMAX );StringFormat strfmtText;StringAlignment align = GetAlignment();strfmtText.SetAlignment( align );strfmtText.SetLineAlignment( StringAlignmentNear );if( szTxt[0] != 0 ){graph.MeasureString( szTxt, (int)_tcslen(szTxt),&fnt, rtfText, &strfmtText,&boundText );}int nImgWidth = 0;int nImgHeight = 0;if ( pImg != NULL ){nImgWidth = pImg->GetWidth();nImgHeight = pImg->GetHeight();}if( StringAlignmentFar == GetAlignment() ){lpTextRect->left = (LONG)(rtCtrl.Width() - boundText.Width);lpTextRect->top = 0;lpTextRect->right = rtCtrl.Width();lpTextRect->bottom = rtCtrl.Height();int ytmp = rtCtrl.Height() - nImgHeight;lpImageRect->left = lpTextRect->left - nImgWidth - 5 ;lpImageRect->top = ( ytmp < 0 ? 0 : ytmp ) / 2;lpImageRect->right = lpImageRect->left + nImgWidth;lpImageRect->bottom = lpImageRect->top + nImgHeight;}else if( StringAlignmentCenter == GetAlignment() ){int nTotalWidth = (int)(nImgWidth + 10 + boundText.Width);int nLeft = ( rtCtrl.Width() - nTotalWidth ) / 2;nLeft = nLeft < 0 ? 0: nLeft;int ytmp = rtCtrl.Height() - nImgHeight;lpImageRect->left = nLeft;lpImageRect->top = ( ytmp < 0 ? 0 : ytmp ) / 2;lpImageRect->right = lpImageRect->left + nImgWidth;lpImageRect->bottom = lpImageRect->top + nImgHeight;lpTextRect->left = lpImageRect->right + 5;lpTextRect->top = 0;lpTextRect->right = (LONG)(lpTextRect->left + boundText.Width + 2);lpTextRect->bottom = rtCtrl.Height();}else{int ytmp = (int)(rtCtrl.Height() - nImgHeight);lpImageRect->left = 0;lpImageRect->top = ( ytmp < 0 ? 0 : ytmp ) / 2;lpImageRect->right = lpImageRect->left + nImgWidth;lpImageRect->bottom = lpImageRect->top + nImgHeight;lpTextRect->left = lpImageRect->right + 5;lpTextRect->top = 0;lpTextRect->right = (LONG)rtCtrl.right;//(LONG)(lpTextRect->left + boundText.Width+2);lpTextRect->bottom = rtCtrl.Height();}graph.ReleaseHDC( hDC );ReleaseDC( hDC );DeleteObject( hFont );}/***@method DrawItem*@brief 按鈕重畫函數* *@param LPDRAWITEMSTRUCT lpdis*@return void*/void DrawItem( LPDRAWITEMSTRUCT lpdis ){if(m_dwStyle&QS_CHK_SYSYSTEM){return ;}int width = lpdis->rcItem.right - lpdis->rcItem.left;int height = lpdis->rcItem.bottom - lpdis->rcItem.top;//創建內存作圖對象WTL::CDC memDC;memDC.CreateCompatibleDC( lpdis->hDC );WTL::CBitmap memBitmap;memBitmap.CreateCompatibleBitmap( lpdis->hDC, width, height );HBITMAP hOldBmp = memDC.SelectBitmap( memBitmap );//獲得控件背景memDC.SetBkMode( TRANSPARENT );::SendMessage( GetParent(), WM_DRAWBKGNDUI, ( WPARAM )memDC.m_hDC, ( LPARAM )lpdis->hwndItem );//繪制按鈕DrawButton( memDC.m_hDC, lpdis->rcItem );//提交圖像::BitBlt( lpdis->hDC, 0, 0, width, height, memDC.m_hDC, 0, 0, SRCCOPY );memDC.SelectBitmap( hOldBmp );memBitmap.DeleteObject();memDC.DeleteDC();} protected:/***@method OnSetCheck*@brief 設置狀態消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 詳見MSDN*@param LPARAM lParam 詳見MSDN*@param BOOL &*@return LRESULT*/LRESULT OnSetCheck( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ){if(m_dwStyle&QS_CHK_SYSYSTEM){return DefWindowProc(uMsg, wParam, lParam);}switch( wParam ){case BST_CHECKED:case BST_INDETERMINATE:m_nCheck = BST_CHECKED;break;default:m_nCheck = BST_UNCHECKED;break;}Invalidate();//OutputDebugStr( _T("OnSetCheck\r\n") );return 0;}/***@method OnGetCheck*@brief 讀取狀態消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 詳見MSDN*@param LPARAM lParam 詳見MSDN*@param BOOL &*@return LRESULT 詳見MSDN*/LRESULT OnGetCheck( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ){if(m_dwStyle&QS_CHK_SYSYSTEM){return DefWindowProc(uMsg, wParam, lParam);}return m_nCheck;}/***@method OnLButtonDown*@brief 鼠標左鍵被按下消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT 詳見MSDN*/LRESULT OnLButtonDown( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ){//OutputDebugStr( _T("OnLButtonDown\r\n") );m_bMouseDown = true;//Invalidate();bHandled = FALSE;return 0;}/***@method OnMouseMove*@brief 鼠標進入消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT*/LRESULT OnMouseMove( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ){if(m_dwStyle&QS_CHK_SYSYSTEM){return TRUE;}if( m_pCurImage != GetImage( CONTROL_BTN_MOUSEIN ) ){//Invalidate();// 啟動鼠標離開時間TRACKMOUSEEVENT tme;tme.cbSize = sizeof(tme);tme.hwndTrack = m_hWnd;tme.dwFlags = TME_LEAVE;TrackMouseEvent(&tme);}bHandled = FALSE;return 0;}/***@method OnMouseLeave*@brief 鼠標離開消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT 詳見MSDN*/LRESULT OnMouseLeave( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ){if(m_dwStyle&QS_CHK_SYSYSTEM){return TRUE;}//Invalidate();bHandled = FALSE;return 0;}/***@method OnLButtonUp*@brief 鼠標左鍵被放開消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT 詳見MSDN*/LRESULT OnLButtonUp( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL/*& bHandled*/ ){//OutputDebugStr( _T("OnLButtonUp\r\n") );m_bMouseDown = false;SendMessage(WM_KILLFOCUS,0,0);int nCtrlID = GetDlgCtrlID( );SetCheck( !GetCheck() );Invalidate();::SendMessage( GetParent(), WM_COMMAND, (WPARAM)nCtrlID,LPARAM(m_hWnd));//bHandled = FALSE;return 0;}/***@method OnEraseBKGnd*@brief 背景繪制消息函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT 詳見MSDN*/LRESULT OnEraseBKGnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ){if(m_dwStyle&QS_CHK_SYSYSTEM){return DefWindowProc(uMsg, wParam, lParam);}return 0;}/***@method OnClicked*@brief 按鈕被按下消息響應函數* *@param WORD wNotifyCode 通知消息代碼*@param WORD wID 發送該消息的控件ID*@param HWND hWndCtl 發送該消息的控件的句柄*@param BOOL& bHandled 消息是否繼續處理標志*@return LRESULT*/LRESULT OnClicked(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/){if(m_dwStyle&QS_CHK_SYSYSTEM){return 0;}//OutputDebugStr( _T("OnClicked\r\n") );SetCheck( !GetCheck() );Invalidate();return 0;}private:/***@method GetButtonTextFormat*@brief 得到Button文字的對齊方式(用DrawText()輸出時的格式)* *@param const LONG lStyle 控件風格 *@return UINT 用DrawText()輸出時的格式 button上的字必須是一行 */UINT GetButtonTextFormat(const LONG lStyle){UINT uFormat = DT_SINGLELINE; //button上的字必須是一行//x方向if ( (lStyle & BS_CENTER)==BS_CENTER )//x方向,中uFormat |= DT_CENTER;else if ( (lStyle & BS_RIGHT)==BS_RIGHT )//x方向,右uFormat |= DT_RIGHT;else if ( (lStyle & BS_LEFT) == BS_LEFT )//x方向,左uFormat |= DT_LEFT;else//缺省,x中uFormat |= DT_LEFT;//y方向if ( (lStyle & BS_VCENTER ) == BS_VCENTER )//y,中uFormat |= DT_VCENTER;else if ( (lStyle & BS_TOP)==BS_TOP )//y方向,上uFormat |= DT_TOP;else if ( (lStyle & BS_BOTTOM)==BS_BOTTOM )//y方向,下uFormat |= DT_BOTTOM;else//缺省,y中uFormat |= DT_VCENTER;return uFormat;}/***@method GetCurrentImage*@brief 得到當前CheckBox使用的圖片* *@param void*@return Image* 當前圖片的的對象指針*/Image* GetCurrentImage( void ){Image *pImg = NULL;UINT uStateFont = GetState();pImg = GetImage( uStateFont );//如果沒有對應狀態的圖片if( pImg == NULL ){if( m_pCurImage != NULL ){pImg = m_pCurImage;}else{pImg = GetImage( CONTROL_BTN_NORMAL );}}return pImg;}/***@method DrawButton*@brief 繪制按鈕函數* *@param HDC hDC DC句柄*@param RECT itemRect 按鈕位置*@return void*/void DrawButton( HDC hDC, RECT /*itemRect*/ ){HDC hdc = hDC;SetBkMode( hdc, TRANSPARENT );LONG lStyle = GetWindowLong( GWL_STYLE );BOOL bIsDisabled = ( ( lStyle & WS_DISABLED ) != 0 ); //是否被禁止//判斷鼠標是否在按鈕上CRect rc;GetWindowRect( rc );POINT pt;GetCursorPos( &pt );Image *pImg = GetCurrentImage( );//如果當前圖片相同if( m_pCurImage != pImg ){//保存上一個狀態的圖片if( m_pCurImage != NULL){m_pLastImage = m_pCurImage;}else{m_pLastImage = pImg;}m_pCurImage = pImg;}CRect rtImage, rtText;GetTextImageRect( rtText, rtImage );if( m_pCurImage != NULL ){//繪制圖片Graphics graph( hDC );graph.SetPageScale( 1.0 );graph.SetPageUnit( UnitPixel ); graph.SetSmoothingMode( SmoothingModeNone );graph.DrawImage( m_pCurImage, rtImage.left, rtImage.top, rtImage.Width(), rtImage.Height() );graph.ReleaseHDC( hDC );}//繪制文字TCHAR szTxt[TXTMAX] = {0};GetWindowText( szTxt, TXTMAX );//獲得控件當前使用的字體HFONT hFont = GetTextFont( );WTL::CDCHandle dc( hDC );Graphics graph(dc.m_hDC);Gdiplus::Font fnt( dc.m_hDC, hFont );StringFormat strfmt;strfmt.SetAlignment(StringAlignmentCenter);strfmt.SetLineAlignment(StringAlignmentCenter);CRect rtf( rtText.left,rtText.top,rtText.right,rtText.Height()); if( bIsDisabled ){//SolidBrush sdb(m_unenableColor);//graph.DrawString( szTxt,(int)_tcslen(szTxt), &fnt, rtf,&strfmt, &sdb ); HFONT hOldFont = dc.SelectFont( hFont );dc.SetTextColor(m_unenableColor.ToCOLORREF());dc.DrawText( szTxt, -1, &rtf, GetButtonTextFormat( lStyle ) );dc.SelectFont( hOldFont );//SolidBrush sdb(m_unenableColor);//graph.DrawString( szTxt,(int)_tcslen(szTxt), &fnt, rtf,&strfmt, &sdb );}else{HFONT hOldFont = dc.SelectFont( hFont );dc.SetTextColor(m_enableColor.ToCOLORREF());dc.DrawText( szTxt, -1, &rtf, GetButtonTextFormat( lStyle ) );dc.SelectFont( hOldFont );//SolidBrush sdb(m_enableColor); //可用狀態時字體的顏色//graph.DrawString( szTxt,(int)_tcslen(szTxt),&fnt, rtf,&strfmt,&sdb );}graph.ReleaseHDC(dc.m_hDC);DeleteObject( hFont );} };總結
以上是生活随笔為你收集整理的WTL 自绘控件库 (CQsCheckBox)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 采访 Paradigm合伙人 :Cryp
- 下一篇: ZBrush 4R8用起来了!