Есть ли способ добавить объект, кроме CString в CComboBox в MFC?

Я пытаюсь добавить объект, который имеет переменную-член CString к CCombobox, Я не могу просто добавить строку, потому что я пытаюсь взаимодействовать с инструментом, который требует, чтобы у меня была другая переменная-член, отличная от строки в качестве элемента списка в CComboBox, Ниже то, что я пытаюсь сделать.

CComboBox::AddString(myOwnObject);

Я хочу только строку myOwnObject отображать, но чтобы весь объект находился в списке, чтобы другая переменная-член была доступна другому инструменту.

1

Решение

Класс 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_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 :: SetItemData или же CComboBox :: SetItemDataPtr, как показано на πάντα ῥεῖ ответ.

3

Другие решения

«Я думаю, что нужно сделать, это переопределить 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)
}
0