FAQ: Frequently Asked Questions About 16-bit Foundation ClassesLast reviewed: July 22, 1997Article ID: Q109039 |
This article applies to: The Microsoft Foundation Classes (MFC) included with: - Microsoft Visual C++ for Windows, 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 QuestionsThe following questions are addressed in this document:
(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 List1. 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 \* Q99161 --------------------------------------------------------------- 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: ARTICLE-ID: Q99562 TITLE : 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: ARTICLE-ID: Q99198 TITLE : 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: q&a q & a faq 2.00 2.50
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |