Obtain other class pointers in the MFC class

Source: Internet
Author: User

When Visual C ++ Application Wizard is used to generate applications otherProgramWill automatically generate View class, document class, main frame window class, application class and so on.

Generally, the core data and operations of a program are implemented in the document class. The interface-related data and operations are implemented in the View class.

When using data that does not belong to this class in a class, you must obtain the pointer of the class to which the summary data belongs. Obtain the pointer of the document class from the View class.

It is easy to use getdocument (). This is introduced in the general MFC Document and is also a common operation in programming, such as the view class.

Data in the document class is often used for re-painting and other operations. However, it is far from enough to obtain the document class pointer from the View class,

Each class has a set of methods for obtaining other class pointers.

For convenience, we assume that an SDI application test has been generated using App Wizard, which includes the following classes:

Ctestapp, ctestdoc, ctestview, cmaimframe

1: Get the document class pointer from the View class

As mentioned above, before you reference the document class in the View class, use the following statement:

Ctestdoc * pdoc = (ctestdoc *) getdocument ();

You can use the pdoc pointer to access the document class later.

The forced type conversion here is not required in the test application, because the program only has one view class, and in the initinstance ()

The SDI document template is reused for assembly. You can see the following statement in the initinstance () method of test. cpp:

Csingledoctemplate * pdoctemplate;

Pdoctemplate = new csingledoctemplate (idr_mainrame, runtime_class (ctestdoc), runtime_class (cmainframe), runtime_class (ctestview ));

Adddoctemplate (pdoctemplate );

And testview. h:

Inline ctestdoc * ctestview: getdocument ()

{Return (ctestdoc *) m_pdocument ;}

In short, the getdocument () function of ctestview naturally considers ctestdoc to be "compatible" with it. when an application with multiple view classes is generated (for example, csplitterwnd divides the window into two columns, but these two columns are not derived from the same view class. The specific implementation is beyond the scope of this article). Only one view class can be assembled with a unique document class using a document template, in order to obtain the pointer of the document class in another unassembled class, a forced type conversion is required.

2: Get the View class pointer from the document class

The cdocument class provides two functions for positioning the View class: getfirstviewposition () and getnestview (),

Virtual position getfirstviewposition () const;

Virtua cview * getnextview (Position & rposition) const;

Note: The parameters in the getfirstview () Brackets use the reference method, so the value may change after execution.

Getfitstviewposition () is used to return the position of the first view (the return is not a view class pointer, but a position value). getnextview () has two functions: return the pointer of the next View class and use the reference call and method to change the value of the input position type parameter. Obviously, there is only one view class in the test program. Therefore, you only need to call these two functions once to obtain the ctestview pointer as follows (you need to define a position structure variable to assist in the operation ):

Ctestview * ptestview;

Positisonpos = getfirstviewposition ();

Ptestview = getnextview (POS );

In this way, the pointer ptestview of the ctestview class is obtained. After these statements are executed, the variable Pos = NULL, because there is no next View class, and naturally there is no position of the next View class.

However, these statements are too simple to have strong versatility and security features. As mentioned earlier, when a pointer to a specified class is returned in multiple view classes, we need to traverse all view classes until the specified class is found. When determining whether a pointer points to an instance of a class, the iskindof () member function can be used as a row check, for example:

Pview-> iskindof (RUNTIME-CLASS (ctestview ));

Check whether pview is a ctestview class.

With the above foundation, we can obtain any class pointer from the document class. For convenience, we use it as a document class and member function. It has a parameter to indicate which class pointer is to be obtained, and it returns the pointer of this class. The implementation is as follows:

Cview * ctestdoc: getview (cruntimeclass * Pclass)

