Analyze the six key technologies of MFC (Part 1)

Source: Internet
Author: User
Tags exit in

Analyze the six key technologies of MFC
Digress:
I don't think that MFC reduces the burden on programmers. Although it seems that the goal of MFC is to enable programmers to program windows without having to know too much, however, I have been wandering in MFC for a long time (because there was no detailed description of the principles of MFC in books at that time), and I had no gains. Maybe my friends will say, why do we have to know the specifics of MFC? isn't the "black box" job good? Isn't that Microsoft's original intention?
No !!! In this case, I would rather never choose MFC! Before learning computer, I learned things mostly related to Art. I won the Silver Prize when I participated in the National calligraphy and painting competition in elementary school. My childhood hobby is to draw on a piece of paper as you like! The MFC "black box" is like a huge Abstract Image (which you cannot understand). It uses a pencil to draw lines and then fill in the color.
How can we endure "black box" tasks? We chose C ++ because it is free and artistic. We can release our fantasies here. Therefore, we need to conquer MFC.
The great teacher Sun tried his best to analyze MFC, but he may not be very clear about it due to space limitations (I believe many students have such feelings ). Here, I want to share with you the six key technologies of the famous MFC.
Where can I start? I think it's best to get back to the first time exploring MFC.
I know that a programmer always forgets how he came along and what a student wants to know most. A small question (one or two sentences can be explained). I tried to remember how I made myself suddenly open up.
Transfer subject:
The six key technologies of MFC include:
The initialization process of the MFC program.
Runtime type recognition (rtti ).
Dynamic Creation.
Save permanently.
Message ing.
Message transmission.
The initialization process of the MFC Program
1. Design a simple and complete MFC program to generate a window. Of course, this does not allow the Appwizard to be automatically generated for us. We can write as follows in the Win32 Application Project:
# Include <afxwin. h>
Class MyApp: Public cwinapp
{
Public:
Bool initinstance () // ② program entry point
{
Cframewnd * frame = new cframewnd (); // construct the framework
M_pmainwnd = frame; // set m_pmainwnd to frame;
Frame-> Create (null, "simplest window"); // create a framework
Frame-> showwindow (sw_show); // display frame
Return true; // return
}
};
MyApp theapp; // ① create an application.

Set the link to the MFC Library and run it. A window is displayed.

From the above, we can see that it is easy to create an MFC window. It takes only two steps: one is to derive an application class from cwinapp (MyApp here ),, then, you can create an Application Object (theapp) to generate a window that you need (that is, you can create a window in initinstance ).
The whole program will rewrite an initinstance () function. Creating an object (theapp) is a complete window program. This is the charm of the "black box" job !!!!
When we were trying to applaud Microsoft, we suddenly felt empty. We wanted to know what Microsoft did for us, what do we need to do when we want to compile our own program? I am afraid we still have some unclear points in the above lines of programs. For example, why is there a m_pmainwnd pointer variable, where does it come from and where does it go? Think about how wonderful it is to program in DOS. If we need any variable, we can declare the variable, function, function, or reference the function library ...... But what should we do now !!!
We can reverse-think about how MFC achieves this effect? First of all, we need to understand that VC is not a language, it is like a notepad editor when we are learning C language (please forgive me for not an apt metaphor), so, in VC, we use C ++ programming, and C ++ is fundamental (Beginners always think that VC is a new language, A complex language that is much more advanced than C ++ ). After talking about this, I would like to use a simple sentence to summarize "MFC 'black box' is something that helps us insert 'C ++ Code ".
Since the MFC black box inserts code for us, what code does it help us insert? Will he help us Insert the code for solving the quadratic equation of one dollar? Of course not, so it inserts the common code that is required for every compilation of window programs.
Next, let's look at what is universal? Every time we program windows, we need to write the winmain () function. There must be a registration window to generate windows, message loops, callback functions ...... As a matter of fact, every time you need something, let them disappear from our eyes and let the MFC help write!
To understand the MFC initialization process, you can certainly trace the execution program. Miss Sun has been following the third lesson for a long time. I believe everyone is confused. I think that's even if you understand the MFC code, it's easy to find the north. If we don't understand it at all, how can we find the exit in the maze of thousands of lines of programs?
We need to change the method. It is better to re-compile an MFC Library, thanks! Don't laugh. Be careful with your big teeth. I am not a madman (although I am not crazy ). What we want to write is the simplest MFC class library, which is to write down the macro and theoretical content of MFC. We need to simplify the code to just run it.
Since this section describes the initialization process of the MFC program, we have an executable MFC program. The program only uses two MFC classes: cwinapp and cframewnd. Of course, there are many important MFC classes, such as view classes and document classes. But the above program does not need to be used, so it is saved temporarily (in short, it is for simplicity ).
Okay. Now, let's start writing the MFC class library ...... Alas, another big challenge is to let everyone back up the MFC hierarchy chart. God, how can I remember that piece of fish net? But since we want to understand it, we have to know that it is derived from it.
Considering that everyone is working very hard, let's take a look at the parent-child relationship of the above two classes (arrows represent derivation ):
Cobject-> csf-target-> cwinthread-> cwinapp-> overwrite the initinstance () Application class.
Cobject (same as above)-> cframetarget (same as above)-> cwnd-> cframewnd

