我正在尝试添加一个具有成员变量CString
到CCombobox
的对象。我不能只是添加字符串,因为我正试图与一个工具接口,要求我有另一个成员变量,而不仅仅是一个字符串作为CComboBox
中的列表项。下面是我要做的。
CComboBox::AddString(myOwnObject);
我只想显示myOwnObject
的字符串,但对于整个对象在列表框中,以便其他工具可以到达其他成员变量。
CComboBox类包装了一个本地组合框控件。这是一个相当基本的实现,可以满足最常见的用例:显示供用户选择的字符串。
如果您需要额外的功能,您可以使用CComboBoxEx类代替。它公开底层ComboBoxEx控件的全部操作。特别是,可以将项目配置为在运行时基于任意信息检索项目的字符串表示形式。
下面假设您的自定义项数据布局如下:
struct CustomItemData {
CStringW m_Name;
int m_SomeInteger;
};
项目数据可以任意复杂,并包含您希望存储的任何信息。用项填充CComboBoxEx
需要调用CComboBoxEx::InsertItem,传递一个适当填充的COMBOBOXEXITEM结构:
// CustomItemData's lifetime must exceed that of the CComboBoxEx; don't use a
// stack-based (automatic) variable.
CustomItemData* pcid = new CustomItemData( myName, myInteger );
CCOMBOBOXEXITEM cbei = { 0 };
cbei.mask = CBEIF_TEXT | CBEIF_LPARAM;
cbei.iItem = currentIndex; // The zero-based index of the item.
cbei.pszText = LPSTR_TEXTCALLBACK; // The control will request the information by using
// the CBEN_GETDISPINFO notification codes.
cbei.lParam = reinterpret_cast<LPARAM>( pcid ); // Assign custom data to item.
myComboBox.InsertItem( &cbei );
此时,ComboBox控件已填充了项目,并将从应用程序请求显示信息。cben_getdisinfo被发送到控件父控件,因此通知处理程序必须被放置到父控件的窗口(通常是一个对话框)实现中。处理程序使用ON_NOTIFY宏连接到通知消息:
// Inside the parent's message map:
ON_NOTIFY( CBEN_GETDISPINFO, IDC_MY_COMBOBOX, GetCBDispString )
// Message handler inside the parent's class
void CMyDlg::GetCBDispString( NMHDR* pNMHDR, LRESULT* pResult ) {
NMCOMBOBOXEX* pncbe = reinterpret_cast<NMCOMBOBOXEX*>( pNMHDR );
COMBOBOXEXITEM& cbei = pncbe->ceItem;
if ( cbei.mask & CBEIF_TEXT ) {
// Text is requested -> fill the appropriate buffer.
const CustomItemData& cd = *reinterpret_cast<const CustomItemData*>( cbei.lParam );
wcscpy( cbei.pszText, cd.m_Name );
// Prevent future callbacks for this item. This is an optional optimization
// and can be used, if the m_Name member doesn't change.
cbei |= CBEIF_DI_SETITEM;
}
// Mark notification as handled
*pResult = 0;
}
有时需要将
CBEN_GETDISPINFO
回调放在自定义的ComboBox实现中。MFC提供必要的基础设施来实现消息反射(参见TN062: Windows控件的消息反射)。这允许父窗口将通知消息反射回相应的子控件进行处理。它有时是有用的,但不是实现这个问题的解决方案所必需的。如果您不需要在运行时完全控制构造显示字符串,您可以使用一个简单的
CComboBox
控件,并调用CComboBox::SetItemData或CComboBox::SetItemDataPtr附加额外的信息,如π α ντα ρ ε ε ε的答案所示。"我认为需要做的是重写
CComboBox::AddString
"
不,正好相反,你不能重写 CComboBox::AddString
,但是要实现其他对象类型以具有适当的转换操作符:
operator const CString& () const { return myCStringMember; }
您可能还想使用CComboBox::SetItemData()
函数来存储相关类实例的this
指针。
您可以使用' CComboBox::AddString() '的返回值,以获得调用
所需的索引int SetItemData(
int nIndex, // <<< Fill in result of AddString
DWORD_PTR dwItemData
);
应该看起来像这样(假设您已经实现了如上所述的转换操作符):
MyOwnObject myOwnObject("MyOwnObject1");
int newItemIndex = comboBox.AddString(myOwnObject);
if(newItemIndex > 0) {
comboBox.SetItemData(newItemIndex,(DWORD_PTR)&myOwnObject)
}