更换CComboBox的属性

原文链接:http://www.codeproject.com/KB/combobox/recreatecombobox.aspx

这篇文章不错,担心以后被网站删除掉,难以看到,于是,放在这。以后自己查看也方便。呵呵

 

Dynamically re-creating a combo box

By Paul Vickery | 2 Aug 2002
Function to recreate a combo box at run-time to allow new styles, preserving its data

Introduction

Something which I frequently find myself needing to do is to switch a combo box to or from sorted. This is one reason (though not the main reason) I came up with my Dynamically Switchable Control. However, changing these styles after creation is something that combo-box does not support. This function presented here will recreate the combo box so that style changes take effect. The function will retain all list items, with item data, and the currently selected, or entered, text.

When the style is modified on a combobox to include or remove the CBS_SORT for example, it can be seen (by using GetStyle(), or using a tool such as Spy++) that the control does in fact have the new style, and yet the control's behaviour has not changed. The function here simply gets the current info from the control, i.e. styles, font etc, and recreates the control using these values.

How to use

I originally had a CComboBox-derived class which one member function to recreate the controls, but decided that this was more trouble than it was worth, as most of my combos derived from other things. Therefore I have presented this as a single function, which should be included in a global library file, so that you can invoke it on any combobox at any time.

In order to change the style of a combo, you should perform the usual method of setting the new style e.g.

Collapse | Copy Code
combo.ModifyStyle(0, CBS_SORT);

and then after that call you should call:

Collapse | Copy Code
RecreateComboBox(&combo)

The function takes an optional void pointer, lpParam, which is passed to CreateEx on recreating the control. If you have special requirements when creating your controls, and you normally pass in some data for the creation parameters, then you should pass the same info in here. Most developers can simply ignore this parameter.

The Function

The function to recreate the combo is below:

