讓DuiLib CheckBox支持全選、全不選、非全選三種狀態

原文 https://blog.csdn.net/EveyX/article/details/38433783函數

 

  DuiLib官方庫中的Checkbox只有Checked和Uncheck兩種狀態,但咱們每每要實現這中需求:ui

 

    顯然,Checkbox自帶的屬性和方法都不能知足這種需求,這就須要咱們自定義重寫CheckBox控件。this

其實選擇狀態仍是隻有2種,由於SetCheck(bool bCheck) 參數只能爲true或者false。但咱們能夠重寫CheckBox的spa

void PaintStatusImage(HDC hDC) 方法,讓但全部Checkbox都選中時繪製選中圖標,全未選時繪製全未選圖標,.net

未全選時繪製一種半選狀態的圖標。code

    修改UICheckBox.horm

#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__blog

    UICheckBox.cpp文件:get

#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中加入一些自定義的宏和方法:
自定義半選狀態宏io

// 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="圖標路徑",這就能夠這個全選按鈕有三種狀態了 :),若是有什麼不懂的,能夠問我 :)

    若是以爲修改麻煩,能夠去下載我已經修改好的源文件。

相關文章
相關標籤/搜索