• 让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")) == 0) SetSelectGroup(pstrValue);
    else if (_tcscmp(pstrName, _T("halfselectedimage")) == 0) 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) != 0 )
    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 = 0; 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 = 0; 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 = 0;
    for (int i = 0; i < aSelectGroup->GetSize(); i++) {
    CCheckBoxUI* pItem = static_cast<CCheckBoxUI*>(aSelectGroup->GetAt(i));
    cnt += pItem->IsSelected() ? 1 : 0;
    }
    CCheckBoxUI* pSelectAll = static_cast<CCheckBoxUI*>(m_pManager->FindControl(m_sSelectGroupName));
    if (cnt == 0) // 全不选
    {
    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) != 0 && IsSelected() && !m_sSelectedHotImage.IsEmpty()) {
    if( !DrawImage(hDC, (LPCTSTR)m_sSelectedHotImage) )
    m_sSelectedHotImage.Empty();
    else goto Label_ForeImage;
    }
    else if( (m_uButtonState & UISTATE_SELECTED) != 0 ) {
    if( !m_sSelectedImage.IsEmpty() ) {
    if( !DrawImage(hDC, (LPCTSTR)m_sSelectedImage) ) m_sSelectedImage.Empty();
    else goto Label_ForeImage;
    }
    else if(m_dwSelectedBkColor != 0) {
    CRenderEngine::DrawColor(hDC, m_rcPaint, GetAdjustColor(m_dwSelectedBkColor));
    return;
    }    
    }
    else if( (m_uButtonState & UISTATE_HALFSELECTED) != 0 ) {
    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 = 0; i < aSelectGroup->GetSize(); i++ ) {
    if( static_cast<CControlUI*>(aSelectGroup->GetAt(i)) == pControl ) {
    return false;
    }
    }
    aSelectGroup->Add(pControl);
    }
    else {
    CStdPtrArray* aSelectGroup = new CStdPtrArray(6);
    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 = 0; 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 = 0; 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="图标路径",这就可以这个全选按钮有三种状态了 :),如果有什么不懂的,可以问我 :)

        如果觉得修改麻烦,可以去下载我已经修改好的源文件。

  • 相关阅读:
    【笔记】vue中websocket心跳机制
    【笔记】MySQL删除重复记录保留一条
    oss上传实例
    jquery实现图片点击旋转
    IDEA卡顿解决方法
    斐波那契数列
    【笔记】接口发送数据及接收
    【笔记】获取新浪财经最新的USDT-CNY的汇率
    【笔记】Java 信任所有SSL证书(解决PKIX path building failed问题)
    IDEA中报错“cannot resolve symbol toDF”,但编译正确可以运行
  • 原文地址:https://www.cnblogs.com/hei-hei-hei/p/10937691.html
Copyright © 2020-2023  润新知