最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

带复选框的下拉列表

来源:动视网 责编:小OO 时间:2025-09-27 06:18:48
文档

带复选框的下拉列表

用自定义的‍CCheckComboBox类做带复选框的下拉列表1、添加ComboBox控件2.、改属性Style:DropList  ; OwnerDraw:Fixed; Hasstring:true;Sort:false3、头文件中添加:     CCheckComboBoxm_comboBox;4、DoDataExchange(CDataExchange*pDX)中添加:    DDX_Control(pDX,IDC_COMBO1,m_comboBox);5、对话框初始化时添加   m_c
推荐度:
导读用自定义的‍CCheckComboBox类做带复选框的下拉列表1、添加ComboBox控件2.、改属性Style:DropList  ; OwnerDraw:Fixed; Hasstring:true;Sort:false3、头文件中添加:     CCheckComboBoxm_comboBox;4、DoDataExchange(CDataExchange*pDX)中添加:    DDX_Control(pDX,IDC_COMBO1,m_comboBox);5、对话框初始化时添加   m_c
用自定义的‍CCheckComboBox类做带复选框的下拉列表

1、添加Combo Box控件

2.、改属性Style:DropList  ; Owner Draw:Fixed ; Has string:true ;Sort:false

3、头文件中添加:

     CCheckComboBox m_comboBox;

4、DoDataExchange(CDataExchange* pDX)中添加:

     DDX_Control(pDX, IDC_COMBO1, m_comboBox);

5、对话框初始化时添加

    m_comboBox.AddString(_T("1"));//加入项目

    m_comboBox.AddString(_T("2"));

    m_comboBox.AddString(_T("3"));

    m_comboBox.AddString(_T("4"));

    m_comboBox.SetCheck(0, TRUE);//设置选择状态

    m_comboBox.SetCheck(1, FALSE);

    m_comboBox.SetCheck(2, TRUE);

    m_comboBox.SetCheck(3, TRUE);

    ‍‍‍

#if !defined(AFX_CHECKCOMBOBOX_H__66750D93_95DB_11D3_9325_444553540000__INCLUDED_)

#define AFX_CHECKCOMBOBOX_H__66750D93_95DB_11D3_9325_444553540000__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

class CCheckComboBox : public CComboBox

{

public:

CCheckComboBox();

virtual ~CCheckComboBox();

BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);

// Selects all/unselects the specified item

INT SetCheck(INT nIndex, BOOL bFlag);

// Returns checked state

BOOL GetCheck(INT nIndex);

// Selects all/unselects all

void SelectAll(BOOL bCheck = TRUE);

protected:

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CCheckComboBox)

protected:

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);

//}}AFX_VIRTUAL

//{{AFX_MSG(CCheckComboBox)

afx_msg LRESULT OnCtlColorListBox(WPARAM wParam, LPARAM lParam);

afx_msg LRESULT OnGetText(WPARAM wParam, LPARAM lParam);

afx_msg LRESULT OnGetTextLength(WPARAM wParam, LPARAM lParam);

afx_msg void OnDropDown();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

public:

   CString m_strText;

protected:

// Routine to update the text

void RecalcText();

// The subclassed COMBOLBOX window (notice the 'L')

HWND m_hListBox;

// The string containing the text to display

BOOL m_bTextUpdated;

// A flag used in MeasureItem, see comments there

BOOL m_bItemHeightSet;

};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_CHECKCOMBOBOX_H__66750D93_95DB_11D3_9325_444553540000__INCLUDED_)

 

/**  CheckComboBox.cpp  **/

// CheckComboBox.cpp 

//

// Written by Magnus Egelberg (magnus.egelberg@lundalogik.se)

//

// Copyright (C) 1999, Lundalogik AB, Sweden. All rights reserved.

// 

//

#include "stdafx.h"

// #include "CheckCombo.h"

#include "CheckComboBox.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

static WNDPROC m_pWndProc = 0;

static CCheckComboBox *m_pComboBox = 0;

BEGIN_MESSAGE_MAP(CCheckComboBox, CComboBox)

//{{AFX_MSG_MAP(CCheckComboBox)

ON_MESSAGE(WM_CTLCOLORLISTBOX, OnCtlColorListBox)

ON_MESSAGE(WM_GETTEXT, OnGetText)

ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLength)

ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropDown)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

//

// The subclassed COMBOLBOX message handler

//

extern "C" LRESULT FAR PASCAL ComboBoxListBoxProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)

