DOCERR: Incorrect DialogBoxIndirect() Code in Win32 SDK Docs

ID: Q140725


The information in this article applies to:


SUMMARY

The Win32 SDK documentation demonstrates how to create a template in memory for a modal dialog box by using DialogBoxIndirect() in a section called "Creating a Template in Memory." The code included in this section of the documentation has problems in Windows 95 and Windows NT version 3.51, which may cause the dialog box to come up with only one control or may cause DialogBoxIndirect() to return -1, indicating failure.

The same problems occur if the call to DialogBoxIndirect() is replaced with CreateDialogIndirect().

NOTE: This docerr is fixed in Windows NT version 4.0 beta documents.


MORE INFORMATION

There are four problems with the DialogBoxIndirect() code. The corrected code appears at the end of this article.

  1. The code was intended to bring up a modal dialog box that contains a static control (an OK button) and a Help button. However, because of two conflicting lines of code that were supposed to set the DLGTEMPLATE struct's cdit member to the number of controls in the dialog box, the system is made to think there is only one control in the dialog.
    
          lpdt->cdit = 3;  // number of controls
          lpdt->cdit = 1; 

    As is, the code works when pasted into an application, although the dialog box comes up with only the OK button and the other two controls are not shown. The second line should be removed because the dialog box actually contains three controls, not one. However, doing this while leaving the rest of the code as is causes no dialog box to come up and DialogBoxIndirect() returns -1 as a result of two other problems described in this article.


  2. The DLGTEMPLATE structure passed to the DialogBoxIndirect or CreateDialogIndirect() functions is followed by one or more DLGITEMTEMPLATE structures. These DLGITEMTEMPLATE structures need to be DWORD aligned. Calling the following lpwAlign() function will do just that:
    
          /*
             Helper routine.  Take an input pointer, return closest
             pointer that is aligned on a DWORD (4 byte) boundary.
          */ 
          LPWORD lpwAlign ( LPWORD lpIn)
          {
             ULONG ul;
    
             ul = (ULONG) lpIn;
             ul +=3;
             ul >>=2;
             ul <<=2;
             return (LPWORD) ul;
          } 


  3. The help button and the static control have identical (x,y) coordinates as well as width and height (cx,cy):

    
          lpdit-&gt;x  = 55; lpdit-&gt;y  = 10;
          lpdit-&gt;cx = 40; lpdit-&gt;cy = 20; 
    This causes the static control to overlap the help button. You need to adjust these values accordingly so that they both show up in the dialog box. The following code shows how the modified code looks like so far. Note the calls to the lpwAlign function each time a DLGITEMTEMPLATE structure is added. This works fine in Windows NT version 3.51.

    
          #define ID_HELP   150
          #define ID_TEXT   200
          LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner,
             LPSTR lpszMessage)
          {
    
           HGLOBAL hgbl;
           LPDLGTEMPLATE lpdt;
           LPDLGITEMTEMPLATE lpdit;
           LPWORD lpw;
           LPWSTR lpwsz;
           LRESULT ret;
    
           hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
           if (!hgbl)
               return -1;
    
           lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
    
           // Define a dialog box.
    
           lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
                       | DS_MODALFRAME | WS_CAPTION;
           lpdt->cdit = 3;  // number of controls
       //  lpdt->cdit = 1;  // COMMENTED OUT -- unnecessary code
    
           lpdt->x  = 10;  lpdt->y  = 10;
           lpdt->cx = 100; lpdt->cy = 100;
    
           lpw = (LPWORD) (lpdt + 1);
           *lpw++ = 0;   // no menu
           *lpw++ = 0;   // predefined dialog box class (by default)
    
           lpwsz = (LPWSTR) lpw;
           lstrcpyW(lpwsz, L"My Message");  // dialog title (Unicode)
           lpw = (LPWORD) (lpwsz + lstrlenW(lpwsz) + 1);
    
           //-----------------------
           // Define an OK button.
           //-----------------------
           lpw = lpwAlign (lpw);
           lpdit = (LPDLGITEMTEMPLATE) lpw;
           lpdit->x  = 10; lpdit->y  = 70;
           lpdit->cx = 80; lpdit->cy = 20;
           lpdit->id = IDOK;  // OK button identifier
           lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
    
           lpw = (LPWORD) (lpdit + 1);
           *lpw++ = 0xFFFF;
           *lpw++ = 0x0080;    // button class
    
           lpwsz = (LPWSTR) lpw;
           lstrcpyW(lpwsz, L"OK");  // button label (Unicode)
           lpw = (LPWORD) (lpwsz + lstrlenW(lpwsz) + 1);
           *lpw++ = 0;              // no creation data
    
           //-----------------------
           // Define a Help button.
           //-----------------------
           lpw = lpwAlign (lpw);
    
           lpdit = (LPDLGITEMTEMPLATE) lpw;
           lpdit->x  = 55; lpdit->y  = 10;
           lpdit->cx = 40; lpdit->cy = 20;
           lpdit->id = ID_HELP;    // Help button identifier
           lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
    
           lpw = (LPWORD) (lpdit + 1);
           *lpw++ = 0xFFFF;
           *lpw++ = 0x0080;                 // button class atom
           lpwsz = (LPWSTR) lpw;
           lstrcpyW(lpwsz, L"Help");        // button label (Unicode)
           lpw = (LPWORD) (lpwsz + lstrlenW(lpwsz) + 1);
           *lpw++ = 0;                      // no creation data
    
           //-----------------------
           // Define a static text control.
           //-----------------------
           lpw = lpwAlign (lpw);
    
           lpdit = (LPDLGITEMTEMPLATE) lpw;
           lpdit->x  = 10; lpdit->y  = 10;    // Changed this from (55,10)
           lpdit->cx = 40; lpdit->cy = 20;
           lpdit->id = ID_TEXT;  // text identifier
           lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
    
           lpw = (LPWORD) (lpdit + 1);
           *lpw++ = 0xFFFF;
           *lpw++ = 0x0082;                         // static class
    
           for (lpwsz = (LPWSTR)lpw;
               *lpwsz++ = (WCHAR) *lpszMessage++;
               );
           lpw = (LPWORD)lpwsz;
           *lpw++ = 0;                              // no creation data
    
           GlobalUnlock(hgbl);
           ret = DialogBoxIndirect(hinst,
                                   (LPDLGTEMPLATE) hgbl,
                                   hwndOwner, (DLGPROC) DialogProc);
           GlobalFree(hgbl);
    
           return ret;
          } 


  4. As previously stated, this modified code works fine in Windows NT 3.51. In Windows 95, however, the dialog box and the controls come up, but with no text for the help and OK buttons or for the dialog box.

    Notice how the text in the code copies the text onto the memory block using lstrcpyW(), which is not implemented in Windows 95, so it returns ERROR_NOT_IMPLEMENTED. To generate Unicode strings in Windows 95, the application must use MultiByteToWideChar().