After seeing the hierarchical relationship diagram, you can finally write the MFC class library. According to the above hierarchies, we can write the following six classes (for the sake of intuition, the constructor and destructor are not saved ).
//////////////////////////////////////// /////////////////
Class cobiect {}; // base class of the MFC class.
Class c0000target: Public cobject {};
------------------------------------------------
Class cwinthread: Public c0000target {};
Class cwinapp: Public cwinthread {};
------------------------------------------------
Class cwnd: Public c0000target {};
Class cframewnd: Public cwnd {};
//////////////////////////////////////// /////////////////
Let's try again. What should I do in the above class? You will soon think that the cwinapp class or its base class csf-target should have a virtual function virtual bool initinstance (), yes, because it is the entry point of the program and the place where the program is initialized, that is essential. Some may say that initinstance () must be reloaded in the derived class anyway. I do not define it in the ccmdtarget or cwinapp class. I will leave it to the cwinapp's derived class to add this function. It may be a bit more and more difficult to talk about this problem, but I want to believe that C ++'s friends should not have too many problems with virtual functions. In general, it is much easier for programmers to define a function as a virtual function if they clearly know that a function of the base class is used by a derived class. Some may ask why C ++ does not automatically define all functions of the base class as virtual functions, which saves a lot of trouble, in this way, all functions follow the defined functions of the derived class to call the derived class. If there is no definition, the base class will be called, so it is good not to write the virtual! In fact, many object-oriented languages do this. However, to define a virtual function, you need to generate a virtual function table, which occupies system space. The more virtual functions there are, the larger the table will be. Sometimes the loss is worth the candle! Here, I am a few trembling words, because the message ing that will be explained in the future will be more experienced by everyone. Well, let's try again.
The above solves the problem by writing a virtual bool initinstance () in csf-targe ().
Let's think about it again. We also need to "hide" the MFC: winmain () function, design window class, window registration, message loop, callback function ...... We immediately wanted to encapsulate them. It seems that it is not easy to encapsulate winmain (). winmain () is a special function. In many cases, it represents the start and end of a program. Therefore, when writing programs in the past, we used to write programs from winmain () to the left margin, to the right margin arc to return and end the program.
From another angle, let's think about something that can be done outside winmain (). Many beginners always think that the winmain () function is a huge function, all functions seem to be running in it. In fact, this understanding is one-sided and even incorrect. We can write such a C ++ program:
//////////////////////////////////////// ////////////
# Include <iostream. h>
Class test {
Public:
Test () {cout <"change your opinion on the main () function! "<Endl ;}
};
Test test1;
/**************************/
Void main (){}
//////////////////////////////////////// ////////////
In the above program, the main () function of the entry does nothing on the surface, but the program is executed (note: the actual entry function does something we don't know ), and output a sentence (Note: The Global Object runs first than main ). Now you can know that our winmain () function can do nothing, and the program can still run, but without this entry function, an error will be reported.
Which class will the winmain () function put above? Please refer to the following program:
# Include <afxwin. h>
Class MyApp: Public cwinapp
{
Public:
Bool initinstance () // ② program entry point
{
Afxmessagebox ("the program can still run! ");
Return true;
}
};

MyApp theapp; // ① create an application.

As you can see, I have not constructed a framework, but the program can run it. A dialog box is displayed (if there is no winmain () function program, an error is reported ). For the sake of intuition, we only need to write two lines of programs:
# Include <afxwin. h>
Cwinapp theapp;
// The whole program constructs only one cwinapp class object, and the program can run any task!
Therefore, as long as we construct a cwinapp object, we can execute the winmain () function. We immediately believe that the winmain () function is in the cwinapp class or its base class, rather than in other classes. In fact, this is wrong. We know that when writing a C ++ program, it is impossible for you to include an entry function in a class. winmain () is called by the system, it is essentially different from the functions called by our programs. We can simply imagine that when the cwinapp object is constructed, winmain () is executed.
Now everyone understands that most of the "General Code (we want to encapsulate hidden things)" can be put into the cwinapp class. How does it run? Why does a cwinapp Class Object automatically execute so many things.
After the cwinapp class object is constructed, it will automatically execute its own constructor. Then we can put the code that we want to execute automatically into the constructor of the cwinapp class.
Therefore, the cwinapp class may be designed like this (whether or not it is correct or not ):
Class cwinapp: Public cwinthead {
Public:
Virtual bool initinstance (); // the entry point of the interpreted Program
Cwinapp: cwinapp () {// Constructor
////////////////////////
Winmain (); // This is an error that you can see at a glance.
Create (); // design, create, and update the display window
Run (); // message loop
//////////////////////
}
};
After writing it, everyone immediately felt that it was wrong. The winmain () function seems to be useless and can be called like this (please allow me to declare it in the Bible: winmain () is not a common function. It needs to initialize the application, including the initialization of global variables. It is called by the system rather than the program itself. After winmain () returns, the program ends, and the process is revoked ). Let's look at the CREATE () function. Can it determine what kind of window to design and what kind of window to create? If it can be determined in the cwinapp constructor, We will design the MFC program in the future as a window, and it will become necessary to write the program. Let's look at the run () function. Can it run outside the winmain () function?
Looking back, can we make the winmain () function not contain a statement? No. Let's take a look at the four parameters of the winmain () function:
Winmain (hinstance, hinstance, lpstr, INT)
The first parameter points to an instance handle. We must specify the instance handle when designing wndclass. We must design window classes for Window Programming. Therefore, winmain () should be written as follows:
Int winmain (hinstance hinst, hinstance hprevinstance, lpstr lpcmdline, int ncmdshow)
{Hinstance = hinst}
Since the instance handle can be known only when the program starts to execute, the CREATE () function used to create the window must be executed within winmain () [because if you wait until winmain () after the execution is complete, the program ends and the process is withdrawn. Of course, the CREATE () window cannot be created.]
So how can we execute run () (message loop) in it? As we all know, a message loop is the same code, but we should not try to put it out of the winmain () function.
Therefore, in the winmain () function, we need to write the program as follows:
Winmain (......)
{
...... Create window functions for window objects ......
...... Program objects execute message loop functions ......
}
To sum up the problem of winmain (), we cannot encapsulate it into the cwinapp class during encapsulation. However, due to the immutability of winmain ), MFC is fully capable of helping us complete those lines of code when we construct cwinapp class objects.
After a big circle, we seem to have returned to the beginning of SDK programming. But now we can clearly understand that, on the surface, MFC and SDK programming are completely different, but in essence, MFC only encapsulates SDK functions in the form of classes. After encapsulation, we () the function only requires several lines of code to complete a window program. We also learned how to encapsulate the application class (cwinapp) and the main framework window class (cframewnd ). The two classes are designed as follows.
For the sake of simplicity, we ignore the compiling of the base classes and derived classes of these two classes. You may think this is a very irresponsible practice, but I think this can reduce the burden, we do not need to wear them between different categories to better understand them (we will make a note in key areas ). Also, I write all the code in the same file, so that you don't need to work hard, but this is the least recommended way to write code!

