HOWTO: Add MFC Support to an ATL Project [visualc]
ID: Q173974 CREATED: 16-SEP-1997 MODIFIED: 22-OCT-1998
WINDOWS:2.0,2.1,3.0
WINDOWS
PUBLIC | kbvc600 kbvc500 kbATL300 kbATL210 kbATL200
======================================================================
---------------------------------------------------------------------
The information in this article applies to:
- The Microsoft Active Template Library (ATL), versions 2.0, 2.1, 3.0
included with:
- Microsoft Visual C++, 32-bit Editions, version 5.0, 6.0
---------------------------------------------------------------------
SUMMARY
=======
When creating an ATL EXE project using the AppWizard, the MFC support check
box is disabled. This article explains how to add MFC support to an ATL EXE
project. This article also explains how to add MFC support to an ATL DLL
project if you failed to initially select the "support MFC" check box in
the AppWizard.
MORE INFORMATION
================
Adding MFC Support to an ATL EXE Project
----------------------------------------
1. Add the following #include directives to StdAfx.h prior to including
Atlbase.h:
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation extensions
2. Change project settings to use MFC. From the Project Settings dialog
box, click the General tab, and change the setting in the "Microsoft
Foundation Classes" list box to MFC.
3. Add a CWinApp derived class and declare a global variable of that type
as follows:
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
};
CMyApp theApp;
4. Replace the _tWinMain function with the following InitInstance and
ExitInstance code:
BOOL CMyApp::InitInstance()
{
// Initialize OLE libraries.
if (!AfxOleInit())
{
AfxMessageBox(_T("OLE Initialization Failed!"));
return FALSE;
}
// Initialize CcomModule.
_Module.Init(ObjectMap,m_hInstance);
_Module.dwThreadID = GetCurrentThreadId();
// Check command line arguments.
TCHAR szTokens[] = _T("-/");
BOOL bRun = TRUE;
LPCTSTR lpszToken = FindOneOf(m_lpCmdLine, szTokens);
while (lpszToken != NULL)
{
// Register ATL and MFC class factories.
if (lstrcmpi(lpszToken, _T("Embedding"))==0 ||
lstrcmpi(lpszToken, _T("Automation"))==0)
{
AfxOleSetUserCtrl(FALSE);
break;
}
// Unregister servers.
// There is no unregistration code for MFC
// servers. Refer to Q186212 "HOWTO: Unregister MFC
// Automation Servers" for adding unregistration
// code.
else if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
{
VERIFY(SUCCEEDED(_Module.UpdateRegistryFromResource(IDR_Atlexe,
FALSE)));
VERIFY(SUCCEEDED(_Module.UnregisterServer(TRUE)));
bRun = FALSE;
break;
}
// Register ATL and MFC objects in the registry.
else if (lstrcmpi(lpszToken, _T("RegServer"))==0)
{
VERIFY(SUCCEEDED(_Module.UpdateRegistryFromResource(IDR_Atlexe,
TRUE)));
VERIFY(SUCCEEDED(_Module.RegisterServer(TRUE)));
COleObjectFactory::UpdateRegistryAll();
bRun = FALSE;
break;
}
lpszToken = FindOneOf(lpszToken, szTokens);
}
if (bRun)
{
// Comment out the next line if not using VC 6-generated
// code.
_Module.StartMonitor();
VERIFY(SUCCEEDED(_Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE)));
VERIFY(COleObjectFactory::RegisterAll());
// To run the EXE standalone, you need to create a window
// and assign the CWnd* to m_pMainWnd.
}
return TRUE;
}
int CMyApp::ExitInstance()
{
// MFC's class factories registration is
// automatically revoked by MFC itself.
_Module.RevokeClassObjects(); // Revoke class factories for ATL.
_Module.Term(); // Cleanup ATL Global Module.
return CWinApp::ExitInstance();
}
5. For unicode builds make sure the entry point is set to
wWinMainCRTStartup in the "Output" category of the "Link" field in the
Project Settings dialog box. For additional information, please see the
following article in the Microsoft Knowledge Base:
ARTICLE-ID: Q125750
TITLE : PRB: Error LNK2001: '_WinMain@16': Unresolved External
Symbol
6. Add the following line of code to the beginning of every member function
of a COM interface, window procedure, and exported function:
AFX_MANAGE_STATE(AfxGetAppModuleState());
For more information on AFX_MANAGE_STATE, consult the VC++ online
documentation.
Adding MFC Support to an ATL DLL Project
----------------------------------------
Follow steps 1 to 3 from above.
4. Move the code in the AppWizard generated DllMain's DLL_PROCESS_ATTACH
and DLL_PROCESS_DETACH to the CMyApp's InitInstance and ExitInstance and
remove the DllMain as follows:
BOOL CMyApp::InitInstance()
{
_Module.Init(ObjectMap, m_hInstance);
return CWinApp::InitInstance();
}
int CMyApp::ExitInstance()
{
_Module.Term();
return CWinApp::ExitInstance();
}
5. Add the following line of code to the beginning of every member function
of a COM interface, window procedure and exported function:
AFX_MANAGE_STATE(AfxGetStaticModuleState());
For additional information, please see the following article in the
Microsoft Knowledge Base:
ARTICLE-ID: Q140850
TITLE : HOWTO: Converting DLLTRACE to Use MFC in Shared Library
NOTE: For all release builds make sure that the _ATL_MIN_CRT preprocessor
definition has been removed. You can find these definitions in the
"Preprocessor" category of the C/C++ tab in the Project Settings dialog
box.
When adding a class derived from a MFC class using the ClassWizard to an
ATL EXE project or to an ATL DLL project without "MFC Support", the
compiler will issue a C2504 error.
REFERENCES
==========
MfcAtl Sample included with Visual C++ 5.0
ARTICLE-ID: Q166480
TITLE : INFO: Active Template Library(ATL) Frequently Asked Questions
ARTICLE-ID: Q186212
TITLE : HOWTO: Unregister MFC Automation Servers
(c) Microsoft Corporation 1997, All Rights Reserved.
Contributions by Chuck Bell, Microsoft Corporation
Mark A. Richman <ma...@programmer.net> wrote in article
<36C5A767...@programmer.net>...
> How do I add MFC to an existing ATL DLL project? I need to add support
> for CString, CTime, CStdioFile, and CFileException in one of my
> methods. I already changed the project settings to support MFC in a
> shared DLL.
>
> I tried #include <afxwin.h>, and <afxext.h> in the stdafx.h, but it
> gives this linker error:
>
> --------------------Configuration: ErrorCollection - Win32
> Debug--------------------
> Compiling...
> StdAfx.cpp
> Compiling...
> ErrorCollection.cpp
> IcnError.cpp
> IcnErrors.cpp
> Generating Code...
> Linking...
> nafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined
> in ErrorCollection.obj
> nafxcwd.lib(dllmodul.obj) : warning LNK4006: _DllMain@12 already defined
> in ErrorCollection.obj; second definition ignored
> Creating library Debug/ErrorCollection.lib and object
> Debug/ErrorCollection.exp
> Debug/ErrorCollection.dll : fatal error LNK1169: one or more multiply
> defined symbols found
> Error executing link.exe.
>
> ErrorCollection.dll - 2 error(s), 1 warning(s)
>
----------------------------------------------------------------------------
----------------------------
>
> I read this MSKB article:
> http://support.microsoft.com/support/kb/articles/q173/9/74.asp, but I
> don't think I should have to add any CWinApp-derived classes since I
> just need the class definitions for the aforementioned classes.
>
> Thanks,
> Mark
>
>
Add the following line of code to the beginning of every member function
of a COM interface, window procedure, and exported function:
AFX_MANAGE_STATE(AfxGetAppModuleState());
Thanks,
Mark
MFC maintains a structure for each DLL within a process that is using MFCs
runtime DLL. As the applications context switches between these dlls, MFC
must remember which module context it is running in. AFX_MANAGE_STATE macro
makes sure the module state is correct for the given DLL context.
All method should have this AFX_MANAGE_STATE macro call BEFORE any other
code in the module.
Also, have a look at Tech. Note 58.
Larry Wall, MCSE
Team Leader, Microsoft Group
Integration Technology
Mark A. Richman <ma...@programmer.net> wrote in message
news:36C61961...@programmer.net...
>