Application Information and Management
The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.
The latest version of this topic can be found at Application Information and Management.
When you write an application, you create a single CWinApp-derived object. At times, you may want to get information about this object from outside the CWinApp
-derived object.
The Microsoft Foundation Class Library provides the following global functions to help you accomplish these tasks:
Application Information and Management Functions
AfxBeginThread | Creates a new thread. |
AfxEndThread | Terminates the current thread. |
AfxFreeLibrary | Decrements the reference count of the loaded dynamic-link library (DLL) module; when the reference count reaches zero, the module is unmapped. |
AfxGetApp | Returns a pointer to the application's single CWinApp object. |
AfxGetAppName | Returns a string that contains the application's name. |
AfxGetInstanceHandle | Returns an HINSTANCE representing this instance of the application. |
AfxGetMainWnd | Returns a pointer to the current "main" window of a non-OLE application, or the in-place frame window of a server application. |
AfxGetPerUserRegistration | Use this function to determine whether the application redirects registry access to the HKEY_CURRENT_USER ( HKCU) node. |
AfxGetResourceHandle | Returns an HINSTANCE to the source of the application's default resources. Use this to access the application's resources directly. |
AfxGetThread | Retrieves a pointer to the current CWinThread object. |
AfxInitRichEdit | Initializes the version 1.0 rich edit control for the application. |
AfxInitRichEdit2 | Initializes the version 2.0 and later rich edit control for the application. |
AfxLoadLibrary | Maps a DLL module and returns a handle that can be used to obtain the address of a DLL function. |
AfxRegisterClass | Registers a window class in a DLL that uses MFC. |
AfxRegisterWndClass | Registers a Windows window class to supplement those registered automatically by MFC. |
AfxSetPerUserRegistration | Sets whether the application redirects registry access to the HKEY_CURRENT_USER ( HKCU) node. |
AfxSetResourceHandle | Sets the HINSTANCE handle where the default resources of the application are loaded. |
AfxSocketInit | Called in a CWinApp::InitInstance override to initialize Windows Sockets. |
AfxWinInit | Called by the MFC-supplied WinMain function, as part of the CWinApp initialization of a GUI-based application, to initialize MFC. Must be called directly for console applications that use MFC. |
AfxBeginThread
Call this function to create a new thread.
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
Parameters
pfnThreadProc
Points to the controlling function for the worker thread. Cannot be NULL. This function must be declared as follows:
UINT __cdecl MyControllingFunction( LPVOID pParam );
pThreadClass
The RUNTIME_CLASS of an object derived from CWinThread.
pParam
Parameter to be passed to the controlling function as shown in the parameter to the function declaration in pfnThreadProc
.
nPriority
The desired priority of the thread. For a full list and description of the available priorities, see SetThreadPriority in the Windows SDK.
nStackSize
Specifies the size in bytes of the stack for the new thread. If 0, the stack size defaults to the same size stack as the creating thread.
dwCreateFlags
Specifies an additional flag that controls the creation of the thread. This flag can contain one of two values:
CREATE_SUSPENDED Start the thread with a suspend count of one. Use CREATE_SUSPENDED if you want to initialize any member data of the
CWinThread
object, such as m_bAutoDelete or any members of your derived class, before the thread starts running. Once your initialization is complete, use CWinThread::ResumeThread to start the thread running. The thread will not execute untilCWinThread::ResumeThread
is called.0 Start the thread immediately after creation.
lpSecurityAttrs
Points to a SECURITY_ATTRIBUTES structure that specifies the security attributes for the thread. If NULL, the same security attributes as the creating thread will be used. For more information on this structure, see the Windows SDK.
Return Value
Pointer to the newly created thread object, or NULL if a failure occurs.
Remarks
The first form of AfxBeginThread
creates a worker thread. The second form creates a thread that may serve as a user-interface thread or as a worker thread.
AfxBeginThread
creates a new CWinThread
object, calls its CreateThread function to start executing the thread, and returns a pointer to the thread. Checks are made throughout the procedure to make sure all objects are deallocated properly should any part of the creation fail. To end the thread, call AfxEndThread from within the thread, or return from the controlling function of the worker thread.
Multithreading must be enabled by the application; otherwise, this function will fail. For more information on enabling multithreading, refer to /MD, /MT, /LD (Use Run-Time Library) under Visual C++ Compiler Options.
For more information on AfxBeginThread
, see the articles Multithreading: Creating Worker Threads and Multithreading: Creating User-Interface Threads.
Example
See the example for CSocket::Attach.
AfxEndThread
Call this function to terminate the currently executing thread.
void AFXAPI AfxEndThread(
UINT nExitCode,
BOOL bDelete = TRUE);
Parameters
nExitCode
Specifies the exit code of the thread.
bDelete
Deletes the thread object from memory.
Remarks
Must be called from within the thread to be terminated.
For more information on AfxEndThread
, see the article Multithreading: Terminating Threads.
AfxFreeLibrary
Both AfxFreeLibrary
and AfxLoadLibrary
maintain a reference count for each loaded library module.
BOOL AFXAPI AfxFreeLibrary(HINSTANCE hInstLib);
Parameters
hInstLib
A handle of the loaded library module. AfxLoadLibrary returns this handle.
Return Value
TRUE if the function succeeds; otherwise, FALSE.
Remarks
AfxFreeLibrary
decrements the reference count of the loaded dynamic-link library (DLL) module. When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid. This reference count is incremented each time AfxLoadLibrary
is called.
Before unmapping a library module, the system enables the DLL to detach from the processes using it. Doing so gives the DLL an opportunity to clean up resources allocated on behalf of the current process. After the entry-point function returns, the library module is removed from the address space of the current process.
Use AfxLoadLibrary
to map a DLL module.
Be sure to use AfxFreeLibrary
and AfxLoadLibrary
(instead of the Win32 functions FreeLibrary and LoadLibrary) if your application uses multiple threads. Using AfxLoadLibrary
and AfxFreeLibrary
ensures that the startup and shutdown code that executes when the extension DLL is loaded and unloaded does not corrupt the global MFC state.
Example
See the example for AfxLoadLibrary.
AfxGetApp
The pointer returned by this function can be used to access application information such as the main message-dispatch code or the topmost window.
CWinApp* AFXAPI AfxGetApp();
Return Value
A pointer to the single CWinApp
object for the application.
Remarks
If this method returns NULL, it might indicate that the application’s main window has not been fully initialized yet. It might also indicate a problem.
Example
// Print the application's executable filename.
TRACE(_T("Executable filename = %s\n"), AfxGetApp()->m_pszExeName);
AfxGetAppName
The string returned by this function can be used for diagnostic messages or as a root for temporary string names.
LPCTSTR AFXAPI AfxGetAppName();
Return Value
A null-terminated string containing the application's name.
Example
// Print the application name to the debugger output window.
TRACE(_T("Application name is %s\n"), AfxGetAppName());
AfxGetInstanceHandle
This function allows you to retrieve the instance handle of the current application.
HINSTANCE AFXAPI AfxGetInstanceHandle();
Return Value
An HINSTANCE
to the current instance of the application. If called from within a DLL linked with the USRDLL version of MFC, an HINSTANCE
to the DLL is returned.
Remarks
AfxGetInstanceHandle
always returns the HINSTANCE
of your executable file (.EXE) unless it is called from within a DLL linked with the USRDLL version of MFC. In this case, it returns an HINSTANCE
to the DLL.
Example
// Print the application instance handle to the debugger output window.
TRACE(_T("Application instance handle is 0x%0X\n"), AfxGetInstanceHandle());
AfxGetMainWnd
If your application is an OLE server, call this function to retrieve a pointer to the active main window of the application instead of directly referring to the m_pMainWnd member of the application object.
CWnd* AFXAPI AfxGetMainWnd();
Return Value
If the server has an object that is in-place active inside a container, and this container is active, this function returns a pointer to the frame window object that contains the in-place active document.
If there is no object that is in-place active within a container, or your application is not an OLE server, this function simply returns the m_pMainWnd
of your application object.
If AfxGetMainWnd
is called from the application's primary thread, it returns the application's main window according to the above rules. If the function is called from a secondary thread in the application, the function returns the main window associated with the thread that made the call.
Remarks
If your application is not an OLE server, then calling this function is equivalent to directly referring to the m_pMainWnd
member of your application object.
Example
//The following line send a WM_CLOSE message
// to the Application's main window. This will cause the
// Application to exit.
AfxGetMainWnd()->PostMessage(WM_CLOSE, 0, 0);
AfxGetPerUserRegistration
Use this function to determine whether the application redirects registry access to the HKEY_CURRENT_USER ( HKCU) node.
BOOL AFXAPI AfxGetPerUserRegistration();
Return Value
TRUE
indicates that the registry information is directed to the HKCU node; FALSE
indicates that the application writes registry information to the default node. The default node is HKEY_CLASSES_ROOT ( HKCR).
Remarks
If you enable registry redirection, the framework redirects access from HKCR to HKEY_CURRENT_USER\Software\Classes. Only the MFC and ATL frameworks are affected by the redirection.
To change whether the application redirects registry access, use AfxSetPerUserRegistration.
AfxGetResourceHandle
Use the HINSTANCE
handle returned by this function to access the application's resources directly, for example, in calls to the Windows function FindResource.
extern HINSTANCE AfxGetResourceHandle();
Return Value
An HINSTANCE
handle where the default resources of the application are loaded.
Example
//Load the menu specifying the module handle where resource is to be
//found & resource ID
HMENU hMenu = ::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
AfxGetThread
Call this function to get a pointer to the CWinThread object representing the currently executing thread.
CWinThread* AfxGetThread();
Return Value
Pointer to the currently executing thread; otherwise NULL.
Remarks
Must be called from within the desired thread.
Note
If you are porting an MFC project calling AfxGetThread
from Visual C++ versions 4.2, 5.0, or 6.0, AfxGetThread
calls AfxGetApp if no thread is found. In Visual C+ .NET and later, AfxGetThread
returns NULL if no thread was found. If you want the application thread, you must call AfxGetApp
.
Example
//Print the current thread ID in the Debug Window
TRACE(_T("Current Thread ID = 0x%X\n"), AfxGetThread()->m_nThreadID);
AfxInitRichEdit
Call this function to initialize the rich edit control (version 1.0) for the application.
BOOL AFXAPI AfxInitRichEdit();
Remarks
This function is provided for backward compatibility. Applications created with Visual C++ .NET and later use AfxInitRichEdit2.
AfxInitRichEdit
loads RICHED32.DLL to initialize version 1.0 of the rich edit control. To use version 2.0 and 3.0 of the rich edit control, RICHED20.DLL needs to be loaded. This is accomplished with a call to AfxInitRichEdit2. If you have dialog resources with the rich edit control created prior to Visual C++ .NET, the rich edit controls are automatically version 1.0. Rich edit controls inserted using the Visual C++ .NET Resource Editor are version 2.0.
To update rich edit controls in existing Visual C++ applications to version 2.0, open the .RC file as text, change the class name of each rich edit control from "RICHEDIT" to "RichEdit20a". Then replace the call to AfxInitRichEdit
with AfxInitRichEdit2
.
This function also initializes the common controls library, if the library hasn't already been initialized for the process. If you use the rich edit control directly from your MFC application, you should call this function to assure that MFC has properly initialized the rich edit control runtime. If you call the Create method of CRichEditCtrl, CRichEditView, or CRichEditDoc, you typically don't need to call this function, but in some cases it might be necessary.
AfxInitRichEdit2
Call this function to initialize the rich edit control (version 2.0 and later) for the application.
BOOL AFXAPI AfxInitRichEdit2();
Remarks
Call this function to load the RICHED20.DLL and initialize version 2.0 of the rich edit control. If you call the Create method of CRichEditCtrl, CRichEditView, or CRichEditDoc, you typically don't need to call this function, but in some cases it might be necessary.
AfxLoadLibrary
Use AfxLoadLibrary
to map a DLL module.
HINSTANCE AFXAPI AfxLoadLibrary(LPCTSTR lpszModuleName);
Parameters
lpszModuleName
Points to a null-terminated string that contains the name of the module (either a .DLL or .EXE file). The name specified is the filename of the module.
If the string specifies a path but the file does not exist in the specified directory, the function fails.
If a path is not specified and the filename extension is omitted, the default extension .DLL is appended. However, the filename string can include a trailing point character (.) to indicate that the module name has no extension. When no path is specified, the function searches for the file in the following sequence:
The directory from which the application loaded.
The current directory.
Windows 95/98: The Windows system directory. Windows NT: The 32-bit Windows system directory. The name of this directory is SYSTEM32.
Windows NT only: The 16-bit Windows system directory. There is no Win32 function that obtains the path of this directory, but it is searched. The name of this directory is SYSTEM.
The Windows directory.
The directories that are listed in the PATH environment variable.
Return Value
If the function succeeds, the return value is a handle to the module. If the function fails, the return value is NULL.
Remarks
It returns a handle that can be used in GetProcAddress to get the address of a DLL function. AfxLoadLibrary
can also be used to map other executable modules.
Each process maintains a reference count for each loaded library module. This reference count is incremented each time AfxLoadLibrary
is called and is decremented each time AfxFreeLibrary
is called. When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid.
Be sure to use AfxLoadLibrary
and AfxFreeLibrary
(instead of the Win32 functions LoadLibrary and FreeLibrary) if your application uses multiple threads and if it dynamically loads an extension DLL. Using AfxLoadLibrary
and AfxFreeLibrary
insures that the startup and shutdown code that executes when the extension DLL is loaded and unloaded does not corrupt the global MFC state.
Using AfxLoadLibrary
in an application requires you to dynamically link to the DLL version of MFC; the header file for AfxLoadLibrary
, Afxdll_.h, is only included if MFC is linked to the application as a DLL. This is by design because you have to link to the DLL version of MFC to use or create extension DLLs.
Example
// The following shows how to create a MDI based application
// using a generic CView derived class that is implemented in
// a dynamically loaded MFC Extension DLL.
typedef CRuntimeClass * (*GETDLLVIEW)();
BOOL CUserApp::InitInstance()
{
// Standard Application Wizard generated initialization excluded.
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views
//Load MFC Extension DLL based view class.
m_hViewDll = AfxLoadLibrary(szMyViewDllPath);
if (!m_hViewDll)
{
CString str;
str.Format(_T("Error: Cannot find component %s"), szMyViewDllPath);
AfxMessageBox(str);
return FALSE;
}
GETDLLVIEW GetMyView = (GETDLLVIEW)GetProcAddress(m_hViewDll, "GetMyView");
ASSERT(GetMyView != NULL);
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_NVC_MFC_DLLUserTYPE,
RUNTIME_CLASS(CUserDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
GetMyView());
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// Standard Application Wizard generated initalization excluded.
return TRUE;
}
int CUserApp::ExitInstance()
{
if (NULL != m_hViewDll)
{
AfxFreeLibrary(m_hViewDll);
m_hViewDll = NULL;
}
return CWinApp::ExitInstance();
}
AfxRegisterClass
Use this function to register window classes in a DLL that uses MFC.
BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass);
Parameters
lpWndClass
Pointer to a WNDCLASS structure containing information about the window class to be registered. For more information on this structure, see the Windows SDK.
Return Value
TRUE if the class is successfully registered; otherwise FALSE.
Remarks
If you use this function, the class is automatically unregistered when the DLL is unloaded.
In non-DLL builds, the AfxRegisterClass
identifier is defined as a macro that maps to the Windows function RegisterClass, since classes registered in an application are automatically unregistered. If you use AfxRegisterClass
instead of RegisterClass, your code can be used without change both in an application and in a DLL.
Example
// Register your unique class name that you wish to use
WNDCLASS wndcls;
memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
//you can specify your own window procedure
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hIcon = LoadIcon(wndcls.hInstance, MAKEINTRESOURCE(IDI_MYICON));
wndcls.hCursor = LoadCursor(wndcls.hInstance, MAKEINTRESOURCE(IDC_ARROW));
wndcls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndcls.lpszMenuName = NULL;
// Specify your own class name for using FindWindow later
wndcls.lpszClassName = _T("MyNewClass");
// Register the new class and trace if it fails
if(!AfxRegisterClass(&wndcls))
{
TRACE("Class Registration Failed\n");
}
AfxRegisterWndClass
Allows you to register your own window classes.
LPCTSTR AFXAPI AfxRegisterWndClass(
UINT nClassStyle,
HCURSOR hCursor = 0,
HBRUSH hbrBackground = 0,
HICON hIcon = 0);
Parameters
nClassStyle
Specifies the Windows class style or combination of styles, created by using the bitwise-OR ( |) operator, for the window class. For a list of class styles, see the WNDCLASS structure in the Windows SDK. If NULL, the defaults will be set as follows:
Sets the mouse style to CS_DBLCLKS, which sends double-click messages to the window procedure when the user double-clicks the mouse.
Sets the arrow cursor style to the Windows standard IDC_ARROW.
Sets the background brush to NULL, so the window will not erase its background.
Sets the icon to the standard, waving-flag Windows logo icon.
hCursor
Specifies a handle to the cursor resource to be installed in each window created from the window class. If you use the default of 0, you will get the standard IDC_ARROW cursor.
hbrBackground
Specifies a handle to the brush resource to be installed in each window created from the window class. If you use the default of 0, you will have a NULL background brush, and your window will, by default, not erase its background while processing WM_ERASEBKGND.
hIcon
Specifies a handle to the icon resource to be installed in each window created from the window class. If you use the default of 0, you will get the standard, waving-flag Windows logo icon.
Return Value
A null-terminated string containing the class name. You can pass this class name to the Create member function in CWnd
or other CWnd-derived classes to create a window. The name is generated by the Microsoft Foundation Class Library.
Note
The return value is a pointer to a static buffer. To save this string, assign it to a CString
variable.
Remarks
The Microsoft Foundation Class Library automatically registers several standard window classes for you. Call this function if you want to register your own window classes.
The name registered for a class by AfxRegisterWndClass
depends solely on the parameters. If you call AfxRegisterWndClass
multiple times with identical parameters, it only registers a class on the first call. Subsequent calls to AfxRegisterWndClass
with identical parameters simply return the already-registered classname.
If you call AfxRegisterWndClass
for multiple CWnd-derived classes with identical parameters, instead of getting a separate window class for each class, each class shares the same window class. This can cause problems if the CS_CLASSDC class style is used. Instead of multiple CS_CLASSDC window classes, you end up with one CS_CLASSDC window class, and all C++ windows that use that class share the same DC. To avoid this problem, call AfxRegisterClass to register the class.
Refer to Technical Note TN001: Window Class Registration for more information on window class registration and the AfxRegisterWndClass
function.
Example
CString strMyClass;
// load stock cursor, brush, and icon for
// my own window class
try
{
strMyClass = AfxRegisterWndClass(
CS_VREDRAW | CS_HREDRAW,
::LoadCursor(NULL, IDC_ARROW),
(HBRUSH) ::GetStockObject(WHITE_BRUSH),
::LoadIcon(NULL, IDI_APPLICATION));
}
catch (CResourceException* pEx)
{
AfxMessageBox(_T("Couldn't register class! (Already registered?)"));
pEx->Delete();
}
AfxSetPerUserRegistration
Sets whether the application redirects registry access to the HKEY_CURRENT_USER ( HKCU) node.
void AFXAPI AfxSetPerUserRegistration(BOOL bEnable);
Parameters
[in] bEnable
TRUE
indicates that the registry information is directed to the HKCU node; FALSE
indicates that the application writes registry information to the default node. The default node is HKEY_CLASSES_ROOT ( HKCR).
Remarks
Before Windows Vista, applications that access the registry usually use the HKEY_CLASSES_ROOT node. However, with Windows Vista, you must run an application in elevated mode to write to HKCR.
This method enables your application to read and write to the registry without running in elevated mode by redirecting registry access from HKCR to HKCU. For more information, see Linker Property Pages.
If you enable registry redirection, the framework redirects access from HKCR to HKEY_CURRENT_USER\Software\Classes. Only the MFC and ATL frameworks are affected by the redirection.
The default implementation accesses the registry under HKCR.
AfxSetResourceHandle
Use this function to set the HINSTANCE
handle that determines where the default resources of the application are loaded.
void AFXAPI AfxSetResourceHandle(HINSTANCE hInstResource);
Parameters
hInstResource
The instance or module handle to an .EXE or DLL file from which the application's resources are loaded.
Example
// This code is taken from CMyApp::InitInstance
HINSTANCE hRes = NULL;
hRes = LoadLibrary(_T("Resource.dll"));
if(hRes)
AfxSetResourceHandle(hRes);
AfxSocketInit
Call this function in your CWinApp::InitInstance
override to initialize Windows Sockets.
BOOL
AfxSocketInit(WSADATA* lpwsaData = NULL);
Parameters
lpwsaData
A pointer to a WSADATA structure. If lpwsaData
is not equal to NULL
, then the address of the WSADATA
structure is filled by the call to WSAStartup
. This function also ensures that WSACleanup
is called for you before the application terminates.
Return Value
Nonzero if the function is successful; otherwise 0.
Remarks
When using MFC sockets in secondary threads in a statically linked MFC application, you must call AfxSocketInit
in each thread that uses sockets to initialize the socket libraries. By default, AfxSocketInit
is called only in the primary thread.
AfxWinInit
This function is called by the MFC-supplied WinMain
function, as part of the CWinApp initialization of a GUI-based application, to initialize MFC.
BOOL AFXAPI AfxWinInit(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow);
Parameters
hInstance
The handle of the currently running module.
hPrevInstance
A handle to a previous instance of the application. For a Win32-based application, this parameter is always NULL.
lpCmdLine
Points to a null-terminated string specifying the command line for the application.
nCmdShow
Specifies how the main window of a GUI application would be shown.
Remarks
For a console application, which does not use the MFC-supplied WinMain
function, you must call AfxWinInit
directly to initialize MFC.
If you call AfxWinInit
yourself, you should declare an instance of a CWinApp
class. For a console application, you might choose not to derive your own class from CWinApp
and instead use an instance of CWinApp
directly. This technique is appropriate if you decide to leave all functionality for your application in your implementation of main.
Note
When it creates an activation context for an assembly, MFC uses a manifest resource provided by the user module. The activation context is created in AfxWinInit
. For more information, see Support for Activation Contexts in the MFC Module State.
Example
#include <afx.h>
#include <afxdb.h>
int _tmain(int /*argc*/, TCHAR* /*argv[]*/, TCHAR* /*envp[]*/)
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
// try to connect to an ODBC database that doesn't exist
// (this wouldn't work at all without initializing MFC)
CDatabase db;
try
{
db.Open(_T("This Databsae Doesn't Exist"));
// we shouldn't realistically get here
_tprintf_s(_T("Successful!\n")
_T("Closing ...\n"));
db.Close();
_tprintf_s(_T("Closed!"));
}
catch (CDBException* pEx)
{
// we got an exception! print an error message
// (this wouldn't work without initializing MFC)
TCHAR sz[1024];
_tprintf_s(_T("Error: "));
if (pEx->GetErrorMessage(sz, 1024))
_tprintf_s(sz);
else
_tprintf_s(_T("No error message was available"));
_tprintf_s(_T("\n"));
pEx->Delete();
nRetCode = 1;
}
}
return nRetCode;
}