{Cview * pview; positionpos = gitfirstviewposition (); While (Pos! = NULL) {pview = gitnextview (POS );

If (pview-> iskindof (Pclass) break ;}

If (! Pview-> iskindof (Pclass) {afxmessagebox ("connot locate the view .");

Return NULL ;}

Return pview ;}

Two View class member functions iskindof () are used to determine whether to exit the while loop. There are three possible reasons:

1. If POS is null, the next view does not exist;

2. The pview meets the requirements;

Both 3.1 and 2 are met. This is because the get-nextview () function is to change POs to the position of the next view and return the current view pointer. Therefore, POS is the position of the next View class of pview, it is entirely possible that Pos = NULL and pview meet the requirements. This applies when the required view is the last view class. Therefore, two judgments are required.

Use this function in the following format (taking the ctestview pointer as an example ):

Ctestview * ptestview = (ctestview *) getview (RUNTIME-CLASS (ctestview ));

RUNTIME-CLASS () is a macro that can simply understand its role:

Converts a class and a name to a cruntimeclass class pointer.

Forced type conversion is also for the sake of security, because it is compatible between classes derived from the same base class and their pointer types with the base class. This forced type conversion may not be necessary, but it can avoid some possible troubles.

3: Get the pointer of another view class from one view class

Combining 1 and 2, it is easy to obtain the method of getting pointers between view classes: it is to use the document class as a transit, first use the 1 method to get the pointer of the document class, and then use the 2 method, positioning functions in the view of the document:

(Suppose you want to get an injection pointing to other view classes from ctestaview)

Cview * ctestaview: getview

(Cruntimeclass * Pclass)

{Ctestdoc * pdoc =

(Ctestdoc *) getdecument ();

Cview * pview;

Position Pos = pdoc-> getfistviewposition ();

While (Pos! = NULL ){

Pview = pdoc-> getnextview (POS );

If (pview-> iskindof (Pclass ))

Break ;}

If (! Pview-> iskindof (Pclass )){

Afxmessagebox ("connot Iocate The View .");

Return NULL ;}

Return pview ;}

Compared with getview () in 2, this function has the first place to get the document class pointer, and the second is to add the document class pointer before getfirstviewposition () and getnextview, to indicate that they are document class member functions.

With this function, to obtain the ctestbview injection from ctestaview, you only need:

Ctestbview

Ctestbview * ptestbview = (ctestbview *)

Getview (RUNTIME-CLASS (ctestbview ));

4. Obtain the View class pointer from the primary frame window class

This is very simple for the SDI Program "test" mentioned in this article. You only need to use the getactiveview () member function of the cframewnd class. The format is as follows:

Cframewnd: getactiveview ()

However, when this function is applied to the cmdiframewnd class of the MDI application, it does not obtain the View class of the current active subwindow as expected, but returns NULL. This is a conceptual issue. In the MDI program, cmdiframewnd has no relationship with any view class, that is, no view class directly belongs to it. Only the subwindow class cmdichildwnd is the parent window of all child window view classes. The parent window of the sub-frame window is cframewnd. Therefore, the correct method to obtain the active View class in the MDI program should be: first obtain the active sub-frame window, and then obtain the activity View class from the sub-frame window: (the following section)CodeSimilar to the Demo code of getactiveview in infoviewer of VC ++, the sample code is described in detail. It is not described here)

// Obtain the activity sub-frame window

Cmdichildwnd * pchild = (cmdichildwnd *)

Getactiveframe ();

// Or: cmdichildwnd * pchild = mdigetactive ();

// Obtain the activity view of the activity sub-frame window

Cmyview * pview = (cmyview *) pchild-> getaetiveview ();

5. Obtain the primary frame window class pointer from the View class

Use the cwnd: getparentframe () function ()

Can achieve the goal. It works by searching in the parent window chain until cframewnd or its derived class is found and Its pointer is returned. The usage is described in detail in infoviewer.

6. Obtain the application class from any class

You can use the global function afxgetapp () of MFC.

7. Obtain the Frame Generation window class from the application class

The cwinthread class has a data member named M-pmainwnd. Since the cwinapp class is derived from the zcwinthread class, our application class is derived from the cwinapp class, therefore, our ctestapp class also has a m-pmainwnd Member, which points to the cmainframe class. (Appropriate forced type conversion is required ).

For example, in the application class, assign a value to nintvar, an integer variable of the frame window class:

(Cmainframe *) m-pmainwnd)-& gt; nintvar = 100;

Notes:

With the above several pointer acquisition methods, the program has been more flexible and efficient because it is convenient to obtain pointers of other classes in the class. Note the following two points:

1. When Class A obtains the pointer of Class B, Class A should contain the header file of Class B.

For example, to obtain the cmainframe pointer in ctestview, add # include "mainfrm. H" to the header of the testview. cpp file ". Otherwise, compilation fails.

2. In most cases, force type conversion is required. Note the brackets.

The compatibility between the derived class and the parent class pointer type makes it very important to distinguish classes clearly. When you are not sure, it is best to add forced type conversion. For example:

Ctestbview * ptestbview = (ctestbview *)

Getview (runtime_class (ctestbview ));

Make the obtained class pointer stronger than the ctestbview * type.

In addition, because the operator "->" of the pointer member has a higher priority than the forced type conversion, the determination of parentheses is very important. See example:

(Cmainframe *) m-pmainwnd-> nintvar= 100;

This statement is incorrect. It is equivalent to converting the (cmainframe *) type to nintvar. It will cause an error during compilation and inform you that the integer cannot be converted to the cmainframe * type. The correct statement is as follows:

(Cmainframe *) m-pmainwnd)-& gt; nintvar = 100

This is undoubtedly a trivial small problem, but it is also because it is small and difficult to perceive. If you do not pay attention to it, it may waste a lot of time.

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.