MFC中如何改装SDK的WinMain函数

 

  

1.在TCHAR.H文件中定义了一个宏:
#define _tWinMain WinMain
这样MFC源代码在编译的时候,_tWinMain就会被替换为WinMain(),这样操作系统就可以调用了。


2.在APPMODUL.CPP文件中,定义了_tWinMain(),在_tWinMain()中 return AfxWinMain();

1 extern "C" int WINAPI
2 _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
3     LPTSTR lpCmdLine, int nCmdShow)
4 {
5     // call shared/exported WinMain
6     return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
7 }

 

3.在WINMAIN.CPP中定义了 AfxWinMain函数,

在里面调用pApp->InitApplication()

     pApp->InitInstance()

             pThread->Run();  

 

 1 int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 2     LPTSTR lpCmdLine, int nCmdShow)
 3 {
 4     ASSERT(hPrevInstance == NULL);
 5 
 6     int nReturnCode = -1;
 7     CWinThread* pThread = AfxGetThread();
 8     CWinApp* pApp = AfxGetApp();
 9 
10     // AFX internal initialization
11     if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
12         goto InitFailure;
13 
14     // App global initializations (rare)
15     if (pApp != NULL && !pApp->InitApplication())
16         goto InitFailure;
17 
18     // Perform specific initializations
19     if (!pThread->InitInstance())
20     {
21         if (pThread->m_pMainWnd != NULL)
22         {
23             TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
24             pThread->m_pMainWnd->DestroyWindow();
25         }
26         nReturnCode = pThread->ExitInstance();
27         goto InitFailure;
28     }
29     nReturnCode = pThread->Run();
30 
31 InitFailure:
32 #ifdef _DEBUG
33     // Check for missing AfxLockTempMap calls
34     if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
35     {
36         TRACE1("Warning: Temp map lock count non-zero (%ld).\n",
37             AfxGetModuleThreadState()->m_nTempMapLock);
38     }
39     AfxLockTempMaps();
40     AfxUnlockTempMaps(-1);
41 #endif
42 
43     AfxWinTerm();
44     return nReturnCode;
45 }

 稍加整理之后可以理解为

 int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
     LPTSTR lpCmdLine, int nCmdShow)
 {
 
 
     CWinThread* pThread = AfxGetThread();
     CWinApp* pApp = AfxGetApp();
 
     AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
 
     pApp->InitApplication();
         
     pThread->InitInstance();

     nReturnCode = pThread->Run();
 
 
     return nReturnCode;
 }

 

4.在APPINIT.CPP中查看AfxWinInit()

 1 BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 2     LPTSTR lpCmdLine, int nCmdShow)
 3 {
 4     ASSERT(hPrevInstance == NULL);
 5 
 6     // handle critical errors and avoid Windows message boxes
 7     SetErrorMode(SetErrorMode(0) |
 8         SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
 9 
10     // set resource handles
11     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
12     pModuleState->m_hCurrentInstanceHandle = hInstance;
13     pModuleState->m_hCurrentResourceHandle = hInstance;
14 
15     // fill in the initial state for the application
16     CWinApp* pApp = AfxGetApp();
17     if (pApp != NULL)
18     {
19         // Windows specific initialization (not done if no CWinApp)
20         pApp->m_hInstance = hInstance;
21         pApp->m_hPrevInstance = hPrevInstance;
22         pApp->m_lpCmdLine = lpCmdLine;
23         pApp->m_nCmdShow = nCmdShow;
24         pApp->SetCurrentHandles();
25     }
26 
27     // initialize thread specific data (for main thread)
28     if (!afxContextIsDLL)
29         AfxInitThread();
30 
31     return TRUE;
32 }

 

 在AfxWinInit中主要是做了一些初始化工作,以及使用AfxInitThread() hook一些消息 我目前还不明确

 

5.AfxWinInit之后 执行pApp->InitApplication()   APPCORE.CPP

6.接着执行 pApp->InitInstance()  在CWinApp中可以看到

     

BOOL CWinApp::InitInstance()
{
    return TRUE;
}

这是一个需要我们在派送类里面进行重写的函数,利用它来显示窗口 也就是CFrameWnd类的派生类  简单的写法如下

BOOL  CMyWinApp::InitInstance()
{
   m_pMainWnd = new CMyFrameWnd();
   m_pMainWnd->ShowWindow(m_nCmdShow);
   m_pMainWnd->UpdateWindow();
   return TRUE;
  
}

其中CMyFrame是我自己写的CFrameWnd的派送类

MFC生成的是这样的

 1 BOOL CGraphApp::InitInstance()
 2 {
 3         // Standard initialization
 4         // If you are not using these features and wish to reduce the size
 5         //  of your final executable, you should remove from the following
 6         //  the specific initialization routines you do not need.
 7 
 8 #ifdef _AFXDLL
 9         Enable3dControls();                     // Call this when using MFC in a shared DLL
10 #else
11         Enable3dControlsStatic();       // Call this when linking to MFC statically
12 #endif
13 
14         LoadStdProfileSettings();  // Load standard INI file options (including MRU)
15 
16         // Register the application's document templates.  Document templates
17         //  serve as the connection between documents, frame windows and views.
18 
19         CMultiDocTemplate* pDocTemplate;
20         pDocTemplate = new CMultiDocTemplate(
21                 IDR_GRAPHTYPE,
22                 RUNTIME_CLASS(CGraphDoc),
23                 RUNTIME_CLASS(CChildFrame), // custom MDI child frame
24                 RUNTIME_CLASS(CGraphView));
25         AddDocTemplate(pDocTemplate);
26 
27         pDocTemplate = new CMultiDocTemplate(
28                 IDR_NEWTYPE,
29                 RUNTIME_CLASS(CNewDoc),
30                 RUNTIME_CLASS(CMDIChildWnd), // use directly ! because CChildFrame::OnCreateClient be overrided for Graph Doc Type
31                 RUNTIME_CLASS(CEditView));
32         AddDocTemplate(pDocTemplate);
33 
34         // create main MDI Frame window
35         CMainFrame* pMainFrame = new CMainFrame;
36         if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
37                 return FALSE;
38         m_pMainWnd = pMainFrame;
39 
40         // Enable drag/drop open
41         m_pMainWnd->DragAcceptFiles();
42 
43         // Enable DDE Execute open
44         EnableShellOpen();
45         RegisterShellFileTypes(TRUE);
46 
47         // Parse command line for standard shell commands, DDE, file open
48         CCommandLineInfo cmdInfo;
49         ParseCommandLine(cmdInfo);
50 
51         // Dispatch commands specified on the command line
52         if (!ProcessShellCommand(cmdInfo))
53                 return FALSE;
54 
55         // The main window has been initialized, so show and update it.
56         pMainFrame->ShowWindow(m_nCmdShow);
57         pMainFrame->UpdateWindow();
58 
59         return TRUE;
60 }

 

7.在InitInstance()中创建了一个CMyFrameWnd对象,故要先调用CMyFrameWnd的构造函数,因为CMyFrameWnd的基类是CFrameWnd,所以先调用CFrameWnd的构造函数  

  被定义在WINFRM.CPP,可以继续追踪到CWnd类,CCmdTarget类,CObject类,但是都没有发现有关窗口创建的函数被调用。其实是利用

pMainFrame->LoadFrame(IDR_MAINFRAME)   完成的

    

8.CFrameWnd::LoadFrame()函数定义在WINFRM.CPP中 

 1 BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
 2     CWnd* pParentWnd, CCreateContext* pContext)
 3 {
 4     // only do this once
 5     ASSERT_VALID_IDR(nIDResource);
 6     ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
 7 
 8     m_nIDHelp = nIDResource;    // ID for help context (+HID_BASE_RESOURCE)
 9 
10     CString strFullString;
11     if (strFullString.LoadString(nIDResource))
12         AfxExtractSubString(m_strTitle, strFullString, 0);    // first sub-string
13 
14     VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
15 
16     // attempt to create the window
17     LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
18     LPCTSTR lpszTitle = m_strTitle;
19     if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,
20       pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
21     {
22         return FALSE;   // will self destruct on failure normally
23     }
24 
25     // save the default menu handle
26     ASSERT(m_hWnd != NULL);
27     m_hMenuDefault = ::GetMenu(m_hWnd);
28 
29     // load accelerator resource
30     LoadAccelTable(MAKEINTRESOURCE(nIDResource));
31 
32     if (pContext == NULL)   // send initial update
33         SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
34 
35     return TRUE;
36 }

 

可以看到在LoadFrame中主要做了2件事,第一,注册窗口。第二,创建窗口

先来看注册窗口 AfxDeferRegisterClass() 在

AFXIMPL.H

#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

AfxEnDeferRegisterClass() 定义在WINCORE.CPP

  1 BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
  2 {
  3     // mask off all classes that are already registered
  4     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  5     fToRegister &= ~pModuleState->m_fRegisteredClasses;
  6     if (fToRegister == 0)
  7         return TRUE;
  8 
  9     LONG fRegisteredClasses = 0;
 10 
 11     // common initialization
 12     WNDCLASS wndcls;
 13     memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults
 14     wndcls.lpfnWndProc = DefWindowProc;
 15     wndcls.hInstance = AfxGetInstanceHandle();
 16     wndcls.hCursor = afxData.hcurArrow;
 17 
 18     INITCOMMONCONTROLSEX init;
 19     init.dwSize = sizeof(init);
 20 
 21     // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go
 22     if (fToRegister & AFX_WND_REG)
 23     {
 24         // Child windows - no brush, no icon, safest default class styles
 25         wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
 26         wndcls.lpszClassName = _afxWnd;
 27         if (AfxRegisterClass(&wndcls))
 28             fRegisteredClasses |= AFX_WND_REG;
 29     }
 30     if (fToRegister & AFX_WNDOLECONTROL_REG)
 31     {
 32         // OLE Control windows - use parent DC for speed
 33         wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
 34         wndcls.lpszClassName = _afxWndOleControl;
 35         if (AfxRegisterClass(&wndcls))
 36             fRegisteredClasses |= AFX_WNDOLECONTROL_REG;
 37     }
 38     if (fToRegister & AFX_WNDCONTROLBAR_REG)
 39     {
 40         // Control bar windows
 41         wndcls.style = 0;   // control bars don't handle double click
 42         wndcls.lpszClassName = _afxWndControlBar;
 43         wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
 44         if (AfxRegisterClass(&wndcls))
 45             fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;
 46     }
 47     if (fToRegister & AFX_WNDMDIFRAME_REG)
 48     {
 49         // MDI Frame window (also used for splitter window)
 50         wndcls.style = CS_DBLCLKS;
 51         wndcls.hbrBackground = NULL;
 52         if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
 53             fRegisteredClasses |= AFX_WNDMDIFRAME_REG;
 54     }
 55     if (fToRegister & AFX_WNDFRAMEORVIEW_REG)
 56     {
 57         // SDI Frame or MDI Child windows or views - normal colors
 58         wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
 59         wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
 60         if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
 61             fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
 62     }
 63     if (fToRegister & AFX_WNDCOMMCTLS_REG)
 64     {
 65         // this flag is compatible with the old InitCommonControls() API
 66         init.dwICC = ICC_WIN95_CLASSES;
 67         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);
 68         fToRegister &= ~AFX_WIN95CTLS_MASK;
 69     }
 70     if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)
 71     {
 72         init.dwICC = ICC_UPDOWN_CLASS;
 73         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);
 74     }
 75     if (fToRegister & AFX_WNDCOMMCTL_TREEVIEW_REG)
 76     {
 77         init.dwICC = ICC_TREEVIEW_CLASSES;
 78         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TREEVIEW_REG);
 79     }
 80     if (fToRegister & AFX_WNDCOMMCTL_TAB_REG)
 81     {
 82         init.dwICC = ICC_TAB_CLASSES;
 83         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TAB_REG);
 84     }
 85     if (fToRegister & AFX_WNDCOMMCTL_PROGRESS_REG)
 86     {
 87         init.dwICC = ICC_PROGRESS_CLASS;
 88         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PROGRESS_REG);
 89     }
 90     if (fToRegister & AFX_WNDCOMMCTL_LISTVIEW_REG)
 91     {
 92         init.dwICC = ICC_LISTVIEW_CLASSES;
 93         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_LISTVIEW_REG);
 94     }
 95     if (fToRegister & AFX_WNDCOMMCTL_HOTKEY_REG)
 96     {
 97         init.dwICC = ICC_HOTKEY_CLASS;
 98         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_HOTKEY_REG);
 99     }
100     if (fToRegister & AFX_WNDCOMMCTL_BAR_REG)
101     {
102         init.dwICC = ICC_BAR_CLASSES;
103         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_BAR_REG);
104     }
105     if (fToRegister & AFX_WNDCOMMCTL_ANIMATE_REG)
106     {
107         init.dwICC = ICC_ANIMATE_CLASS;
108         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ANIMATE_REG);
109     }
110     if (fToRegister & AFX_WNDCOMMCTL_INTERNET_REG)
111     {
112         init.dwICC = ICC_INTERNET_CLASSES;
113         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_INTERNET_REG);
114     }
115     if (fToRegister & AFX_WNDCOMMCTL_COOL_REG)
116     {
117         init.dwICC = ICC_COOL_CLASSES;
118         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_COOL_REG);
119     }
120     if (fToRegister & AFX_WNDCOMMCTL_USEREX_REG)
121     {
122         init.dwICC = ICC_USEREX_CLASSES;
123         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_USEREX_REG);
124     }
125     if (fToRegister & AFX_WNDCOMMCTL_DATE_REG)
126     {
127         init.dwICC = ICC_DATE_CLASSES;
128         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_DATE_REG);
129     }
130 
131     // save new state of registered controls
132     pModuleState->m_fRegisteredClasses |= fRegisteredClasses;
133 
134     // special case for all common controls registered, turn on AFX_WNDCOMMCTLS_REG
135     if ((pModuleState->m_fRegisteredClasses & AFX_WIN95CTLS_MASK) == AFX_WIN95CTLS_MASK)
136     {
137         pModuleState->m_fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
138         fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
139     }
140 
141     // must have registered at least as mamy classes as requested
142     return (fToRegister & fRegisteredClasses) == fToRegister;
143 }

可以看到MFC预先定义了很多窗口类,调用AfxRegisterClass()函数进行注册

 

 1 BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
 2 {
 3     WNDCLASS wndcls;
 4     if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
 5         &wndcls))
 6     {
 7         // class already registered
 8         return TRUE;
 9     }
10 
11     if (!::RegisterClass(lpWndClass))
12     {
13         TRACE1("Can't register window class named %s\n",
14             lpWndClass->lpszClassName);
15         return FALSE;
16     }
17 
18     if (afxContextIsDLL)
19     {
20         AfxLockGlobals(CRIT_REGCLASSLIST);
21         TRY
22         {
23             // class registered successfully, add to registered list
24             AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
25             LPTSTR lpszUnregisterList = pModuleState->m_szUnregisterList;
26             // the buffer is of fixed size -- ensure that it does not overflow
27             ASSERT(lstrlen(lpszUnregisterList) + 1 +
28                 lstrlen(lpWndClass->lpszClassName) + 1 <
29                 _countof(pModuleState->m_szUnregisterList));
30             // append classname + newline to m_szUnregisterList
31             lstrcat(lpszUnregisterList, lpWndClass->lpszClassName);
32             TCHAR szTemp[2];
33             szTemp[0] = '\n';
34             szTemp[1] = '\0';
35             lstrcat(lpszUnregisterList, szTemp);
36         }
37         CATCH_ALL(e)
38         {
39             AfxUnlockGlobals(CRIT_REGCLASSLIST);
40             THROW_LAST();
41             // Note: DELETE_EXCEPTION not required.
42         }
43         END_CATCH_ALL
44         AfxUnlockGlobals(CRIT_REGCLASSLIST);
45     }
46 
47     return TRUE;
48 }

最终调用了SDK中的RegisterClass()

接着回到窗口的创建中,这是在CFrameWnd::LoadFrame()中调用Create()函数创建的,因为派生类没有改写Create() 所以还是调用了CFrameWnd::Create()

BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
    LPCTSTR lpszWindowName,
    DWORD dwStyle,
    const RECT& rect,
    CWnd* pParentWnd,
    LPCTSTR lpszMenuName,
    DWORD dwExStyle,
    CCreateContext* pContext)
{
    HMENU hMenu = NULL;
    if (lpszMenuName != NULL)
    {
        // load in a menu that will get destroyed when window gets destroyed
        HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);
        if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)
        {
            TRACE0("Warning: failed to load menu for CFrameWnd.\n");
            PostNcDestroy();            // perhaps delete the C++ object
            return FALSE;
        }
    }

    m_strTitle = lpszWindowName;    // save title for later

    if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
        rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
        pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
    {
        TRACE0("Warning: failed to create CFrameWnd.\n");
        if (hMenu != NULL)
            DestroyMenu(hMenu);
        return FALSE;
    }

    return TRUE;
}

 在CFrameWnd::Create()中又调用了CreateEx(),因为CFrameWnd没有改写,所以调用CWnd::CreateEx() WINCORE.CPP

 1 BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
 2     LPCTSTR lpszWindowName, DWORD dwStyle,
 3     int x, int y, int nWidth, int nHeight,
 4     HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
 5 {
 6     // allow modification of several common create parameters
 7     CREATESTRUCT cs;
 8     cs.dwExStyle = dwExStyle;
 9     cs.lpszClass = lpszClassName;
10     cs.lpszName = lpszWindowName;
11     cs.style = dwStyle;
12     cs.x = x;
13     cs.y = y;
14     cs.cx = nWidth;
15     cs.cy = nHeight;
16     cs.hwndParent = hWndParent;
17     cs.hMenu = nIDorHMenu;
18     cs.hInstance = AfxGetInstanceHandle();
19     cs.lpCreateParams = lpParam;
20 
21     if (!PreCreateWindow(cs))
22     {
23         PostNcDestroy();
24         return FALSE;
25     }
26 
27     AfxHookWindowCreate(this);
28     HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
29             cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
30             cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
31 
32 #ifdef _DEBUG
33     if (hWnd == NULL)
34     {
35         TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X\n",
36             GetLastError());
37     }
38 #endif
39 
40     if (!AfxUnhookWindowCreate())
41         PostNcDestroy();        // cleanup if CreateWindowEx fails too soon
42 
43     if (hWnd == NULL)
44         return FALSE;
45     ASSERT(hWnd == m_hWnd); // should have been set in send msg hook
46     return TRUE;
47 }

关于PreCreateWindow()依据多态性 先调用派生类,接着是CMDIFrameWnd,然后是CFrameWnd的PreCreateWindow函数 在WINFRM.CPP中如下:

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
 if (cs.lpszClass == NULL)
 {
  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
 }

 if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
  cs.style |= FWS_PREFIXTITLE;

 if (afxData.bWin4)
  cs.dwExStyle |= WS_EX_CLIENTEDGE;

 return TRUE;
}

9.接着回到p->InitInstance()中来 showWindow(),UpdataWindow()

10.接着是p-> Run(),派送类没改写的Run()的话 调用CWinApp::Run()

 1 int CWinApp::Run()
 2 {
 3     if (m_pMainWnd == NULL && AfxOleGetUserCtrl())
 4     {
 5         // Not launched /Embedding or /Automation, but has no main window!
 6         TRACE0("Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.\n");
 7         AfxPostQuitMessage(0);
 8     }
 9     return CWinThread::Run();
10 }

而CWinThread::Run()定义如下

 1 int CWinThread::Run()
 2 {
 3     ASSERT_VALID(this);
 4 
 5     // for tracking the idle time state
 6     BOOL bIdle = TRUE;
 7     LONG lIdleCount = 0;
 8 
 9     // acquire and dispatch messages until a WM_QUIT message is received.
10     for (;;)
11     {
12         // phase1: check to see if we can do idle work
13         while (bIdle &&
14             !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
15         {
16             // call OnIdle while in bIdle state
17             if (!OnIdle(lIdleCount++))
18                 bIdle = FALSE; // assume "no idle" state
19         }
20 
21         // phase2: pump messages while available
22         do
23         {
24             // pump message, but quit on WM_QUIT
25             if (!PumpMessage())
26                 return ExitInstance();
27 
28             // reset "no idle" state after pumping "normal" message
29             if (IsIdleMessage(&m_msgCur))
30             {
31                 bIdle = TRUE;
32                 lIdleCount = 0;
33             }
34 
35         } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
36     }
37 
38     ASSERT(FALSE);  // not reachable
39 }

而CWinThread::PumMessage()

 1 BOOL CWinThread::PumpMessage()
 2 {
 3     ASSERT_VALID(this);
 4 
 5     if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
 6     {
 7 #ifdef _DEBUG
 8         if (afxTraceFlags & traceAppMsg)
 9             TRACE0("CWinThread::PumpMessage - Received WM_QUIT.\n");
10         m_nDisablePumpCount++; // application must die
11             // Note: prevents calling message loop things in 'ExitInstance'
12             // will never be decremented
13 #endif
14         return FALSE;
15     }
16 
17 #ifdef _DEBUG
18     if (m_nDisablePumpCount != 0)
19     {
20         TRACE0("Error: CWinThread::PumpMessage called when not permitted.\n");
21         ASSERT(FALSE);
22     }
23 #endif
24 
25 #ifdef _DEBUG
26     if (afxTraceFlags & traceAppMsg)
27         _AfxTraceMsg(_T("PumpMessage"), &m_msgCur);
28 #endif
29 
30     // process this message
31 
32     if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
33     {
34         ::TranslateMessage(&m_msgCur);
35         ::DispatchMessage(&m_msgCur);
36     }
37     return TRUE;
38 }

 

posted @ 2015-08-31 11:38  水玉木青  阅读(951)  评论(0编辑  收藏  举报