Collapse | Copy Code
// recreate the combo box by copying styles etc, and list items
// and applying them to a newly created control
BOOL RecreateComboBox(CComboBox* pCombo, LPVOID lpParam/*=0*/)
{
	if (pCombo == NULL)
		return FALSE;
	if (pCombo->GetSafeHwnd() == NULL)
		return FALSE;

	CWnd* pParent = pCombo->GetParent();
	if (pParent == NULL)
		return FALSE;

	// get current attributes
	DWORD dwStyle = pCombo->GetStyle();
	DWORD dwStyleEx = pCombo->GetExStyle();
	CRect rc;
	pCombo->GetDroppedControlRect(&rc);
	pParent->ScreenToClient(&rc);	// map to client co-ords
	UINT nID = pCombo->GetDlgCtrlID();
	CFont* pFont = pCombo->GetFont();
	CWnd* pWndAfter = pCombo->GetNextWindow(GW_HWNDPREV);

	// get the currently selected text (and whether it is a valid list selection)
	CString sCurText;
	int nCurSel = pCombo->GetCurSel();
	BOOL bItemSelValid = nCurSel != -1;
	if (bItemSelValid)
		pCombo->GetLBText(nCurSel, sCurText);
	else
		pCombo->GetWindowText(sCurText);

	// copy the combo box items into a temp combobox (not sorted)
	// along with each item's data
	CComboBox comboNew;
	if (! comboNew.CreateEx(dwStyleEx, _T("COMBOBOX"), _T(""), 
                                 dwStyle, rc, pParent, nID, lpParam))
	  return FALSE;
	comboNew.SetFont(pFont);
	int nNumItems = pCombo->GetCount();
	for (int n = 0; n < nNumItems; n++)
	{
		CString sText;
		pCombo->GetLBText(n, sText);
		int nNewIndex = comboNew.AddString(sText);
		comboNew.SetItemData(nNewIndex, pCombo->GetItemData(n));
	}
	// re-set selected text
	if (bItemSelValid)
		comboNew.SetCurSel(comboNew.FindStringExact(-1, sCurText));
	else
		comboNew.SetWindowText(sCurText);

	// destroy the existing window, then attach the new one
	pCombo->DestroyWindow();
	HWND hwnd = comboNew.Detach();
	pCombo->Attach(hwnd);

	// position correctly in z-order
	pCombo->SetWindowPos(pWndAfter == NULL ? 
                                &CWnd::wndBottom : 
                               pWndAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

	return TRUE;
}

History

  • Version 1 - 26 Jul 2002 - First version
  • Version 2 - 30 Jul 2002 - modified to include changes suggested by Jean-Michel LE FOL and Davide Zaccanti

<think>好的,用户让我介绍一下CComboBox,首先我需要确认这个术语的上下文。CComboBox常见于MFC(Microsoft Foundation Classes)库中,是MFC提供的一个组合框控件类。所以,我应该从MFC的角度来回答这个问题。 首先,我得解释CComboBox是什么,以及它的基本功能。组合框结合了编辑框和列表框,用户可以选择列表中的项或者直接输入。然后,需要提到CComboBox的继承关系,它继承自CWnd,这样用户知道它是窗口控件的一部分。 接下来,可能需要列出CComboBox的主要成员函数,比如AddString、InsertString这些用于添加项的方法,还有GetCurSel、SetCurSel用于获取和设置当前选择。DeleteString和ResetContent用于管理列表项。另外,像GetLBText这样的函数用来获取列表项的文本,这也是常用的操作。 然后,应该举一个简单的例子,展示如何在MFC对话框中创建和使用CComboBox。这里需要注意代码的结构,包括如何声明控件变量,如何在OnInitDialog中初始化,以及如何处理事件,比如CBN_SELCHANGE消息。同时,要说明如何添加项、设置默认选项等步骤。 在常见应用场景方面,需要提到配置选择、数据输入和动态内容更新这些情况。比如,用户选择国家、输入自定义值或者根据其他控件选择动态加载内容。 可能的问题点方面,内存泄漏需要注意,特别是在动态添加大量项时要及时清理。线程安全也是关键,因为MFC控件不是线程安全的,跨线程操作需要同步。还有资源管理,比如使用资源编辑器正确设置控件属性,避免显示问题。 最后,用户可能会混淆CComboBox和标准C++中的其他组合框实现,比如Qt的QComboBox,所以需要指出CComboBox属于MFC框架,适用于Windows桌面应用。 现在要检查是否有遗漏的部分,比如虚函数的使用?可能不需要,因为CComboBox是MFC封装的类,主要使用成员函数而不是继承多态。另外,是否需要提到消息映射?在示例代码中确实用到了ON_CBN_SELCHANGE,所以可以解释一下消息映射机制,但可能用户已经了解,所以示例中简要带过即可。 确保代码示例正确,比如使用Create方法创建控件,正确设置样式,如CBS_DROPDOWN。并且事件处理函数如OnComboSelChange需要正确绑定到消息。 最后,相关问题部分需要围绕MFC控件、组合框的使用、消息处理、资源管理等方面提问,帮助用户深入理解。</think><< `CComboBox`是MFC(Microsoft Foundation Classes)库中用于实现组合框控件的类,它继承自`CWnd`。组合框结合了编辑框和列表框的功能,允许用户从下拉列表中选择项或直接输入文本。以下是其核心功能及用法: ### 主要成员函数 1. **添加/删除项** - `AddString()`:添加字符串到列表末尾。 - `InsertString()`:在指定位置插入字符串。 - `DeleteString()`:删除指定位置的项。 - `ResetContent()`:清空所有项。 2. **获取/设置选中项** - `GetCurSel()`:获取当前选中项的索引。 - `SetCurSel()`:设置选中项。 - `GetLBText()`:获取指定索引项的文本。 3. **控件操作** - `ShowDropDown()`:强制显示或隐藏下拉列表。 - `GetDroppedState()`:检查下拉列表是否可见。 ### 示例代码(MFC对话框中使用) ```cpp // 在对话框类头文件中声明控件变量 class CMyDialog : public CDialogEx { DECLARE_MESSAGE_MAP() public: CComboBox m_comboBox; afx_msg void OnComboSelChange(); }; // 对话框初始化时添加项 BOOL CMyDialog::OnInitDialog() { CDialogEx::OnInitDialog(); m_comboBox.AddString(_T("Item 1")); m_comboBox.AddString(_T("Item 2")); m_comboBox.SetCurSel(0); // 默认选中第一项 return TRUE; } // 绑定消息处理(.cpp文件中) BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx) ON_CBN_SELCHANGE(IDC_COMBO1, &CMyDialog::OnComboSelChange) END_MESSAGE_MAP() // 选中项变化时的处理 void CMyDialog::OnComboSelChange() { int index = m_comboBox.GetCurSel(); CString str; m_comboBox.GetLBText(index, str); MessageBox(str, _T("Selected Item")); } ``` ### 常见应用场景 1. **配置选择**:如选择语言、国家等固定选项。 2. **动态输入**:允许用户输入自定义值(需设置`CBS_DROPDOWN`样式)。 3. **级联更新**:根据其他控件的选择动态更新内容。 ### 问题与注意事项 1. **内存泄漏**:动态添加大量项时,需及时调用`ResetContent()`清理。 2. **线程安全**:MFC控件非线程安全,跨线程操作需通过`PostMessage`同步。 3. **样式设置**:需在资源编辑器中正确设置`Dropdown`/`Drop List`等样式,否则可能无法正常显示。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值