Following is the modified code that works in Windows 95:


      #define ID_HELP   150
      #define ID_TEXT   200
      LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner,
         LPSTR lpszMessage)
      {

       HGLOBAL hgbl;
       LPDLGTEMPLATE lpdt;
       LPDLGITEMTEMPLATE lpdit;
       LPWORD lpw;
       LPWSTR lpwsz;
       LRESULT ret;
       hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
       if (!hgbl)
           return -1;

       lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);

       // Define a dialog box.

       lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
                      | DS_MODALFRAME | WS_CAPTION;
       lpdt->cdit = 3;  // number of controls
       lpdt->x  = 10;  lpdt->y  = 10;
       lpdt->cx = 100; lpdt->cy = 100;

       lpw = (LPWORD) (lpdt + 1);
       *lpw++ = 0;   // no menu
       *lpw++ = 0;   // predefined dialog box class (by default)

       lpwsz = (LPWSTR) lpw;
       nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "My Dialog", -1,
                                       lpwsz, 50);
       lpw   += nchar;

       //-----------------------
       // Define an OK button.
       //-----------------------
       lpw = lpwAlign (lpw);

       lpdit = (LPDLGITEMTEMPLATE) lpw;
       lpdit->x  = 10; lpdit->y  = 70;
       lpdit->cx = 80; lpdit->cy = 20;
       lpdit->id = IDOK;  // OK button identifier
       lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;

       lpw = (LPWORD) (lpdit + 1);
       *lpw++ = 0xFFFF;
       *lpw++ = 0x0080;    // button class

       lpwsz = (LPWSTR) lpw;
       nchar = 1+MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
       lpw   += nchar;
       *lpw++ = 0;              // no creation data

       //-----------------------
       // Define a Help button.
       //-----------------------
       lpw = lpwAlign (lpw);

       lpdit = (LPDLGITEMTEMPLATE) lpw;
       lpdit->x  = 55; lpdit->y  = 10;
       lpdit->cx = 40; lpdit->cy = 20;
       lpdit->id = 101; //ID_HELP;    // Help button identifier
       lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;

       lpw = (LPWORD) (lpdit + 1);
       *lpw++ = 0xFFFF;
       *lpw++ = 0x0080;                 // button class atom


       lpwsz = (LPWSTR) lpw;
       nchar = 1+MultiByteToWideChar (CP_ACP, 0, "Help", -1, lpwsz, 50);
       lpw   += nchar;
       *lpw++ = 0;                      // no creation data

       //-----------------------
       // Define a static text control.
       //-----------------------
       lpw = lpwAlign (lpw);

       lpdit = (LPDLGITEMTEMPLATE) lpw;
       lpdit->x  = 10; lpdit->y  = 10;
       lpdit->cx = 40; lpdit->cy = 20;
       lpdit->id = 200; //ID_TEXT;  // text identifier
       lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;

       lpw = (LPWORD) (lpdit + 1);
       *lpw++ = 0xFFFF;
       *lpw++ = 0x0082;                         // static class

       for (lpwsz = (LPWSTR)lpw;
           *lpwsz++ = (WCHAR) *lpszMessage++;
          );

       lpw = (LPWORD)lpwsz;
       *lpw++ = 0;                              // no creation data

       GlobalUnlock(hgbl);
       ret = DialogBoxIndirect(hinst,
                               (LPDLGTEMPLATE) hgbl,
                               hwndOwner,
                               (DLGPROC) DialogProc);
       GlobalFree(hgbl);

       return ret;
      } 

Keywords          : kbcode kbdocfix kbdocerr kbDlg kbNTOS kbGrpUser kbWinOS 
Version           : 
Platform          : 
Issue type        : 

Last Reviewed: March 7, 1999