让DuiLib CheckBox支持全选、全不选、非全选三种状态
原文 https://blog.csdn.net/EveyX/article/details/38433783
DuiLib官方库中的Checkbox只有Checked和Uncheck两种状态,但我们往往要实现这中需求:
显然,Checkbox自带的属性和方法都不能满足这种需求,这就需要我们自定义重写CheckBox控件。
其实选择状态还是只有2种,因为SetCheck(bool bCheck) 参数只能为true或者false。但我们可以重写CheckBox的
void PaintStatusImage(HDC hDC) 方法,让但所有Checkbox都选中时绘制选中图标,全未选时绘制全未选图标,
未全选时绘制一种半选状态的图标。
修改UICheckBox.h
#ifndef __UICHECKBOX_H__
#define __UICHECKBOX_H__ #pragma once namespace DuiLib
{
/// 最普通的单选按钮控件,只有是、否两种结果
/// 派生于COptionUI,只是每组只有一个按钮而已,组名为空,配置文件默认属性举例:
/// <CheckBox name="CheckBox" value="height='20' align='left' textpadding='24,0,0,0' normalimage='file='sys_check_btn.png' s///ource='0,0,20,20' dest='0,0,20,20'' selectedimage='file='sys_check_btn.png' source='20,0,40,20' dest='0,0,20,20'' disable///dimage='file='sys_check_btn.png' source='40,0,60,20' dest='0,0,20,20''"/> class UILIB_API CCheckBoxUI : public COptionUI
{
public:
~CCheckBoxUI();
LPCTSTR GetClass() const;
void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
LPCTSTR GetSelectGroup() const;
void SetSelectGroup(LPCTSTR pStrGroupName); LPCTSTR GetHalfSelectedImage();
void SetHalfSelectedImage(LPCTSTR pStrImage);
void PaintStatusImage(HDC hDC);
void Selected(bool bSelected);
void SetCheck(bool bCheck);
bool GetCheck() const;
private:
CStdPtrArray m_selectGroup;
CDuiString m_sSelectGroupName;
CDuiString m_sHalfSelectedImage; };
} #endif // __UICHECKBOX_H__
UICheckBox.cpp文件:
#include "stdafx.h"
#include "UICheckBox.h" namespace DuiLib
{
CCheckBoxUI::~CCheckBoxUI()
{
if( !m_sSelectGroupName.IsEmpty() && m_pManager ) m_pManager->RemoveSelectGroup(m_sSelectGroupName, this);
} LPCTSTR CCheckBoxUI::GetClass() const
{
return _T("CheckBoxUI");
} void CCheckBoxUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
if (_tcscmp(pstrName, _T("selectgroup")) == ) SetSelectGroup(pstrValue);
else if (_tcscmp(pstrName, _T("halfselectedimage")) == ) SetHalfSelectedImage(pstrValue);
else COptionUI::SetAttribute(pstrName, pstrValue);
} LPCTSTR CCheckBoxUI::GetSelectGroup() const
{
return m_sSelectGroupName;
} void CCheckBoxUI::SetSelectGroup(LPCTSTR pStrGroupName)
{
if( pStrGroupName == NULL ) {
if( m_sSelectGroupName.IsEmpty() ) return;
m_sSelectGroupName.Empty();
}
else {
if( m_sSelectGroupName == pStrGroupName ) return;
if (!m_sSelectGroupName.IsEmpty() && m_pManager) m_pManager->RemoveSelectGroup(m_sSelectGroupName, this);
m_sSelectGroupName = pStrGroupName;
} if( !m_sSelectGroupName.IsEmpty() ) {
if (m_pManager) m_pManager->AddSelectGroup(m_sSelectGroupName, this);
}
else {
if (m_pManager) m_pManager->RemoveSelectGroup(m_sSelectGroupName, this);
} Selected(m_bSelected);
} LPCTSTR CCheckBoxUI::GetHalfSelectedImage()
{
return m_sHalfSelectedImage;
} void CCheckBoxUI::SetHalfSelectedImage(LPCTSTR pStrImage)
{
m_sHalfSelectedImage = pStrImage;
Invalidate();
} void CCheckBoxUI::Selected(bool bSelected)
{
if( m_bSelected == bSelected ) return;
m_bSelected = bSelected;
if( m_bSelected ) m_uButtonState |= UISTATE_SELECTED;
else m_uButtonState &= ~UISTATE_SELECTED; if( (m_uButtonState & UISTATE_HALFSELECTED) != )
m_uButtonState &= ~UISTATE_HALFSELECTED; if( m_pManager != NULL ) {
if( !m_sGroupName.IsEmpty() ) {
if( m_bSelected ) {
CStdPtrArray* aOptionGroup = m_pManager->GetOptionGroup(m_sGroupName);
for( int i = ; i < aOptionGroup->GetSize(); i++ ) {
COptionUI* pControl = static_cast<COptionUI*>(aOptionGroup->GetAt(i));
if( pControl != this ) {
pControl->Selected(false);
}
}
m_pManager->SendNotify(this, DUI_MSGTYPE_SELECTCHANGED);
}
}
if (m_pManager->GetSelectGroup(GetName()) != NULL) {
CStdPtrArray* aSelectGroup = m_pManager->GetSelectGroup(GetName());
for (int i = ; i < aSelectGroup->GetSize(); i++) {
COptionUI* pControl = static_cast<COptionUI*>(aSelectGroup->GetAt(i));
pControl->Selected(m_bSelected);
}
}
if (!m_sSelectGroupName.IsEmpty()) {
CStdPtrArray* aSelectGroup = m_pManager->GetSelectGroup(m_sSelectGroupName);
UINT cnt = ;
for (int i = ; i < aSelectGroup->GetSize(); i++) {
CCheckBoxUI* pItem = static_cast<CCheckBoxUI*>(aSelectGroup->GetAt(i));
cnt += pItem->IsSelected() ? : ;
}
CCheckBoxUI* pSelectAll = static_cast<CCheckBoxUI*>(m_pManager->FindControl(m_sSelectGroupName));
if (cnt == ) // 全不选
{
pSelectAll->m_bSelected = false;
pSelectAll->m_uButtonState &= ~UISTATE_SELECTED;
pSelectAll->m_uButtonState &= ~UISTATE_HALFSELECTED;
}else if (cnt == aSelectGroup->GetSize()) { // 全选
pSelectAll->m_bSelected = true;
pSelectAll->m_uButtonState |= UISTATE_SELECTED;
pSelectAll->m_uButtonState &= ~UISTATE_HALFSELECTED;
}else { // 非全选
pSelectAll->m_uButtonState &= ~UISTATE_SELECTED;
pSelectAll->m_uButtonState |= UISTATE_HALFSELECTED;
}
pSelectAll->NeedUpdate();
}
else {
m_pManager->SendNotify(this, DUI_MSGTYPE_SELECTCHANGED);
}
} Invalidate();
} void CCheckBoxUI::PaintStatusImage(HDC hDC)
{
m_uButtonState &= ~UISTATE_PUSHED; if( (m_uButtonState & UISTATE_HOT) != && IsSelected() && !m_sSelectedHotImage.IsEmpty()) {
if( !DrawImage(hDC, (LPCTSTR)m_sSelectedHotImage) )
m_sSelectedHotImage.Empty();
else goto Label_ForeImage;
}
else if( (m_uButtonState & UISTATE_SELECTED) != ) {
if( !m_sSelectedImage.IsEmpty() ) {
if( !DrawImage(hDC, (LPCTSTR)m_sSelectedImage) ) m_sSelectedImage.Empty();
else goto Label_ForeImage;
}
else if(m_dwSelectedBkColor != ) {
CRenderEngine::DrawColor(hDC, m_rcPaint, GetAdjustColor(m_dwSelectedBkColor));
return;
}
}
else if( (m_uButtonState & UISTATE_HALFSELECTED) != ) {
if( !m_sHalfSelectedImage.IsEmpty() ) {
if( !DrawImage(hDC, (LPCTSTR)m_sHalfSelectedImage) ) m_sHalfSelectedImage.Empty();
else goto Label_ForeImage;
}
} CButtonUI::PaintStatusImage(hDC); Label_ForeImage:
if( !m_sForeImage.IsEmpty() ) {
if( !DrawImage(hDC, (LPCTSTR)m_sForeImage) ) m_sForeImage.Empty();
}
} void CCheckBoxUI::SetCheck(bool bCheck)
{
Selected(bCheck);
} bool CCheckBoxUI::GetCheck() const
{
return IsSelected();
}
}
还要在UIManager.h中加入一些自定义的宏和方法:
自定义半选状态宏
// Flags used for controlling the paint
#define UISTATE_FOCUSED 0x00000001
#define UISTATE_SELECTED 0x00000002
#define UISTATE_DISABLED 0x00000004
#define UISTATE_HOT 0x00000008
#define UISTATE_PUSHED 0x00000010
#define UISTATE_READONLY 0x00000020
#define UISTATE_CAPTURED 0x00000040
#define UISTATE_HALFSELECTED 0x00000080
添加选项组添加/删除方法(例如添加周几、删除周几到选项组)
bool AddOptionGroup(LPCTSTR pStrGroupName, CControlUI* pControl);
CStdPtrArray* GetOptionGroup(LPCTSTR pStrGroupName);
void RemoveOptionGroup(LPCTSTR pStrGroupName, CControlUI* pControl);
void RemoveAllOptionGroups(); CStdPtrArray* GetSelectGroup(LPCTSTR pStrGroupName);
bool AddSelectGroup(LPCTSTR pStrGroupName, CControlUI* pControl);
void RemoveSelectGroup(LPCTSTR pStrGroupName, CControlUI* pControl);
void CPaintManagerUI::RemoveAllSelectGroups();
添加选项组map映射(例如weeks对应周一,周二...)
CStdPtrArray m_aNotifiers;
CStdPtrArray m_aTimers;
CStdPtrArray m_aPreMessageFilters;
CStdPtrArray m_aMessageFilters;
CStdPtrArray m_aPostPaintControls;
CStdPtrArray m_aDelayedCleanup;
CStdPtrArray m_aAsyncNotify;
CStdPtrArray m_aFoundControls;
CStdStringPtrMap m_mNameHash;
CStdStringPtrMap m_mOptionGroup;
CStdStringPtrMap m_mSelectGroup;
在UIManager.cpp中析构函数~CPaintManagerUI()
RemoveAllFonts();
RemoveAllImages();
RemoveAllDefaultAttributeList();
RemoveAllOptionGroups();
RemoveAllSelectGroups();
RemoveAllTimers();
自定义方法的实现
CStdPtrArray* CPaintManagerUI::GetSelectGroup(LPCTSTR pStrGroupName)
{
LPVOID lp = m_mSelectGroup.Find(pStrGroupName);
if( lp ) return static_cast<CStdPtrArray*>(lp);
return NULL;
} bool CPaintManagerUI::AddSelectGroup(LPCTSTR pStrGroupName, CControlUI* pControl)
{
LPVOID lp = m_mSelectGroup.Find(pStrGroupName);
if( lp ) {
CStdPtrArray* aSelectGroup = static_cast<CStdPtrArray*>(lp);
for( int i = ; i < aSelectGroup->GetSize(); i++ ) {
if( static_cast<CControlUI*>(aSelectGroup->GetAt(i)) == pControl ) {
return false;
}
}
aSelectGroup->Add(pControl);
}
else {
CStdPtrArray* aSelectGroup = new CStdPtrArray();
aSelectGroup->Add(pControl);
m_mSelectGroup.Insert(pStrGroupName, aSelectGroup);
}
return true;
} void CPaintManagerUI::RemoveSelectGroup(LPCTSTR pStrGroupName, CControlUI* pControl)
{
LPVOID lp = m_mSelectGroup.Find(pStrGroupName);
if( lp ) {
CStdPtrArray* aSelectGroup = static_cast<CStdPtrArray*>(lp);
if( aSelectGroup == NULL ) return;
for( int i = ; i < aSelectGroup->GetSize(); i++ ) {
if( static_cast<CControlUI*>(aSelectGroup->GetAt(i)) == pControl ) {
aSelectGroup->Remove(i);
break;
}
}
if( aSelectGroup->IsEmpty() ) {
delete aSelectGroup;
m_mSelectGroup.Remove(pStrGroupName);
}
}
} void CPaintManagerUI::RemoveAllSelectGroups()
{
CStdPtrArray* aSelectGroup;
for( int i = ; i< m_mSelectGroup.GetSize(); i++ ) {
if(LPCTSTR key = m_mSelectGroup.GetAt(i)) {
aSelectGroup = static_cast<CStdPtrArray*>(m_mSelectGroup.Find(key));
delete aSelectGroup;
}
}
m_mSelectGroup.RemoveAll();
}
这样CheckBox就支持三种状态了,例如我现在又周一到周日的几个CheckBox控件,首先先把这几个控件加selectgroup属性,属性的值就填那个做全选按钮name的值,例如这个全选按钮的值为weeks,其他的按钮就都设置selectgroup="weeks",然后再设置CheckBox未全选(半选)的图标属性halfselectedimage="图标路径",这就可以这个全选按钮有三种状态了 :),如果有什么不懂的,可以问我 :)
如果觉得修改麻烦,可以去下载我已经修改好的源文件。
让DuiLib CheckBox支持全选、全不选、非全选三种状态的更多相关文章
- TreeView的三种状态,全选,全不选,半选中
我知道的设置treeview节点的三种状态,如果不是买的控件,那么通过代码,只能设置两种状态,我知道的有三种方法, 第一种是重写treeview,第二种是把三种状态做成小图标,让节点复选框随着不同的状 ...
- WPF中CheckBox三种状态打勾打叉和滑动效果
本文分为两个demo, 第一个demo实现checkBox的打叉或打勾的效果: 第二个demo部分实现checkBox的滑动效果. Demo1: wpf的CheckBox支持三种状态,但是美中不足的是 ...
- 【翻译】checkbox的第三种状态
checkbox只有两种值:选中(checked)或未选中(unchecked).它可以有任何值,但是表单提交时checkbox的值只能是checked或unchecked.它的默认值是uncheck ...
- IOS(苹果手机)使用video播放HLS流,实现在内部播放及全屏播放(即非全屏和全屏播放)。
需求: 实现PC及移动端播放HLS流,并且可以自动播放,在页面内部播放及全屏播放功能. 初步:PC及安卓机使用hls.js实现hls流自动播放及全屏非全屏播放 首先使用了hls.js插件,可以实现在P ...
- (最全)Xpath、Beautiful Soup、Pyquery三种解析库解析html 功能概括
一.Xpath 解析 xpath:是一种在XMl.html文档中查找信息的语言,利用了lxml库对HTML解析获取数据. Xpath常用规则: nodename :选取此节点的所有子节点 // : ...
- checkbox,三种状态设置
多选按钮的 选中.未选中.半选中(常用于子项有选中,未全选) <input id="ckeckbox" type="checkbox"> $('# ...
- checkbox的三种状态处理
checkbox只有两种值:选中(checked)或未选中(unchecked).它可以有任何值,但是表单提交时checkbox的值只能是checked或unchecked.它的默认值是uncheck ...
- Devexpress treelist 树形控件 实现带三种状态的CheckBox
树形控件是使用频率很高的一种控件.对于属性控件往往需要下面两个功能 1.TreeList带有CheckBox,并且节点要有三种状态(所有的子节点都选中,所有的子节点都没选择,一部分子节点选中).使用 ...
- HTML5文件上传qq、百度、taobao等比较(改进支持三种状态提示)
拖拽过程详解: 1:文件未拖出文件选择框的时候提示:将要上传的文件或文件夹拖拽至此区域 2:文件拖出文件选择框但未拖入上传的文件框提示:请继续拖拽文件或文件夹至此区域 3:文件拖出文件选择框且已拖入上 ...
随机推荐
- python 字符串 - python基础入门(12)
在 python变量 文章中我们对python变量做了一个简单的了解,整数/浮点数/bool值相对来讲都比较简单,今天详细在讲解一下关于字符串的内容,字符串俗称:str. 在本文会大量的使用print ...
- MySQL(二) decimal数据默认处理
create table decimal_test(id int auto_increment PRIMARY key,score decimal(5,2) -- 取值范围是 -999.99 到 99 ...
- 转载:微信开放平台开发第三方授权登陆(二):PC网页端
微信开放平台开发第三方授权登陆(二):PC网页端 2018年07月24日 15:13:32 晋文子上 阅读数 12644更多 分类专栏: 微信开发 第三方授权登录 版权声明:本文为博主原创文章,遵 ...
- 【数据结构】Tournament Chart
Tournament Chart 题目描述 In 21XX, an annual programming contest, Japan Algorithmist GrandPrix (JAG) has ...
- SAS学习笔记29 logistic回归
变量筛选 当对多个自变量建立logistic回归模型时,并不是每一个自变量对模型都有贡献.通常我们希望所建立的模型将具有统计学意义的自变量都包含在内,而将没有统计学意义的自变量排除在外,即进行变量筛选 ...
- SpringBoot exception异常处理机制源码解析
一.Spring Boot默认的异常处理机制 1:浏览器默认返回效果 2:原理解析 为了便于源码跟踪解析,在·Controller中手动设置异常. @RequestMapping(value=&quo ...
- 解决 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 以及MyBatis批量加载xml映射文件的方式
错误 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 的出现,意味着项目需要xml文件来 ...
- 调整统计信息JOB采样时间
一.需求说明 Oracle数据库中存在定时JOB,自动执行收集统计信息的程序.但是对于7*24小时系统来说,Oracle配置的定时收集时间不太合理,需要人为调整.本篇博客就是基于这种需求,调整JOB采 ...
- 怎样理解new命令的执行过程
通过new命令生成一个实例对象经历了四个步骤: 1. 创建一个空对象, 作为将要返回的实例; 2. 将空对象的原型指向构造函数的prototype属性; 3. 将空对象赋值给构造函数的this; 4. ...
- Centos 在VM中设置静态ip
cd /etc/sysconfig/network-scripts 然后代开第一个文件 一般是ifcfg-ens331)开始配置原来是这样的 修改/etc/sysconfig/network # Cr ...