Comprehensive Analysis of the MFC Application Framework

Source: Internet
Author: User
For programmers, if they want to improve the programming efficiency, a good-to-use, powerful and handy programming tool will often give us Program Personnel bring great convenience. In fact, for the current programming tool, which tool is not the key to the problem, the important thing is how much you can use, after all, the current tool is very powerful, for general programming tasks, there is no incompetent tool. Otherwise, I am afraid he will not be able to exist in this world, even if it is only one month of life. However, based on the personal interests and the influence of people around us, we will use one or more tools. Comparing Visual Basic, C ++ builder, Delphi and other programming tools, using VC ++ to write Windows applications is the most challenging and difficult. In this article, I have no intention to compare the quality of various tools. I will share my experiences and experiences with Visual C ++ MFC and share them with you, I also hope that I can meet more like-minded friends.

As far as my personal prejudice is concerned, I should learn his class library MFC (Microsoft Foundation Classes) when learning VC ++ ). Some people may find it daunting to hear about MFC. This is understandable. After all, although Microsoft has given us a powerful and complex class library, it has not brought us good convenience to learn from it. Looking back at the helplessness, confusion, and detours I learned when I was learning MFC, I still have a lot to worry about. Although I am still in a very elementary entry-level stage, however, I am happy to share my experiences with you. I hope you can give me some advice.

I. SDK application structure

I learned the path to MFC from the beginning of Windows Programming (maybe this is a detour ). First, let's take a look at a Windows application with the SDK application structure. Of course, it is also the classic "Hello world !" The compilation process does not have to be long-winded. The mainSource code(I generated it using the wizard, but it was edited a little for ease of reading ):

Lresult callback wndproc (hwnd, uint, wparam, lparam );

Int apientry winmain (hinstance, hinstance hprevinstance, lpstr lpcmdline, int ncmdshow)
{
// Todo: Place code here.
MSG;
....................................
Myregisterclass (hinstance );
If (! Initinstance (hinstance, ncmdshow ))
{
Return false;
}

// Main message loop:
While (getmessage (& MSG, null, 0, 0 ))
{
If (! Translateaccelerator (msg. hwnd, hacceltable, & MSG ))
{
Translatemessage (& MSG );
Dispatchmessage (& MSG );
}
}
Return msg. wparam;
}

Bool initinstance (hinstance, int ncmdshow)
{
........................
Return true;
}

// Window Function wndproc (), callback function

Lresult callback wndproc (hwnd, uint message, wparam, lparam)
{
Int wmid, wmevent;
........................
Switch (Message)
{
Case wm_command:
..................
Break;
Case wm_paint:
HDC = beginpaint (hwnd, & PS );
// Todo: add any drawing code here...
Rect RT;
Getclientrect (hwnd, & RT );
Drawtext (HDC, szhello, strlen (szhello), & RT, dt_center );
Endpaint (hwnd, & PS );
Break;
Case wm_destroy:
......
Default:
Return defwindowproc (hwnd, message, wparam, lparam );
}
Return 0;
}

SDK "Hello World" source program

First, let's take a look at the structure of this program. winmain () is the entry point of the function. The main task of this function is to complete some initialization work and maintain a message loop. Their workflow is as follows: entry (winmain () --- à myregisterclass () ----> initinstance ()-à while message loop. The function is executed at the entry, and then the myregisterclass () is called to register the window class. Then the initinstance () is generated and the window is displayed. After that, the initialization of a window is completed (of course, in myregisterclass () and initinstance (), the corresponding API functions must be called for specific implementation. However, here I focus on the analysis of its structure, so, without considering the specific implementation details), and then maintaining the message loop, so far, the basic structure of this program is almost established. In the future, program operations will be driven by a message loop.

Now let's look at the structure of the message loop. In the example program, we want the program to output a "hello World" in the window ". In the main program, we seem to have analyzed all the frameworks of the application, but we have not seen that the program is required to output "Hello World? This is the role of Windows messages. Of course, we still remember that we just said that the main program still maintains a message loop.Article. Window applications are message-driven. When a system or user requires an application to complete a task, messages are relied on, the system puts user requirements or system requirements in a message structure, sends them to the application, and then processes them. Now let's take a look at how the application completes our tasks. After the application Initialization is complete, an API function of the display window is called, so the system knows that the program is going to display the window. (Note that this is the time to generate messages ), in this case, a wm_paint message is generated in the message queue, so that the message loop of the application can capture the message and send it to the window function (note, this function is called by the system), and then the window function processes the message. We let him complete our task when he processes the message. From this process, we can see that if we want to interact with the program, we only need to select the appropriate time for the system to generate messages. Now, we can fully understand the operation process of the SDK program.

The framework of an SDK application program has been established. Let's take a look at how to build an MFC Application Framework and the relationship between the two.

 

Ii. MFC ApplicationProgramStructure

Previously, I analyzed the structure of a classic SDK application, but now I want to enter the topic "MFC application structure. There are many kinds of MFC applications. In order to make a clearer comparison with the previous article, we will look at an SDI application here. Of course, the example is still the classic "Hello World. After you use the Wizard to generate an application, you will find several files, according to the program execution, the main source code is extracted and analyzed. (because the Application Generated by MFC is not very easy to read, I edited them here ).

Chelloworldapp theapp;

Int afxapi afxwinmain (hinstance, hinstance hprevinstance,

Lptstr lpcmdline, int ncmdshow)
{
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 ");
Pthread-> m_pmainwnd-> destroywindow ();
}
Nreturncode = pthread-> exitinstance ();
Goto initfailure;
}
Nreturncode = pthread-> Run ();

Initfailure:
........................
Afxwinterm ();
Return nreturncode;
}

Bool cwinapp: initapplication ()
{
If (cdocmanager: pstaticdocmanager! = NULL)
{
If (m_pdocmanager = NULL)
M_pdocmanager = cdocmanager: pstaticdocmanager;
Cdocmanager: pstaticdocmanager = NULL;
}

If (m_pdocmanager! = NULL)
M_pdocmanager-> adddoctemplate (null );
Else
Cdocmanager: bstaticinit = false;
Return true;
}

Bool chelloworldapp: initinstance ()
{
Afxenablecontrolcontainer ();
....................................
// Change the registry key under which our settings are stored.
// Todo: You shocould modify this string to be something appropriate
// Such as the name of your company or organization.

Setregistrykey (_ T ("Local Appwizard-generated Applications "));
Loadstdprofilesettings (); // Load Standard INI File options (including MRU)
// Register the application's document templates. document templates
// Serve as the connection between documents, frame windows and views.

Csingledoctemplate * pdoctemplate;
Pdoctemplate = new csingledoctemplate (
Idr_mainframe,
Runtime_class (chelloworlddoc ),
Runtime_class (cmainframe), // main SDI frame window
Runtime_class (chelloworldview ));

Adddoctemplate (pdoctemplate );

// Parse command line for standard shell commands, DDE, file open
Ccommandlineinfo using info;
Parsecommandline (partition info );

// Dispatch commands specified on the command line
If (! Processshellcommand (cmdinfo ))
Return false;
// The one and only window has been initialized, so show and update it.
M_pmainwnd-> showwindow (sw_show );
M_pmainwnd-> updatewindow ();

Return true;
}

Bool cwinapp: initinstance ()
{
Return true;
}

"Hello World" for MFC applications"

At a glance, it seems that this program cannot be analyzed, or even the entry point of the program cannot be found. As a matter of fact, the above procedures have been sorted out before they look like this. Okay. Let's take a look at how this program runs. (Note that the above program comes from different files. The layout here is just to better express the structure of the program, as for the file organization of MFC, I will analyze it in the following topic. I will not consider it here ).

First, at the beginning of the program, we first defined a global variable theapp. Now we only need to know that it represents the existence of the entire program, and then the program starts to intervene in the entry point. Are there any mistakes? Where is the entrance point? No. In fact, int afxapi afxwinmain () is the entry point of this program. Strange! But it doesn't matter. It's like we saw the main () function in C for the first time. You only need to know about it. In afxwinmain (), the member functions of some classes are called respectively. Following the preceding analysis method, you can also draw a program execution path. Entry point ----> afxgetthread () ------> afxgetapp () ------- à afxwininit () ------- à PAPP-> initapplication () ----- à pthread-> initinstance () ------ à pthread-> Run (). We can see that the program has a clue to execution, but compared with the SDK, it is beyond the control of the whole world. Does the clear program structure of the past exist in these programs? The answer is yes, but their specific implementations are packaged in MFC. So, let's take a look at how the application starts and runs.

After the program starts running with afxwinmain (), it first calls afxgetapp () to obtain the Object Pointer PAPP of the application, and then calls the relevant member functions through this pointer to complete initialization and startup, finally, the run () function is called. Here, the run () function represents the message loop in the SDK.

The development of things is expected, but what seems to be missing? Yes, there is still another job that we have not completed. This is what we need. "Hello World" seems to have not been output yet! This is not my negligence, but an intentional arrangement, because MFC adopts a new (of course, relative to the SDK) Message Processing Mechanism, at least on the surface. However, here I don't plan to solve the problem at once. After all, this is a bit complicated. I will answer this question after we understand the relationship between the MFC files.

I didn't expect this article to be so long. At the beginning, I thought I could give this question clearly at once, but in fact I wrote the same idea as I did when I analyzed the program, it's a long process! Therefore, it is necessary for me to remind myself and my friends who have read this article to take a break. Now I am glad that I have divided this problem into several small issues to solve. I will continue to discuss in the following topics the files generated by the MFC program and the call relationships between them.

 

Iii. MFCProgramStructure Analysis

In the previous sections, I gave the frameworks of the SDK and the MFC application respectively, and slightly managed the relationship between them. However, it is not enough for an MFC program to understand its framework. Now, I want to continue to analyze the above MFC program, hoping to see through the MFC application framework clearly as I mentioned in the title.

First, let's take a look at the main files of the MFC Application generated by the Application Wizard, including the classes and the corresponding functions of the related classes and their relationships (re-describe, I am concerned about the Framework Structure of the program here, so I will not mention some things that have little to do with the topic ).

In the above SDI application, the wizard generates four main classes for us. These classes are derived classes of the MFC class, which are included in the corresponding header files and implementation files respectively.

1. Framework window class and Related Files

The framework window class corresponds to the main window of the application. After understanding this, you can establish a perceptual knowledge of this class. Its definition is in the header file mainfrm. h, while the implementation is in mainfrm. CPP file. All functions related to frame window light are defined and implemented here.

2. Document classes and Related Files

There is no intuitive correspondence between document classes in applications. However, one thing we should know is that a feature of the MFC framework is the document/view structure. Here, we can abstract it a bit. For example, if we open a file in word, this file is actually a document, but what we see is only a view of this file, therefore, the document provides support for application display, but what we can see is a view. The definition of the document class is in "Hello worlddoc. h, and its implementation is in "Hello worlddoc. CPP file.

3. View class and Related Files

The View class is used to display the content of the document object. The interface we see in the Word program is a view. To modify the view, the first object to operate on the drawing is the view, the View class provides what you can see from the user's perspective, as shown in his name. The View class is defined in "Hello worldview. H" and implemented in the "Hello worldview. H" file.

4. Application classes and Related Files

The initialization, start, and end of the MFC application are completed by the Application object. The corresponding files are "Hello world. cpp" and "Hello world. H ".

After learning about the role of application objects, let's take a look at the relationships between them, as shown in ).

From the figure above, we can roughly see the relationship between the MFC application objects. The application generates an application object at the beginning (for the content here, refer to the previous article). Then, a document template object (managed by cdocmanager) will be created in initinstance, applications can manage documents, views, and framework windows by creating template objects.

at this point, my article has finally come to an end. In this article, I mainly analyze the application framework and ignore many implementation details. In fact, learning MFC is a very long way to go. Different views and understandings will be generated at different stages. I believe that with the deepening of learning, everyone will have their own understanding. But here I give my own experience: when learning MFC, we must have a perceptual knowledge of its application framework at a macro level! After that, we will have an obvious direction in learning and know what we are learning. I didn't realize this at the beginning, so I often don't know what to do next in the learning process, I don't know what I want to do. I hope you can learn from this article!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.