1

我正在尝试将具有成员变量的对象添加CStringCCombobox. 我不能只添加字符串,因为我正在尝试与一个工具交互,该工具要求我拥有另一个成员变量,而不仅仅是一个字符串作为CComboBox. 以下是我正在尝试做的事情。

CComboBox::AddString(myOwnObject);

我只希望显示的字符串myOwnObject,但要显示整个对象在列表框中,以便其他工具可以访问其他成员变量。

4

2 回答 2

3

CComboBox 类包装了本机组合控件。这是一个相当基本的实现,可以满足最常见的用例:显示字符串供用户选择。

如果您需要其他功能,则可以改用CComboBoxEx 类它公开了底层ComboBoxEx控件的全套操作。特别是,项目可以配置为在运行时根据任意信息检索项目的字符串表示。

以下假设,您的自定义项目数据布局如下:

struct CustomItemData {
    CStringW m_Name;
    int m_SomeInteger;
};

项目数据可以任意复杂,并包含您希望存储的任何信息。使用项目填充aCComboBoxEx需要调用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_GETDISPINFO被发送到父控件因此必须将通知处理程序放置到父窗口(通常是对话框)实现中处理程序使用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::SetItemDataCComboBox::SetItemDataPtr的附加信息,如πάντα ῥεῖ 的答案所示。

于 2015-05-30T16:58:03.803 回答
1

“我认为需要做的是覆盖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)
}
于 2015-05-29T16:22:47.537 回答