MFC programming 1

xiaoxiao2021-03-06  39

MFC programming 1

Microsoft Basic Class Base (MFC: Microsoft Foundation

Class) is Microsoft's object-oriented Windows programming interface provided by Windows programmers, which greatly simplifies Windows programming. The benefits of using the MFC class are: First, MFC provides a standardized structure so that developers do not have to create and manage a standard Windows application, but "stand on giant shoulders", from a comparison High starting point programming, saves a lot of time; secondly, it provides a lot of code to guide user programming to implement certain techniques and functions.

For the user, the final application developed with MFC has a standard, familiar Windows interface, which is easy to use; in addition, the new application can immediately support all standard Windows feature, and use ordinary, Clearly defined form. In fact, a new standard -mfc standard is defined on the basis of the Windows application interface.

First, MFC class library concept and composition

Class library is a collection of interrelated C classes that can be used in applications. Microsoft provides an underlying class library MFC, which contains C and C

A set of classes of the Windows application. The core of the basic class library is to encapsulate most of the Windows in the form of C .

API. Class library representations Windows, dialogs, device contexts, public GDI objects such as brush, palette, control box, and other standard Windows parts. These classes provide an interface for simple C member functions in Windows.

The MFC can be divided into two main parts: (1) Basic class (2) macro and full function.

1. MFC basic class: The class in the MFC is divided into the following categories by function.

Base class application framework class application class command related class document / view class

Thread Class Visual Object Class Window

Property Table Control class menu class device description table painting object class

General class file diagnostic exception collection

Template Collect other support class OLE2 class OLE class OLE Visual Edit Package

OLE Visual Edit Server Program Class OLE Data Transfer Class OLE Dialog Box Class Other OLE Class Database Class

2, macro and global function: If a function or variable is not a member of a class, it is a full function or variable. Microsoft basic macros and full functions provide the following features:

Data Type Runtime Object Type Service Diagnostics Service Exception Processing

CString Formatting and Information Box Displays Message Mapping Application Messages and Management Object Connections and Embedded (OLE) services

Standard command and windows IDS

3, agreement: The full function is prefixed as "AFX", all full variables are prefixed as "AFX", and the macro does not have any special prefix, but all uppercase.

Common global functions and macros: AFXGetApp, AFXGetMainWnd, AfxMessageBox, Debug_New, etc. We will use them in later chapters and introduce them.

From the inheritance relationship, you can divide the classes in the MFC into two categories: Most of the MFC classes are inherited from cobject; others are not inherited from the COBJECT class, including: string CSTRING, date Time class CTIME, rectangular class CRECT, point CPOINT, etc., they provide program assistance.

Since most of the MFC is inherited from cobject, the COBJECT class describes some public features of other classes in the MFC, so we need to understand the COBJECT class.

Let's first check the definition of the COBJECT class, the COBJECT class defines the following list 2.1 shows: Listing 2.1CObject class definition

// Class COBject Is The Root of All Compliant (Subbby, Adaptive) Objects

Class COBJECT

{

PUBLIC:

// Object Model (Types, Destruction, Allocation)

Virtual cruntimeclass * getruntimeclass () const;

Virtual ~ cobject (); // Virtual Destructors Are Necessary

// Diagnostic (diagnosed) allocations (configuration)

Void * Pascal Operator new (size_t nsize);

Void * Pascal Operator New (size_t, void * p);

Void Pascal Operator Delete (Void * P);

#if defined (_Debug) &&! defined (_AFX_NO_DEBUG_CRT)

// for file name / line number tracking using debug_new

Void * Pascal Operator New (size_t nsize, lpcstr lpszfilename, int nline);

#ENDIF

// disable the copy constructor and assignment by Default So you will get

// compiler errors instead of unexpected behaviour if you pass Objects

// by value or assocign objects.

protected:

COBJECT ();

Private:

COBJECT (Const Cobject & ObjectSrc); // NO Implementation

Void Operator = (const cobject & objectsrc); // no importation

// attributes

PUBLIC:

Bool isserializable () const;

Bool iskindof (const cruntimeclass * pclass) const;

// Overridables

Virtual Void Serialize (CARCHIVE & A);

// Diagnostic Support

Virtual void assertvalid () const;

Virtual Void Dump (CDumpContext & DC) Const;

// Implementation

PUBLIC:

Static const AFX_DATA CRUNTIMECLASS CLASSCOBJECT;

#ifdef _AFXDLL

Static cruntimeclass * pascal _getbaseclass ();

#ENDIF

}

The COBJECT class provides the following services for derived classes:

1. Object diagnosis. MFC provides many diagnostic features, which can:

Output object internal information: CDUMPContext class with the member function dump of COBJECT, used to output an object internal data when debugging the program.

Object Validity Check: The ASSERTVALID member function of the base class can provide a validity check for the object of the derived class.

Information about the runtime Access class: MFC provides a very useful feature that can be used for runtime. If a class is derived from the COBject and uses one of the following three macros (IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE or IMPLEMENT_SERIAL), you can: Run the name

Safe and reliable use of universal COBJECT pointers to derived pointers

For example, we define a main window class.

CMYFRAME: PUBLIC CFRAMEWND

{

......

}

Then we use this class:

CMYFRAME * PFRAME = (CMYFrame *) AFXGETMAINWND ();

Pframe-> DOSMEOPERATION ();

AFXGetMainWnd is a full-class function that returns a pointer to the main window of the application, which is CWND *, so we must force it to force type conversion, but how do we know if the conversion is successful? We can use the cobject's iskindof () member function to check the type of PFrame, the usage is as follows:

Assert (pframe-> iskindof (run_timeclass (cmyframe));

Before inserting the previous statement into Pframe-> DOSMEOPERATION (), you can check when the runtime is used. When the type check fails, an assert is triggered (Assert [Asserable]), the interrupt program is executed.

2, the subject sustained.

Based on the archive CARCHIVE derived with non-COBJECT, it is provided to renew the performance of the object in the memory in binary forms in binary forms and in the disk file, and based on the object status data in the disk file.

However, MFC is more than just a class library, but it also provides a layer of additional application frameworks built on a C package in Windows API. The framework provides most public user interfaces for Windows programs.

The so-called application framework refers to the integration of various soft components necessary to generate a general application. The application framework is a supercoming of class libraries. The general class library is just a collection of isolated classes that can be embedded in any program (such as image processing, serial communication), but the application frame defines the structure of the application, it The class is independent of each other, interdependent, forming a unified whole, can be used to construct most applications. The Turbo Vision and Windows under the DOS, which are familiar with Chinese users, is an example of an application framework.

Let's take a specific example to explain the application framework provided by the MFC, such as Listing 2.2.

Listing 2.2 Application Framework Example

#include

// derived an Application Class

Class Cminmfcapp: Public CWINAPP

{

PUBLIC:

Bool initInstance ();

}

// derive the main window class

Class CMainWindow: Public CFrameWnd

{

PUBLIC:

CMAINWINDOW ();

Declare_message_map ()

}

Begin_MESSAGE_MAP (CMainWindow, CFrameWnd)

END_MESSAGE_MAP ()

/ * CMINMFCAPP MEMBER FUNCTIONS * /

Bool cminmfcapp :: initInstance ()

{

m_pmainwnd = new cmainwindow ();

m_pmainwnd-> showwindow (m_ncmdshow);

m_pmainwnd-> UpdateWindow ();

Return True;

}

/ * Cmainwindow member functions * /

CMAINWINDOW :: CMainWindow () // Constructor

{

Create (NULL, "Min Mfc Application", WS_OVERLAPPEDWINDOW, RectDefault, Null, NULL)

}

/ * an instance of type cminmfcapp * /

CMINMFCAPPPPPPP;

Listing 2.2 The program segment defines the framework program required for the smallest MFC application. The CMINMFCAPP class is declared, which is derived from the application class CWINAPP; and the window CMAINWINDOW class, which is derived from the frame window CFRAMEWND class. We also define a global object thisApp with CMINMFCAPP. The reader may ask, why don't there a winmain function? Because the MFC has already packaged it. At the time of the program, the MFC application first calls the standard WinMain function provided by the frame. In the WinMain function, first initialize the unique instance defined by CMINMFCAPP, then call CMINMFCAPP to inherit the CWINAPP's RUN member function, enter the message loop. Call the CWINAPP's ExitInstance function when exiting.

As can be seen from the above description, the application framework not only provides the class (CWINAPP, CFrameWnd et al), but also defines the basic execution structure of the program. All applications do different features on this basic structure basis.

In addition to defining program execution structures, MFC also defines three basic main window models: Single document window, multi-document window, and dialog box as the main window.

Visual C provides two important tools for supporting application frameworks, which are mentioned earlier AppWizard and ClassWizard. AppWizard is used to quickly generate the basic structure of the user on the application framework. ClassWizard is used to maintain this application structure.

Second, the advantages of MFC

Microsoft MFC has the following advantages that are different from other class libraries:

Fully support all functions, controls, messages, gdi basic graphics functions, menus, and dialogs. The design of the class and the combination of API functions are quite reasonable.

Use the same naming rules as traditional Windows API, namely Hungarian nomenclature.

When performing message processing, you do not use a Switch / CASE statement that is easy to generate, all messages maps to the class's member function, which applies to all messages to all messages. It enables the message to the mapping of the member function through macro, and these functions do not have to be a virtual member function, which does not need to generate a large virtual function table (V table) for the message mapping function, save memory.

The member variable can also be confirmed by sending a better judgment support through the ability to send the object information to the file.

Support for abnormal errors, reduce opportunities for programs error

Determine the type of data object at runtime. This allows instantiation to dynamically operate all domains

There are fewer code and fast speed. The MFC library only increases less than 40K target code, which is only 5% lower than traditional C Windows programs.

You can quickly develop a powerful application using tools such as APPWizard and ClassWizard, which is closely bound to MFC.

In addition, it is also allowed to use a conventional function call when using the MFC.

Third, the management of the MFC on the message

The management of Windows messages includes messaging and processing. To support message transmission mechanism, MFC provides three functions: SendMessage, PostMessage, and SenddlgItemMessage. The message processing is relatively complex. The MFC uses a new mechanism to replace the Switch / Case branch of Windows messages when the C language programming, simplifies Windows programming, enabling program readability, and maintains maintainability. 1, MFC processing of the message

The MFC uses a message mapping mechanism to determine how to handle specific messages. Such a message mapping mechanism includes a set of macros for identifying message processing functions, mapping class members functions, and corresponding messages. Among them, use AFX_MSG to be placed in front of the function returns to mark it is a message processing member function. If a class contains at least one message processing function, then a declare_message_map () macro is needed, which initializes the message mapping defined by the program execution section. Listing 2.3 demonstrates examples of message processing functions:

Listing 2.3 Message Processing Equipment Example

Class CMAINFRAME: cframewnd {

PUBLIC:

CMAINFRAME ();

protected:

// {{AFX_MSG (CMAINFRAME)

AFX_MSG Int Oncreate (LPCReatestruct LPCreateStruct);

AFX_MSG void OneDitCopy ();

AFX_MSG void onclose ();

//}} AFX_MSG

Declare_message_map ()

}

Member function oncreate, oneDitcopy, onclose, used to process messages WM_CREATE, ID_EDIT_COPY and WM_CLOSE. Where WM_CREATE and WM_CLOSE are system predefined messages, included in Windows.h. And id_edit_copy is an identifier of menus Edit-> Copy, that is, the user generated when the user selects the Edit-> COPY menu item, which is generally defined in the resource file header file. The definition of these three member functions is given in the implementation section of the class, as well as special message mapping macro. The message mapping macro is defined as follows:

Begin_MESSAGE_MAP (CMAINFRAME, CFRAMEWND)

ON_WM_CREATE ()

ON_COMMAND (id_edit_copy, oneditcopy)

ON_WM_CLOSE ()

END_MESSAGE_MAP ()

Message mapping macro by begin_MESSAGE_MAP () and end_message_map (). Among them, the Begin_Message_Map macro includes two parameters CMAINFRAME classes and CFrameWnd, which represents the currently defined classes and its parent class. Between Begin_Message_Map () and End_Message_MAP (), the entry of the respective Windows messages to be processed by the main window. In this example, three messages are included. The ON_WM_CREATE is used to specify the default member function on CREATE corresponding to WM_CREATE. In the MFC, a large number of predefined message mapping macro is included to specify that the various member functions correspond to a variety of WM_XXXX messages. If the ON_WM_CLOSE macro specifies the processing member function of the WM_Close message is OnClose. At this time, I just need to write the message to be dealt with, it is not necessary to write the processing function. Message mapping macro ON_COMMAND is used to link menu items and user-defined commands to their processing member functions. In the previous example, the user performs an onEditCopy () function when the user selects the Edit-> COPY menu item. The general definition form of the ON_COMMAND macro is as follows:

ON_COMMAND (Command, Command_Function)

Among them, Command is a menu message or a user-defined message, and Command_Function is a message processing function. The MFC allows the user to customize the message, the constant WM_USER, and the first message value correspond to the user's message, and the offset range is between 0 ~ 0x3FFF, which is between 0 ~ 0x3FFF, the user must define the offset value of the WM_USER. Say it is enough. Users can use the #define statement directly to define their own message: #define wm_user1 (WM_USER 0)

#define WM_USER2 (WM_USER 1)

#define WM_USER3 (WM_USER 2)

The following table lists the range of Windows message values ​​in Windows 95.

Constant value message value

WM_USER0X04000X0000-0X03FFWINDOWS message

0x0400-0x7FFF user-defined message

0x8000-0XBFFFFWINDOWS reserved value

0xC000-0xFFFF supplies string messages

To illustrate how to use user-defined messages, let's take an example, see the program list 2.4:

Listing 2.4 Using User Custom Messages

#include

#define cm_apple (WM_USER 0)

#define cm_oragenge (WM_USER 1)

Class CMAINFRAME: cframewnd {

PUBLIC:

CMAINFRAME ();

protected:

AFX_MSG Int Oncreate (LPCReatestruct LPCreateStruct);

AFX_MSG void onclose ();

// Handle User SELECT APPL

AFX_MSG LRESULT CMAPPLE (WPARAM WPARAM, LPARAM LPARAM);

// Handle User SELECT ORANGE

AFX_MSG LRESULT CMORANGE (WPARAM WPARAM, LPARAM LPARAM);

Declare_message_map ()

}

// The corresponding message mapping is as follows:

Begin_MESSAGE_MAP (CMAINFRAME, CFRAMEWND)

ON_WM_CREATE ()

ON_MESSAGE (CM_Apple, CMAPLE)

ON_MESSAGE (cm_oragen, cmorance)

ON_WM_CLOSE ()

END_MESSAGE_MAP ()

The first ON_MESSAGE macro is used to specify the processing member function of the cm_apple command message is CMAPPLE, and the second ON_MESSAGE macro is used to specify the processing function of the cm_oragenge command message is CMORANGE.

2, sending the message

The Windows application allows the application to send messages to themselves, send messages to other applications, and even send messages to the Windows operating system itself (such as to shut down the operating system or restart the operating system). Windows offers three API functions for sending messages, these three functions are: SendMessage, PostMessage, and SenddlgItemMessage.

SendMessage is used to send messages to the window, which is as follows:

LResult SendMessage (HWND HWND, // message to send the handle of the window

UINT MSG, // message to send

WPARAM WPARAM, // Message's first parameter

LPARAM LPARAM // The second parameter of the message);

This function calls the window function of the target window until the message is processed.

The PostMessage function is similar to sendMessage. It places the message in the message queue created by the specified window, and then returns the message processing, not when sendMessage must wait until the message processing is completed. The target window is removed and processed from the message queue from the message queue through GetMessage or PeekMessage. The PostMessage function describes the following: BOOL PostMessage (HWND HWND, // message sent to the window

UINT MSG, // message to send

WPARAM WPARAM, // Message's first parameter

LPARAM LPARAM // The second parameter of the message);

The SenddlgiteMmessage function is used to send messages to a control to the dialog, and the function declaration is as follows:

Long Senddlgitemmessage (HWND HDLG, // Dialog Handle

INT Niddlgitem, // Dialog Paper Control ID

UINT MSG, // message to send

WPARAM WPARAM, // Message's first parameter

LPARAM LPARAM // The second parameter of the message);

The MFC encapsulates the three functions to the member function of the CWND class, hides the window handle and the dialog handle. These three member functions are used to send messages to this window, and the description of the function is as follows:

LResult SendMessage (uint message, wparam wparam = 0, lparam lparam = 0);

Bool PostMessage (uint message, wparam wparam = 0, lparam lparam = 0);

LResult Senddlgitemmessage (int Nid, Uint Message, WPARAM WPARAM = 0, LPARAM LPARAM = 0);

Fourth, learning MFC method

First, you must have a certain understanding of the Windows API, otherwise you can't learn the MFC in-depth. At least you know what Windows means what you mean, what work can be done, some of its common data structures, etc.

Another point is not too dependent on Wizards. Wizards can do a lot of work, but at the same time, there are too many details. You should see AppWizard and ClassWizard for your work. Run the debugger in Mainfrm.cpp to observe the flow of MFC operations. Unless you understand the meaning of the generated code, you can't understand how the program is running.

It is also important to learn about the problem of grasping abstract, do not understand. Many people start learning Visual

C is trying to understand the entire MFC class library, in fact, it is almost impossible. The general learning method is, which is generally aware of the MFC, knowing its concept, composition, and basic agreed. Starting from the simplest classes, from shallow depth, step by step, and is accumulated in the month. At first, when using the class provided by the MFC, you only need to know some of its common methods, external interfaces, unnecessary to understand its details and internal implementation, use it as a module or black box, this is an abstraction Learning method. When you learn to a certain level, you can reach in-depth research, and use inheritance methods to modify and expand the behavior of the original class, and derive the class you need.

Learning MFC, the most important point is to understand and use the MFC class library, not memory.

APWIZARD creation

According to options, the files created by AppWizard will be slightly different. Standard AppWizard files include:

· Workspace file, project file and make file

· Application source file and header file

· resource

· Pre-translated header

· Added AppWizard files according to optional options

I, work area, project file and make file

Hello.dsw: This is the auto-generated workspace file that MFC, which contains information about the items included in the current workspace. Hello.dsp: This is the project file generated by the MFC, which contains information such as the current project, the files contained.

Hello.mak: This is a project file for the MFC project, which is also a file compatible with NMAKE. If the external make file is selected

Options, you can edit it, but you cannot use Visual C Many project editing features.

Hello.clw: This file contains information that is used by ClassWizard to edit existing or new categories. ClassWizard still uses this file

To save the information you need to create and edit message mapping and dialog data, or create the information you need to create a virtual member function.

Second, the application source file and header file

Depending on the type of application - single document, multi-document, or dialog box, AppWizard will create some of the following application source files and some files in the header file. In this example, AppWizard generates as follows:

Hello.h: This is the main header file of the application, which contains all global symbols and a #include directive for containing other header files.

Hello.cpp: This file is the main source file for the application. It will create an object of the ChelloApp class (derived from CWINAPP),

And override the initInstance member function.

Mainfrm.cpp, mainfrm.h:

These two files will derive the CMAINFRAME class from the CFrameWnd (SDI application) or CMDIFrameWnd (MDI application). If you are in AppWizard's Application

The corresponding options are selected in the Options page (step 4 in step 6), and the CMAINFRAME class will process the creation of the toolbar buttons and status bars. The mainfrm.cpp file also contains object IDs for the default toolbar buttons provided by the MFC application - called Buttons arrays.

Hellodoc.cpp, Hellodoc.h

These files are derived from the CDocument class and implemented a document class called CHELLODOC and contains a framework for initializing documents, serialization (saving, and loading) documents and some member functions for debugging diagnostics.

Helloview.cpp, Helloview.h

These files are derived and implemented as ChelLoview's view classes, used to display and print document data. The CHELLOVIEW class is born from CView or its derived class, contains some member function frameworks that draws and use to debug diagnostics.

Third, the resource file: AppWizard creates some files related to the resource.

Hello.rc, resource.h, hello.rc2

This is the header file of the project and its resource files. The resource file contains the default menu definition and acceleration key table, and string tables for general MFC applications. It also specifies the default About dialog and an icon file (RES / HELLO.ICO). The resource file has the resource of the standard MFC class. If the support toolbar is specified, it will also specify the toolbar graph file (res / toolbar.bmp). Hello.RC2 is used to store resources that Visual Studio cannot directly edit.

Fourth, pre-compiled head file: stdafx.cpp, stdafx.h

These two files are used to build a precompiled header file hello.pch and a predefined type file stdafx.obj. Since the MFC architecture is very large, there is a lot of header files, and if you compile, you will be compared. Therefore, we put all commonly used MFC headers in stdafx.h, such as AFXWIN.H, AFXT.H, AFXDisp.h, AFXCMN.H, and then let Stdafx.cpp contain this stdafx.h file. Thus, since the compiler can identify which files have been compiled, stdafx.cpp is only compiled once and generates a so-called pre-translated head file (because it is stored by the information after the header file is compiled, the name). If the reader does not want some MFC header files to be compiled each time, you can add it to stdafx.h. Adopt the pre-compiled head file can accelerate the compilation process. Application implementation mechanism

First, WinMain function

Under DOS, the execution of the program starts from the main function. Under Windows, the corresponding function is WinMain. However, if you browse all methods and global functions of the Hello program, you can't find the WinMain function. MFC takes into account most of the initialization work required by the typical Windows program is standardized, so the WinMain function is hidden in the application's framework, and the function will be automatically connected to the executable when compiling. Programmers can override the Winmain function, but do not need to do this.

The following program list 3-1 gives the code for the WinMain function. Among them, the _twinmain function is defined in /devstudio/vc/mfc/src/appmodul.cpp, which is defined in WinMain.cpp in the same directory. The name is _twinmain function instead of WinMain, which is considered support for different character sets, there is _twinmain's macro definition in tchar.h. When compiling under the ANSI character set, _twinmain turns WinMain, compiles under Unicode, _twinmain turns wwinmain.

Tip: Unicode is a coding standard with fixed width, unified text and characters. Since Unicode is 16-bit encoding, it can contain characters and technical symbols of writing systems around the world (such as Chinese are also in Unicode), so that the ASCII code is expanding in the shortcomings of multilingual text, expanded. Benefits of the ASCII code 7-bit coding scheme. Unicode treats all characters equally, and does not need to change the code sequence (escape) when any character indicating a variety of languages. Win32 and Visual

C is very good to support the Unicode character set.

Listing 3-1 _twinmain function definition

// Export Winmain to Force (Forced) Linkage (United) to this module

Extern int AFXAPI AFXWINMAIN (Hinstance Hinstance, Hinstance Hprevinstance,

LPTSTR LPCMDLINE, INT NCMDSHOW);

#ifdef _mac

EXTERN "C" int Pascal

#ELSE

EXTERN "C" int WinApi

#ENDIF

_twinmain (Hinstance Hinstance, Hinstance Hprevinstance, LPTSTR LPCMDLINE, INT

ncmdshow)

{

// call shared / exported WinMain

Return Afxwinmain (Hinstance, Hprevinstance, LPCMDLINE, NCMDSHOW);

AFXWINMAIN function definition:

// Standard WinMain Implementation

// can be replaced as long as 'afxwininit' Is Called First

Int Afxapi AFXWINMAIN (Hinstance Hinstance, Hinstance Hprevinstance,

LPTSTR LPCMDLINE, INT NCMDSHOW)

{

Assert (hprevinstance == null);

INT nreturNCode = -1;

CWINAPP * PAPP = AFXGetApp ();

// afX Internal Initialization

IF (! AFXWININIT (Hinstance, Hprevinstance, Lpcmdline, ncmdshow)

Goto Initfailure;

// APP Global Initializations (Rare)

Assert_Valid (PAP);

IF (! PAPP-> INITAPPLICATION ())

Goto Initfailure;

Assert_Valid (PAP);

// Perform Specific Initializations

IF (! PAPP-> InitInstance ())

{

IF (PAPP-> M_PMAINWND! = null)

{

Trace0 ("Warning: Destroying Non-Null M_pmainWnd / N");

PAPP-> m_pmainwnd-> destroyWindow ();

}

NRETURNCODE = PAP-> EXITINSTANCE ();

Goto Initfailure;

}

Assert_Valid (PAP);

NRETURNCODE = PAPP-> Run ();

Assert_Valid (PAP);

Initfailure:

#ifdef _Debug

// Check for missing AfxLockTempmap Calls

IF (AFXGETMODULETHREADSTATATE () -> m_ntempmaplock! = 0)

{

Trace1 ("Warning: Temp Map Lock Count Non-Zero (% ld) ./ N",

AFXGETMODULETHREADSTATE () -> M_NTEMPMapLock);

}

AfxlockTempmaps ();

AFXUNLOCKTEMPMAPS (-1);

#ENDIF

Afxwinterm ();

Return nreturNCode;

}

When the application is executed, Windows automatically calls the WinMain function within the application framework. As shown in Listing 3-1, the WinMain function looks for a global constructor of the application. This object is constructed by CWINAPP, and there is only one. It is a global object, so it has been constructed when the program starts.

Subsequently, WinMain will call the INITAPPLICATION and InitInstance member functions of this object to complete the initialization of the application instance. Subsequently, WinMain calls the RUN member function and runs the application loop of the application. At the end of the program, WinMain calls the AFXWINTERM function and make some cleaning work.

Second, the application class

Each application must send its own application class from CWINAPP and define a global object. The application class contains the initialization, operation, and ending process of the application under Windows. The framework-based application must have one (and only one) object from the CWINAPP derived class. In the Hello program, we have a ChelloApp class from CWINAPP and define a global object thatApp. The ChelloApp class is defined in hello.cpp. To access an object of an application class constructor, you can call global functions AFXGetApp (). AFXGetApp () returns a pointer to the global object. It can be converted to our derived application class by mandatory type conversion.

For example: cheloApp * PAPP = (chelloApp *) AFXGetApp ();

In the ChelloApp application class, we also overloaded CWINAPP member functions initInstance. The InitInstance function mainly completes the following: Set the registration database, load standard settings (recently open file list, etc.), register the document template. The main window is created in the registration document template process. Next, processing the command line parameters, display the window, and then return, enter the message loop. The following program list 3.2 gives the INITINSTANCE function code for the Hello program.

Listing 3.2 InitInstance function

Bool chelloApp :: InitInstance ()

{

AFXENABLECONTROLCONTAINER ();

// Standard Initialization

// if you are not usning these features and hope to reduce the size

// of Your Final Executable, You Should Remove from the FOLLOWING

// the specificin itization routines you do not need.

#ifdef _AFXDLL

Enable3dControls (); // Call thisime by the sale mfc in a shared dll

#ELSE

Enable3dControlsStatic (); // call thisime1 linking to mfc staticly

#ENDIF

// Change The Registry Key Under Which Our Settings Are Stored.

// you shop modify this string to becomething 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 (chellodoc),

Runtime_class (cmainframe), // main sdi frame windowruntime_class (chelloview);

AddDDOCTemplate (pdoctemplate);

// Parse Command Line for 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 has been initialized, so show and update it.

m_pmainwnd-> showwindow;

m_pmainwnd-> UpdateWindow ();

Return True;

}

In CWINAPP's derived class, you must override the InitInstance function, because CWINApp does not know what kind of window you need, it can multi-document window, single document window, or a dialog.

Run member function

WinMain then calls the RUN function to handle the message loop after initializing the application instance. The RUN member function constantly performs a message loop, checking there is any message in the message queue. If there is a message, RUN dispatches it, then handles the framework, and then returns the continuation message loop. If there is no message, Run will call OnIdle to do a user or frame, you might need to do it when you are idle, and the user interface update message processing we told later. If there is no message to be handled, it is not available when there is no time, and the application will wait until the event occurs. When the application ends, RUN will call EXITINSTANCE. The flowchart of the message loop is shown in Figure 3-10.

Figure 3-10 Message Cycle of Run Member Function

Close application

The user can terminate the application by selecting the File-Exit menu or the off button of the point to close the main window. At this point, the application class first deletes the m_pmainwnd main frame window object, then exits the Run function, and then exits WinMain, and remove theApp object after exiting WinMain.

Several window types

First, frame window

The frame window provides a structural frame for the application's user interface. It is the main window of the application. It is responsible for managing its tolerant windows. The top-level frame window of an application is the first window created when the application is started.

MFC offers three types of frames: Single Document Window, Multi-Document Window (MDI), dialog. The MFC single document window can only open a document frame window at a time, while the MDI application is running, open multiple document frame windows in one instance of the application, which is called the sub-window (Child

Window. These documents can be the same type or may be different types. Visual

Studio can open different types of windows such as resource file windows and source windows. At this point, activate different types of MDI sub-windows, and the menu will also change accordingly.

The MFC provides three class CFrameWnd, CMDIFrameWnd, CmdichildWnd, and CDialogs to support a single document window, multi-document window, and dialogs, respectively.

Cframewnd

For the SDI frame window, form a single document and a border thereof. The frame window is both the main frame window of the application and a border of the view corresponding to the current document.

Cmdiframewnd

The main frame window for the MDI application. The main frame window is a container of all MDI document windows and sharess menu bars with them. The MDI frame window is a top-level window that appears in the desktop. Cmdichildwnd

The various documents used in the MDI main frame window are displayed. Each document has an MDI sub-frame window, which is included in the MDI main frame window. The sub-frame window looks similar to a general frame border window, but it is included in the main frame window, not at the desktop, and cuts the main window. And the MDI child window does not have its own menu, which shares the menu with the main MDI Frame window window.

CDIALOG

The dialog is a special type of window that is generally not adjustable, and the internal contains some control windows.

To generate a single document window, the main window must be derived from the CFraMewnd; to generate a multi-document window, the main window must derive from the cmdiframewnd, and the sub-window must be derived from cmdichildwnd; and the dialog-based window program is Derived from CDIALOG to the main window class.

Child window

The child window is a window with a WS_CHILD style, and there must be a parent window. All controls are sub-windows. The sub-window can have no border. The sub-window is fully limited inside the parent window.

Parent window

The parent window is a window with a child window.

Pop-up window

Has a WS_POPUP style, it can have no parent window. This window is almost all, it can be seen as a rectangular area.

Second, the creation of the window

The creation of the window is divided into two steps: The first step is to create a C window object with NEW, but this is only the data member of the initialization window, and does not really create a window (this is different from the general object).

Step 1: Create a C object, where CMAINFRAME is the object derived from the CFrameWnd.

CMAINFRAME * PMYFRAME = New cmainframe (); // Create a window object with a New operator

or

CMAINFRAME MyFrame; / / Define a window object and automatically call its constructor

Step 2: Create a window. CFrameWnd's Create member function is made, and saves its hwnd in the public in C object.

Data member m_hwnd.

PMYFRAME-> CREATE (NULL, "My Frame Window);

or

Myframe.create (NULL, "My Frame Window);

The original shape of the CREATE function is as follows:

Bool Create (lpctstr lpszclassname, lpctstr lpszwindowname, dword dwstyle =

WS_OVERLAPPEDWINDOW, Const Rect & Rect = RectDefault, CWnd * PparentWnd = NULL,

LPCTSTR LPSZMENUNAME = NULL, DWORD DWEXSTYLE = 0, ccreatecontext * pContext =

NULL);

The CREATE function first parameter is a window registration class name, which specifies the icon and type of the window. Here we use null as its value, indicating the use of default attributes. The second parameter is a window title. The remaining parameters specify the style, size, parent window, menu name, etc. of the window.

This function looks more complicated. For the window derived for CFrameWnd, we can use LoadFrame to create a window from the resource file, which only needs a parameter.

PMYFRAME-> LoadFrame (iDR_frame);

LoadFrame uses this parameter to get many defaults from the resource, including the title, icon, menu, acceleration key, etc. of the main border window. However, when using LoadFrame, you must ensure that the title string, icon, menu, and accelerator, etc. use the same ID identifier. Tip: We can't see the process of creating a window in InitInstance in the Hello program. In fact,

PDOCTEMPLATE = New CSINGLEDOCTEMPLATE

IDR_MAINFRAME,

Runtime_class (chellodoc),

Runtime_class (cmainframe), // main SDI Frame WinDow

Runtime_class (chelloview);

AddDDOCTemplate (pdoctemplate);

In the program clip, we see that the second parameter of the CSINGEDEMPLATE constructor is IDR_MAINFRAME. Inside the constructor, the creation process of the application main window has been completed by calling m_pmainwnd-> loadingframe (idR_mainframe).

In InIntInstance, after the window is created, the window calls the showWindow member function to display the window. ShowWindow with a parameter, indicating what is displayed in the window (maximize, minimize or general). The default mode is SW_SHOW, but in fact, we often want the application to maximize the window when the application starts, and this parameter can be sw_showmaxmized, that is, call m_pmainwnd-> showWindow (sw_showmaximized);

In Mainfrm.cpp, we also see that the CMAINFRAME class has an OnCreate method. The oncreate member function is defined as Listing 3.3. When CREATE or CREATEEX is called, the operating system sends a WM_CREATE message to the window. This function is used to respond to WM_CREATE messages.

Listing 3.3 Oncreate Member Function Definition

INT CMAINFRAME :: OnCreate (lpcreatestruct lpcreatestruct)

{

IF (cframewnd :: oncreate (lpcreatestruct) == -1)

Return -1;

IF (! m_wndtoolbar.create (this) ||! m_wndtoolbar.loadtoolbar (iDR_mainframe))

{

Trace0 ("Failed to Create Toolbar / N);

Return -1; // fail to create

}

IF (! m_wndstatusbar.create (this) ||! m_wndstatusbar.setindicators (Indicators,

SIZEOF (INDICATORS) / SIZEOF (UINT))))

{

Trace0 ("Failed to Create Status Bar / N);

Return -1; // fail to create

}

// Todo: Remove this if you don't want Tips or a Resizeable Toolbar

m_wndtoolbar.setbarstyle (m_wndtoolbar.get barStyle () |

CBRS_Tooltips | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

// Todo: Delete these Three Lines if you don't wantbar to be Dockable

M_WndtoolBar.enableDocking (CBRS_ALIGN_ANY); Enabledocking (CBRS_ALIGN_ANY);

DockControlbar (& M_WndToolbar);

Return 0;

}

In the oncreate function, first call the CFRAMEWND's default processing method onCreate complete the window creation work. Behind the application main window, in the above program, create the toolbar and status bar. Some initialization work can be added here, such as load settings from the INI file, showing Splash

Window and so on.

Third, registration window

Traditional Windows

In the C program, all messages given to a window are processed in its window function. The process of linking a window with its window function is called a registration window class. The registration window includes specifying a window function (a pointer to the window function) and the cursor, background brush, etc. of the setting window. A registration window class can be shared by multiple windows. The registration window is done by calling the API function registerclass.

Under the MFC, the framework provides the default auto window registration process. The framework still uses traditional registration classes, and provides several standard registration classes, which are registered in the standard application initialization function. Call the AFXREGISTERWNDCLASS global function to register additional window classes, then pass the registered class to the CREATE member function of CWnd. Users can customize their own registration procedures to provide some additional features. For example, icon, background, cursor, etc. set up window. Below is an example of a registered window.

Bool CMAINFRAME :: PrecreateWindow (CreateStruct & Cs)

{

// Todo: modify the window class or styles Here by modifying the createStructcs

UINT ClassStyle = CS_VREDRAW | CS_HREDRAW;

cs.style = cs.style & (~ fws_addtotitle); / / Specify window title style, turn off the function of automatically add document title

// Specify the window using the arrow cursor, the background brush uses the color of the window color label, the icon uses the icon specified by the IDR_MAINFRAME identifier.

cs.lpszclass = AFXREGISTERWNDCLASS (ClassStyle,

AfxGetApp () -> LoadStandardCursor (IDC_ARROW),

(Hbrush) (Color_Window 1), // for brush

AFXGetApp () -> loadicon (idR_mainframe);

Return True;

}

The registration window is done in the PrecreateWnd method of the cframewnd. From the member function name PrecreateWindow, you can see that the work of the registration window must be done before calling the CREATE function creation window.

Fourth, close and destroy the window

The frame window not only maintains the creation of the window, but also manages the shutdown and destruction process of the window. When the window is turned off, the operating system sends WM_Close and WM_DESTROY messages in turn. The default processing function on the WM_Close message calls DestroyWindow to destroy the window;

Do not use the C Delete operator to destroy the frame window, and the CWnd's DestroyWindow member function should be used to destroy. DESTROYWINDOW first deletes sub-windows, then delete the window itself. If the window is generated in a variable mode (ie, allocated on the stack), the window object will be automatically cleared. If the object is created with a New operator (that is, allocating memory on the heap), you need to handle it yourself. OnClose () Common features: Save some status of the window, the toolbar status, prompt to save unsaved data, etc.

Void cmainframe :: onClose ()

{

Savebarstate ("MyDockState"); // Save the tool strip status

CframeWnd :: onClose ();

}

V. Window activation

Activity window must be a top window without a parent window, including the Frame Window, and dialog. When the top window is activated, Windows sends a WM_ACTIVATE message to the window, and the default processing of this message is to set the moving window to have input focus.

Input focus is used to indicate which window is eligible to receive the keyboard input message. A window with an input focus or an active window, or a sub-window of the active window. When a top window gets the input focus, Windows sends a WM_SETFOCUS message to the window, which relocates the input focus to its sub-window. The sub-window does not automatically get the input focus. The window that lost the focus will receive a WM_KILLFOCUS message. When the child window has input focus, the parent window does not process the keyboard input.

Use menu

Now we have to join your own menu in the main window. Menu program is generally divided into three steps:

1. Edit menu resources, set menu properties (including menu names and id);

2. Automatically map menu messages and member functions with ClassWizard;

3. Manually edit the member function, join the menu message processing code.

First, edit menu resources

Still using the Hello program we generated in front, edit the menu resource generated by AppWizard. To edit menu resources:

Menu Name Menu ID Menu Tip (Prompt)

Say & Helloid_SAY_HELLOSAY HELLO to you!

& RedId_select_redthe color is red.

& Blueid_select_bluethe color is blue.

& YellowId_select_yellowthe color is Yellow.

Tip: If Chinese wants to use in the menu, except in the menu name, set the language properties of the menu resource to Chinese. Method is: Right-click the menu resource IDR_MAINFRAME, pop up the shortcut menu, select Properties, and select the property dialog box of the entire menu resource, select Chinese in the Languages ​​drop-down list box.

(P.r.c.). This will use the menu to use and display Chinese correctly. If other resources such as dialogs or strings should be used in Chinese, it is also necessary to change the language attribute of the resource to Chinese (p.r.c).

Close the menu editor window now. We want to be Say

The Hello menu adds an accelerator key Ctrl H. To edit the accelerator, select the Accelerator resource type, double-click Open the IDR_MAINFRAME accelerator resource. To delete the accelerator, you can press the DEL key directly. To increase the acceleration key, you can press the INS button to pop up the Acceleration Keys Properties dialog box. Select ID_SAY_HELLO in the ID drop-down list box, enter H in the Key column, complete the acceleration key settings.

Second, automatically map menu messages and members functions with ClassWizard

First introduce the usage of ClassWizard.

1. Use the ClassWizard management class and Windows message ClassWizard helps create a Windows message and command handler, create and manage classes, create class member variables, creating OLE Automation methods and properties, create database classes, and other work.

ClassWizard also helps cover virtual functions in the MFC class. First select classes, then select the virtual function that needs to be overwritten. The rest of this process is similar to message processing.

2, launch the ClassWizard application

Select ClassWizard from the View Menu or Source Program Edit window. The dialog contains several tabs and provides the following options:

Message Maps: It manages the mapping relationship between messages and member functions.

Member Variables: It allows users to add some data members to perform data exchange with various controls.

Automations: It provides a variety of features support OLE2.0, including increasing attributes, methods, and processing events for Ole Automation.

ActiveX Events: Adds the property, method, and the ActiveX control event to increase the processing function for the ActiveX control event.

Class INFO: It allows users to create new classes to support dialogs and various visual classes (including control, windows, etc.). You can also import class to the current project from the class library file.

3, Message Maps option

You can let users join the member function to process messages, delete member functions, and edit the member function. The Message Maps page includes the following control options:

Projects Combination Box: Allows users to select the project included in the current workspace.

Class Name Combination Box: Allows users to select classes in the current project.

Objects IDS list box: List the currently selected class name and related ID. For windows and terms, these IDs are menu identifiers; for dialogs, these IDs are the ID of the control box.

Messages list box: List the overloaded virtual method of the currently selected class and the received message.

MEMBER FUNCTIONS list box: List all member functions included in the currently selected item in the ClassName group box. Users can increase, delete member functions, or edit the member function.

Add Class ... button: It allows users to add new classes to the project. There is a downward arrow on the right side of the button, indicating that the button will pop up a menu. The menu contains two items: New ... can create a category;

From A Type lib is used to import classes from a class library.

Add Function button: It allows users to add a new message processing member function to the Member Functions list box that is used to respond to the currently selected message in the Message Maps list.

DELETE FUNCTION button: Used to delete the item selected in the MEMBER FUNCTIONS list box.

Edit Code button: It allows the user to edit the item selected in the Member functions. At this time, Visual Studio will turn off the MFC ClassWizard dialog box and open the corresponding file and position the cursor at the beginning of the function definition.

Message box function

AfxMessageBox is used to pop up a message box, and its function prototype has two versions:

INT AFXMessageBox (lpctstr lpsztext, uint ntype = mb_ok, uint nidhelp = 0);

INT AFXAPI AFXMESSAGEBOX (uint nidprompt, uint ntype = mb_ok, uint nidhelp = (uint) -1); in the first form, lpsztext represents the text of the message displayed inside the message box, the header of the message box is the executable of the application Name (such as Hello). In the second form, NidPrompt is the ID of the text string to be displayed in the string table. The string is automatically loaded from the string table when the function is called and displayed in the message box. NTYPE is a combination of button style and icon style displayed in the message box, which can be combined with a variety of styles.

Button style

The ABORT, RETRY, IGNORE button is displayed in the MB_ABortRetryIgnore message box.

MB_OK Displays the OK button

MB_OKCANCEL display OK, Cancel button

MB_RETRYCANCEL Displays Retry, Cancel Button

MB_YESNO Shows Yes, NO Buttons

MB_YESNOCANCEL shows Yes, No, Cancel button

Icon style

MB_ICONInInformation displays an I icon, indicating that the prompt

MB_ICONEXCLAMATION displays an exclamation mark that means warning

MB_ICONSTOP shows hand icons, indicating warnings or serious errors

MB_ICONQUESTION displays the question mark icon, indicating that questions

For example: To display a question mark in the message box, a "yes" button, a "no" button, can call AFXMessageBox in the following manner.

AFXMessageBox ("Are you Sure?", MB_YESNO | MB_ICONQUESTION;

There is also a function MESSAGEBOX similar to the AFXMessageBox, which is a CWND class member function:

INT MessageBox (LPCTSTR LPSZTEXT, LPCTSTR LPSZCAPTION = NULL, UINT NTYPE = MB_OK);

Unlike the AFXMessageBox, it has a lpszcaption parameter. From the name, you can infer the title indicating the message box, so you can set the title of the message box without having to use the executable file name as the title.

The difference between the two functions: AFXMessageBox is simpler than MessageBox, because it is a full-time function, but does not need a corresponding window class, but cannot control the message box title, the internal data output or warning of the debugger; MessageBox is officially officially official, Commonly used in the application versions you want to submit, you can control the title content without having to use the unknown executable file name.

Update Command User Interface (UI) Message

In general, menu items and toolbar buttons are not only one state, and we often need to change according to the internal state of the application. For example, if it is effective or invalid, there is a check mark. To this end, the MFC application framework introduces update command user interface messages to simplify this work.

Update_command_ui is an update command user interface message, which is specifically used to process updates to menu items and toolbar buttons. Each menu command corresponds to an update command user interface message. You can write a message processing function to update the message processing function to update the message processing function (including the menu and toolbar buttons). If a command has multiple user interface objects (such as a menu item and a toolbar button), both are sent to the same processing function. Thus, for all equivalent user interface objects, the user interface can be updated in the same place.

First, the user interface update principle

In order to understand the user interface update mechanism, let's take a look at how the application framework is updated by the user interface. When we select an Edit menu, a WM_INITMENUPOPUP message will be generated. The framework update mechanism will update all items before the menu pulls down, and then display the menu. To update all menu items, the application framework sends a route by the standard command to send the update command in the pop-up menu. You can update any menu item by matching commands and appropriate message mapping entries (in -_update_command_ui), and calls the appropriate update processor function. For example, there are four menu items such as undo, cut, copy, and paste, and send four user interface update commands. If the command ID of the menu item has an update processor, it will be called for updates; if there is no existence, the framework checks if the process ID is exist, and makes the menu valid or invalid as needed.

If the on_UPDATE_COMMAND_UI item corresponding to the command is not found during the command, the framework checks if there is an ON_COMMAND item that exists, if there is, the menu is valid, otherwise it is invalid (ashing). This update mechanism is only available for pop-up menus, and this update mechanism cannot be used for the top menu icon File and EDIT menu.

The button command update mechanism is similar to the menu command interface update mechanism, just the command interface update of the toolbar button is complete when the idle cycle is idle.

Second, user interface update mechanism programming

When the frame sends an update command to the handler, it delivers a pointer to the CCMDUI object to the handler. This object contains a pointer to the corresponding menu item or toolbar button. The update process function uses the pointer to call the command interface function of the menu item or the toolbar to update the user interface object (including gray, make, enable, selected menu items and toolbar buttons, etc.). Below we use the previous example demonstrate how to use the user interface update mechanism:

1. Press CTRL W to activate ClassWizard and select the Message Map option page.

2. Select ID_SELECT_RED in the Object IDS list, double-click the on_update _command_ui entry in the Messages list, pop up the Add Member Function dialog, the default function is onUpdateelect Red, and press the OK button to receive this function name.

3. Now manually edit the member function you just generated:

Listing 3.5

Void CMAINFRAME :: OnUpdateectred (ccmdui * pcmdui)

{

PCMDUI-> setCheck (m_ncolor == red); // red menu is selected

}

Similarly, in accordance with a status switch menu, you can also generate a command interface to update member functions for menus. For example, in the EDIT menu, if the current clipboard has no content, the Paste menu should be set to invalid, the program can write this:

Void CMAINFRAME :: OnUpdateEditPaste (ccmdui * pcmdui)

{

PCMDUI-> Enable (! isclipboardempty ());

}

Where isclipboardemtpy () is a function written by the reader to determine if there is content in the clipboard.

Shortcut menu

Right click on any object to pop up a menu related to the selected current object, and a set of operations for the current object are listed in the menu. Now let's discuss how to use Visual C to add the right-click menu for the application.

Use the component tool for Visual Studio to add a shortcut menu to the Frame Window. Select Project-> Add Toproject-> Component and Controls menu, pop-up Component and Controls

The Gallery dialog box, select the developer studio components directory, select the Popup Menu component in this directory.

Press the INSERT button. Pop up the Poup Menu dialog box, select CMAINFRAME in the Add Popup Menu to drop down list box, click OK button, turn off Popup

Menu dialog. Press the CLOSE button to close Component and Controls

Gallery dialog. Compilation Hello, press the right button after the pop-up window, pop up the shortcut menu shown in Figure 3-16. The menu contains three items: CUT, COPY, PASTE. Because there is no corresponding message stands up, all of these menus are gray, non-active.

Figure 3-16

Now, let's see how the Component Gallery implements shortcut menu. First look at the menu resource of the resource view, Component Gallery adds an ID for the cg_idr_popup_main_frame, and the menu contains three menu items we have seen: CUT, COPY, PASTE. Switch to a class view, browse the CMAINFRAME class, you can see that CMAINFRAME adds an onContextMenu member function, which is a method of CWnd, for handling the right mouse button, the prototype is as follows:

AFX_MSG Void OnContextMenu (CWND * PWND, CPOINT);

Where PWND points to the window that is right-click, it can be a sub-window of a window. For example, we also pop up the same menu when you click on the toolbar, and the toolbar is a sub-window of the Frame Window. The onContextMenu function is defined as shown in Listing 3.6.

Listing 3.6 Right-click menu

Void CMAINFRAME :: OnContextMenu (CWND * PWND, CPOINT POINT)

{

// cg: this block Was Added by the pop-up menu Component

{

IF (Point.x == -1 && Point.y == -1) {

// If it is a shortcut menu that is activated, the shortcut menu is displayed in the position of the upper left corner 5, 5 on the window.

CRECT RECT;

GetClientRect (Rect);

Clienttoscreen (Rect);

Point = Rect.Topleft ();

Point.offset (5, 5);

}

// Load shortcut menu resources

CMenu Menu;

Verify (Menu.LoadMenu (cg_idr_popup_main_frame);

/ / Get the first submenu of this menu

Cmenu * ppopup = menu.getsubmenu (0);

Assert (ppopup! = Null);

CWND * PWNDPOPUPOWNER = THIS;

// If the current window is a child window, take his parent window as the owner of the pop-up menu

While (PWndPopuPowner-> getStyle () & ws_child)

PWNDPOPUPOWNER = PWNDPOPUPOWNER-> getParent ();

// Display the pop-up menu in Point.x, Point.Y and track its selection

PPOPUP-> TrackPopupMenu (TPM_LEFTALIGN | TPM_RightButton, Point.x, Point.y, PWNDPupuPowner);

In general, we can use the Component Gallery's Popup Menu component to add a shortcut menu for a window, dialog, view, etc. without manual programming. What we have to do is editors to modify the default menu for our own shortcut menu, and generate the necessary member functions with ClassWizard, join your code. If you really have to do it, you should first add a menu with the menu editor, then add an onContextMenu method for the corresponding window, and the onContextMenu can refer to the above program.

Component Gallery's functionality is far more than the shortcut menu to the program, which can also increase the startup screen (Splash Window), a multi-page dialog, password check dialog, and more.

Toolbar and status bar

In the previous lesson, students have learned some basic interface design techniques. This lesson will guide you how to design the implementation of the toolbar and status column and further deepen the understanding of the message drive mechanism.

In a standard Windows application, most of the tools of the toolbar do the same as the menu command, the purpose of doing the image and an abstract user interface to facilitate the user's use.

The status bar is located at the bottom of the main frame window, mainly used to display some prompt information, which can be subsequently divided into several panes. The main function of the status bar is to briefly explain the selected menu command or toolbar button command, and display the status of the Scroll Lock, Num Lock.

First, the visual design of the toolbar

In MFC, the function of the toolbar is implemented by class CToolbar. Tools Resources and Tools Ctoolbar are two elements of the toolbar. The basic steps for creating the toolbar are:

1. Create toolbar resources.

2. Build a ctoolbar object.

3. Call the CToolBar :: Create function Create a toolbar window.

4. Call CToolBar :: LoadToolBar load toolbar resources.

When using the default configuration, AppWizard automatically creates a toolbar. This toolbar contains some common buttons such as opening files, storage, printing, and more. Users can modify this toolbar, remove the useless buttons, join the buttons you need. If the user needs to create more than two toolbars, you can't depend entirely on AppWizard and you need to create it hand.

1. Automatically create using AppWizard

Automatic creation toolbar is simple, please read by following:

1). Select the file-> new command.

2). Select the Projects page in the pop-up tab dialog box, then select the MFC AppWizard (EXE) entry in this page, and enter Record in the Project Name column to create a project called Record. Press Enter or to click the Create button with the mouse to enter the MFC AppWizard dialog.

3) Click the FINISH button with the mouse and press the OK button in the then the dialog.

After completing the above operation, the project RECORD is created and automatically loaded into developer studio. Switch the project workspace to the resource view and expand the resource, you will find that one of these Toolbar (Toolbar) resources named IDR_MAINFRAME. Double-click "iDR_mainframe" with a mouse, developer Studio opens a powerful toolbar resource editing window, as shown in Figure 4.2. The upper part of the window shows the button on the toolbar. When the user selects a button with a mouse, the bitmap of the button will appear in the lower part of the window.

Before modifying the toolbar, first modify the menu resource. Please modify menu resources as follows:

1). Switch the project workspace to the resource view, select and open the Menu resource type, double-click the menu resource named IDR_MAINFRAME. 2). Delete the EDIT menu.

3). Delete all menu items other than EXIT in the File menu.

4). Insert a new menu called & Record after the File menu and inserts the & Start and ST & OP two menu items, and their command ID (identifier) ​​is ID_record_start and id_record_stop. START indicates that the recording is started, while the STOP represents stopping the recording.

The next task is to modify the toolbar resources, the specific steps are:

1). Select and open the Toolbar resource type, double-click the toolbar name called IDR_MAINFRAME to open the corresponding resource editing window.

2). Delete all buttons in front of the "?" Button, the method of deleting is to drag the tool bar with the button to be deleted.

3). First select the blank button behind the "?" Button, and then use a red painted circle on the magnified bitmap of the button to indicate the start recording function. Then select the blank button and draw a solid rectangle on the amplified bitmap with black to indicate the stop function. The position of the button is adjusted by dragging the button with the mouse.

4). The command ID is specified for two newly added buttons, respectively, ID_Record_Start and ID_Record_Stop. The method of specifying the ID is to select a button, then press Enter to enter ID (or select ID_Record_Start and ID_Record_stop from the ID_Record_start and ID_Record_stop) from the ID drop-down list, in the pop-up list. Note that the ID of the two buttons is the same as the two menu items in the Record menu, so that the same command can be executed by the menu or by the toolbar.

5). Specify command prompt for two newly added buttons. Enter Start Record / NStart and Stop Record / NStop in the Prompt column in the Properties dialog box of the two buttons. The command prompt is actually saved as a string in the String Table string resource. The command prompts to explain the meaning of the command, and two status columns prompts and tools are prompted. In the PROMPT column, both are separated by / n.

Tip: If the button is too small, the reader can use the mouse to drag around the lower right corner of the virtual box of the button, put the button. Note All buttons in the toolbar will be enlarged

After the modification, the reader can compile and run the Record to see the result of the modified. Readers will soon notice that Start and Stop menu items and buttons are gray. Interesting is that the toolbar can be dragged, and the toolbar can be floated, i.e., when double-click the blank of the toolbar with a mouse, the toolbar has become a floating window, which can be dragged to any place on the screen.

2, manual creation

If you want to add a toolbar, AppWizard is powerless, you must create it manually. Suppose the sound sampling frequency of the Record program has 11kHz and 44kHz selection. Now our task is to create a toolbar that allows users to choose these two grades. The function of this should be located within the first toolbar, but to demonstrate the manual creation of the toolbar, here you may wish to have more.

The first menu must first be modified. Open the IDR_MAINFRAME menu resource, join two menu items, and its properties are shown in Table 4.1.

CaptionIdprompt

& Low QualityID_LOW_QUALITYLOW Quality (11K) / N11K

& High QualityID_High_QualityHigh Quality (44K) / N44K

Then create a new toolbar resource, follow these steps:

Select the insert-> resource command, then select Toolbar in the Insert Resource dialog. After pressing the OK button, there will be a new source of IDR_Toolbar1 in the Toolbar resource class. Add two buttons in the new tool bar.

The command ID is id_low_quality and id_high_quality specified for two newly added buttons.

To add this new design toolbar to the program, you need to add some source code related to creation in the program. When creating the first toolbar, AppWizard automatically joins the creation source code in the program. It is easy to create the second toolbar by imitation of these code.

In MFC, the function of the toolbar is implemented by class CToolbar. The toolbar is actually a sub-window of the main frame window, so the tool bar object should be attached to the main frame window object. In the MFC program created in AppWizard, the class name of the main frame window is CMAINFRAME, which is a derived class for the MFC standard CFrameWnd class. Switch the project workspace to a class view and expand the CMAINFRAME class, and the reader will find that the class has a member named m_wndtoolbar. Double-click the member, the developer Studio automatically opens the header file where the class CMAINFRAME is located and stops the cursor at the definition of the M_WndToolbar member. CToolbar M_Wndtoolbar;

This shows that m_wndtoolbar is a ctoolbar object, which is a member of CMAINFRAME. Please add this member to a new member immediately: ctoolbar m_wndtoolbar1;

M_WndToolbar1 represents the second toolbar. Readers don't think it is performed for CMAINFRAME to join a CToolbar object. The actual creation of the toolbar will not be completed when constructing the CToolbar object, only after the member function of CTOOLBAR is called, creating a job can end.

The actual creation of the toolbar is completed in the CMAINFRAME :: onCreate function. The oncreate function is called when the window is created. At this time, the creation of the window has been partially completed, and the HWND handle stored in the M_HWND member of the window object is also valid, but the window is still invisible. It is therefore generally in an oncreate function to make initialization work such as a creative sub-window.

Find the CMAINFRAME :: oncreate function, some modifications to this function, the modified portion, such as the black body word shown in Listing 4.1. In the future, any part of the manual modification in the program is generally displayed in black.

Listing 4.1 Modified CMAINFRAME :: oncreate function

INT CMAINFRAME :: OnCreate (lpcreatestruct lpcreatestruct)

{

IF (cframewnd :: oncreate (lpcreatestruct) == -1)

Return -1;

IF (! m_wndtoolbar.create (this) ||! m_wndtoolbar.loadtoolbar (iDR_mainframe))

{

Trace0 ("Failed to Create Toolbar / N);

Return -1; // fail to create

}

IF (! m_wndtoolbar1.create (this) ||! m_wndtoolbar1.loadtoolbar (idR_toolbar1))

{

Trace0 ("Failed to Create Toolbar / N);

Return -1; // fail to create

}

IF (! m_wndstatusbar.create (this) ||! m_wndstatusbar.setindicators (Indicators, Sizeof (Indicators) / Sizeof (UINT)))

{

Trace0 ("Failed to Create Status Bar / N"); Return -1; // Fail to Create

}

// Todo: Remove this if you don't want Tips or a Resizeable Toolbar

M_WndToolBar.setbarstyle (m_wndtoolbar.getbarstyle () | CBRS_Tooltips | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

M_WndToolbar1.setbarstyle (m_wndtoolbar1.getbarstyle () | CBRS_Tooltips | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

// Todo: Delete these Three Lines if you don't wantbar to be Dockable

m_wndtoolbar.enabledocking (CBRS_ALIGN_ANY);

M_WndToolbar1.enableDocking (CBRS_ALIGN_ANY);

Enabledocking (CBRS_ALIGN_ANY);

DockControlbar (& M_WndToolbar);

DockControlbar (& M_WndToolbar1);

Return 0;

}

Note that in the CMAINFRAME :: oncreate function first calls CFrameWnd :: OnCreate. This line of code is automatically added by AppWizard, but it is necessary to explain it. CMAINFRAME is the inheritance class of the CFrameWnd class, first to call the oncreate function of the base class cframewnd in CMAINFRAME :: OnCreate, because the base class also performs some initialization work, and the base class's oncreate function will not be called automatically, so it is necessary to inherit the class Explicit calls in the oncreate function. OnCreate is actually a message processing function for the WM_CREATE message, the reader may ask, why is the derived class's oncreate to process the WM_CREATE message instead of the base class. If the reader carefully observes the oncreate function in the CMAINFRAME header file, it will find an AFX_MSG prefix before the function. The role of AFX_MSG is similar to the Virtual keyword, which causes the function that the function has a virtual function, that is, the message is processed by the inheritance class rather than the base class.

The interpretation of the creation code for the second toolbar is: First, call CToolBar :: Create to create a toolbar window, Note that the parameter of the Create function is this pointer, because the main frame window is the parent window of the toolbar. Then call CToolBar :: LoadToolbar (idR_toolbar1) to load the toolbar resources. Then call the CToolbar :: setbarstyle specified the style of the toolbar, call CToolbar :: getBarsTyle first to get the style of the toolbar, then specify CBRS_Tooltips on the original style, and then specify CBRS_Tooltips on the original style.

CBRS_FLYBY and CBRS_SIZE_DYNAMIC style, which makes the toolbar to display tooltips and dynamically change the size. Then call CToolBar :: EnableDocking (CBRS_ALIGN_ANY) to make the toolbar can be moored, but you also need to call CFrameWnd :: EnableDocking (CBRS_ALIGN_ANY), only in this way can only achieve mooring toolbar. Finally call CFrameWnd :: DockControlbar to moor toolbar.

转载请注明原文地址:https://www.9cbs.com/read-62088.html

New Post(0)