1. Relationship between MFC object and Windows Object
The most important encapsulation in MFC is the encapsulation of Win32 APIs. Therefore, we need to understand Windows Object and MFC object (C ++ object, a C ++ class instance) the relationship between them is one of the key to understanding MFC. Windows Object is a Windows operating system object represented by a handle in Win32, and MFC object is a C ++ object, is an example of a C ++ class. Here (within the scope of this article) the MFC object has a specific meaning, which refers to the C ++ object that encapsulates windows objects, it does not mean any c ++ object.
The MFC object and windows object are different, but they are closely related. Take the window object as an example:
An MFC window object is an instance of a C ++ cwnd class (or a derived class) and is directly created by a program. During program execution, it is generated with the call of window class constructor, and disappears with the call of the destructor. Windows is an instance of an internal data structure in windows. It is identified by a "window handle". Windows creates it and allocates system resources to it. After an MFC window object is created in Windows, it is created by the create member function of the cwnd class. The "window handle" is saved in the m_hwnd member variable of the window object. Windows windows can be destroyed by a program or by user actions.
(1) Data Structure comparison
The MFC object is an example of the corresponding C ++ class, which is defined by the MFC or programmer;
Windows Object is the internal structure of a Windows system and is referenced by a handle;
MFC defines a member variable for these classes to save the windows object handle corresponding to the MFC object. For the device description table CDC class, two HDC handles are saved.
(2) Hierarchical comparison
MFC object is high-level, while windows object is low;
The MFC object encapsulates most or all of the functions of Windows objects. Users of the MFC object do not need to directly apply the windows object handle (handle) to use the Win32 API, instead, it refers to the member functions that reference the corresponding MFC object.
(3) comparison from creation
The MFC object is directly created by the program through the constructor; the windows object is created by the corresponding SDK function.
To use these MFC objects in MFC, follow these steps: first, create an MFC object, create it in the stack, or create it in the heap, the instance variable of the MFC object handle is null, or is not a valid handle. Then, call the MFC object member function to create the corresponding windows object. The MFC handle variable stores a valid handle.
The CDC (device description table class) is created differently.
Of course, you can create the corresponding windows object in the MFC object constructor. the GDI class of MFC is implemented in this way, but in essence, the creation of an MFC object is different from that of a Windows Object.
(4) comparison from conversion
You can obtain the corresponding windows object handle from an MFC object. Generally, you can use the MFC object member function getsafehandle to obtain the corresponding handle.
You can create a corresponding MFC object from an existing windows object. Generally, you can use the member function attach or fromhandle of the MFC object to create a permanent object, the latter may obtain a temporary object.
(5) use range comparison
The MFC object is invisible and unavailable to other processes of the system. Once a windows object is created, its handle is global throughout the Windows system. Some handles can be used by other processes. Typically, a process can obtain the window handle of another process and send messages to the window.
For the thread of the same process, only the MFC object created by this thread can be used, and the MFC object of other threads cannot be used.
(6) Comparison on destruction
The MFC object disappears with the calling of the destructor, but the windows object must be destroyed by the corresponding Windows system function.
The devices in the device description table have different CDC objects. The corresponding HDC handle objects may not be destroyed but released.
Of course, the destruction of Windows objects can be completed in the destructor of the MFC object, and the GDI class of the MFC object is implemented in this way. However, we should see that the destruction of the two is different.
Each type of windows object has a corresponding MFC object. The following table lists the mappings between them, as shown in the following table:
Description |
Windows handle |
MFC object |
Window |
Hwnd |
Cwnd and cwnd-Derived classes |
Device context |
HDC |
CDC and CDC-Derived classes |
Menu |
Hmenu |
Cmenu |
Pen |
Hpen |
Cgdiobject class, cpen and cpen-Derived classes |
Brush |
Hbrush |
Cgdiobject class, cbrush and cbrush-Derived classes |
Font |
Hfont |
Cgdiobject class, cfont and cfont-Derived classes |
Bitmap |
Hbitmap |
Cgdiobject class, cbitmap and cbitmap-Derived classes |
Color palette |
Hpalette |
Cgdiobject class, cpalette and cpalette-Derived classes |
Region |
Hrgn |
Cgdiobject class, crgn and crgn-Derived classes |
Image list |
Himagelist |
Cimagelist and cimagelist-Derived classes |
Socket |
Socket |
Csocket, casynsocket and Its Derived classes |
Broadly speaking, document objects and files can be considered as a pair of MFC objects and Windows objects, which are described using the cdocument class and file handle respectively.
Windows Object: You can use the Win32 API of the SDK to write various Windows applications. The common rule is as follows: first, you can write the winmain function and wndproc in the window process for processing messages and events, register the window (register window) in winmain, create the window, and start the message loop of the application.
The MFC application is no exception, because MFC is a programming framework built on the sdk api. The difference for programmers is that, in general, the MFC framework automatically completes Windows Registration and creation.
2. MFC window encapsulation for Windows
(1) Windows Registration
Before creating a window of a type, an application must first register the window class ). Note that this is not a class of the C ++ class. Register window associates the Window Process, window type, and other type information with the window class to be registered.
Data structure of "window class"
The window class is the data structure of the Windows system. It can be understood as the type definition of the Windows system, while the Windows window is an instance of the corresponding window class. Windows uses a structure to describe "window class". Its definition is as follows:
Typedef struct _ wndclassex {
Uint cbsize; // The number of bytes in this structure
Uint style; // the style of the window class
Wndproc lpfnwndproc; // Window Process
Int cbclsextra;
Int cbwndextra;
Handle hinstance; // The application instance of the Window Process of the window class
Hicon; // The image ID used by the window class
Hcursor; // cursor used by the window class
Hbrush hbrbackground; // specifies the background brush used by the window class.
Lpctstr lpszmenuname; // menu resources used by the window class
Lpctstr lpszclassname; // name of the window class
Hicon hiconsm; // The image ID used by the window class
} Wndclassex;
It can be seen from the definition of "window class" that it contains important information about a window, such as the window style, Window Process, display and drawing information required by the window, and so on. The Window Process will be discussed in detail in subsequent sections such as message ing. During Windows system initialization, some global "Window classes" will be registered (register), such as general control window classes. When creating your own window, the application must first register its own window class. In the MFC environment, there are several methods that can be used to register the "window class", which are discussed below.
① Call afxregisterclass Registration
The afxregisterclass function is a global function of MFC. Afxregisterclass function prototype:
Bool afxapi afxregisterclass (wndclass * lpwndclass );
The lpwndclass parameter is a pointer to the wndclass structure, indicating a "window class ".
First, afxregisterclass checks whether the "window class" you want to register has been registered. If yes, it indicates that it has been registered and returns true. Otherwise, it continues to process.
Next, call: registerclass (lpwndclass) to register the window class;
Then, if the current module is a DLL module, add the registered "window class" name to the module status domain m_szunregisterlist. This field is a fixed-length buffer, which stores the names of the "window classes" registered by the module in sequence (each name is a string ending ). This is done to automatically cancel the window class registered by the DLL when it exits (unregister.
Finally, return true to indicate successful registration.
② Call afxregisterwndclass to register
The afxregisterwndclass function is also a global function of MFC. Afxregisterwndclass function prototype:
Lpctstr afxapi afxregisterwndclass (uint nclassstyle, hcursor, hbrush hbrbackground, hicon );
Parameter 1 specifies the window class style. Parameters 2, 3, and 4 respectively specify the cursor, background brush, and image handle used by the window class. The default value is 0.
This function dynamically generates the name of the window class based on the window class attributes, and then determines whether the class has been registered. If yes, the window class name is returned; otherwise, use the properties of the specified window class (the window process is specified as the default Window Process), call afxregistercalss to register the window class, and return the class name.
③ Call: registerwndclass Registration
Directly call the window registration function of Win32: registerwndclass registers the "window class", which has a disadvantage: if it is a DLL module, in this way, the registered "window class" will not be automatically canceled when the program exits (unregister ). Therefore, you must remember to cancel the registered window class when the DLL module exits.
Subclass is a "window class" that automatically obtains its "window class" attribute.
(2) MFC window class cwnd
In Windows, the properties of a window are stored in two places: one is placed in the "window class", which is specified when the window is registered as described above; the other is placed in the windows object itself, for example: window Size, window position (X, Y axis), window Z axis order, window status (active, minimized, maxmized, restored ...), Relationship with other windows (parent window, Child Window ...), Whether the window can receive keyboard or mouse messages, and so on.
To express the commonality of all these windows, MFC designs a window base class cwnd. It is very important that cwnd provides a standard and common MFC Window Process, which is used by all windows in MFC. As for the general window process, different operations can be implemented for each window, that is, the mysteries and functions of the MFC message ing mechanism.
Cwnd provides a series of member functions, encapsulation of Win32-related functions, or some newly designed functions of cwnd. These functions are roughly as follows.
Window Creation Function
The create and createex functions are discussed here. They encapsulate the Win32 Window Creation function: createmediawex. The create prototype is as follows:
Bool cwnd: Create (lpctstr lpszclassname,
Lpctstr lpszwindowname, DWORD dwstyle,
Const rect & rect,
Cwnd * pparentwnd, uint NID,
Ccreatecontext * pcontext)
Create is a virtual function used to create subwindows (desktop windows and pop up windows cannot be created ). The basic class of cwnd can overwrite this function. For example, the border window class overwrites this function to create a border window. The class uses this function to create a window interface.
Create calls the member function createex. The following is a prototype of cwnd: createex:
Bool cwnd: createex (DWORD dwexstyle, lpctstr lpszclassname,
Lpctstr lpszwindowname, DWORD dwstyle,
Int X, int y, int nwidth, int nheight,
Hwnd hwndparent, hmenu nidorhmenu, lpvoid lpparam)
Createex has 11 parameters, which will call: createmediawex to complete the creation of the window. These 11 parameters are passed to: createmediawex. The parameter specifies the window extension style, "window class", window name, window size and position, parent window handle, Window menu, and window creation parameters.
The wm_create message is sent when the window is created. The Message Parameter lparam points to a variable in the createstruct structure, which has 11 fields. In Windows, the variable is filled with the same content as the createex parameter.
Window destroy Function
Destroywindow function, destroy window
Postncdestroy (), called after the window is destroyed, virtual function
Function used to set, obtain, and change window properties
Setwindowtext (cstring tiltle) set the window title
Getwindowtext () to get the window title
Seticon (hicon, bool bbigicon );
GetIcon (bool bbigicon );
Getdlgitem (int nid); get the control subwindow with the specified ID of the window class.
Getdc (); get the device context of the window
Setmenu (cmenu * pmenu); set the Window Menu
Getmenu (); get the window menu
...
The function used to complete window actions. It is used to update Windows, scroll windows, and so on. Some member functions are designed as overloaded functions, overridden functions, or MFC message processing functions. These functions either implement some functions or are just empty functions. For example:
Functions related to message sending:
Sendmessage (uint message, wparam = 0, lparam = 0); send a message to the window, call now
Postmessage (uint message, wparam = 0, lparam = 0); send messages to the window and put them in the Message Queue
Functions for changing the window status:
Movewindow (lpcrect lprect, bool brepaint = true); move the window to the specified position
Showwindow (bool); display window to make it visible or invisible
Functions that implement the Message Processing Mechanism of MFC:
Virtual lresult windowproc (uint message, wparam, lparam); Window Process, virtual function
Virtual bool oncommand (wparam, lparam); process command messages
Message Processing functions:
Oncreate (lpcreatestruct); message processing function of the MFC window, called by the MFC framework during Window Creation
Onclose (); MFC window message processing function, called by the MFC framework during Window Creation
The export classes of cwnd are window classes with more specific types and better functions. They inherit the properties and methods of cwnd, and provides new member functions (message processing functions, virtual functions, and so on)
3. Create a window object under MFC
Create a window object under MFC in two steps. First, create an MFC window object and then create a corresponding windows window. In terms of memory usage, the MFC window object can be created in the stack or heap (created using new. The specific statement is as follows:
Create an MFC window object. You can define an instance variable of a cwnd or its derived class or dynamically create an instance of an MFC window. The former creates an MFC window object in the stack space, and the latter creates an MFC window object in the heap space.
In MFC, a dynamic creation technology is also provided. The process of dynamic creation is actually divided into two steps as described above, except that the Framework automatically completes the entire process using MFC. The Framework Window, document Framework Window, and dynamic creation are usually used.
Some messages will be sent during windows window creation, such:
After creating a non-client area in the window, send the message wm_nccreate;
After creating the client area in the window, send the message wm_create;
The window process receives the two messages before the window is displayed.
If it is a child window, after sending the above two messages, send the wm_parenatnotify message to the parent window. Other class or style Windows may send more messages. For more information, see the SDK development documentation.
4. Use of the MFC window
MFC provides a large number of window classes with different functions and uses. What classes should programmers choose to use and how to use them?
Directly use the window class provided by MFC or first derive a new C ++ class from the MFC window class and then use it. In general, programmers do not need to provide the code for window registration. Whether to derive a new C ++ class depends on whether the existing window class of MFC can meet the requirements. The derived C ++ class inherits the features of the base class and changes or extends its functions, such as adding or changing special processing for messages and events.
It mainly uses or inherits the following MFC window classes:
Cframewnd and cmdiframewnd;
Documentation framework: cmdichildwnd;
View cview and cview are derived from views with special functions, such as list clistview, ceditview editing, ctreeview tree list, cricheditview supporting RTF, and dialog box-based view cformview.