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 }
时间: 2024-10-10 00:37:44

MFC中如何改装SDK的WinMain函数的相关文章

VC/MFC中通过CWebPage类调用javascript函数(给js函数传参,并取得返回值)

转自:http://www.cnblogs.com/javaexam2/archive/2012/07/14/2632959.html ①需要一个别人写好的类CWebPage,将其对于的两个文件WebPage.h和WebPage.cpp添加到工程中. CWebPage类头文件和实现文件下载地址: http://download.csdn.net/detail/masikkk/4427190 ②添加WebBrowser控件,在视图/对话框类的头文件中#include "webbrowser2.h&

MFC中利用CString和Format成员函数将数字格式化输出

str.Format("格式控制字符串”,输出列表): 格式控制字符串包括格式字符串和非格式字符串,用双引号括起来.其中非格式字符串原样输出. 格式字符串是以%开头的字符串:%[标识][输出最小宽度][精度]转换说明符. 常用转换说明符:d,整型:f,浮点型,双精度:e,指数形式输出,双精度:s,输出字符串,参数为char*指针:等. []内是可以省略的. 标识有 - . + : -表示左对齐,右边补空:+反之. 输出最小宽度,用十进制整数表示. 精度,以.号开始,后跟十进制整数.其含义是如果输

【转】VC的MFC中重绘函数的使用总结(整理)

原文网址:http://www.cnblogs.com/x8023z/archive/2008/12/09/mfc33.html 在刷新窗口时经常要调用重绘函数MFC提供了三个函数用于窗口重绘InvalidateRect(&Rect)Invalidate()UpdateWindow()当需要更新或者重绘窗口时,一般系统会发出两个消息WM_PAINT(通知客户区有变化)和WM_NCPAINT(通知非客户区有变化)--WM_NVPAINT系统会自己搞定--WM_PAINT消息对应的函数是OnPain

MFC中的Invalidate、OnDraw、OnPaint函数的作用

MFC中的Invalidate.OnDraw.OnPaint函数的作用 CWnd::Invalidate voidInvalidate( BOOL bErase = TRUE ); 该函数的作用是使 整个窗口客户区无效.窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘. 这时Windows会在应用程序的消息队列中放置WM_PAINT消息.MFC为窗口类提供了WM_PAINT的消息处理函数 OnPaint,OnPaint负责

MFC中的消息处理函数

1.在Windows API编程中,直接在消息处理函数中编写WM_PAINT处理代码. 2.在MFC中,CFrameWnd的消息处理过程在哪里呢?MFC时如何将消息处理函数和窗口关联起来的. 在CFrameWnd::CreateEx中,调用PreCreateWindows来注册窗口. AfxDefRegisterClass(AFX_WNDFRAMEORVIEW_REG):注册一个固定的窗口类,这个窗口类中的消息处理过程时一个固定的消息处理过程, 真正将我门的消息处理过程CWnd::WindowP

【VS开发】MFC中调用C函数模块的解决方案

[VS开发]MFC中调用C函数模块的解决方案 标签(空格分隔): [VS开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:最近调试基于MFC的程序,当通过外部C文件引入某个function的时候,又一次忘记了C文件与C++文件的区别,直接按照一般的方式,将函数声明放入头文件,将函数定义放入C文件,然后再MFC中通过包含头文件来引用对应的function,然而爆出了链接时无法定位的错误,本文就来梳理一下C++中调用C中功能函数的方法. 首先在C

MFC 中的 “printf” 函数

还念C语言的我,MFC没法使用的C语言printf函数,于是: int MFCprintf(const char* m_data, ...){ CString str; char printf_buf[1024]; va_list args; /* args为定义的一个指向可变参数的变量,va_list以及下边要用到的va_start,va_end都是是在定义 可变参数函数中必须要用到宏, 在stdarg.h头文件中定义 */ int printed; va_start(args, m_data

MFC的运行机制 以及 MFC中的DC、CDC、HDC、句柄、设备上下文 [转]

在MFC程序中,我们并不经常直接调用Windows API,而是从MFC类创建对象并调用属于这些对象的成员函数.也就是说MFC封装了Windows API.你说你喜欢C++而MFC换一种说法就是一个用C++写的一个函数库 然后你来调用 只不过这个类不是你写的 MFC提供数百个类,最重要的.也是编写任何VC++应用程序都必不可少的两个类CWinApp和CFrameWnd,这两个类是编写复杂庞大应用程序的基石. 1>封装特性:构成MFC框架的是MFC类库而MFC类库又是C++的一个类库.这些类封装W

MFC中利用OpenCV实现视频播放

近期项目中在学习全景相机相关知识 当然首先要开始将基本的MFC学会才能封装SDK 首先建立MFC对话框工程 具体的详细知识就不说了,网上有很多的教程. 添加如下控件 中间显示部分是picture control控件 采用定时器更新picture 显示框 首先包含opencv相关的头文件,在CUpanoCameraDlg.h中添加以下变量 private: CRect rect; CStatic* pStc; //标识图像显示的Picture控件 CDC* pDC; //视频显示控件设备上下文 H