让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:文件拖出文件选择框且已拖入上 ...
随机推荐
- C#基础知识学习 三
- google搜索设置,在新的窗口打开
- EasyUI 对话框弹出文件输入框
目前用的EasyUI的dialog,要实现弹出文件输入框(或者其他输入框和对话框),我的实现方案是,首先写一个close的div,然后里面就是样式和输入框的一些代码和一个确定按钮,然后页面上一个按钮, ...
- Java的设计模式(2)--单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点. 好处: (1)频繁使用的对象,可以省略new操作花费的时间,这对于那些重量级对象而言,是非常客观的一笔开销. (2)由于new的次数 ...
- js实现放烟花效果——点击处会从下向上升起烟花
一个box中,点击其中的任意位置,会有烟花从正下方升起到点击处,并燃放出一圈圆形的烟花.代码如下: 首先是布局以及样式: <style> .box{ width: 1100px; heig ...
- python3 获取自建gitlab用户提交信息
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019-12-03 14:20 # @Author : Anthony # @Emai ...
- 去除element-ui table表格右侧滚动条的高度
/* //element-ui table的去除右侧滚动条的样式 */ ::-webkit-scrollbar { width: 1px; height: 1px; } /* // 滚动条的滑块 */ ...
- (二)easyUI之消息提示框
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- (四)Maven中的仓库
一.分类 maven的仓库只有两大类: 1.本地仓库 2.远程仓库,在远程仓库中又分成了3种: 2.1 中央仓库 2.2 私服 2.3 其它公共库 二.本地仓库 本地仓库,顾名思义,就是Maven在本 ...
- 十大经典排序【Java实现,手工作坊式】
终于把排序这个硬骨头,但是又很基础的知识点,自己手撕了一遍!之前,使用Python看着算法导论的书手撕过一遍,印象不是很深刻,容易忘记!好记性不如烂笔头!多自己思考解决问题 1,交换类CAS[最简单] ...