{

switch (nMsg) {

  

   case WM_RBUTTONDOWN: {

    // If you want to select all/unselect all using the

    // right button, remove this ifdef. Personally, I don't really like it

    #if FALSE

     if (m_pComboBox != 0) {

      INT nCount = m_pComboBox->GetCount();

      INT nSelCount = 0;

      for (INT i = 0; i < nCount; i++) {

       if (m_pComboBox->GetCheck(i))

        nSelCount++;

      }

      m_pComboBox->SelectAll(nSelCount != nCount);

      // Make sure to invalidate this window as well

      InvalidateRect(hWnd, 0, FALSE);

      m_pComboBox->GetParent()->SendMessage(WM_COMMAND, MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd);

     }

    #endif

    break;

   }

   // Make the combobox always return -1 as the current selection. This

   // causes the lpDrawItemStruct->itemID in DrawItem() to be -1

   // when the always-visible-portion of the combo is drawn

   case LB_GETCURSEL: {

    return -1;

   }

   case WM_CHAR: {

    if (wParam == VK_SPACE) {

     // Get the current selection

     INT nIndex = CallWindowProcA(m_pWndProc, hWnd, LB_GETCURSEL, wParam, lParam);

     CRect rcItem;

     SendMessage(hWnd, LB_GETITEMRECT, nIndex, (LONG)(VOID *)&rcItem);

     InvalidateRect(hWnd, rcItem, FALSE);

     // Invert the check mark

     m_pComboBox->SetCheck(nIndex, !m_pComboBox->GetCheck(nIndex));

     // Notify that selection has changed

     m_pComboBox->GetParent()->SendMessage(WM_COMMAND, MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd);

     return 0;

    }

    break;

   }

   case WM_LBUTTONDOWN: {

    CRect rcClient;

    GetClientRect(hWnd, rcClient);

    CPoint pt;

    pt.x = LOWORD(lParam);

    pt.y = HIWORD(lParam);

    if (PtInRect(rcClient, pt)) {

     INT nItemHeight = SendMessage(hWnd, LB_GETITEMHEIGHT, 0, 0);

     INT nTopIndex   = SendMessage(hWnd, LB_GETTOPINDEX, 0, 0);

     // Compute which index to check/uncheck

     INT nIndex = nTopIndex + pt.y / nItemHeight;

     CRect rcItem;

     SendMessage(hWnd, LB_GETITEMRECT, nIndex, (LONG)(VOID *)&rcItem);

     if (PtInRect(rcItem, pt)) {

      // Invalidate this window

      InvalidateRect(hWnd, rcItem, FALSE);

      m_pComboBox->SetCheck(nIndex, !m_pComboBox->GetCheck(nIndex));

      // Notify that selection has changed

      m_pComboBox->GetParent()->SendMessage(WM_COMMAND, MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd);

     }

    }

    // Do the default handling now (such as close the popup

    // window when clicked outside)

    break;

   }

   case WM_LBUTTONUP: {

    // Don't do anything here. This causes the combobox popup

    // windows to remain open after a selection has been made

    return 0;

   }

}

return CallWindowProc(m_pWndProc, hWnd, nMsg, wParam, lParam);

}

 

CCheckComboBox::CCheckComboBox()

{

m_hListBox       = 0;

m_bTextUpdated   = FALSE;

m_bItemHeightSet = FALSE;

}

CCheckComboBox::~CCheckComboBox()

{

}

BOOL CCheckComboBox::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)

{

// Remove the CBS_SIMPLE and CBS_DROPDOWN styles and add the one I'm designed for

dwStyle &= ~0xF;

dwStyle |= CBS_DROPDOWNLIST;

// Make sure to use the CBS_OWNERDRAWVARIABLE style

dwStyle |= CBS_OWNERDRAWVARIABLE;

// Use default strings. We need the itemdata to store checkmarks

dwStyle |= CBS_HASSTRINGS;

return CComboBox::Create(dwStyle, rect, pParentWnd, nID);

}

LRESULT CCheckComboBox::OnCtlColorListBox(WPARAM wParam, LPARAM lParam) 

{

// If the listbox hasn't been subclassed yet, do so...

if (m_hListBox == 0) {

   HWND hWnd = (HWND)lParam;

   if (hWnd != 0 && hWnd != m_hWnd) {

    // Save the listbox handle

    m_hListBox = hWnd;

    // Do the subclassing

    m_pWndProc = (WNDPROC)GetWindowLong(m_hListBox, GWL_WNDPROC);

    SetWindowLong(m_hListBox, GWL_WNDPROC, (LONG)ComboBoxListBoxProc);

   }

}

return DefWindowProc(WM_CTLCOLORLISTBOX, wParam, lParam);

}

void CCheckComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 

{

HDC dc = lpDrawItemStruct->hDC;

CRect rcBitmap = lpDrawItemStruct->rcItem;

CRect rcText   = lpDrawItemStruct->rcItem;

CString strText;

// 0 - No check, 1 - Empty check, 2 - Checked

INT nCheck = 0;

// Check if we are drawing the static portion of the combobox

if ((LONG)lpDrawItemStruct->itemID < 0) {

   // Make sure the m_strText member is updated

   RecalcText();

   // Get the text

   strText = m_strText;

   // Don't draw any boxes on this item

   nCheck = 0;

}

// Otherwise it is one of the items

else {

   GetLBText(lpDrawItemStruct->itemID, strText);

   nCheck = 1 + (GetItemData(lpDrawItemStruct->itemID) != 0);

   TEXTMETRIC metrics;

   GetTextMetrics(dc, &metrics);

   rcBitmap.left    = 0;

   rcBitmap.right   = rcBitmap.left + metrics.tmHeight + metrics.tmExternalLeading + 6;

   rcBitmap.top    += 1;

   rcBitmap.bottom -= 1;

   rcText.left = rcBitmap.right;

}

 

if (nCheck > 0) {

   SetBkColor(dc, GetSysColor(COLOR_WINDOW));

   SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));

   UINT nState = DFCS_BUTTONCHECK;

   if (nCheck > 1)

    nState |= DFCS_CHECKED;

   // Draw the checkmark using DrawFrameControl

   DrawFrameControl(dc, rcBitmap, DFC_BUTTON, nState);

}

