There is a bug in ATL when creating a dialog resource with a combobox that contains string initialization data. The problem is the strings do not appear in the combobox at runtime, but work in dialog test mode. This problem does not appear with MFC, because MFC recognizes this as a problem and fixes it the call to OnInitDialog in the function ExecuteDlgInit. The basic problem lies in combobox resource data being initialized with old message IDs. The code below fixes this problem if called from your WM_INITDIALOG function. This code was hoisted from the MFC source files and is changed to be ATL friendly.
Place in your dialogbox code:
Add this as a file in your project.
LRESULT CMyDialog::OnInitDialog(UINT uMsg, WPARAM
wParam, LPARAM lParam, BOOL& bHandled)
{
ExecuteDlgInit( m_hWnd, MAKEINTRESOURCE(IDD) );
return 1;
}
#include "stdafx.h"
#include
#include
#include "DoDlgInit.h"
BOOL ExecuteDlgInit(HWND hwndDlg, LPVOID lpResource);
BOOL ExecuteDlgInit(HWND hwndDlg, LPCTSTR lpszResourceName)
{
// find resource handle
LPVOID lpResource = NULL;
HGLOBAL hResource = NULL;
if (lpszResourceName != NULL)
{
HRSRC hDlgInit =
::FindResource(_Module.m_hInstResource,
lpszResourceName, _ATL_RT_DLGINIT);
if (hDlgInit != NULL)
{
// load it
hResource = LoadResource(_Module.m_hInstResource, hDlgInit);
if (hResource == NULL)
return FALSE;
// lock it
lpResource = LockResource(hResource);
_ASSERT(lpResource != NULL);
}
}
// execute it
BOOL bResult = ExecuteDlgInit(hwndDlg, lpResource);
// cleanup
if (lpResource != NULL && hResource != NULL)
{
UnlockResource(hResource);
FreeResource(hResource);
}
return bResult;
}
BOOL ExecuteDlgInit(HWND hwndDlg, LPVOID lpResource)
{
BOOL bSuccess = TRUE;
if (lpResource != NULL)
{
UNALIGNED WORD* lpnRes = (WORD*)lpResource;
while (bSuccess && *lpnRes != 0)
{
WORD nIDC = *lpnRes++;
WORD nMsg = *lpnRes++;
DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
// In Win32 the WM_ messages have changed. They have
// to be translated from the 32-bit values to 16-bit
// values here.
#define WIN16_LB_ADDSTRING 0x0401
#define WIN16_CB_ADDSTRING 0x0403
#define AFX_CB_ADDSTRING 0x1234
// unfortunately, WIN16_CB_ADDSTRING == CBEM_INSERTITEM
if (nMsg == AFX_CB_ADDSTRING)
nMsg = CBEM_INSERTITEM;
else if (nMsg == WIN16_LB_ADDSTRING)
nMsg = LB_ADDSTRING;
else if (nMsg == WIN16_CB_ADDSTRING)
nMsg = CB_ADDSTRING;
#ifdef _DEBUG
// For AddStrings, the count must exactly delimit the
// string, including the NULL termination. This check
// will not catch all mal-formed ADDSTRINGs, but will
// catch some.
if (nMsg == LB_ADDSTRING
|| nMsg == CB_ADDSTRING
|| nMsg == CBEM_INSERTITEM)
_ASSERT(*((LPBYTE)lpnRes + (UINT)dwLen - 1) == 0);
#endif
if (nMsg == CBEM_INSERTITEM)
{
USES_CONVERSION;
COMBOBOXEXITEM item;
item.mask = CBEIF_TEXT;
item.iItem = -1;
item.pszText = A2T(LPSTR(lpnRes));
if (::SendDlgItemMessage(hwndDlg, nIDC, nMsg, 0, (LPARAM) &item)
== -1)
bSuccess = FALSE;
}
else if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING)
{
// List/Combobox returns -1 for error
if (::SendDlgItemMessageA(hwndDlg, nIDC, nMsg, 0, (LPARAM) lpnRes)
== -1)
bSuccess = FALSE;
}
// skip past data
lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
}
}
// send update message to all controls after all other siblings loaded
// if (bSuccess)
// SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, FALSE, FALSE);
return bSuccess;
}