Microsoft KB Archive/109039

From BetaArchive Wiki

FAQ: Frequently Asked Questions About 16-bit Foundation Classes

Q109039



The information in this article applies to:


  • The Microsoft Foundation Classes (MFC) included with:
    • Microsoft Visual C++, versions 1.0, 1.5





SUMMARY


Microsoft Foundation Class Library Questions and Answers
Last revised: June 14, 1993





The text below presents a list of 25 frequently asked questions regarding the Microsoft Foundation Class (MFC) Library and the answers to these questions. For additional information regarding the Microsoft Foundation Class Library, please refer to the Microsoft Knowledge Base and to the Microsoft Software Library.

Index to Questions

The following questions are addressed in this document:


  1. How do I perform multiple levels of derivation with ClassWizard?
  2. How do I size a CFormView?
  3. How do I use new views with document templates?
  4. How do I size a view?
  5. How do I create an application that is initially maximized?
  6. How do I activate a previous instance of an application?
  7. How do I change the background color of a view?
  8. How do I update the text of a pane in a status bar?
  9. What are the user interface guidelines?
  10. Can I use the CTRL3D three-dimensional controls dynamic-link library (DLL) in a application developed with the Microsoft Foundation Class (MFC) Library?
  11. Should I use in my application functions of the Microsoft Foundation Class Library that are not listed in the printed documentation or in the Help file?
  12. Do I need to use documents and views?
  13. How should I define the WEP in an MFC DLL?
  14. Do I need a CWinApp object in a DLL developed with the Microsoft Foundation Class Library?
  15. Can I use a VBX control in a DLL developed with the Microsoft Foundation Class Library?
  16. How can I work around the fact that the HSZ data type is different for VBX controls and for the Dynamic Data Exchange Management Library (DDEML)?
  17. When will the Microsoft Foundation Class Library support version 2.0 of the Object Linking and Embedding (OLE) specification?
  18. When will the Microsoft Foundation Class Library version 2.0 be available for Windows NT?
  19. How can I track down memory leaks in my application?
  20. How do I enable TRACE macros in my application?
  21. Why does the debug version of Windows run so slowly?
  22. How do I change the styles of a window that is created by the framework?
  23. How do I create a C++ object that corresponds to a control in a dialog box?
  24. How do I perform background processing in an application developed with the Microsoft Foundation Class Library?
  25. How do I use a custom icon for a window in an application developed with the Microsoft Foundation Class Library?

Microsoft Foundation Class Library Frequently Asked Questions List




  1. Q. How do I perform multiple levels of derivation with ClassWizard?

    A. A Microsoft Knowledge Base article discusses this issue. The full text of this article is reproduced below.

    Deriving from Classes Not Listed in ClassWizard

           ---------------------------------------------------------------
           The information in this article applies to:
    
            - Microsoft Visual Workbench for Windows, version 1.0
           ---------------------------------------------------------------
    
           SUMMARY
           =======
    
           Microsoft ClassWizard version 1.0 supports deriving classes
           only from the classes listed in the Class Type field of the Add
           Class dialog box. To create a class derived from a previously
           derived class or to derive from another class based on the
           Microsoft Foundation Class Library CWnd class that is not
           listed in the Class Type field, a few extra steps are required.
    
           MORE INFORMATION
           ================
    
           For example, suppose the following derivation tree is desired:
    
              MyDerivedClass
                    ^
                    |
                MyBaseClass
                    ^
                    |
                 CDialog
    
           or, it is desirable to derive a class from a class based on
           CWnd that is not listed in the Class Type field in the Add
           Class dialog box, such as CFileDialog. There is no predefined
           method to create this type of class hierarchy using the
           ClassWizard. However, by using the parsing techniques
           ClassWizard uses, you can create these class hierarchies.
    
           The steps below use CDialog as the default class type. Before
           proceeding, determine which predefined class type is closest to
           the desired base class. For example, CFileDialog is similar to
           CDialog. If none of the classes correspond closely to your
           desired class, use the generic CWnd class.
    
           To create a class with multiple levels of derivation, perform
           the following three steps:
    
           1. Use ClassWizard to create MyDerivedClass, deriving it from
              CDialog (or another appropriate predefined class).
    
           2. Use ClassWizard to create MyBaseClass, deriving it from
              CDialog (or another appropriate predefined class).
    
           3. Edit the code generated for MyDerivedClass and replace all
              references to CDialog with MyBaseClass. This step is very
              important; many errors occur if this is not done correctly
              and these errors may  be difficult to track down.
    
           To create a class based on a class based on CWnd that is not
           supported by ClassWizard, perform the following two steps:
    
           1. Use ClassWizard to create MyDerivedClass, deriving it from
              CDialog (or another appropriate predefined class based on
              CWnd).
    
           2. Edit the code generated for MyDerivedClass and replace all
              references to CDialog with the name of the class from which
              you are deriving this class, for example, CFileDialog. This
              step is very important; many errors occur if this is not
              done correctly and these errors may be difficult to track
              down.
    
           Then, for either type of class, perform the following three
           steps:
    
           1. Delete the project .CLW file.
    
           2. Start App Studio, load your project .RC file, and activate
              ClassWizard.
    
           3. Because the project does not have a .CLW file, ClassWizard
              prompts to generate a .CLW file. Choose Yes to generate the
              file. NOTE: You must generate this file in App Studio. If
              you attempt to generate the file in Visual Workbench, VWB
              instructs you to generate the file in App Studio.
    
           Once App Studio has created the .CLW file, the base class of
           the derived class has been changed successfully. To verify
           this, view the class in ClassWizard and see the data in the
           Class Info dialog box.
    
           For classes created using multiple levels of derivation, you
           can use ClassWizard to pass system messages, such as
           WM_INITDIALOG, to the base class as well. To do this, perform
           the following nine steps:
    
           1. Start ClassWizard.
    
           2. Select the MyDerivedClass class.
    
           3. Select MyDerivedClass in the Object IDs window.
    
           4. Select the WM_INITDIALOG message in the Messages window.
    
           5. Choose Add Function to add a function skeleton that calls
              the OnInitDialog() function in MyBaseClass.
    
           6. Select the MyBaseClass class.
    
           7. Select MyBaseClass in the Object IDs window.
    
           8. Select the WM_INITDIALOG message in the Messages window.
    
           9. Choose Add Function to add a function skeleton that calls
              the OnInitDialog() function in CDialog. This step is
              required only once. If you derive additional classes from
              the base class, you do not need to redo this operation. 
  2. Q. How do I size a CFormView?

    A. Knowledge Base article Q98598 discusses this issue. The full text of this article is reproduced below.

           Using CFormView in SDI and MDI Applications
    
           ---------------------------------------------------------------
           The information in this article applies to:
    
            - Microsoft Foundation Class Library for Windows, version 2.0
           ---------------------------------------------------------------
    
           SUMMARY
           =======
    
           The CFormView class provides a convenient method to place
           controls into a view that is based on a dialog box template.
           The general procedure to use a CFormView is described in the
           documentation for the class and is illustrated in the VIEWEX
           and CHKBOOK sample applications provided with Microsoft
           Foundation Class Library version 2.0. However, these
           applications do not demonstrate making the initial size of the
           frame window to be the same as the initial size of the form.
    
           In an application that uses the CFormView class, CFormView
           replaces the default AppWizard CView class. The documentation
           does not demonstrate editing a Visual C++ project to remove the
           unneeded CView class and reconstruct the ClassWizard .CLW file.
           The text below demonstrates this technique.
    
           The following section lists the steps required to support
           creating a single document interface (SDI) or multiple document
           interface (MDI) application based on a CFormView, sizing the
           initial frame window around the form, changing the style of the
           frame, and closing an MDI document using a button in the form.
    
           MORE INFORMATION
           ================
    
           No fully automated method exists to use a CFormView object in
           an application generated by AppWizard. However, the following
           nine steps are quite straightforward.
    
           1. Use the AppWizard to generate an SDI or MDI application
              skeleton.
    
           2. Design the form (dialog box) in App Studio. Set the styles
              according to the CFormView documentation.
    
           3. Use ClassWizard to create a new class based on CFormView.
              Either delete the default OK and Cancel buttons, or modify
              the ID for these buttons. The values IDOK and IDCANCEL cause
              ClassWizard to generate incorrect entries in the message map
              and incorrect message handler functions when they are used
              in a class derived from CFormView.
    
           4. In the main .CPP file for the application, find the
              AddDocTemplate function. Replace the name of the view class
              that AppWizard generates with the name of the class derived
              from CFormView. Use the #include statement to include the .H
              file for the CFormView class.
    
           5. Delete the .CPP and .H files that AppWizard generated to
              contain the original CView object. Edit other files in the
              project to remove any references to these files.
    
           6. In the Visual Workbench, edit the project to remove
              references to the view files deleted in step 5 above.
    
           7. In ClassWizard, choose the deleted view class. ClassWizard
              displays its "Repair Class Information" dialog box. Choose
              the Remove button to delete the obsolete class from the
              project's ClassWizard (.CLW) file.
    
           8. Override the OnUpdate() and UpdateData() member functions as
              documented in the CFormView documentation to update the
              member variables with the current document data and to
              perform dialog data exchange (DDX).
    
           9. If you would like to set the initial size of the form view,
              override the OnInitialUpdate() function. The text below
              provides additional information about this step, which is
              slightly different in an SDI or MDI application.
    
           Changing the Size of an SDI Main Frame Around a CFormView
           ---------------------------------------------------------
    
           To change the size of the main frame of an SDI application
           (that uses CFormView as its view class) to be the appropriate
           size for the form you designed in App Studio, override the
           OnInitialUpdate() function in your class derived from
           CFormView, as follows:
    
              void CMyFormView::OnInitialUpdate()
              {
                 CFormView::OnInitialUpdate();
                 GetParentFrame()->RecalcLayout();
                 ResizeParentToFit(/*FALSE*/); // default argument is TRUE
              }
    
           If the size of the CMyFormView window, before calling
           ResizeParentToFit(), is smaller than the size specified in the
           dialog box template, and the application overrides the default
           TRUE argument in the ResizeParentToFit() function with FALSE,
           the following two consequences may occur:
    
            - In the ResizeParentToFit() call, the new size of the parent
              window may be calculated based on a form that includes
              scroll bars. This takes place if the initial size chosen by
              Microsoft Windows is smaller than the form designed in App
              Studio.
    
              Because the scroll bars are not needed after changing the
              size of the view, the view includes extra unused area on the
              right side and at the bottom of the resized form in a width
              equal to that of the scroll bars. To work around this
              behavior, call ResizeParentToFit() twice; once to "expand"
              the view and remove the scroll bars, and the second time to
              reduce the size of the view to the smallest size available
              without scroll bars. In the second call, the default
              bShrinkOnly = TRUE parameter is appropriate.
    
            - The main frame may be too large for the screen if the form
              is designed on a system that has a high-resolution monitor
              and the code runs on a system that has a standard VGA
              resolution.
    
           The ResizeParentToFit() function does not prevent the form from
           changing size when the user changes the size of the application
           main frame (scroll bars are added automatically if needed). To
           modify the style of the frame window that is the parent of a
           form view, you can override the PreCreateWindow() function in
           the CMainFrame class generated by AppWizard. For example, to
           remove the WS_THICKFRAME style and prevent the user from
           changing the size of the window, declare PreCreateWindow() in
           MAINFRM.H and add the following code to MAINFRM.CPP:
    
              BOOL CMainFrame::PreCreateWindow(CREATESTRUCT &cs)
              {
                 cs.style &= ~WS_THICKFRAME;
                 return CFrameWnd::PreCreateWindow(cs);
              }
    
           Changing the Size of an MDI Child Frame Around a CFormView
           ----------------------------------------------------------
    
           The process of changing the size of an MDI child frame is
           similar to changing the size of a main frame for an SDI
           application, as explained above. However, the RecalcLayout()
           call is not required.
    
           To change the size of an MDI child frame around a form view,
           override the OnInitialUpdate() function in your class derived
           from CFormView as follows:
    
              void CMDIFormView::OnInitialUpdate()
              {
                 CFormView::OnInitialUpdate();
                 ResizeParentToFit(/*FALSE*/); // default argument is TRUE
              }
    
           If the application overrides the default argument to the
           ResizeParentToFit() function, essentially the same consequences
           occur as for an SDI application, as explained above. In
           addition, the child window may be too large for the enclosing
           MDI main frame or for the entire screen.
    
           To change the style of the MDI child frame (for example, to
           remove the WS_THICKFRAME style so the user cannot change the
           size of the window), derive an MDI child window class and
           override the PreCreateWindow function as demonstrated in the
           SDI example above.
    
           Closing an MDI Form with a Button
           ---------------------------------
    
           To create a button on a form that closes the document, use
           ClassWizard to add a message handler for the BN_CLICKED message
           to the CFormView class. Make sure that the buttons in CFormView
           do not have the default IDOK or IDCANCEL identifiers. If they
           do, ClassWizard creates incorrect entries in the message map
           and incorrect functions for the buttons.
    
           Once the message handler is in place, you can simulate the
           Close command on the File menu with the following code:
    
              void CMyForm::OnClickedButton1()
              {
                 PostMessage(WM_COMMAND, ID_FILE_CLOSE);
              }
    
           This method to close a form prompts the user to save the file
           if the IsModified() member function associated with the
           document returns TRUE. 
  3. Q. How do I use new views with document templates?

    A. In an application created with AppWizard, you have two options: change the derivation of the current view, or create a new view and use the new view in your MDI application along with the original view.

    To create a new view, use ClassWizard to create a new class derived from CView. After the class has been created, the steps to use the new view or to modify the view provided by AppWizard are the same.

    1. Modify the header file for the view class to change all references to CView to the name of the desired view class. In this example, the class is derived from CScrollView. Usually, this step involves changing the class the view class is derived from as follows:

                   class CMyView : public CScrollView
              
    2. Modify the implementation file for the view class to change all references to CView to the name of the desired view class. This involves changing the IMPLEMENT_DYNCREATE line as follows

                   IMPLEMENT_DYNCREATE(CMyView, CScrollView)
              

      changing the BEGIN_MESSAGE_MAP as follows

                   BEGIN_MESSAGE_MAP(CMyView, CScrollView)
              

      and changing any other references to CView to CScrollView.

    3. No further modifications are required if you are modifying a view created by AppWizard. If you create a new view, find the AddDocTemplate() call in the CWinApp::InitInstance() function. The third parameter to AddDocTemplate() is RUNTIME_CLASS(CSomeView). To replace the current view with the new view class, change CSomeView to CMyView. In an MDI application, you can use multiple view types by adding a second AddDocTemplate() call that changes RUNTIME_CLASS(CSomeView) to RUNTIME_CLASS(CMyView).

    For additional information, please see the following article(s) in the Microsoft Knowledge Base:

    Q99562 Switching views in a Single Document Interface Program

  4. Q. How do I size a view?

    A. Normally, you can change the size of a window by calling MoveWindow(). In an application developed with the Microsoft Foundation Class (MFC) Library, the view window is a child window of the frame window that surrounds the view. To change the size of the view window, retrieve a pointer to the frame window of the view by calling GetParentFrame(), then call MoveWindow() to change the size of the parent. When the parent frame window changes size, it automatically changes the size of the view window to fit in the parent frame.
  5. Q. How do I create an application that is initially maximized?

    A. For an MDI application, in the CWinApp::InitInstance() function, set CWinApp::m_nCmdShow to SW_SHOWMAXIMIZED before calling pMainFrame->ShowWindow(m_nCmdShow). For example, in an application generated by AppWizard, the code is as follows:

              // create main MDI Frame window
              CMainFrame* pMainFrame = new CMainFrame;
              if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
                  return FALSE;
              m_nCmdShow = SW_SHOWMAXIMIZED;  // ADD THIS LINE!
              pMainFrame->ShowWindow(m_nCmdShow);
              pMainFrame->UpdateWindow();
              m_pMainWnd = pMainFrame; 

    In an SDI application, in the CWinApp::InitInstance() function, set CWinApp::m_nCmdShow to SW_SHOWMAXIMIZED before calling OnFileNew(). For example, in an application generated by AppWizard, the code is as follows:

             m_nCmdShow = SW_SHOWMAXIMIZED;
             // create a new (empty) document
             OnFileNew(); 
  6. Q. How do I activate a previous instance of an application?

    A. Knowledge Base article Q70074 discusses two common techniques to reactivate a previous instance of an application. One technique involves using the FindWindow() function and the other uses the hPrevInst parameter. The hPrevInst method described in this article uses the GetInstanceData() function, which is not available in Windows NT.

    The FindWindow() method requires the application to enumerate top-level windows looking for a WndClass value that matches that of the application. An application developed with the Microsoft Foundation Class (MFC) Library can use this technique; however, the application must register its own WndClass value. By default, an application developed with the Microsoft Foundation Class Library uses classes registered by the Library. For more information on registering private windows classes, please refer to Technical Note #1 in the MFC Tech Notes help file distributed with Microsoft Visual C++ version 1.0 for Windows.
  7. Q. How do I change the background color of a view?

    A. Knowledge Base article Q103786 discusses changing the background color of a CFrameWnd, CView, or CWnd object. The full text of this article is reproduced below.

           Changing Window Background Color with Foundation Classes
    
           ---------------------------------------------------------------
           The information in this article applies to:
    
            - Microsoft Foundation Classes for Windows, version 2.0
           ---------------------------------------------------------------
    
           SUMMARY
           =======
    
           To change the background color for a CView, CFrameWnd, or CWnd
           object, process the WM_ERASEBKGND message. The text below
           demonstrates doing this.
    
              BOOL CSampleView::OnEraseBkgnd(CDC* pDC)
              {
                 // Set brush to desired background color
                 CBrush backBrush(RGB(255, 128, 128));
    
                 // Save old brush
                 CBrush* pOldBrush = pDC->SelectObject(&backBrush);
    
                 CRect rect;
                 pDC->GetClipBox(&rect);     // Erase the area needed
    
                 pDC->PatBlt(rect.left, rect.top, rect.Width(),
                    rect.Height(), PATCOPY);
                 pDC->SelectObject(pOldBrush);
                 return TRUE;
              }
    
           MORE INFORMATION
           ================
    
           To change the background color of a CFormView object, either
           process the WM_ERASEBKGND message and use the code above or
           process the WM_CTLCOLOR message to change the background color.
    
           For more information on changing the background color of a
           dialog box by processing the WM_CTLCOLOR message, please search
           in the Microsoft Knowledge Base on the following words:
    
              Changing Background Color MFC 
  8. Q. How do I update the text of a pane in a status bar?

    A. By default, a CStatusBar pane is not enabled when the pane is created. To activate a pane, you must call the ON_UPDATE_COMMAND_UI() macro for each pane on the status bar and update the panes. Because panes do not send WM_COMMAND messages, you cannot use ClassWizard to activate panes; you must type the code manually. For example, suppose one pane has ID_INDICATOR_PAGE as its identifier and that it contains the current page number in a document. To make the ID_INDICATOR_PAGE pane display text, add the following to a header file (probably the MAINFRM.H file):

              afx_msg void OnUpdatePage(CCmdUI *pCmdUI); 

    Add the following to the application message map:

              ON_UPDATE_COMMAND_UI(ID_INDICATOR_PAGE, OnUpdatePage) 

    Add the following to a source code file (probably MAINFRM.CPP):

              void CMainFrame::OnUpdatePage(CCmdUI *pCmdUI)
              {
                 pCmdUI->Enable();
              } 

    To display text in the panes, either call SetPaneText() or call CCmdUI::SetText() in the OnUpdate() function. For example, you might want to set up an integer variable m_nPage that contains the current page number. Then, the OnUpdatePage() function might read as follows:

              void CMainFrame::OnUpdatePage(CCmdUI *pCmdUI)
              {
                 pCmdUI->Enable();
                 char szPage[16];
                 wsprintf((LPSTR)szPage, "Page %d", m_nPage);
                 pCmdUI->SetText((LPSTR)szPage);
              } 

    This technique causes the page number to appear in the pane during idle processing in the same manner that the application updates other indicators.

    For additional information, please see the following article(s) in the Microsoft Knowledge Base:

    Q99198 Displaying the Current Time in a CStatusBar Pane

  9. Q. What are the user interface guidelines?

    A. Most "first class" applications for the Microsoft Windows operating system share a familiar and consistent user interface. This improves the usability of the application because the user is not forced to relearn common operations. For example, a user that regularly prints documents from Microsoft Word intuitively looks for a Print option on the File menu when confronted with the task of printing in an unfamiliar application.

    Microsoft provides suggested guidelines for applications to use the standard Windows user interface objects and environment in a consistent manner. The book "The Windows Interface: An Application Design Guide" is available from Microsoft Press; it contains a chapter on overall principles and methodology along with specific guidelines for keyboard input, windows, menus, and so on. For a brief introduction to usability and its associated issues, please refer to pages 18-19 of the "Presenting Visual C++" tabloid provided with Microsoft Visual C++ version 1.0 for Windows.

    The Microsoft Foundation Class (MFC) Library, and especially the skeleton applications created with AppWizard, provide a good starting point to develop an application that conforms to the published guidelines. These tools ease the process of developing an application that has the "look and feel" expected by experienced users of the Windows environment.

    Please note that the Microsoft Foundation Class Library was designed to support the published user interface guidelines. Overriding the default behavior in derived classes may be vary difficult in some cases. However, adding to the default behavior is relatively simple.
  10. Q. Can I use the CTRL3D three-dimensional controls dynamic-link library (DLL) in a application developed with the Microsoft Foundation Class Library?

    A. CTL3D.DLL was updated recently to be compatible with version 2.0 of the Microsoft Foundation Class Library. The new version of CTL3D.DLL is available in the Microsoft Developer Network (MSDN) software library.
  11. Q. Should I use in my application functions of the Microsoft Foundation Class Library that are not listed in the printed documentation or in the online help file?

    A. In general, it is best to use functions that are listed in the "Class Libraries Reference" manual or in the MFC Tech Notes help file. However, classes in the Microsoft Foundation Class Library contain many functions that are not listed in the printed manuals but that may be useful to develop an application. The class definitions in the Microsoft Foundation Class Library header files list each of the functions in a class. These functions are grouped into different categories such as Constructors, Operations, Overrideables, and Implementation. If you choose to use a function not listed in the printed documentation, it is best to avoid functions in the Implementation section. Even though any function not listed in the printed documentation is subject to change in a future version of the Microsoft Foundation Class Library, the functions in the Implementation section are most likely to change and functions in the remaining sections are less likely to change.
  12. Q. Do I need to use documents and views?

    A. The architecture of applications developed with version 2.0 of the Microsoft Foundation Class Library was designed using the document/view concept. However, it is not necessary to use this in your application. For example, even though the HELLOAPP sample application uses neither a document nor a view, you can use any applicable tool (such as ClassWizard or App Studio) with the application and you can incorporate any desired features from the Microsoft Foundation Class Library, such as status bars or tool bars.
  13. Q. How should I define the WEP in an MFC DLL?

    A. Knowledge Base article Q98374 discusses this issue. The full text of this article is reproduced below.

           Using the C Run-Time WEP() in an MFC 2.0 _USRDLL Library
    
           ---------------------------------------------------------------
           The information in this article applies to:
    
            - Microsoft Foundation Class Library for Windows, version 2.0
           ---------------------------------------------------------------
    
           SUMMARY
           =======
    
           In a dynamic-link library (DLL) built with Microsoft Foundation
           Class Library version 2.0, the _USRDLL model uses the WEP()
           (Windows exit procedure) function provided in the C run-time
           library. Because the code uses the C library WEP() function,
           the destructors for static and global objects in the DLL are
           called and the CWinApp::ExitInstance() function for the DLL
           application object is called.
    
           MORE INFORMATION
           ================
    
           To use the WEP() function in the C run-time library, the DLL
           must export WEP in its module definition (.DEF) file. To do so,
           add the following statement  to the .DEF file:
    
              EXPORTS
                 WEP  @1 RESIDENTNAME
    
           While the ordinal number you choose is not important, you must
           specify the RESIDENTNAME attribute when you export WEP(). Do
           not include a WEP() function in the DLL code. If you do,
           Windows calls that function instead of the C library WEP() and
           the destructors for global objects and static objects, and
           CWinApp::ExitInstance() are not called.
    
           If you DLL must contain clean-up code, overload the
           ExitInstance() function. If your DLL uses an import library to
           link to another DLL developed with the Microsoft Foundation
           Classes, be sure to list the Microsoft Foundation Class Library
           and the C run-time library before the import library for the
           other DLL. This step ensures that the linker includes the WEP()
           in the C run-time library instead of linking in a reference to
           the WEP() in the other DLL.
    
           The instructions above describe building a _USRDLL that unloads
           itself and cleans up properly. The text below describes the
           process that occurs when a DLL cleans up.
    
           When Windows unloads the DLL, it calls the WEP() function in
           the DLL, which, using the procedure above, is the WEP()
           function in the C run-time library. WEP() calls the _WEP()
           function implemented in the Microsoft Foundation Class Library.
           The _WEP() function calls CWinApp::ExitInstance(). When
           ExitInstance() and _WEP() return, the WEP function calls the
           destructors for any static or global objects in the DLL.
    
           For more information about using the C run-time library WEP()
           function in an _USRDLL, please refer to Technical Note 11:
           "Using MFC as Part of a DLL" in the MFC Tech Notes help file
           distributed with Visual C++ version 1.0. 
  14. Q. Do I need a CWinApp object in a DLL developed with the Microsoft Foundation Class (MFC) Library?

    A. The Microsoft Foundation Class Library supports two types of DLLs: _USRDLL and _AFXDLL. The _USRDLL model requires one CWinApp object to perform the initialization and cleanup of the Microsoft Foundation Class Library Windows classes that the DLL uses. This requirement is described in MFC Tech Note 11; the DLLTRACE sample demonstrates a _USRDLL that contains a CWinApp object.

    An _AFXDLL does not require a CWinApp object. Because it shares the Microsoft Foundation Class Library classes with the application, it does not require a CWinApp to provide initialization and cleanup. Instead, an _AFXDLL requires a special version of LibMain() and a DLL initialization function. MFC Tech Note 33 describes these requirements in detail.
  15. Q. Can I use a VBX control in a dynamic-link library (DLL) developed with the Microsoft Foundation Class (MFC) Library?

    A. You can use VBX controls in an _AFXDLL but not in an _USRDLL. If using a VBX control in a AFXDLL, please read below: Because VBX controls are not standard Windows controls, they do not have a class name. MFC works around this by providing a Windows class, VBControl, which it can use to create VBX controls. The VBControl class is used as the class name in the dialog box template for every VBX control used in the dialog box.

    When the application that calls the DLL calls the EnableVBX() function, it registers the VBControl window class with Microsoft Windows. The VBControl class is registered as a local window class, not as a global window class. A local window class is available only to the module in which the class is registered. Because a DLL has its own module that is different from the calling application, the VBControl class is not available to the DLL.

    Workarounds to this problem:

    • The application can call the Create() member function of the CVBControl class to create the VBX control. Call Create() in the OnInitDialog() function (for a modal dialog box) or in the OnCreate() function (for a modeless dialog box).
    • Re-register the VBControl class in the DLL so that it can be used from the DLL. Also, change the resource instance handle during the OnInitDialog() function so that resource in the DLL will be used while the controls are being created.
    This second method is demonstrated in the AFXVBX sample described in article Q104239.
  16. Q. How can I work around the fact that the HSZ data type is different for VBX controls and for the Dynamic Data Exchange Management Library (DDEML)?

    A. If you want to use VBX controls and the DDEML in the same application, then you must perform the following:

    • Separate the VBX code and the DDEML code into different modules. In the module that contains the DDEML code, define the preprocessor symbol NO_VBX_SUPPORT.
  17. Q. When will the Microsoft Foundation Class (MFC) Library support version 2.1 of the Object Linking and Embedding (OLE) specification?

    A. Microsoft is actively working on MFC classes for OLE 2.1 and expects to release these classes by the end of this year.
  18. Q. When will the Microsoft Foundation Class (MFC) Library version 2.0 be available for Windows NT?

    A. Microsoft has announced that Visual C++ for Windows NT, which includes version 2.0 of the Microsoft Foundation Class Library, will be released within 90 days of the retail release of Windows NT.
  19. Q. How can I track down memory leaks in my application?

    A. Most of the text below is present in the Microsoft Foundation Class (MFC) Library online help file.

    You can substitute DEBUG_NEW for the new operator in each location that the application allocates storage from the help. In debugging mode (when the code is compiled with the _DEBUG symbol defined), DEBUG_NEW tracks the filename and line number for each object it allocates. Then, when the application calls the CMemoryState::DumpAllObjectsSince() member function, the application displays each memory object allocated with DEBUG_NEW along with the filename and line number of the statement that performed the allocation. To use DEBUG_NEW in your application, insert the following directive into your source files:

              #define new DEBUG_NEW 

    Once this directive is in place, the preprocessor replaces all occurrences of new with DEBUG_NEW and the Microsoft Foundation Class Library handles the remainder of the processing. When you compile a release version of your application, DEBUG_NEW reverts to the new operator and eliminates the filename and line number overhead.

    If you define DEBUG_NEW and your application has a memory leak, the system displays information about the memory leak when the application terminates. The system writes the data to a terminal connected to COM1 (or to the DBWIN application if it is running).

    For example, modify the HELLOAPP sample by adding the following lines to the CHelloApp::InitInstance() function (beginning on line 33 in the HELLOAPP.CPP file)

              char *p;
              p = new char[1]; 

    and define DEBUG_NEW at the beginning of the file. Compile the application for debugging mode. When you exit the application, it displays text such as the following on your debugging terminal or in the DBWIN window:

              Detected memory leaks!
              Dumping objects ->
              {5} c:\msvc\mfc\samples\helloapp\helloapp.cpp(34) :
                  non-object block at $45CF3Eg
              Object dump complete. 

    Line 34 is the line that contains the new operator.

    For more information on the DEBUG_NEW macro, please refer to Chapter 15 of the "Class Libraries User's Guide."

  20. Q. How do I enable TRACE macros in my application?

    A. If you use Visual C++ 1.0, run the TRACER application from your Microsoft Visual C++ program group (its icon has the title "MFC Trace Options"). Select "Enable Tracing," then choose OK.

    If you use Microsoft C/C++ 7.0, you must copy the AFX.INI file from the Microsoft Foundation Class (MFC) Library source directory (by default, C:\C700\MFC\SRC) to your Windows directory (by default, C:\WINDOWS). This file should contain a section such as the following:

              [Diagnostics]
              TraceEnabled = 1
              TraceFlags = 0 

    As long as TraceEnabled is set to 1, tracing is enabled.

    This AFX.INI file is the same for both C/C++ 7.0 and Visual C++ 1.0.

  21. Q. Why does the debug version of Windows run so slowly?

    A. The debug version of Windows runs slightly slower than the retail version because it performs extensive parameter validation on calls to Windows application programming interface (API) functions.
  22. Q. How do I change the styles of a window that is created by the framework?

    A. Knowledge Base article Q99847 discusses this issue. The full text of this article is reproduced below.

           Changing Window Attributes in an MFC Application
    
           ---------------------------------------------------------------
           The information in this article applies to:
    
            - Microsoft Foundation Class Library for Windows, version 2.0
           ---------------------------------------------------------------
    
           SUMMARY
           =======
    
           To change the default window attributes used by a framework
           application created in AppWizard, override the window's
           PreCreateWindow() virtual member function. PreCreateWindow()
           allows an application to access the creation process normally
           processed internally by the CDocTemplate class. The framework
           calls PreCreateWindow() just prior to creating the window. By
           modifying the CREATESTRUCT structure parameter to
           PreCreateWindow(), your application can change the attributes
           used to create the window.
    
           The CTRLBARS sample application, provided with the Microsoft
           Foundation Class Library version 2.0, demonstrates this
           technique to change window attributes. Note that depending on
           what your application changes in PreCreateWindow(), it may be
           necessary to call the base class implementation.
    
           MORE INFORMATION
           ================
    
           In a single document interface (SDI) application, the default
           window style in the framework is a combination of the
           WS_OVERLAPPEDWINDOW and FWS_ADDTOTITLE styles. FWS_ADDTOTITLE
           is a framework-specific style that instructs the framework to
           add the document title to the window's caption. To change the
           window attributes in an SDI application, override the
           PreCreateWindow() function in your class derived form
           CFrameWnd. For example:
    
           BOOL CMainFrame::PreCreateWindow(CREATESTRUt& cs)
           {
              // Create a window without
              // min/max buttons or sizable border
              cs.style = WS_OVERLAPPED | WS_SYSMENU | WS_BORDER;
    
              // Size the window to 1/3 screen size and center it
              cs.cy = ::GetSystemMetrics(SM_CYSCREEN) / 3;
              cs.cx = ::GetSystemMetrics(SM_CXSCREEN) / 3;
              cs.y = ((cs.cy * 3) - cs.cy) / 2;
              cs.x = ((cs.cx * 3) - cs.cx) / 2;
    
              return CFrameWnd::PreCreateWindow(cs);
              }
    
           A little more work is required to change the window style of a
           child window in a multiple document interface (MDI)
           application. By default, an MDI application generated in
           AppWizard uses the default CMDIChildWnd class defined in the
           Microsoft Foundation Class Library. To change the window style
           of an MDI child window, your application must derive a new
           class from CMDIChildWnd and replace all references to
           CMDIChildWnd in your project with references to the new class.
           Most likely, the only reference to CMDIChildWnd in the
           application is located in your application's InitInstance()
           member function.
    
           The default window style used in an MDI application is a
           combination of the WS_CHILD, WS_OVERLAPPEDWINDOW, and
           FWS_ADDTOTITLE styles. To change the window attributes of an
           MDI application's child windows, override the PreCreateWindow()
           function in your class derived from CMDIChildWnd. For example:
    
              BOOL CMyChildWnd::PreCreateWindow(CREATESTRUCT& cs)
              {
                 // Create a child window without the maximize button
                 cs.style &= ~WS_MAXIMIZEBOX;
                 return CMDIChildWnd::PreCreateWindow(cs);
              }
    
           For more information about the PreCreateWindow() function,
           please refer to the Microsoft Visual C++ "Class Library
           Reference, Volume 1" or to the Visual C++ Help file. 
  23. Q. How do I create a C++ object that corresponds to a control in a dialog box?

    A. You can use the CWnd::GetDlgItem() function to retrieve a pointer to the specified control or child window in a dialog box. Specify the control ID as an argument and the function returns a CWnd pointer. Usually, you need to cast the return value to the proper type. An example of using this function follows:

              MyEditCtrlPtr =  (CEdit *)GetDlgItem(IDC_MYEDITCTRL); 
  24. Q. How do I perform background processing in an application developed with the Microsoft Foundation Class (MFC) Library?

    A. Knowledge Base article Q99999 discusses this issue. The full text of this article is reproduced below.

           Background Processing In an MFC Application
    
           ---------------------------------------------------------------
           The information in this article applies to:
    
            - Microsoft Foundation Class Library for Windows, version 2.0
           ---------------------------------------------------------------
    
           SUMMARY
           =======
    
           Many applications perform lengthy processing "in the
           background" during intervals that the user is not otherwise
           interacting with the application. In an application developed
           for the Microsoft Windows operating system, an application can
           perform background processing by splitting a lengthy process
           into many small fragments. After processing each fragment, the
           application yields execution control to Windows using a
           PeekMessage() loop.
    
           An application developed with the Microsoft Foundation Class
           Library can perform background processing either by using the
           PeekMessage() loop in the library code's main message loop or
           by embedding another PeekMessage() loop in the application.
    
           MORE INFORMATION
           ================
    
           In an application developed with the Microsoft Foundation Class
           Library, the main message loop in the CWinApp class contains a
           PeekMessage() loop. This loop calls the CWinApp::OnIdle()
           function between messages. An application can process messages
           in this idle time by overriding the OnIdle() function. For more
           information about performing background processing in the
           OnIdle() function, please refer to the documentation for the
           CWinApp::OnIdle() function in the "Class Libraries Reference"
           manual.
    
           Another method to perform background processing in an
           application involves embedding a PeekMessage() loop in a
           function. Because a PeekMessage() loop is very similar to the
           main message loop, such a loop in an application developed with
           the Microsoft Foundation Class Library must perform many of the
           functions of the main message loop in the library. The
           following code fragment demonstrates writing a PeekMessage()
           loop that is compatible with the Microsoft Foundation Class
           Library:
    
              while (bDoingBackgroundProcessing)
              {
                 while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                 {
                    if (msg.message == WM_QUIT)
                    {
                       bDoingBackgroundProcessing = FALSE;
                       ::PostQuitMessage();
                       break;
                    }
                    if (!AfxGetApp()->PreTranslateMessage(&msg))
                    {
                       ::TranslateMessage(&msg);
                       ::DispatchMessage(&msg);
                    }
                 }
                 AfxGetApp()->OnIdle(0);   // updates user interface
                 AfxGetApp()->OnIdle(1);   // frees temporary objects
    
                 // Perform some background processing here
              } 
  25. Q. How do I use a custom icon for a window in an application developed with the Microsoft Foundation Class (MFC) Library?

    A. The Microsoft Foundation Class Library stores icons for the main frame window and the MDI frame window as resources. The icon with resource ID AFX_IDI_STD_MDIFRAME is the icon for the MDI frame window, and the icon with resource ID AFX_IDI_STD_FRAME is the icon for the main frame window. To replace these icons in your application, add an icon to your resources file with the appropriate ID.

    The application specifies the icon for a view in an MDI child window when it creates the template. The application uses the icon with the specified resource ID when the user minimizes the MDI child window that contains the corresponding view.

    This technique allows you to specify one icon for the application to associate with these windows. Windows also supports dynamically painting a minimized window. To do this with the Microsoft Foundation Class Library, use AfxRegisterWndClass() to register a window class with a NULL icon handle. Override the PreCreateWindow() function in the window class for the dynamically painted icon and copy the name returned by AfxRegisterWndClass() into the lpszClassName member of the CREATESTRUCT. This creates the window using the class that has a NULL icon. When the user minimizes this window, the icon receives WM_PAINT messages that it can process to display information appropriately. To do so, override the OnPaint() message handler and call the IsIconic() function to see if the window is minimized. If so, create a CPaintDC object and use it to draw on the icon. If the window is not minimized, call the base class version of OnPaint() to update the window normally.

Additional query words: qa q a faq 2.00 2.50

Keywords : kbprogramming kb16bitonly kbnokeyword kbMFC kbVC
Issue type : kbinfo
Technology :


Last Reviewed: May 8, 2001
© 2001 Microsoft Corporation. All rights reserved. Terms of Use.