我试图将具有成员变量CString的对象添加到CCombobox。我不能仅仅添加字符串,因为我试图与一个工具连接,该工具需要我在CComboBox中将另一个成员变量而不只是字符串作为列表项。以下是我正在尝试做的事情。

CComboBox::AddString(myOwnObject);

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

最佳答案

CComboBox Class包装了本地Combo Box控件。这是一个非常基本的实现,可以满足最常见的用例:显示字符串供用户选择。

如果需要其他功能,可以改用CComboBoxEx Class。它公开了基础ComboBoxEx控件的完整操作集。特别地,可以将项目配置为基于任意信息在运行时检索项目的字符串表示形式。

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

struct CustomItemData {
    CStringW m_Name;
    int m_SomeInteger;
};

商品数据可以任意复杂,并且可以保存您要存储的任何信息。用项填充CComboBoxEx要求调用CComboBoxEx::InsertItem,并传递适当填充的COMBOBOXEXITEM structure:
// 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: Message Reflection for Windows Controls)。这允许父窗口将通知消息反射(reflect)回各自的子控件以进行处理。有时它可能很有用,但不需要实现该问题的解决方案。

如果不需要在运行时完全控制构造显示字符串,则可以使用简单的CComboBox控件,并附加称为CComboBox::SetItemDataCComboBox::SetItemDataPtr的其他信息,如πάντα ῥεῖ's answer所示。

10-08 11:40