For programmers, if you want to improve the efficiency of programming, a useful, powerful and easy-to-use programming tool will often bring great convenience to our programmers. In fact, for today's programming tools, the use of which tool is not the key to the problem, it is important that you can use to what extent, after all, the tools are very powerful, for general programming tasks are not incompetent tools, Otherwise, he would not have been able to live in this world for even a mere one months.
But depending on the individual's well-being and the people around us, we will use one or several tools. Comparing programming tools such as Visual Basic, C + + Builder, and Delphi, writing Windows applications with VC + + can be said to be the most challenging and arduous. In this article I have no intention to compare the good or bad of various tools, just for my own learning of Visual C + + MFC experience and experience to share and exchange with you, but also hope to meet more like-minded friends.
As for my personal prejudice, learning VC + + should be to learn his class library MFC (Microsoft Foundation Classes). Some people may have heard that MFC is a bit daunting, it is understandable, after all, Microsoft has given us a strong and very complex class library, but did not bring us to learn his good convenience. Think of my own learning MFC helpless and confused, and the Detour, and now think of it still haunted, although I am still in a very elementary introductory stage, but still very happy to take their own experience and experience to share with you. Also hope to get everyone's advice.
I. SDK Application Architecture
I learned the path of MFC from the beginning of Windows programming (perhaps this is the beginning of a detour). First of all, please follow me. See an SDK application architecture for Windows applications. And, of course, the classic "Hello world!." , the process of writing no need to wordy, the following gives his main source code (I use the wizard generated, but for the convenience of reading a little bit of editing):
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
int Apientry WinMain (hinstance hinstance,hinstance hprevinstance,lpstr lpcmdline,int ncmdshow) { Todo:place code here. MSG 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 hinstance, int ncmdshow) { ........................ return TRUE; }
Window function WndProc (), callback function
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM WPARAM, LPARAM 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; }
|
The "Hello World" source program of the SDK
First let's look at the structure of this program, WinMain () is the entry point of the function, the main task of the 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 by the portal, followed by the MyRegisterClass () Registration window class, followed by InitInstance () to generate and display the window, so that a window is completed after the initial chemical (of course, in the MyRegisterClass (), InitInstance () need to invoke the corresponding API functions to implement the specific implementation, but I am here to focus on the analysis of his structure, so do not consider his specific implementation details, and then is to maintain the message loop, the basic structure of this program is almost established. Later, the operation of the program is 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 the application's framework all the analysis of the watertight, but did not see the request program output "Hello World" ah? That's what Windows messages do, and we certainly remember that we've just said that the main program also maintains a message loop, well, it's great article in this loop. Window application is characterized by message-driven, when the system or the user requires the application to complete a task, depends on the message, the system will put the user's requirements or system requirements into a message structure, and then sent to the application, and then to deal with. Let's take a look at how the application is doing our job. After the application initialization is completed, a display window API function is called, so the system knows the program to display the window, at this time (note that this is the time to generate the message), this time in the message queue to generate a WM_PAINT message, so that the The message loop of the application captures the message and sends it to the window function (Note that the function is called by the system), and then the window function processes the message, and we are going to 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 need to do is to choose the right time for the system to generate the message. Now, we can finally fully understand the operation process of the SDK program.
The framework for an SDK application is built, so let's look at how to build an MFC application framework and the correspondence between the two.
II. Application of MFC program structure
In the previous section I analyzed the structure of a classic SDK application, but now I want to go into the topic "MFC Application Architecture". There are many MFC applications, in order to be more clearly compared to the previous article, we look at an SDI application here, of course, the example is the classic "Hello World". After using the wizard to build the application, you will find that there are several files, first of all, no matter what files, according to the main main source of the program execution of the analysis (because MFC generated the application is not very easy to read, so here I will re-edit them).
Chelloworldapp Theapp;
int AFXAPI Afxwinmain (hinstance 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::p staticdocmanager! = NULL) { if (M_pdocmanager = = NULL) M_pdocmanager = Cdocmanager::p staticdocmanager; Cdocmanager::p staticdocmanager = NULL; }
if (M_pdocmanager! = NULL) M_pdocmanager->adddoctemplate (NULL); Else Cdocmanager::bstaticinit = FALSE; return TRUE; }
BOOL chelloworldapp::initinstance () { AfxEnableControlContainer (); .................................... The change of the registry key under which our settings is stored. Todo:you should 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 to standard shell commands, DDE, File Open CCommandLineInfo Cmdinfo; ParseCommandLine (Cmdinfo);
Dispatch commands specified on the command line if (! ProcessShellCommand (Cmdinfo)) return FALSE; The one and only window have 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 one glance, it seemed as if the program had not been analyzed and even the entry point of the program could not be found. In fact, the above procedure is still after the collation of the appearance. Well, the same way to see how the program is running it (to note that the above program comes from a different file, where the layout is only to more clearly represent the structure of the program, as for the MFC file organization I will be in the following topic specific analysis, here can be temporarily not considered).
First, at the beginning of the program, we first defined a global variable Theapp, and now we just need to know that he represents the entire program, and then the program begins to intervene in the entry point. Is there a mistake, where is the entry point? Less than, in fact, int AFXAPI Afxwinmain () is the entry point of this program, strange! But it doesn't matter, it's like the first time we see the main () function in C, as long as you know. The member functions of some classes are called in Afxwinmain (), and a program execution path diagram can be drawn in the previous analysis method. Entry point----〉afxgetthread ()------〉afxgetapp ()-------àafxwininit ()-------àpapp->initapplication ()-----àpthread- >initinstance ()------àpthread->run (). As you can see, there is a clue to the execution of the program, but, as with the SDK, it is now beyond recognition, and what is the clear program structure of the past in these programs? The answer is yes, but their implementation is packaged in MFC, so let's see how the application starts and runs.
After the program is run by Afxwinmain (), First call AfxGetApp () to get the application's object pointer Papp, and then call the relevant member function through this pointer to complete the initialization and start work, and finally call the run () function, where run () The function represents the message loop in the SDK.
Things are happening in anticipation, but there seems to be something missing. Yes, we do have one more job unfinished, and that's what we need for "Hello world" as if it hadn't been lost! This is not my negligence, but intentional arrangement, because MFC uses a new (certainly relative to the SDK) of the message processing mechanism, at least on the surface. However, here I do not intend to solve the problem at once, after all, it is a bit complicated, and so we understand the relationship between MFC files I will answer this question.
I did not expect this article to be so long, just at the beginning of the time I thought I can put this problem clearly, but in fact, I am writing the idea of the same as my analysis process, unexpectedly is a long process! So I also need to remind myself as well as the friends who read this article, should take a break. I'm starting to be thankful that I've broken this problem down into a few small problems, and I'll continue to talk about it in the next topic. The files generated by the MFC program and the invocation relationships between them.
Third, MFCprogramStructure Analysis
In the previous I gave the framework of the SDK and MFC application separately, and slightly changed the correspondence between them. But for the MFC program, it is not enough to really understand its framework. Now all I have to do is to continue to analyze the MFC program above, and expect to be able to clearly see through MFC's application framework as I said in my title.
The first is to take a look at the main files that the MFC applications generated by the Application Wizard have, which classes and the corresponding functions of the related classes and their relationships (again, because I am concerned about the framework of the program here, so I will omit anything that is not very important to the topic).
In the above SDI application, the wizard generated 4 main classes for us, all of which are derived classes of the MFC classes, each contained in the corresponding header file and in the implementation file.
1. frame window class and its related files
The frame window class corresponds to the application's main window, which is understood to create a perceptual knowledge of the class, which is defined in the header file MainFrm.h and implemented in the MainFrm.cpp file. All the functions of the frame window to the light are defined and implemented here.
2. Document classes and their related files
The document class does not have an intuitive correspondence in the application, but one thing we should know is that the framework of MFC is a feature of the document/view architecture. This can be abstracted to understand, for example, we open a file in Word, in fact, this file is a document, and what we see is only a view of the file, so that the document provides support for the application display, but we really see the application shows a view, The document class is defined in "Hello WorldDoc.h", and his implementation is in the "Hello WorldDoc.cpp" file.
3. View class and its related files
The view class is used to display the contents of the Document object, the interface we see in the Word program is a view, we want to modify, paint the first action of the object is the view, so, the view class as his name points out, provided from the user perspective of things. The definition of the view class is in "Hello WorldView.h", and the implementation is in the file "Hello WorldView.h".
4. Application classes and their associated files
The initialization of an MFC application, startup run, and end are all done by the Application object. The file he corresponds to is "Hello World.cpp" and "Hello World.h".
After a general understanding of the role of application objects, let's look at the relationship between them (as shown).
The relationship between MFC application objects can be broadly seen from the diagram above. The application starts by building the Application object (which can refer to the previous article) and then creates a document template object (through Cdocmanager management) in InitInstance, which allows the application to manage documents, views, and frame windows.
At this point, my article finally can be temporarily finished, in the article I mainly analyze the framework of the application, so ignoring a lot of implementation details. In fact, learning MFC is a very long way, in different stages will produce different views and understanding, I believe that with the deepening of learning, each person will have their own understanding. But here I give my own experience is: in the study of MFC, must be on the macro of his application framework has a perceptual understanding! Because then, we will have a clear direction when learning, know what we are learning. In the beginning, I did not realize this, so often in the learning process, often do not know what to do next, and do not understand what they are looking at what to do with. Hope that through this article can learn together with you!
MFC application Framework (RPM)