FIX: Border of Modeless CPropertySheet Is Not 3D in Windows NT

ID: Q147206


The information in this article applies to:
  • The Microsoft Foundation Classes (MFC), included with:
    • Microsoft Visual C++, 32-bit Editions, version 4.0


SYMPTOMS

If you create a modeless CPropertySheet under Windows NT, its outer border will not be a 3D border. A modal CPropertySheet will have a 3D border. Both modal and modeless CPropertySheets have a 3D border under Windows 95.


CAUSE

MFC sets up a callback function for modeless CPropertySheets called AfxPropSheetCallback(). This function checks for PSCB_PRECREATE, which is a message that is received before a property sheet is created. In this handler, MFC takes out the DS_MODALFRAME style.

Ctl3d32.dll is used by Windows NT to paint 3D borders for controls and windows. For a dialog box to have a 3D border, CTL3D requires a style of DS_MODALFRAME.


RESOLUTION

  1. Derive a class from CPropertySheet (CMySheet) and override its Create(). Comment the call to CWnd::Create() that the ClassWizard puts in.


  2. Copy code from CPropertySheet::Create() in DLGPROP.CPP (as shown below) into CMySheet::Create(), and change the parameters it takes accordingly.


  3. Change this line:
    
          m_psh.dwFlags |= (PSH_MODELESS|PSH_USECALLBACK); 
    to:
    
          m_psh.dwFlags |= PSH_MODELESS; 
    The callback function isn't set so that PSCB_PRECREATE is not handled, and the DS_MODALFRAME style is not removed.


  4. Comment out this line:
    
       m_psh.pfnCallback = AfxPropSheetCallback; 


  5. Include <afxpriv.h> in MySheet.h.


  6. In MySheet.h, change the MySheet.Create to take the corresponding parameters:
    
       BOOL Create(CWnd* pParentWnd = NULL, DWORD dwStyle = WS_SYSMENU |
                    WS_POPUP | WS_CAPTION | DS_MODALFRAME | WS_VISIBLE,
                    DWORD dwExStyle = WS_EX_DLGMODALFRAME ); 



STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This problem was corrected in Visual C++, 32-bit Edition, version 4.1.


MORE INFORMATION

Sample Code


// in MySheet.h
#include <afxpriv.h>

BOOL Create(CWnd* pParentWnd = NULL, DWORD dwStyle = WS_SYSMENU |
      WS_POPUP | WS_CAPTION | DS_MODALFRAME | WS_VISIBLE,
      DWORD dwExStyle = WS_EX_DLGMODALFRAME );

// In MySheet.cpp
// CMySheet is derived from CPropertySheet
BOOL CMySheet::Create(CWnd* pParentWnd, DWORD dwStyle, DWORD dwExStyle)
{
     _AFX_THREAD_STATE* pState = AfxGetThreadState();
     pState->m_dwPropStyle = dwStyle;
     pState->m_dwPropExStyle = dwExStyle;

     ASSERT_VALID(this);
     ASSERT(m_hWnd == NULL);

 // WS_SYSMENU must not be set if a property sheet is created as a child

     if (dwStyle & WS_CHILD)
          dwStyle &= ~WS_SYSMENU;

     // finish building PROPSHEETHEADER structure
     BuildPropPageArray();
     m_bModeless = TRUE;
// original line specifies a callback function
//   m_psh.dwFlags |= (PSH_MODELESS|PSH_USECALLBACK);
// new line does not specify a callback function
     m_psh.dwFlags |= PSH_MODELESS;
//   m_psh.pfnCallback = AfxPropSheetCallback;
     m_psh.hwndParent = pParentWnd->GetSafeHwnd();

     // hook the window creation process
     AfxHookWindowCreate(this);
     HWND hWnd = (HWND)PropertySheet(&m_psh);

     // clean up on failure, otherwise return TRUE
     if (!AfxUnhookWindowCreate())
          PostNcDestroy();     // cleanup if Create fails

     if (hWnd == NULL || hWnd == (HWND)-1)
          return FALSE;
     ASSERT(hWnd == m_hWnd);

     return TRUE;
}

/* Compile options needed: default
*/ 

Additional query words: kbVC400bug 4.00 border CPropertySheet modeless Property Sheet vcfixlist410

Keywords : kbMFC KbUIDesign kbVC
Version : 4.00
Platform : NT WINDOWS
Issue type :


Last Reviewed: July 29, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.