MFC ins and outs of the program - "simple terms MFC" study notes of the two authors: 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, before the program enters the point, there is a global object (in the Hello program named ", this is the so-called Application Object, when the operating system loads and activated, this global object is configured The constructor will be executed 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 CFrameWnd represents a mainframe window Although WinMain and WndProc internal operations have a considerable degree of invariance, it is necessary to change in the face of different applications, so they must be based on these two classes. Your own class and rewrite some of the member functions. CWINAPP --- Replace WinMain's status Traditionally, WinMain, which is traditional, the work is completed by CWINAPP: Virtual Bool InitApplication (); Virtual Bool InitInstance (); Virtual Bool Run (); cframewnd --- - Replacing the status of WndProc CFRAMEWND Mainly used to master a window detonator ------ Application Object When performing a Hello program, this global object is generated, and the constructor (see appcore.cpp) is executed, CWINAPP Member variables will get configuration and initial values because of the birth of this global object. After the configuration is completed, WinMain is ready, and the linker is added directly to the application). AFXWININIT: is the first operation after the CWINAPP constructor; the following operation is PAPP-> INitApplication (where PAPP points to the CMYWINAPP object, that is, the theApp in this example), because cmywinapp inherits from cwinapp, and initApplication is CWINAPP A virtual function, we didn't rewrite it (there is no need to change it in most cases), so the above operation is equivalent to calling cwinapp :: initApplication. The code of this program appears in AppCore.cpp; after INitApplication, the AFXWINMAIN calls PAPP-> InitInstance, InitInstance is a virtual function of CWINAPP (the application must override this function, because it is empty in cwinapp, there is no silence Operation), we have rewritten it, so the above operation is to tune our own InitInstance function, we will expand our main window life at the site.
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, which uses it, initializes the external frame window in the program with the Document / View structure, the default Null CFrameWnd: Create calls createex in the function (CWnd has this member function However, its derived class cframewnd is not, so the call here is actually CWnd: createex); the latter calls the PrecreateWindow virtual function (it has definitions in CWnd and their class CFrameWnd, so actually call CFrameWnd :: PrecreateWindow, this function calls the AFXDeferRegisterClass macro, indicating that if the value of the Variable AFXREGISTEREDCLASS is already registered with the FCLASS window class, the MFC is not done, otherwise call 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- --- The live water source of the program 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 :: Run WinMain is provided by MFC, window The class has been registered by the MFC, and the link function is also connected by the MFC to connect the message and processing function: Message MAP mechanism MFC provides "very convenient interface" for the application to use two groups of macros, with Hello as an example, The first operation is in Hello.h's CMYFrameWnd plus declare-message-map; second operation is anywhere in hello.cpp (certainly not in function) using macro begin_message_map (cmyframewnd, cframewnd) on_command (IDM_ABOUT, OnAbout) ON_WM_Paint () end_MESSAGE_MAP () Nativity Application Object is generated by the Dragon Detectivity, and the memory is also set up. AFXWINMAIN executes AFXWININIT, the latter is adjusted, and the message queue is added to 96 AFXWINMAIN to perform the initApplication. This is a virtual function of CWINAPP, and we usually do not change its AFXWINMAIN to perform InitInstance. This is a virtual function of CWINAPP, we must overwrite CMYWINAPP :: InitInstance "New" a CMYFrameWnd object CMYFRAMEWND constructor calling create, generating 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. Back to InitInstance Continue ShowWindow, the display window executes UpdateWindow, so WM-PAINT is issued back to AFXWINMAIN, execute Run, and enter the message loop. The program starts running: Programs get WM-PAINT messages (from :: getMessage loops in cwinapp :: runmessage) WM-Paint Via :: DispatchMessage to Window Functions CWnd :: DefWindowProc. CWnd :: DefWindowProc discovers the message to the message mapping table pass the message to the message mapping table, so that the corresponding function is called in the project. This function is set up with the macro between Begin_Message_Map and End_Message_MAP.
The processing program of the standard message also has a standard naming, such as the WM-PAINT must be died by the onpaint handler: Users click File / Close, so I will issue the WM-Close CMYFrameWnd without setting the WM-Close handler, which is handed over to the default process. Program Default Function For WM-Close's processing method to call :: destroyWindow, and thus issue WM-Destroy default WM-DESTROY processing mode is called: postquitMessage, so WM-Quit CWINAPPPP :: Run receives WM-QUIT End the internal message loop, then call EXITInstance, this is a virtual function of CWINAPP; if CMYWINAPP has rewritten EXITInstance, then cmywinapp :: EXITINSTANCE, otherwise cwinapp :: exitInstance final back to AFXWINMAIN, Execute AFXWINTERM, end the program attached to the Hello program part of the code: hello.cpp #include "stdafx.h" #include "hello.h" #includ "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 CMYWINAPP :: OnIdle (long lcount) {cmyframewnd * pwnd = (cmyframewnd *) m_pmainwnd; PWND- > IDletimeHandler (LCOUNT); Return True;} // ---------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- // CMYFRAMEWND '
Smember // ---------------------------------------------- ---------------------- 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; getClientRect (Rect); DC.SetTextAlign (TA_BOTTOM | Ta_Center); :: Lineda (Rect.right / 2, 0 , Rect.right / 2, Rect.Bottom / 2, (LinedDaproc) LineddDacallback, (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, 20, 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 OnAbout (); // for WM_COMMAND (IDM_ABOUT) void IdleTimeHandler (LONG lCount); // We want it call by cmywinapp :: onder private: DECLARE_MESSAGE_MAP () // Declare Message Map Static Void Callback LinedDacallback (int, int, lparam); // }; book Hello program is a simple MFC Program, its main body is WinMain and WndProc, and both 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 CFrameWnd represents a mainframe window Although WinMain and WndProc internal operations have a considerable degree of invariance, it is necessary to change in the face of different applications, so they must be based on these two classes. Your own class and rewrite some of the member functions. CWINAPP --- Replace WinMain's status Traditionally, WinMain, which is traditional, the work is completed by CWINAPP: Virtual Bool InitApplication (); Virtual Bool InitInstance (); Virtual Bool Run (); cframewnd --- - Replacing the status of WndProc CFRAMEWND Mainly used to master a window detonator ------ Application Object When performing a Hello program, this global object is generated, and the constructor (see appcore.cpp) is executed, CWINAPP Member variables will get configuration and initial values because of the birth of this global object. After the configuration is completed, WinMain is ready, and the linker is added directly to the application).
AFXWININIT: is the first operation after the CWINAPP constructor; the following operation is PAPP-> INitApplication (where PAPP points to the CMYWINAPP object, that is, the theApp in this example), because cmywinapp inherits from cwinapp, and initApplication is CWINAPP A virtual function, we didn't rewrite it (there is no need to change it in most cases), so the above operation is equivalent to calling cwinapp :: initApplication. The code of this program appears in AppCore.cpp; after INitApplication, the AFXWINMAIN calls PAPP-> InitInstance, InitInstance is a virtual function of CWINAPP (the application must override this function, because it is empty in cwinapp, there is no silence Operation), we have rewritten it, so the above operation is to tune our own InitInstance function, we will expand our main window life at the site. 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, which uses it, initializes the external frame window in the program with the Document / View structure, the default Null CFrameWnd: Create calls createex in the function (CWnd has this member function However, its derived class cframewnd is not, so the call here is actually CWnd: createex); the latter calls the PrecreateWindow virtual function (it has definitions in CWnd and their class CFrameWnd, so actually call CFrameWnd :: PrecreateWindow, this function calls the AFXDeferRegisterClass macro, indicating that if the value of the Variable AFXREGISTEREDCLASS is already registered with the FCLASS window class, the MFC is not done, otherwise call 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- --- The live water source of the program 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 :: Run WinMain is provided by MFC, window The class has been registered by the MFC, and the link function is also connected by the MFC to connect the message and processing function: Message MAP mechanism MFC provides "very convenient interface" for the application to use two groups of macros, with Hello as an example, The first operation is in Hello.h's CMYFrameWnd plus declare-message-map; second operation is anywhere in hello.cpp (certainly not in function) using macro begin_message_map (cmyframewnd, cframewnd) on_command (IDM_ABOUT, OnAbout) ON_WM_Paint () end_MESSAGE_MAP () Nativity Application Object is generated by the Dragon Detectivity, and the memory is also set up. AFXWINMAIN executes AFXWININIT, the latter is adjusted, and the message queue is added to 96 AFXWINMAIN to perform the initApplication. This is a virtual function of CWINAPP, and we usually do not change its AFXWINMAIN to perform InitInstance. This is a virtual function of CWINAPP, we must overwrite CMYWINAPP :: InitInstance "New" a CMYFrameWnd object CMYFRAMEWND constructor calling create, generating 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. Back to InitInstance Continue ShowWindow, the display window executes UpdateWindow, so WM-PAINT is issued back to AFXWINMAIN, execute Run, and enter the message loop. The program starts running: Programs get WM-PAINT messages (from :: getMessage loops in cwinapp :: runmessage) WM-Paint Via :: DispatchMessage to Window Functions CWnd :: DefWindowProc. CWnd :: DefWindowProc discovers the message to the message mapping table pass the message to the message mapping table, so that the corresponding function is called in the project. This function is set up with the macro between Begin_Message_Map and End_Message_MAP.
The processing program of the standard message also has a standard naming, such as the WM-PAINT must be died by the onpaint handler: Users click File / Close, so I will issue the WM-Close CMYFrameWnd without setting the WM-Close handler, which is handed over to the default process. Program Default Function For WM-Close's processing method to call :: destroyWindow, and thus issue WM-Destroy default WM-DESTROY processing mode is called: postquitMessage, so WM-Quit CWINAPPPP :: Run receives WM-QUIT End the internal message loop, then call EXITInstance, this is a virtual function of CWINAPP; if CMYWINAPP has rewritten EXITInstance, then cmywinapp :: EXITINSTANCE, otherwise cwinapp :: exitInstance final back to AFXWINMAIN, Execute AFXWINTERM, end the program attached to the Hello program part of the code: hello.cpp #include "stdafx.h" #include "hello.h" #includ "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 CMYWINAPP :: OnIdle (long lcount) {cmyframewnd * pwnd = (cmyframewnd *) m_pmainwnd; PWND- > IDletimeHandler (LCOUNT); Return True;} // ---------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- // CMYFRAMEWND '
Smember // ---------------------------------------------- ---------------------- 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; getClientRect (Rect); DC.SetTextAlign (TA_BOTTOM | Ta_Center); :: Lineda (Rect.right / 2, 0 , Rect.right / 2, Rect.Bottom / 2, (LinedDaproc) LineddDacallback, (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, 20, 30); CDC * PDC = New CclientDC (this); str.format ("% 010d", LCOUNT); PDC -> DrawText (Str, & Rect, DT_LEFT | DT_TOP);