# Include <windows. h>
Hinstance;

Class cframewnd
{
Hwnd;
Public:
Cframewnd (); // you can also call create () here ()
Virtual ~ Cframewnd ();
Int create (); // class. Just pay attention to this function!
Bool showwnd ();
};
Class cwinapp1
{
Public:
Cframewnd * m_pmainwnd; // In The Real MFC
// It is a cwnd pointer, but the cwnd class is not written here.
// Write it as a cframewnd pointer
Cwinapp1 * m_pcurrentwinapp; // point to the application object itself
Cwinapp1 ();
Virtual ~ Cwinapp1 ();
Virtual bool initinstance (); // MFC is a function that must be reloaded. The most important function !!!!
Virtual bool run (); // message loop
};
Cframewnd: cframewnd (){}
Cframewnd ::~ Cframewnd (){}

Int cframewnd: Create () // encapsulate the creation window code
{
Wndclass wndcls;
Wndcls. Style = 0;
Wndcls. cbclsextra = 0;
Wndcls. cbwndextra = 0;
Wndcls. hbrbackground = (hbrush) getstockobject (white_brush );
Wndcls. hcursor = loadcursor (null, idc_cross );
Wndcls. hicon = loadicon (null, idc_arrow );
Wndcls. hinstance = hinstance;
Wndcls. lpfnwndproc = defwindowproc; // default window procedure function.
// You can imagine the common window process of MFC.
Wndcls. lpszclassname = "window class name ";
Wndcls. lpszmenuname = NULL;
Registerclass (& wndcls );

Hwnd = createwindow ("window class name", "window instance title name", ws_overlappedwindow, 0, 600,400, null, null, hinstance, null );
Return 0;
}

