Getting ComboBox Strings to Appear with an ATL Project

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:

LRESULT CMyDialog::OnInitDialog(UINT uMsg, WPARAM
wParam, LPARAM lParam, BOOL& bHandled)
{
 ExecuteDlgInit( m_hWnd, MAKEINTRESOURCE(IDD) );
 return 1;
}
Add this as a file in your project.
#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;
}


Comments

  • Adding string is no problem

    Posted by Legacy on 03/21/2002 12:00am

    Originally posted by: Brian van der Beek

    Addstring does work for ComboBoxes in ActiveX components. However If you attach a ComboBoxEx to a CComboBox that you might run in these kinds of problems.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Ever-increasing workloads and the challenge of containing costs leave companies conflicted by the need for increased processing capacity while limiting physical expansion. Migration to HP's new generation of increased-density rack-and-blade servers can address growing demands for compute capacity while reducing costly sprawl. Sponsored by: HP and Intel® Xeon® processors Intel, the Intel logo, and Xeon Inside are trademarks of Intel Corporation in the U.S. and/or other countries. HP is the sponsor …

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds