Click here to Skip to main content
12,752,448 members (38,367 online)
Click here to Skip to main content
Add your own
alternative version


143 bookmarked
Posted 17 Dec 2001

MFC under the hood

, 2 Jul 2002 CPOL
Rate this:
Please Sign up or sign in to vote.
Explains the basic MFC program flow including where WinMain and the message loop are hidden


Most MFC/VC++ programmers generate their projects using App Wizard and are quite happy with that. Once in a while, you have a programmer who will ask you, what happened to WinMain and he is normally satisfied with the answer given that WinMain is hidden within the MFC libraries. In this article I'll try and explain the life-cycle of a typical MFC program. Before I do that I'd like to introduce you to the smallest MFC program you can write that will show a window on screen, other than by using a MessageBox.

Smallest MFC window-program

class CNWinApp  : public CWinApp
    BOOL InitInstance();
#include <afxwin.h>
#include "NWinApp.h"

CNWinApp app;

BOOL CNWinApp::InitInstance()
    CFrameWnd *pnframe=new CFrameWnd;
    return TRUE;

So, what happened to good old WinMain?

When you run your program the kernel first calls this function, WinMainCRTStartup. WinMainCRTStartup first initializes the CRT routines. Then it parses the command line and removes the filename portion and calls WinMain passing the parsed command line as lpszCommandLine. But then where is WinMain? :-) It is defined in appmodul.cpp which you can find in your MFC\SRC directory. Here is how the function is implemented.

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine, int nCmdShow)
    // call shared/exported WinMain
    return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

As you will observe, WinMain simply calls AfxWinMain. AfxWinMain is defined in winmain.cpp which you will find under your MFC\SRC directory. I'll list the function below exactly as it is defined.

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine, int nCmdShow)
    ASSERT(hPrevInstance == NULL);

    int nReturnCode = -1;
    CWinThread* pThread = AfxGetThread();
    CWinApp* pApp = AfxGetApp();

    // AFX internal initialization
    if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
        goto InitFailure;

    // App global initializations (rare)
    if (pApp != NULL && !pApp->InitApplication())
        goto InitFailure;

    // Perform specific initializations
    if (!pThread->InitInstance())
        if (pThread->m_pMainWnd != NULL)
            TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
        nReturnCode = pThread->ExitInstance();
        goto InitFailure;
    nReturnCode = pThread->Run();

#ifdef _DEBUG
    // Check for missing AfxLockTempMap calls
    if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
        TRACE1("Warning: Temp map lock count non-zero (%ld).\n",

    return nReturnCode;

As you can see the functions AfxGetThread and AfxGetApp are used to get pointers to the CWinApp derived global object  and the current thread. If you are surprised as to how the global CWinApp derived object already exists, relax, C++ programs will first create all global and static objects before execution begins. All that happens much before AfxWinMain gets called. By the way, it must have been a slight shock to you to see a goto in there, eh?

Now there might be those of you who might be wondering where AfxGetThread and AfxGetApp got their information from. The answer is simple. Take a look at the CWinApp constructor in appcore.cpp. You'll find the following two lines.

pThreadState->m_pCurrentWinThread = this;


pModuleState->m_pCurrentWinApp = this;

pThreadState is a AFX_MODULE_THREAD_STATE* and pModuleState is a AFX_MODULE_STATE*.

Thus when we create our global CNWinApp object, it's constructor gets called and the AFX_MODULE_STATE structure is setup properly. Now AfxWinInit is called and this function initializes the MFC framework. Now there is a call to InitApplication [this is for backward compatibility with 16-bit applications]. Now it calls the InitInstance of the CWinApp derived object. And as you can see from our code listing above we have overridden InitInstance and created a CFrameWnd object there. I'll repeat the code snippet here so that you won't have to scroll upwards.

BOOL CNWinApp::InitInstance()
    CFrameWnd *pnframe=new CFrameWnd;
    return TRUE;

I have created my CFrameWnd object on the heap, otherwise the moment InitInstance exits, the window will get destroyed. I have also set m_pMainWnd to point to my CFrameWnd window. Once InitInstance returns [if it returns false an error is assumed, so we return true], CWinApp::Run is called. Within the Run function is implemented our default message loop. Run keeps getting and dispatching messages till it receives a WM_QUIT message. Once WM_QUIT is received Run returns and control returns to AfxWinMain which performs clean-up and lastly calls AfxWinTerm which deletes all the global application structures that were created.

Well, that's it. Pretty amusing to think that all this while you were writing MFC applications and you never bothered to think about what was happening under the hood.


None of the information in this article is endorsed by me. I don't work for Microsoft and all my assumptions are just that - assumptions. Some of the info I have given might indeed be incorrect, though I'd say the probability for that is rather low. In case I have erred I'll be delighted if someone can correct those mistakes.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Nish Nishant
United States United States
Nish Nishant is the Principal Software Architect/Consultant for Ganymede Software Solutions LLC, and is based out of Columbus, Ohio. He has over 17 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish was a Microsoft Visual C++ MVP between 2002 and 2015.

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored C++/CLI in Action for Manning Publications in 2005, and had previously co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on and another 250+ blog articles on his WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : If you are interested in hiring Nish as a consultant, you can reach him via his google email id voidnish.

Company Website :

You may also be interested in...

Comments and Discussions

AnswerRe: Is CNWinApp a typo or I am missing something?! Pin
Nish Sivakumar1-Oct-12 3:00
mvpNish Sivakumar1-Oct-12 3:00 
GeneralMy vote of 5 Pin
Nitheesh George1-Aug-12 22:59
memberNitheesh George1-Aug-12 22:59 
AnswerRe: My vote of 5 Pin
Nish Sivakumar1-Oct-12 3:01
mvpNish Sivakumar1-Oct-12 3:01 
GeneralMy vote of 5 Pin
DarrylB19-Oct-11 4:17
memberDarrylB19-Oct-11 4:17 
AnswerRe: My vote of 5 Pin
Nish Sivakumar1-Oct-12 3:00
mvpNish Sivakumar1-Oct-12 3:00 
GeneralMy vote of 5 Pin
Nithin Sundar14-Feb-11 17:55
memberNithin Sundar14-Feb-11 17:55 
GeneralRe: My vote of 5 Pin
Nishant Sivakumar25-Apr-11 12:48
mvpNishant Sivakumar25-Apr-11 12:48 
GeneralUseful! Pin
Gianni Gardini5-Sep-08 6:10
memberGianni Gardini5-Sep-08 6:10 
Questionevent for ownerdrawn button Pin
santhoshv8418-Dec-06 21:10
membersanthoshv8418-Dec-06 21:10 
QuestionAFXAPI Pin
chernobyl15-Dec-06 16:40
memberchernobyl15-Dec-06 16:40 
GeneralWinApp fails initialization Pin
David_Leikis14-Nov-05 9:19
memberDavid_Leikis14-Nov-05 9:19 
GeneralRe: WinApp fails initialization Pin
Nishant Sivakumar14-Nov-05 9:57
staffNishant Sivakumar14-Nov-05 9:57 
GeneralRe: WinApp fails initialization Pin
David_Leikis14-Nov-05 11:06
memberDavid_Leikis14-Nov-05 11:06 
GeneralRe: WinApp fails initialization Pin
RsK_frmrf23-Sep-06 13:12
memberRsK_frmrf23-Sep-06 13:12 
GeneralRe: WinApp fails initialization Pin
Abyss27-May-07 8:18
memberAbyss27-May-07 8:18 
GeneralRe: WinApp fails initialization Pin
Mats_SWE18-Feb-09 4:20
memberMats_SWE18-Feb-09 4:20 
AnswerRe: WinApp fails initialization Pin
Sharjith16-Mar-10 11:31
memberSharjith16-Mar-10 11:31 
GeneralRe: WinApp fails initialization Pin
_infrared_12-Jan-11 14:14
member_infrared_12-Jan-11 14:14 
GeneralRe: WinApp fails initialization Pin
Sharjith16-Mar-10 11:22
memberSharjith16-Mar-10 11:22 
GeneralDeleting a line from text file Pin
Anonymous19-Sep-05 2:01
sussAnonymous19-Sep-05 2:01 
GeneralWinMainCRTStartup Pin
Alois Kraus31-May-05 22:38
memberAlois Kraus31-May-05 22:38 
GeneralRe: WinMainCRTStartup Pin
dwangs27-Jul-05 17:38
memberdwangs27-Jul-05 17:38 
GeneralNew error while linking Pin
Anonymous19-Mar-05 7:02
sussAnonymous19-Mar-05 7:02 
Generalheader file Pin
mimi1234-Oct-04 21:14
membermimi1234-Oct-04 21:14 
GeneralRe: header file Pin
Asad_hyd12-Oct-04 2:03
sussAsad_hyd12-Oct-04 2:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170217.1 | Last Updated 3 Jul 2002
Article Copyright 2001 by Nish Nishant
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid