У меня было частичное решение этой проблемы, но, используя предложение @taspeotis, я написал это, что, похоже, работает довольно хорошо.
template <class T>
void DDX_CBData(CDataExchange* pDX, int nIDC, T& data)
{
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
if (pDX->m_bSaveAndValidate)
{
int index = static_cast<int>(::SendMessage(hWndCtrl, CB_GETCURSEL, 0, 0L));
data = (index == CB_ERR ? NULL : reinterpret_cast<T>(::SendMessage(hWndCtrl, CB_GETITEMDATA, index, 0L)));
}
else
{
int count = static_cast<int>(::SendMessage(hWndCtrl, CB_GETCOUNT, 0, 0L));
for (int i = 0; i != count; ++i)
{
if (reinterpret_cast<T>(::SendMessage(hWndCtrl, CB_GETITEMDATA, i, 0L)) == data)
{
::SendMessage(hWndCtrl, CB_SETCURSEL, i, 0L);
return;
}
}
::SendMessage(hWndCtrl, CB_SETCURSEL, -1, 0L);
}
}