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 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
\* 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. |