Author: XGM 2001-8-14 MFC program is a Windows program, so it also has a WinMain, but we do not see a trace of it in the program. In fact, there is one (and only one) global object before the program entry point (name THEEPP in the Hello program), this is the so-called Application Object, when the operating system
When the program is loaded and activated, this global object acquires configured, and its constructor will execute first, earlier than WinMain.
The Hello program raised in the book is a simple MFC program, and its body is WinMain and WndProc, and these two parts are actually a considerable degree of invariance. The MFC is to encapsulate Winmain internal operation with considerable fixed behavior in CWINAPP; put the WndProc internal operation of a fairly fixed behavior in CFrameWnd. That is, the CWINAPP represents the program body, and the cframeWnd represents a mainframe window.
Although WinMain and WndProc internal operations have a considerable degree of invariance, it is necessary to change in different applications, so they must be derived by these two classes, and they are derived, and some of the member functions are rewritten.
CWINAPP ---- Replace WinMain's status
Traditionally, the work completed by WinMain, the work is now completed by CWINAPP: Virtual Bool InitApplication (); Virtual Bool InitInstance (); Virtual Bool Run (); cframewnd ----- Replace WNDPROC
CframeWnd is mainly used to master a window detonator ------ Application Object
When the Hello program is executed, this global object is generated, so the constructor (see appcore.cpp) is executed, the member variables in CWINAPP will get the configuration and initial value because of the birth of this global object, after the configuration is complete, WinMain (MFC It is already ready, and the linker will be added directly to the application).
AFXWININIT: is the first operation following the CWINAPP constructor;
Since then, the operation is PAPP-> initApplication (where PAPP points to the CMYWINAPP object, that is, theApp in this example), because CMYWINAPP inherits from cwinapp, and initApplication is a virtual function of cwinapp, we did not rewrite it (most cases No need to change it), so the above operation is equivalent to calling CWINAPP :: initApplication. The code of this program appears in AppCore.cpp;
Follow INITAPPLICATION, the AFXWinMain calls PAPP-> InitInstance, InitInstance is a virtual function of CWINAPP (the application must overwrite this function, because it is an empty function in cwinapp, there is no one-time operation), we have rewritten it, so The operation is to adjust our own InitInstance function, we will expand our main window life at the point.
CMYWINAPP :: InitInstance starts new CMYFRAMEWND object, New will trigger constructor cmyframeWnd :: CMYFRAMEWND, which calls the CFrameWnd member function crete, which will generate a window. CREATE functions total eight parameters, first, specify the WNDCLASS window class, if null is placed, indicating that a standard outer box window is to generate a standard outer box window (CREATE function can raise the registration operation of the window class before generating the window) The next paragraph describes this content); second, specify window headings; third, specify window style, default is WS-overlappedWindow, if you don't want the maximum minimum tab in the upper right corner of the window, you can change to WS- Overlapped | WS-CAPTION | WS-SYSMENU | WS-ThickFrame | WS-minimizebox | WS-MaximizeBox, if you want to have a vertical scroll bar, plus WS-VSCROLL; the fourth parameter, the location and size of the specified window, default value RectDefault; fifth, specify the parent window, the sixth specified menu; seventh, for the expansion style, only in: CREATEWINDOWEX (not: CREATEWINDOW) function, in fact, cframeWnd: CREATE is finally called : CREATEWINDOWEX; eighth, is a pointer to the CCReateContext structure, Framework uses it, initializes the external frame window in a program with the Document / View structure, the default value NULL
CFRAMEWND: CREATE calls createex in the function (CWnd has this member function, but its derived class cframewnd is not, so the actual CWnd: createex) is actually called; the latter calls the PrecreateWindow virtual function (it is giving birth to CWND CFrameWnd has definition, so actually calling cframewnd :: precreateWindow), this function calls the AFXDeferRegisterClass macro, indicating that if the variable AFXREGISTEREDCLASS value display system has been registered with the FCLASS window class, MFC is not done, otherwise Calling AFXEnddeferRegisterClass (FCLASS) {It calls two functions to complete the actual window class registration operation, one is RegisterWithicon, one is an AFXREGISTERCLASS}, ready to register.
After the window is displayed and updated CMYFRAMEWND:: CMYFRAMEWND, the window has been born; the program returns to cmywinapp :: InitInstance, so call the showWindow function order window to display, and call the UpdateWindow function to send the Hello program to send WM-PAINT
Cwinapp :: run ---- Live source of the program life
Run is a virtual function of CWINAPP, we did not rewrite it (there is no need to change it in most cases), so the above operation is equivalent to calling cwinapp :: runwinmain has been provided by MFC, window classes have been registered by MFC, The function is also provided by the MFC
Connect the message and the processing function: Message Map mechanism
The "very convenient interface" of MFC is provided to the application is two groups of macros. Take Hello as an example. The first operation is in Hello.h's CMYFrameWnd plus declare-message-map; the second operation is in Hello. No location of CPP (of course, you can't use macro within functions)
Begin_MESSAGE_MAP (CMYFRAMEWND, CFRAMEWND)
ON_COMMAND (IDM_ABOUT, ONWABOUT)
ON_WM_PAINT ()
END_MESSAGE_MAP ()
Total lane
Birth of the program
Application Object is generated, and the memory is also set up, and the initial value is also set up.
AfxwinMain executes AFXWININIT, the latter is adjusted, and the message queue is added as possible.
Big to 96
AFXWINMAIN performs initApplication. This is a virtual function of CWINAPP, and we usually do not change it.
AFXWINMAIN performs initInstance. This is a virtual function of CWINAPP, we must override it.
CMYWINAPP :: InitInstance "New" has a CMYFRAMEWND object
CMYFRAMEWND constructor calls CREATE to generate a main window. The window class we specified in the Create parameter is NULL, so the MFC is based on the type of window, and you register a window class named "AFXFraMeorView42D" according to the window type.
Go back to InitInstance, continue to execute showwindow, display window
Perform UpdateWindow, so WM-PAINT
Go back to AFXWINMAIN, execute Run, enter the message loop.
The program starts running:
Program gets WM-PAINT message (from :: getMessage loop by cwinapp :: run)
WM-PAINT is sent to window functions via :: DispatchMessage.
CWnd :: DEFWINDOWPROC passes messages to message mapping form
During the transfer process, there is a matching item, so that the corresponding function in the project is called. This function is set up with the macro between Begin_Message_Map and End_Message_MAP.
The standard message handler also has standard naming, such as WM-Paint will be processed by ONPAINT.
The death of the program:
Users click File / Close, so I will issue WM-CLOSE
CMYFRAMEWND does not set the WM-CLOSE handler, so it is given to the default handler
The default function is to call :: destroyWindow, and thus issue WM-DESTROY
The default WM-DESTROY process is called: postquitmessage, so WM-quit is issued
CWINAPP :: RUN Received WM-QUIT will end the internal message loop, then call EXITInstance, which is a virtual function of CWINAPP; if CMYWINAPP has rewritten exitInstance, then cwinapp :: run call is CMYWINAPP :: EXITINSTANCE, otherwise Is CWINAPP :: EXITINSTANCE Last Back to AFXWINMAIN, execute AFXWINTERM, end the program
Attached to the Hello program part:
Hello.cpp
#include "stdafx.h"
#include "hello.h"
#include "resource.h"
CMYWINAPP THEAPP; // Application Object
/ / -------------------------------------------------------------------------------------------- --------------------
// CMYWINAPP'S MEMBER
/ / -------------------------------------------------------------------------------------------- --------------------
Bool CMYWINAPP :: InitInstance ()
{
m_pmainwnd = new cmyframeWnd ();
m_pmainwnd-> showwindow (m_ncmdshow);
m_pmainwnd-> UpdateWindow ();
Return True;
}
/ / -------------------------------------------------------------------------------------------- --------------------
// CMYWINAPP'S MEMBER
/ / -------------------------------------------------------------------------------------------- --------------------
Bool CMYWINAPPP :: OnIdle (long lcount)
{
CMYFRAMEWND * PWND = (CMYFRAMEWND *) m_pmainwnd;
PWND-> IdletimeHandler (LCOUNT);
Return True;
}
/ / -------------------------------------------------------------------------------------------- --------------------
// CMYFRAMEWND's MEMBER
/ / -------------------------------------------------------------------------------------------- --------------------
CMYFRAMEWND :: CMYFrameWnd ()
{
Create (Null, "Hello MFC", WS_OVERLAPPEDWINDOW, RectDefault,
Null, "mainmenu");
/ / -------------------------------------------------------------------------------------------- --------------------
Begin_MESSAGE_MAP (CMYFRAMEWND, CFRAMEWND)
ON_COMMAND (IDM_ABOUT, ONWABOUT)
ON_WM_PAINT ()
END_MESSAGE_MAP ()
/ / -------------------------------------------------------------------------------------------- --------------------
Void CMYFrameWnd :: onpaint ()
{
CPAINTDC DC (this);
CRECT RECT;
GetClientRect (Rect);
Dc.SettextAlign (TA_BOTTOM | TA_CENTER); :: Linedda (Rect.right / 2, 0, Rect.right / 2, Rect.Bottom / 2,
(LinedDaproc) Lineddacallback, (LPARAM) (LPVOID) & DC);
}
/ / -------------------------------------------------------------------------------------------- --------------------
Void Callback CMYFRAMEWnd :: LinedDacallback (int X, int y, lparam lpdc)
{
Static char sztext [] = "Hello, MFC";
((Cdc *) LPDC) -> TextOut (x, y, sztext, sizeof (sztext) -1);
For (int i = 1; i <50000; i );
}
/ / -------------------------------------------------------------------------------------------- --------------------
Void CMYFRAMEWND :: OnAbout ()
{
CDIALOG ABOUT ("AboutBox", this); // "Aboutbox"
About.domodal ();
}
/ / -------------------------------------------------------------------------------------------- --------------------
Void CMYFRAMEWND :: idletimeHandler (long lcount)
{
CString Str;
CRECT RECT (10, 10, 200, 30);
CDC * PDC = New CclientDC (this);
Str.Format ("% 010D", LCOUNT);
PDC-> DRAWTEXT (STR, & Rect, DT_LEFT | DT_TOP);
}
Hello.h
Class CMYWINAPP: Public CWINAPP
{
PUBLIC:
Virtual Bool InitInstance (); //
Virtual Bool OnIdle (long lcount); // Onidle E
}
/ / -------------------------------------------------------------------------------------------- --------------------
Class CMYFRAMEWND: PUBLIC CFRAMEWND
{
PUBLIC:
CMYFRAMEWND (); // Constructor
AFX_MSG void onpaint (); // for wm_paint
AFX_MSG VOID ONWABOUT (// for wm_command (idm_about)
Void IDletimeHandler (long lcount); // we want it call by cmywinapp :: onIdle
Private:
DECLARE_MESSAGE_MAP () // Declare Message Map
Static void Callback LineddDacallback (int, int, lparam);
//
}