Bool cframewnd: showwnd () // display the update window
{
Showwindow (hwnd, sw_shownormal );
Updatewindow (hwnd );
Return 0;
}

/////////////
Cwinapp1: cwinapp1 ()
{
M_pcurrentwinapp = this;
}
Cwinapp1 ::~ Cwinapp1 (){}
// The following is the initinstance () function. In MFC, you must rewrite the derived class of cwinapp,
// Put it in the cwinapp class for ease of understanding!
// You only need to remember that the actual MFC can rewrite this function in the derived class.
Bool cwinapp1: initinstance ()
{
M_pmainwnd = new cframewnd;
M_pmainwnd-> Create ();
M_pmainwnd-> showwnd ();
Return 0;
}

Bool cwinapp1: Run () // encapsulate the message loop
{
MSG;
While (getmessage (& MSG, null, 0, 0 ))
{
Translatemessage (& MSG );
Dispatchmessage (& MSG );
}
Return 0;
}/////////////////////////////////////// ///////////// Encapsulate the message loop

Cwinapp1 theapp; // Application Object (global)

Int winapi winmain (hinstance hinst, hinstance hprevinstance, lpstr lpcmdline, int ncmdshow)
{
Hinstance = hinst;
Cwinapp1 * PAPP = theapp. m_pcurrentwinapp;
// A global function afxgetapp is required for the actual MFC to obtain the cwinapp pointer.
PAPP-> initinstance ();
PAPP-> Run ();
Return 0;
}

The code is so long that it actually only writes three functions, one is the CREATE () of the cframewnd class, and the other is the initinstance () and run () of the cwinapp class (). Here, it is particularly worth noting that initinstance (), in actual MFC, We need to rewrite this function according to our own window construction needs.
As you can see, after encapsulating the above two classes, you can write a few lines of code in the entry function winmain to generate a window program. In MFC, because the winmain function is fixed with a few lines of code, MFC can definitely help us automatically complete it (the special feature of MFC is to help us complete regular Code ), so when we create an MFC application, we cannot see the winmain function.
Written here, one of the six key technologies of MFC: the initialization process (simulation) of the MFC program is almost finished. Looking back, I wrote more than eight thousand words. I thought I didn't need to write so many words on the six key technologies. Now I still feel glad that I didn't include documents or videos, otherwise, I do not know when to write it.
Five other key technologies have not been written. Should I write them? I wrote more than eight thousand words above, all of which were typed in one word by one. Every example was made by myself. It took more than 10 hours to get it. It may be the abuse and ridicule of friends in the Forum!
But I think it is worth it. I always think that VC has no enemies. I only have friends and look around and find that there are fewer and fewer friends Learning VC, and I have not found many places to recruit VC programmers. I remember that when I was in college, I met a senior artist who worked in fine arts, like an enemy country (I once worked in fine arts ). The Senior artist has a good artistic skills, but he has never won the first prize in the school. The reason why the award does not know how to appreciate his work. My appearance, he deeply realized that: more than one friend, will be a little lonely! Sometimes I think that a friend who has learned VC is a hero (but I am not a hero, because I have never made any breakthroughs in VC over the years). I am a respectable character. Let's talk about it and correct our mistakes, it's a blessing ......
My QQ: 14653353, e_mail: liyi268@163.net (this is two men and two women share the mailbox, may not necessarily be I received, if noted Mr. Li received another on) Welcome to contact.

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.