if (lpDrawItemStruct->itemState & ODS_SELECTED) {

   SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));

   SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));

}

else {

   SetBkColor(dc, GetSysColor(COLOR_WINDOW));

   SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));

}

// Erase and draw

ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rcText, 0, 0, 0);

DrawText(dc, ' ' + strText, strText.GetLength() + 1, &rcText, DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS);

if ((lpDrawItemStruct->itemState & (ODS_FOCUS|ODS_SELECTED)) == (ODS_FOCUS|ODS_SELECTED))

   DrawFocusRect(dc, &rcText);

}

void CCheckComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) 

{

CClientDC dc(this);

CFont *pFont = dc.SelectObject(GetFont());

if (pFont != 0) {

   TEXTMETRIC metrics;

   dc.GetTextMetrics(&metrics);

   lpMeasureItemStruct->itemHeight = metrics.tmHeight + metrics.tmExternalLeading;

   // An extra height of 2 looks good I think. 

   // Otherwise the list looks a bit crowded...

   lpMeasureItemStruct->itemHeight += 2;

   // This is needed since the WM_MEASUREITEM message is sent before

   // MFC hooks everything up if used in i dialog. So adjust the

   // static portion of the combo box now

   if (!m_bItemHeightSet) {

    m_bItemHeightSet = TRUE;

    SetItemHeight(-1, lpMeasureItemStruct->itemHeight);

   }

   dc.SelectObject(pFont);

}

}

//

// Make sure the combobox window handle is updated since

// there may be many CCheckComboBox windows active

//

void CCheckComboBox::OnDropDown() 

{

m_pComboBox = this;

}

//

// Selects/unselects all items in the list

//

void CCheckComboBox::SelectAll(BOOL bCheck)

{

INT nCount = GetCount();

for (INT i = 0; i < nCount; i++)

   SetCheck(i, bCheck);

}

//

// By adding this message handler, we may use CWnd::GetText()

//

LRESULT CCheckComboBox::OnGetText(WPARAM wParam, LPARAM lParam)

{

// Make sure the text is updated

RecalcText();

if (lParam == 0)

   return 0;

// Copy the 'fake' window text

lstrcpyn((LPWSTR)lParam, m_strText, (INT)wParam);

return m_strText.GetLength();

}

//

// By adding this message handler, we may use CWnd::GetTextLength()

//

LRESULT CCheckComboBox::OnGetTextLength(WPARAM, LPARAM)

{

// Make sure the text is updated

RecalcText();

return m_strText.GetLength();

}

//

// This routine steps thru all the items and builds

// a string containing the checked items

//

void CCheckComboBox::RecalcText()

{

if (!m_bTextUpdated) {

   CString strText;

  

   // Get the list count

   INT nCount    = GetCount();

   // Get the list separator

   TCHAR szBuffer[10] = {0};

   GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, szBuffer, sizeof(szBuffer));

   CString strSeparator = szBuffer;

   // If none found, the the ';'

   if (strSeparator.GetLength() == 0)

    strSeparator = ';';

   // Trim extra spaces

   strSeparator.TrimRight();

   // And one...

   strSeparator += ' ';

   for (INT i = 0; i < nCount; i++) {

    if (GetItemData(i)) {

     CString strItem;

     GetLBText(i, strItem);

     if (!strText.IsEmpty())

      strText += strSeparator;

     strText += strItem;

    }

   }

   // Set the text

   m_strText = strText;

   m_bTextUpdated = TRUE;

}

}

INT CCheckComboBox::SetCheck(INT nIndex, BOOL bFlag)

{

INT nResult = SetItemData(nIndex, bFlag);

if (nResult < 0)

   return nResult;

// Signal that the text need updating

m_bTextUpdated = FALSE;

// Redraw the window

Invalidate(FALSE);

return nResult;

}

BOOL CCheckComboBox::GetCheck(INT nIndex)

{

return GetItemData(nIndex);

}

文档

带复选框的下拉列表

用自定义的‍CCheckComboBox类做带复选框的下拉列表1、添加ComboBox控件2.、改属性Style:DropList  ; OwnerDraw:Fixed; Hasstring:true;Sort:false3、头文件中添加:     CCheckComboBoxm_comboBox;4、DoDataExchange(CDataExchange*pDX)中添加:    DDX_Control(pDX,IDC_COMBO1,m_comboBox);5、对话框初始化时添加   m_c
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top