PRB: Can't Center Explorer-Style FileOpen Common Dialog Box

Last reviewed: December 11, 1995
Article ID: Q140722
The information in this article applies to:
  • Microsoft Win32 Software Development Kit (SDK) for Windows 95 and Windows NT 3.51

SYMPTOMS

Generally, an application that attempts to alter the default behavior of a dialog box before it even comes up on the screen, would process the WM_INITDIALOG message. For common dialogs, this message is processed in the common dialog's hook procedure. However, attempting to center the new Explorer-Style FileOpen Common Dialog in Windows 95 in the hook procedure's WM_INITDIALOG case will result in an off-center dialog box.

CAUSE

This problem arises with the new Explorer-Style common dialog only when the OFN_ENABLETEMPLATE flag is set in the OPENFILENAME structure, and a dialog template is specified in lpTemplateName that includes the new controls that you want to add to the dialog box.

Typically, the code to center a dialog box would first get the dimensions of the dialog box by using GetWindowRect so it could be centered on the screen appropriately. At WM_INITDIALOG time, the FileOpen dialog has not been resized to accomodate the new controls specified in the lpTemplateName member of the OPENFILENAME struct; therefore, GetWindowRect() returns the dimensions of the original FileOpen dialog, not that of the actual customized dialog that comes up on the screen. This then causes the dialog box to come up a few pixels off-center.

RESOLUTION

Call GetWindowRect() and the rest of the code to center the dialog box, in the hook procedure's WM_NOTIFY case, with code set to CDN_INITDONE, a new common dialog notification code for Windows 95. By this time, all the controls have been added in, and the dialog has been resized accordingly.

STATUS

This behavior is by design.

MORE INFORMATION

Here's how the Win32 SDK COMDLG32 sample can be modified to do this. Note that COMMDLG creates the dialog specified by lpTemplateName as a child of the standard FileOpen common dialog box. As a result, the hDlg passed to the application's hook function will be the child of the standard FileOpen dialog box. To get a handle to the standard dialog box from the hook function, an application needs to call GetParent (hDlg).

Code Sample Modification of Win32 SDK COMDLG32 Sample

BOOL NEAR PASCAL TestNotify(HWND hDlg, LPOFNOTIFY pofn) {

 switch (pofn->hdr.code)
 {

     case CDN_INITDONE:
     {
        CenterWindow (GetParent (hDlg), NULL);
        break;
     }

     :
     :
}

// center with respect to another window
// Specifying NULL for hwndParent centers hwndChild relative to the screen.
BOOL CenterWindow(HWND hwndChild, HWND hwndParent) {
    RECT    rcChild, rcParent;
    int     cxChild, cyChild, cxParent, cyParent;
    int     cxScreen, cyScreen, xNew, yNew;
    HDC     hdc;

    // Get the Height and Width of the child window
    GetWindowRect(hwndChild, &rcChild);
    cxChild = rcChild.right - rcChild.left;
    cyChild = rcChild.bottom - rcChild.top;


    if (hwndParent)
    {
    // Get the Height and Width of the parent window
       GetWindowRect(hwndParent, &rcParent);
       cxParent = rcParent.right - rcParent.left;
       cyParent = rcParent.bottom - rcParent.top;
    }

    else
    {
       cxParent = GetSystemMetrics (SM_CXSCREEN);
       cyParent = GetSystemMetrics (SM_CYSCREEN);
       rcParent.left = 0;
       rcParent.top  = 0;
       rcParent.right = cxParent;
       rcParent.bottom= cyParent;
    }

    // Get the display limits
    hdc = GetDC(hwndChild);
    cxScreen = GetDeviceCaps(hdc, HORZRES);
    cyScreen = GetDeviceCaps(hdc, VERTRES);
    ReleaseDC(hwndChild, hdc);

    // Calculate new X position, then adjust for screen
    xNew = rcParent.left + ((cxParent - cxChild) / 2);
    if (xNew < 0)
    {
        xNew = 0;
    }
    else if ((xNew + cxChild) > cxScreen)
    {
        xNew = cxScreen - cxChild;
    }

    // Calculate new Y position, then adjust for screen
    yNew = rcParent.top  + ((cyParent - cyChild) / 2);
    if (yNew < 0)
    {
        yNew = 0;
    }
    else if ((yNew + cyChild) > cyScreen)
    {
        yNew = cyScreen - cyChild;
    }

    // Set it, and return
    return SetWindowPos(hwndChild,
                        NULL,
                        xNew, yNew,
                        0, 0,
                        SWP_NOSIZE | SWP_NOZORDER);
}


Additional reference words: 4.00
KBCategory: kbprg kbprb kbcode
KBSubcategory: UsrCmnDlg


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: December 11, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.