当前位置: 首页 > news >正文

带复选框的combox

1、设置为 fixed

2、代码

#pragma once
#include "HeadAllSys.h"
/******************************
mahongkai 2025-11-12类说明:带checkbox的combox函数说明:1、参考 DataBaseViewDlg 中的使用
******************************/
// CCheckComboBox.h// 自定义通知代码
#define CCBN_CHECKCHANGE (WM_USER + 100)class CCheckComboBox : public CComboBox
{DECLARE_DYNAMIC(CCheckComboBox)public:CCheckComboBox();virtual ~CCheckComboBox();// 添加带复选框的项int AddCheckString(CString lpszString, BOOL bChecked = FALSE);int InsertCheckString(int nIndex, LPCTSTR lpszString, BOOL bChecked = FALSE);// 复选框操作BOOL GetCheck(int nIndex);void SetCheck(int nIndex, BOOL bCheck);// 获取选中项的文本CString GetCheckedItemsText(LPCTSTR lpszDelimiter = _T(";"));// 获取选中项的索引void GetCheckedIndices(CUIntArray& indices);// 删除所有项void ResetContent();protected:DECLARE_MESSAGE_MAP()private:CArray<BOOL, BOOL> m_CheckStates;  // 存储每个项的选中状态CFont m_font;                      // 字体int m_nItemHeight;                 // 项高度BOOL m_bDropdown;                  // 下拉状态map<int, CString> m_ItemTexts;  // 自己存储所有字符串// 子类化下拉列表相关CWnd m_listBox;                  // 下拉列表窗口WNDPROC m_pOldListBoxProc;       // 原窗口过程// 初始化函数void Initialize();// 子类化下拉列表void SubclassListBox();// 静态窗口过程static LRESULT CALLBACK ListBoxProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);public:virtual void PreSubclassWindow();virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);afx_msg void OnCloseUp();afx_msg void OnDropDown();
};
#include "pch.h"
#include "StylusProfilometerApp.h"
#include "CCheckComboBox.h"IMPLEMENT_DYNAMIC(CCheckComboBox, CComboBox)BEGIN_MESSAGE_MAP(CCheckComboBox, CComboBox)ON_WM_LBUTTONDOWN()ON_WM_CREATE()ON_CONTROL_REFLECT(CBN_CLOSEUP, OnCloseUp)ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropDown)
END_MESSAGE_MAP()CCheckComboBox::CCheckComboBox(): m_nItemHeight(20), m_bDropdown(FALSE), m_pOldListBoxProc(NULL)
{
}CCheckComboBox::~CCheckComboBox()
{// 确保取消子类化if (m_listBox.m_hWnd && m_pOldListBoxProc){m_listBox.UnsubclassWindow();}
}// 初始化函数
void CCheckComboBox::Initialize()
{// 设置自绘属性ModifyStyle(0, CBS_OWNERDRAWFIXED | CBS_HASSTRINGS);// 创建字体if (!m_font.m_hObject){CFont* pFont = GetFont();if (pFont){LOGFONT lf;pFont->GetLogFont(&lf);m_font.CreateFontIndirect(&lf);}else{m_font.CreateStockObject(DEFAULT_GUI_FONT);}}// 设置初始文本SetWindowText(_T("请选择..."));
}int CCheckComboBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CComboBox::OnCreate(lpCreateStruct) == -1)return -1;Initialize();return 0;
}void CCheckComboBox::PreSubclassWindow()
{CComboBox::PreSubclassWindow();Initialize();
}int CCheckComboBox::AddCheckString(CString lpszString, BOOL bChecked)
{// 2. 添加到 ComboBox - 添加空字符串或者索引标识int nIndex = AddString(lpszString);// 1. 先添加到自己的字符串数组m_ItemTexts.insert({ nIndex,lpszString });if (nIndex != CB_ERR && nIndex != CB_ERRSPACE){if (nIndex >= m_CheckStates.GetSize())m_CheckStates.SetSize(nIndex + 1);m_CheckStates[nIndex] = bChecked;// 如果有项被选中,更新显示文本if (bChecked){CString strText = GetCheckedItemsText();SetWindowText(strText);}}return nIndex;
}int CCheckComboBox::InsertCheckString(int nIndex, LPCTSTR lpszString, BOOL bChecked)
{if (nIndex >= 0 && nIndex <= m_ItemTexts.size()){m_ItemTexts.insert({ nIndex, lpszString });}else{return CB_ERR;}int nResult = InsertString(nIndex, lpszString);if (nResult != CB_ERR && nResult != CB_ERRSPACE){if (nResult >= m_CheckStates.GetSize())m_CheckStates.SetSize(nResult + 1);// 移动选中状态for (int i = m_CheckStates.GetSize() - 1; i > nResult; i--)m_CheckStates[i] = m_CheckStates[i - 1];m_CheckStates[nResult] = bChecked;// 如果有项被选中,更新显示文本if (bChecked){CString strText = GetCheckedItemsText();SetWindowText(strText);}}return nResult;
}BOOL CCheckComboBox::GetCheck(int nIndex)
{if (nIndex >= 0 && nIndex < m_CheckStates.GetSize())return m_CheckStates[nIndex];return FALSE;
}void CCheckComboBox::SetCheck(int nIndex, BOOL bCheck)
{if (nIndex >= 0 && nIndex < m_CheckStates.GetSize()){m_CheckStates[nIndex] = bCheck;// 更新显示文本CString strText = GetCheckedItemsText();SetWindowText(strText);Invalidate();}
}void CCheckComboBox::ResetContent()
{CComboBox::ResetContent();m_CheckStates.RemoveAll();m_ItemTexts.clear();
}void CCheckComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{if (lpDrawItemStruct->itemID == -1)return;CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);CRect rcItem = lpDrawItemStruct->rcItem;// 保存DC状态int nSavedDC = pDC->SaveDC();// 设置字体CFont* pOldFont = pDC->SelectObject(&m_font);// 绘制背景COLORREF crBackground, crText;if (lpDrawItemStruct->itemState & ODS_SELECTED){crBackground = ::GetSysColor(COLOR_HIGHLIGHT);crText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);}else{crBackground = ::GetSysColor(COLOR_WINDOW);crText = ::GetSysColor(COLOR_WINDOWTEXT);}pDC->FillSolidRect(rcItem, crBackground);pDC->SetTextColor(crText);pDC->SetBkColor(crBackground);// 绘制复选框CRect rcCheckBox = rcItem;rcCheckBox.right = rcCheckBox.left + 16;rcCheckBox.DeflateRect(2, (rcItem.Height() - 13) / 2, 2, (rcItem.Height() - 13) / 2);// 绘制复选框边框和背景pDC->DrawFrameControl(rcCheckBox, DFC_BUTTON, DFCS_BUTTONCHECK);// 如果选中,绘制勾号if (m_CheckStates[lpDrawItemStruct->itemID]){// 使用更粗的笔绘制勾号CPen pen(PS_SOLID, 2, RGB(0, 0, 0));CPen* pOldPen = pDC->SelectObject(&pen);// 绘制勾号pDC->MoveTo(rcCheckBox.left + 3, rcCheckBox.top + 6);pDC->LineTo(rcCheckBox.left + 6, rcCheckBox.top + 9);pDC->LineTo(rcCheckBox.left + 11, rcCheckBox.top + 4);pDC->SelectObject(pOldPen);}// 绘制文本 - 从自己的数组获取CString strText;strText = m_ItemTexts[lpDrawItemStruct->itemID];CRect rcText = rcItem;rcText.left += 20;  // 为复选框留出空间rcText.DeflateRect(2, 0);pDC->DrawText(strText, rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE);// 恢复DCpDC->SelectObject(pOldFont);pDC->RestoreDC(nSavedDC);
}void CCheckComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{lpMeasureItemStruct->itemHeight = m_nItemHeight;
}void CCheckComboBox::OnLButtonDown(UINT nFlags, CPoint point)
{// 只调用基类处理,让下拉列表正常显示// 实际的复选框点击在下拉列表的窗口过程中处理CComboBox::OnLButtonDown(nFlags, point);
}void CCheckComboBox::OnDropDown()
{m_bDropdown = TRUE;// 子类化下拉列表SubclassListBox();
}void CCheckComboBox::OnCloseUp()
{m_bDropdown = FALSE;// 取消子类化if (m_listBox.m_hWnd && m_pOldListBoxProc){m_listBox.UnsubclassWindow();m_listBox.Detach();}
}void CCheckComboBox::SubclassListBox()
{COMBOBOXINFO cbi = { sizeof(COMBOBOXINFO) };if (GetComboBoxInfo(&cbi)){if (cbi.hwndList != NULL && m_listBox.m_hWnd != cbi.hwndList){// 先取消之前的子类化if (m_listBox.m_hWnd && m_pOldListBoxProc){m_listBox.UnsubclassWindow();}// 重新子类化if (m_listBox.SubclassWindow(cbi.hwndList)){m_pOldListBoxProc = (WNDPROC)SetWindowLongPtr(cbi.hwndList, GWLP_WNDPROC, (LONG_PTR)ListBoxProc);SetWindowLongPtr(cbi.hwndList, GWLP_USERDATA, (LONG_PTR)this);}}}
}LRESULT CALLBACK CCheckComboBox::ListBoxProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{CCheckComboBox* pThis = (CCheckComboBox*)GetWindowLongPtr(hWnd, GWLP_USERDATA);if (pThis && message == WM_LBUTTONDOWN){CPoint point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));// 获取点击的项索引int nIndex = (int)::SendMessage(hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(point.x, point.y));if (nIndex >= 0 && nIndex < pThis->GetCount()){// 切换选中状态pThis->m_CheckStates[nIndex] = !pThis->m_CheckStates[nIndex];// 更新显示文本CString strText = pThis->GetCheckedItemsText();pThis->SetWindowText(strText);// 重绘组合框和下拉列表pThis->Invalidate();::InvalidateRect(hWnd, NULL, TRUE);// 发送自定义通知消息pThis->GetParent()->SendMessage(CCBN_CHECKCHANGE, (WPARAM)pThis->GetDlgCtrlID(), (LPARAM)pThis->m_hWnd);return 0; // 已处理,不传递给原窗口过程}}// 调用原窗口过程if (pThis && pThis->m_pOldListBoxProc){return CallWindowProc(pThis->m_pOldListBoxProc, hWnd, message, wParam, lParam);}return ::DefWindowProc(hWnd, message, wParam, lParam);
}CString CCheckComboBox::GetCheckedItemsText(LPCTSTR lpszDelimiter)
{CString strResult;for (int i = 0; i < m_ItemTexts.size(); i++){if (i < m_CheckStates.GetSize() && m_CheckStates[i]){CString strItem = m_ItemTexts[i];if (!strResult.IsEmpty())strResult += lpszDelimiter;strResult += strItem;}}if (strResult.IsEmpty())strResult = _T("请选择...");return strResult;
}void CCheckComboBox::GetCheckedIndices(CUIntArray& indices)
{indices.RemoveAll();for (int i = 0; i < GetCount(); i++){if (m_CheckStates[i])indices.Add(i);}
}

3、使用

    CCheckComboBox mCmbYAxis;afx_msg LRESULT OnCheckChange(WPARAM wParam, LPARAM lParam);  // 处理复选框改变通知ON_MESSAGE(CCBN_CHECKCHANGE, &DataBaseViewDlg::OnCheckChange)
// AddCheckString 使用示例
void cmbInit()
{mCmbYAxis.ResetContent();mCmbYAxis.AddCheckString(cstr, true);
.....}LRESULT dlg::OnCheckChange(WPARAM wParam, LPARAM lParam)
{   int nCmbId = (int)wParam;HWND hWndCtrl = (HWND)lParam;// 根据控件ID处理不同的组合框if (nCmbId == IDC_COMBOBOXEX_YAxis)  // 确保这个ID正确{// 获取选中的项文本CString strChecked = mCmbYAxis.GetCheckedItemsText();}return 0;
}

http://www.dtcms.com/a/606059.html

相关文章:

  • 门户网站开发价格郑州网站建设(智巢)
  • 主从服务器配置
  • 批量坐标转换(Excel版)
  • 在线C语言编译 | 简化开发流程,提升编程效率
  • 建筑企业网站源码免费创业平台
  • 基于Python野生植物识别应用模型的研究
  • BuildingAI技术架构文档
  • 网站技术支持衡水网站公司
  • 一站式做网站哪家专业wordpress保存远程图片
  • WPS Office v18.22.0 国际版
  • 基于Matlab的数字基带通信系统仿真与性能分析
  • Types of Attributes|属性类型
  • 哈尔滨php网站开发公司深圳做网站 肖先生
  • 户用光伏向阳台转移 阳台光伏开启能源新纪元
  • 11月13日numpy总结——花哨的索引
  • 云望物联无人机图传系统与通信技术的全面解析
  • Google政策大更新:涉及金融(个人贷款),社交约会与游戏(未成年人相关),健康等所有类别App
  • 网站开发建设方案公司介绍网页模板
  • Linux内存管理深度剖析:从处理文件映射页面的缺页异常到页面缓存的完整架构
  • 湖北网站建设哪家有宜昌市住房和城乡建设厅官方网站
  • AK/SK 利用与云平台接管工具
  • ClickHouse CPU 排查快速参考指南
  • ClickHouse CPU 排查详细指南
  • 苍穹外卖 —— Spring Task和WebSocket的运用以及订单统一处理、订单的提醒和催单功能的实现
  • 专门做搞笑视频的网站泉州哪个公司网站做的好
  • 用DeepSeek 编写的BFS python求解程序测试出来的几个难解数独
  • 台州汇客网站建设wordpress 网址导航页面
  • leetcode 3228. 将 1 移动到末尾的最大操作次数 中等
  • 做设计那些网站可以卖设计图包装袋设计网站推荐
  • 做网站语言中国十大门户类网站