概述:

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)相关推荐

  1. WTL 自绘控件库 (CQsTabCtrl)

    概述: CQsTabCtrl 继承与 CTabCtrl,通过自绘来背景的绘制,以及各种选中状态的的绘制,以及选中和非选中字体的颜色等一些属性. 代码实现如下: #pragma once; #inclu ...

  2. WTL 自绘控件库 (CQSProgressBar)

    概述: CQSProgressBar 进度条,是显示进度控制.但是需要添加自绘属性. 代码实现如下: #pragma once; #pragma warning(disable:4995 4819)# ...

  3. winform checkbox要点击两次_开源C# Winform控件库SunnyUI强力推荐

    本站(https://dotnet9.com)曾介绍过一款Winform开源控件库<HZHControls>,文章发布后不少朋友热情的咨询相关控件库信息,由此看来Winform在大家心中的 ...

  4. 开源C# Winform控件库《SunnyUI》强力推荐

    本站(https://dotnet9.com)曾介绍过一款Winform开源控件库<HZHControls>,文章发布后不少朋友热情的咨询相关控件库信息,由此看来Winform在大家心中的 ...

  5. Github 开源:升讯威 Winform 开源控件库( Sheng.Winform.Controls)

    Github 地址:https://github.com/iccb1013/Sheng.Winform.Controls 本控件库中的代码大约写于10年前(2007年左右),难免有不成熟与欠考虑之处, ...

  6. 如何在WPF中调用C#控件库(HexEdit)

    1 编写一个Hex Edit控件,使用VS2010建立一个类控件库,分别增加两个类文件,一个命名为HexEdit.cs, 一个命名为TextEditControl.cs,具体内容如下所示: 1)Hex ...

  7. MFC自绘控件系列-按钮PNG贴图(GDI+)

    常规的GDI自绘控件仅支持BMP图片,不支持png图片.png图片体积小,支持透明色,可以做圆角界面.自绘控件想要支持PNG图片,需要在MFC工程引入GDI+.需要注意的是MFC工程默认是不支持GDI ...

  8. UI控件库分享:DWZ(j-UI)、LigerUI、Linb

    DWZ(j-UI): 在线演示地址:http://demo.dwzjs.com 在线文档:http://demo.dwzjs.com/doc/dwz-user-guide.pdf DWZ框架Ajax开 ...

  9. 虚拟桌面模拟查找点击自绘控件

    // VDesktopClick.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h" #include <string> #inclu ...

  10. [原创]基于Extjs的开源控件库 - http://extaspnet.codeplex.com/

    ExtAspNet   ExtAspNet - ExtJS based ASP.NET Controls with Full AJAX Support     ExtAspNet是一组专业的Asp.n ...

最新文章

  1. 周期方波的傅里叶级数系数
  2. 修改initrd做miniLinux
  3. [福大软工] W班 总成绩排行榜
  4. Mac查看本机ip地址
  5. 收藏 | 可能是最详尽的PyTorch动态图解析
  6. Android AES加密算法及事实上现
  7. java四种修饰符_java中的四种修饰符
  8. ueditor样式过滤问题
  9. Android 系统服务列表
  10. mysql 字符串搜_Mysql搜索字符串
  11. MATLAB绘制散点图
  12. VS2015如何添加头文件
  13. http的响应码200,404,302,500表示的含义分别是?
  14. 如何建立个人网站(免费创建个人网站制作流程步骤)
  15. 游戏建模中游戏人物设计要点是什么?
  16. 微信配置JS接口安全域名-Nginx配置 文件的配置
  17. 如何利用Excel批量下载网页图片?
  18. 华为手机下拉菜单变大_华为手机下拉菜单变少了 华为下拉通知栏变白色
  19. 火车头采集翻页内容_八爪鱼采集器 循环翻页只翻3、5页就提示采集结束
  20. 计算机静音图标无法更改怎么办,电脑桌面出现静音图标,是桌面上,不是右下角,怎么处理...

热门文章

  1. aws服务器如何修改远程密码,谷歌云、亚马逊 AWS 设置 root 密码并开启 SSH 登录...
  2. 猜拳php代码,微信猜拳游戏源码
  3. angular ng-show中表达式的写法
  4. openBSD安装桌面
  5. 计算机英语写作题范文,2018年6月英语四级考试写作范文:人与电脑
  6. 详解 物理学四大神兽————拉普拉斯兽
  7. conda install pytorch torchvision torchaudio cudatoolkit=11.6 -c pytorch -c conda-forge遇到的报错
  8. 【操作系统】第二章--进程的描述与控制--深入与解释(1)
  9. HTTP hijack
  10. 目前最新全国行政区域JSON数据截止2015年9月30日