DOCERR: Incorrect DialogBoxIndirect() Code in Win32 SDK Docs

Last reviewed: April 7, 1997
Article ID: Q140725
4.00    | 3.51
WINDOWS | WINDOWS NT kbprg kbdocerr kbcode

The information in this article applies to:

  • Microsoft Win32 Software Development Kit (SDK) for:

        - Window 95
        - Windows NT version 3.51
    

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

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().

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->x = 55; lpdit->y = 10; lpdit->cx = 40; lpdit->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;
       }
    


Additional reference words: 4.00
KBCategory: kbprg kbdocerr kbcode
KBSubcategory: UsrDlgs
Keywords : UsrDlgs kbcode kbdocerr kbprg
Version : 4.00 | 3.51
Platform : NT WINDOWS


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: April 7, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.