WTL 自绘控件库 (CQsRadioBox)
生活随笔
收集整理的這篇文章主要介紹了
WTL 自绘控件库 (CQsRadioBox)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
概述:
CQsRadioBox基礎與 CButton,通過自繪來實現 實現Radion Box的效果,通過BST_CHECKED 屬性來實現。
代碼實現如下:
#pragma once #include "QsInclude.h"#define MAXRADIOXTXT 512#define QS_RAD_SYSYSTEM 0x00000001 //RadioBox系統樣式 #define QS_RAD_OWNERDRAW 0x00000002 //RadioBox自繪樣式,默認為自繪樣式。class CQsRadioBox :public CWindowImpl<CQsRadioBox, CButton>,public CImageMgrCtrlBase< CQsRadioBox>,public COwnerDraw< CQsRadioBox > {typedef CWindowImpl< CQsRadioBox, CButton > theBaseClass;typedef CImageMgrCtrlBase< CQsRadioBox > theImageCtrlBaseClass;Image *m_pCurImage; //當前正在使用的圖片Image *m_pLastImage; //發生狀態改變前使用的圖片volatile int m_nCheck; //是否被選中標志volatile bool m_bMouseDown; //鼠標左鍵按下Color m_enableColor; //可用狀態時字體的顏色Color m_unenableColor; //不可用狀態時字體的顏色 public:BEGIN_MSG_MAP( CQsRadioBox )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< CQsRadioBox >, 1 )CHAIN_MSG_MAP( theImageCtrlBaseClass )DEFAULT_REFLECTION_HANDLER()END_MSG_MAP()/***@method CQsRadioBox*@brief CQsRadioBox類構造函數* *@return */CQsRadioBox():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_RDB_FIRST;m_uLastPos = CONTROL_RDB_LAST;SetQsStyle(QS_RAD_OWNERDRAW);}/***@method ~CQsRadioBox*@brief CQsRadioBox析構造函數* *@return */virtual ~CQsRadioBox(){}/***@method DrawItem*@brief 按鈕重畫函數* *@param LPDRAWITEMSTRUCT lpdis 詳見MSN*@return void*/void DrawItem( LPDRAWITEMSTRUCT lpdis ){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();}/***@method Create*@brief 通過Create來創建窗口。* *@param HWND hWndParent parent window*@param ATL::_U_RECT rect = NULL create window rect*@param LPCTSTR szWindowName = NULL the window name*@param DWORD dwStyle = 0 base window style*@param DWORD dwExStyle = 0 extended window style*@param ATL::_U_MENUorID MenuOrID = 0U menu or ID*@param LPVOID lpCreateParam = NULL create param*@return HWND 非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 SubclassWindow*@brief 類對象關聯* *@param HWND hWnd 對象句柄*@return BOOL*/BOOL SubclassWindow( HWND hWnd ){//在此之前可能已經SetCheckm_nCheck = (int)::SendMessage( hWnd, BM_GETCHECK, 0, 0 );BOOL bRet = theBaseClass::SubclassWindow( hWnd );if(m_dwQsStyle&QS_RAD_OWNERDRAW){UINT nBS = GetButtonStyle();SetButtonStyle( nBS | BS_OWNERDRAW );}return bRet;}/***@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;} protected:/***@method OnSetCheck*@brief 設置狀態消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT*/LRESULT OnSetCheck( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ){if(m_dwQsStyle&QS_RAD_SYSYSTEM){return DefWindowProc(uMsg, wParam, lParam); }//首先獲得check標志m_nCheck = ( wParam != 0 );if( m_nCheck ){CSimpleArray< HWND > lst;lst.Add( m_hWnd );//獲得父窗口句柄HWND hWndParent = GetParent().m_hWnd;//獲得控件窗口句柄HWND hWnd = m_hWnd;while( hWnd ){//獲得同組內控件的窗口句柄hWnd = ::GetNextDlgGroupItem( hWndParent, hWnd, 0 );//在list中查找這個句柄是否被查詢到過int nPos = lst.Find( hWnd );if( nPos != -1 ){//如果找到了這個句柄,那就代表搜索到頭了hWnd = NULL;}if( NULL != hWnd ){//如果沒有搜索完一組,則把當前搜索的句柄添加到list中去(目的是為了不讓同一控件被發送兩次消息)lst.Add( hWnd );//對這個控件發送unChecked消息::PostMessage( hWnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0 );}}}Invalidate();return 0;}/***@method OnGetCheck*@brief 讀取狀態消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT*/LRESULT OnGetCheck( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ){if(m_dwQsStyle&QS_RAD_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*/LRESULT OnLButtonDown( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ){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_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*/LRESULT OnMouseLeave( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ){Invalidate();bHandled = FALSE;return 0;}/***@method OnLButtonUp*@brief 鼠標左鍵被放開消息響應函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT*/LRESULT OnLButtonUp( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ){m_bMouseDown = false;Invalidate();bHandled = FALSE;return 0;}/***@method OnEraseBKGnd*@brief 背景繪制消息函數* *@param UINT uMsg 消息類型*@param WPARAM wParam 未被使用*@param LPARAM lParam 詳見MSDN*@param BOOL& bHandled 未被使用*@return LRESULT*/LRESULT OnEraseBKGnd( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ ){//禁止繪制底色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*/){SetCheck( BST_CHECKED );Invalidate();return 0;}private:/***@method GetButtonTextFormat*@brief 得到Button文字的對齊方式(用DrawText()輸出時的格式)* *@param const LONG lStyle 控件風格*@return UINT 輸出時的格式* 說 明: 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 DrawButton*@brief 繪制按鈕函數* *@param HDC hDC 作圖設備句柄*@param RECT itemRect 按鈕位置*@return void*/void DrawButton( HDC hDC, RECT /*itemRect*/ ){HDC hdc = hDC;WTL::CDCHandle dc( hDC );SetBkMode( hdc, TRANSPARENT );LONG lStyle = GetWindowLong( GWL_STYLE );BOOL bIsDisabled = ( ( lStyle & WS_DISABLED ) != 0 ); //是否被禁止BOOL bIsChecked = ( GetCheck() == BST_CHECKED );//判斷鼠標是否在按鈕上CRect rc;GetWindowRect( rc );POINT pt;GetCursorPos( &pt );Image *pImg = NULL;UINT uStateFont = CONTROL_BTN_NORMAL;//如果當前處于失效狀態if( bIsDisabled ){if( bIsChecked )//如果當前被選擇{pImg = ( GetImage( CONTROL_RDB_DISCHECKED ) != NULL ? GetImage( CONTROL_RDB_DISCHECKED ) : GetImage ( CONTROL_RDB_CHECKED ) );uStateFont = CONTROL_RDB_DISCHECKED; }else{pImg = ( GetImage( CONTROL_RDB_DISUNCHECK ) != NULL ? GetImage( CONTROL_RDB_DISUNCHECK ) : GetImage( CONTROL_RDB_DISCHECKED ) );uStateFont = CONTROL_RDB_DISUNCHECK; //CONTROL_RDB_DISUNCHECK}}else{if( bIsChecked )//如果當前被選擇{pImg = GetImage( CONTROL_RDB_CHECKED );uStateFont = CONTROL_RDB_CHECKED;}else{pImg = GetImage( CONTROL_RDB_UNCHECK );uStateFont = CONTROL_RDB_UNCHECK;}}//如果沒有對應狀態的圖片if( pImg == NULL ){if( m_pCurImage != NULL ){pImg = m_pCurImage;}else{pImg = GetImage( CONTROL_BTN_NORMAL );uStateFont = CONTROL_BTN_NORMAL;}}//如果當前圖片相同if( m_pCurImage != pImg ){//保存上一個狀態的圖片if( NULL != m_pCurImage){m_pLastImage = m_pCurImage;}else{m_pLastImage = pImg;}m_pCurImage = pImg;}//繪制圖片Graphics graph( hDC );int titleStart = 0;if( m_pCurImage != NULL ){graph.SetPageScale( 1.0 );graph.SetPageUnit( UnitPixel ); graph.SetSmoothingMode( SmoothingModeNone );titleStart = m_pCurImage->GetWidth( );graph.DrawImage( m_pCurImage, 0, 0, titleStart, m_pCurImage->GetHeight() );}// 顯示標題TCHAR tstrTitle[MAXRADIOXTXT] = _T("");GetWindowText( tstrTitle, MAXRADIOXTXT);CRect rtWnd;GetWindowRect( &rtWnd );ScreenToClient( &rtWnd );HFONT hFont = GetStateFont(uStateFont); //得到的Font要求銷毀!Gdiplus::Font fontTitle(hDC,hFont);StringFormat format;UINT uStyle = GetButtonStyle();if ( BS_PUSHLIKE & uStyle ){CRect rtfTitle( 0, 0, rtWnd.Width(), rtWnd.Height() );format.SetAlignment(StringAlignmentCenter);format.SetLineAlignment(StringAlignmentCenter);if(!bIsDisabled) //失效狀態{HFONT hOldFont = dc.SelectFont( hFont );dc.SetTextColor(m_enableColor.ToCOLORREF());dc.DrawText( tstrTitle, -1, &rtfTitle, GetButtonTextFormat( lStyle ) );dc.SelectFont( hOldFont );//SolidBrush sbTitle(m_enableColor);//graph.DrawString( tstrTitle,(int) _tcslen(tstrTitle), &fontTitle, rtfTitle, &format, &sbTitle );}else{HFONT hOldFont = dc.SelectFont( hFont );dc.SetTextColor(m_unenableColor.ToCOLORREF());dc.DrawText( tstrTitle, -1, &rtfTitle, GetButtonTextFormat( lStyle ) );dc.SelectFont( hOldFont );//SolidBrush sbTitle(m_unenableColor);//graph.DrawString( tstrTitle,(int) _tcslen(tstrTitle), &fontTitle, rtfTitle, &format, &sbTitle );}}else{ CRect rtfTitle( titleStart, 0, rtWnd.Width() - titleStart, rtWnd.Height() );format.SetAlignment( StringAlignmentNear );format.SetLineAlignment( StringAlignmentCenter );if(!bIsDisabled) //失效狀態{HFONT hOldFont = dc.SelectFont( hFont );dc.SetTextColor(m_enableColor.ToCOLORREF());dc.DrawText( tstrTitle, -1, &rtfTitle, GetButtonTextFormat( lStyle ) );dc.SelectFont( hOldFont );// SolidBrush sbTitle(m_enableColor);// graph.DrawString( tstrTitle, (int)_tcslen(tstrTitle), &fontTitle, rtfTitle, &format, &sbTitle );}else{HFONT hOldFont = dc.SelectFont( hFont );dc.SetTextColor(m_unenableColor.ToCOLORREF());dc.DrawText( tstrTitle, -1, &rtfTitle, GetButtonTextFormat( lStyle ) );dc.SelectFont( hOldFont );//SolidBrush sbTitle(m_unenableColor);//graph.DrawString( tstrTitle, (int)_tcslen(tstrTitle), &fontTitle, rtfTitle, &format, &sbTitle );}}graph.ReleaseHDC( hDC );DeleteObject( hFont );} };總結
以上是生活随笔為你收集整理的WTL 自绘控件库 (CQsRadioBox)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Stata: 断点回归分析 (RDD)
- 下一篇: Linux搭建SVN服务器,并内网穿透实