WTL Detailed Introduction

Source: Internet
Author: User
Tags inheritance
turn from: WTL for MFC programmers, part I-atl GUI Classes
Before you start using WTL or post a message in the discussion section of this article, I would like to ask you to read the material below.

You need to develop the Platform SDK (Platform SDK). You want to use WTL cannot without it, you can use the online upgrade to install the development Platform SDK, or you can download all the files after installing locally. Before using the SDK's include file (. h header file) and library file (. lib file) path to the VC search directory, the SDK has a ready-made tool to complete this work, which is located in the Visual Studio Registration folder of the Development Platform SDK program group.

You need to install WTL. You can download WTL version 7.0 from the Microsoft Web site and check out the "Introduction to Wtl-part 1" and "Easy installation of WTL" articles before installing to learn about the files you want to install, although these articles now have Outdated, but can still provide a lot of useful information. One of the things I think should not be mentioned in this article is to tell VC how to search WTL's include file path, if you use the VC6, click Tools\Options with the mouse, go to the Directories tab, select Include Files in the list box showing the path, The storage path of the WTL containing file is then added to the list of included file search paths.

You need to understand MFC. A good understanding of MFC will help you understand the message-map macros that are mentioned later and be able to edit code that is labeled "do not edit" without problems.

You need to know clearly how to program using the Win32 API. If you are learning Windows programming directly from MFC and have not learned how to handle API-level messaging, unfortunately you will have trouble using WTL. If you do not understand the meaning of the wparam parameter and the lparam parameter in Windows messages, you should understand that you need to read some articles in this area (there are a large number of such articles in CodeProject).

You need to know the syntax of the C + + template, you can go to VC Forum FAQ RELATED links to seek answers.

I just discussed some features that cover VC 6, but as far as I know, all the programs can be used on VC 7. Since I do not use VC 7, I can not help those problems that appear in VC 7, but you can still rest assured that posting your question, because other people may help you.

A general introduction to this series of articles

WTL has two sides, it is true. It is not as powerful as the MFC interface (GUI) class library, but it is capable of generating very small executable files. If you're like me using MFC for interface programming, you'll feel comfortable with the interface control encapsulation provided by MFC, not to mention the MFC built-in message handling mechanism. Of course, if you like me do not want your program just because the use of MFC framework to increase the size of hundreds of K, WTL is your choice. Of course, we have to overcome some obstacles:

ATL-style template classes look a little weird at first.
There is no support for the Class wizard, so all message mappings are processed manually.
MSDN does not have formal documentation support, you need to go everywhere to collect documents about it, even to view the source code of WTL.
No reference books to buy
No official support from Microsoft
ATL/WTL window and MFC window is very different, you know about MFC knowledge is not all applicable and WTL.
On the other hand, WTL also has its own advantages:

There is no need to learn or master a complex document/view framework.
Has the basic interface features of MFC, such as DDX/DDV and command status Automatic Update function (translator Plus: such as menu check mark and enable tag).
Enhancements to some MFC features (such as easier-to-use separation windows).
Can generate smaller executables than statically linked MFC programs (translator Plus: All source code for WTL is statically linked to your program).
You can fix errors (bugs) in the WTL you use without affecting other applications (in contrast, if you fix a bug, the MFC/CRT dynamic library can cause other applications to crash.)
If you still need to use MFC,MFC window and ATL/WTL window can "coexist peacefully". (for example, a prototype in my work uses MFC's CFrameWnd, and contains WTL's Csplitterwindow, and uses MFC's Cdialogs in Csplitterwindow--I'm not trying to show off anything, Just modified MFC's code to make it possible to use WTL's split window, which is much better than MFC's split window.
In this series of articles, I'll start with the ATL window class, after all, WTL is a series of additional classes built on top of ATL, so you need a good understanding of ATL's window classes. After introducing ATL, I'll introduce WTL's features and show how it makes interface programming easy.

a brief introduction to the first chapter

WTL is a cool tool that requires an introduction to ATL before you can understand this. WTL is a series of additional classes built on top of ATL, and if you're a programmer with MFC, you probably don't have access to ATL's interface classes, so please bear with me before I start wtl something else, and it's necessary to take a detour to introduce ATL.

In the first part of this article, I'll give you a little background knowledge of ATL, including some basic knowledge of writing ATL code, and quickly explain some of the most confusing ATL template classes and basic ATL window classes.

ATL Background knowledge

The development history of ATL and WTL


The Active Template Library is an odd name, isn't it. Those older people may remember that it was originally called the "Network Component Template Library," which may be more accurate, because ATL is designed to make it easier to write component objects and ActiveX controls (ATL was developed in the course of Microsoft's development of new product activex-, Those activex-xxx is now known as XXX. NET). Because ATL exists for ease of writing component objects, it provides only simple interface classes, which are equivalent to MFC's Window classes (CWND) and dialog Class (CDialog). Fortunately, these classes are flexible enough to build additional classes like WTL based on them.

WTL is now the Second Amendment, the original version is 3.1, the current version is 7 (the WTL version number is chosen to match the ATL version, so there is no 1 and 2 version number). WTL 3.1 can be used with VC 6 and VC 71, but under the VC 7 need to define several preprocessing labels. WTL 7 backwards compatible with WTL 3.1, and without any modification can be used with the VC 71, it seems that there is no reason to use the 3.1来 for new development work.

Atl-style templates

Even if you can read the template class Code of C + + effortlessly, there are still two things that might make you dizzy, taking the definition of the following class as an example:

[CPP] view plain copy print? Class Cmywnd:public cwindowimpl<cmywnd> {...};

Class  Cmywnd:public cwindowimpl<cmywnd>
{
    ...
};  

This is legal because the syntax of C + + explains that even though the Cmywnd class is only partially defined, the class name Cmywnd has been listed as a recursive inheritance list and is available for use. The class is named as a parameter to the template class because ATL is doing another secretive thing, which is the virtual function call mechanism during compilation.

If you want to see how it workplace, take a look at the following example:

[CPP] View Plain copy print? template <class t>   class b1   {   public:        void sayhi ()         {            T* pT = static_cast<T*> (this);    //  huh??   I will explain below                pT-> Printclassname ();       }   protected:        void printclassname ()  { cout <<  "THIS&NBSP;IS&NBSP;B1"; }   };       class d1 : public b1<d1>   {        // No overridden functions at all  };        class d2 : public b1<d2>   {&NBSP;&NBSp protected:       void printclassname ()  { cout <<  " This is d2 "; }  };       Main ()    {        D1 d1;       D2 d2;           d1. Sayhi ();    // prints  "THIS&NBSP;IS&NBSP;B1"         D2. Sayhi ();    // prints  "This is d2"   }  

Template <class t>
class B1
{public
: 
    void Sayhi () 
    {
        t* PT = static_cast<t*> (This );   HUH?? I will explain the following
 
        Pt->printclassname ();
    }
Protected:
    void Printclassname () {cout << "this is B1";}
};
 
Class D1:public b1<d1>
{
    //No overridden functions at all
};
 
Class D2:public b1<d2>
{
protected:
    void Printclassname () {cout << "this is D2";}
};
 
Main ()
{
    D1 d1;
    D2 D2;
 
    D1. Sayhi ();    Prints "This is B1"
    D2. Sayhi ();    Prints "This is D2"
}

This code static_cast<t*> (this) is where the trick lies. It assigns pointers to the B1 type as a pointer to the D1 or D2 type, depending on the special handling of the function call, because the template code is generated during compilation, so the assignment is secure as long as the compiler generates the correct inheritance list. (If you write:

[CPP] view plain copy print? Class D3:public B1<d2>

Class D3:public B1<d2>

will be in trouble) security is because this object is only possible to point to D1 or D2 (in some cases) type of object, not something else. Note that this is much like C + + polymorphism (polymorphism), except that the Sayhi () method is not a virtual function.

To explain how this works, first look at the invocation of each sayhi () function, in the first function call, the object B1 is assigned as D1, so the code is interpreted as:

[CPP] view plain copy print?           void B1<d1>::sayhi () {d1* PT = static_cast<d1*> (this);   Pt->printclassname (); }

void B1<d1>::sayhi ()
{
    d1* PT = static_cast<d1*> (this);
 
    Pt->printclassname ();
}

Because D1 does not overload printclassname (), the view base class B1,B1 has Printclassname (), so B1 Printclassname () is called.

Now look at the second function call Sayhi (), this time the object is assigned as the D2 type, sayhi () is interpreted as:

[CPP] view plain copy print?           void B1<d2>::sayhi () {d2* PT = static_cast<d2*> (this);   Pt->printclassname (); }

void B1<d2>::sayhi ()
{
    d2* PT = static_cast<d2*> (this);
 
    Pt->printclassname ();
}

This time, D2 contains the Printclassname () method, so D2 's Printclassname () method is called.

The advantage of this technology is that:

You do not need to use pointers to objects.
Save memory because you do not need a virtual function table.
Because there is no virtual function table, a virtual function that is called by a null pointer at run time does not occur.
All function calls are determined at compile time (translator Plus: Dynamic programming that differs from the virtual function mechanism of C + +), which facilitates the compiler to optimize the code.
Saving the virtual function table looks insignificant in this example (only 4 bytes per virtual function), but imagine that if there are 15 base classes, each class contains 20 methods, which adds up quite a bit.

ATL window class

Well, the background knowledge about ATL has been made much more, and it's time to formally speak ATL. ATL's design-time interface definitions and implementations are strictly distinguishable, which is most noticeable in the design of the window class, similar to the Com,com interface definition and implementation being completely separate (or there may be multiple implementations).

ATL has an interface specifically designed for windows that can do all of the window operations, which is CWindow. It is actually the wrapper class for the HWND operation, encapsulating almost all the window APIs with the HWND handle as the first parameter, for example: SetWindowText () and DestroyWindow (). The CWindow class has a public member M_hwnd that allows you to manipulate the handle of the window directly, CWindow also has an operator hwnd, which you can tell the CWindow object to pass to the function of the hWnd parameter, but this with the Cwnd::getsafehwnd () (Translator Plus: MFC's method) does not have any equivalence.

CWindow is very different from the CWnd class of MFC, creating a CWindow object consumes very little resources, because there is only one data member, there is no chain of objects in the MFC window, and MFC maintains this chain of objects internally, and this object chain maps the HWND to the CWnd object. Another thing that differs from MFC's CWnd class is that when a CWindow object goes out of scope, its associated window is not destroyed, which means you don't have to remember to detach the temporary CWindow object you created at any time.

The implementation of a window procedure in an ATL class is CWindowImpl. CWindowImpl contains all the window implementation code, such as: Window class registration, window sub-class, message map and basic WindowProc () function, can see this and MFC design is very different, MFC put all the code in a CWnd class.

There are also two separate classes that contain the implementation of the dialog boxes, which are CDialogImpl and Caxdialogimpl,cdialogimpl, which are used to implement a common dialog box and CAxDialogImpl Implement a dialog box containing ActiveX controls.

defining the implementation of a window

Any non-dialog window is derived from CWindowImpl, and your new class needs to contain three things:

Definition of a window class
A message map chain
The default window type used by Windows, called Window traits
The definition of a window class is implemented by Declare_wnd_class macros or DECLARE_WND_CLASS_EX macros. This macro defines a CWNDCLASSINFO structure that encapsulates the wndclassex structure. The Declare_wnd_class macro lets you specify the class name of the window class, other parameters use the default settings, and the DECLARE_WND_CLASS_EX macro allows you to specify the type of window class and the background color of the window, or you can use NULL as the class name. ATL will automatically generate a class name for you.

Let's start by defining a new class, and in the later chapters I'll step through the definition of this class.

[CPP] view plain copy print? Class Cmywindow:public cwindowimpl<cmywindow> {Public:declare_wnd_class (_t ("My window CLASS")};

Class Cmywindow:public cwindowimpl<cmywindow>
{public
:
    declare_wnd_class (_t ("My window CLASS"))
};

Next is the message map chain, ATL's message map chain is much simpler than MFC's, and the ATL message map chain is expanded into a switch statement, the switch statement is the correct message processor, and the corresponding function is called. Macros using the message map chain are BEGIN_MSG_MAP and End_msg_map, let's add an empty message map chain for our window.

[CPP] view plain copy print?           Class Cmywindow:public cwindowimpl<cmywindow> {Public:declare_wnd_class (_t ("My window CLASS")) Begin_msg_map (CMyWindow) End_msg_map ()};

Class Cmywindow:public cwindowimpl<cmywindow>
{public
:
    declare_wnd_class (_t ("My window CLASS"))
 
    Begin_msg_map (CMyWindow)
    End_msg_map ()
};

I'll expand in the next section to talk about how to add message processing to a message map chain. Finally, we need to define the window's characteristics for our window class, which is a combination of the window type and the extended window type that specifies the window type when the window is created. The window type is specified as a parameter template, so the caller of the window does not need to be bothered by the correct type of the specified window, and the following is an example of the window type defined with the ATL class CWinTraits:

[CPP] view plain copy print? typedef Cwintraits<ws_overlappedwindow |       Ws_clipchildren,ws_ex_appwindow> cmywindowtraits; Class Cmywindow:public Cwindowimpl<cmywindow, CWindow, cmywindowtraits> {public:declare_wnd_class (_T (" My window Class ")) Begin_msg_map (CMyWindow) End_msg_map ()};

typedef Cwintraits<ws_overlappedwindow | Ws_clipchildren,ws_ex_appwindow> cmywindowtraits;
 
Class Cmywindow:public Cwindowimpl<cmywindow, CWindow, cmywindowtraits>
{public
:
    declare_wnd_ Class (_t ("My window Class"))
 
    Begin_msg_map (CMyWindow)
    end_msg_map ()
};

Callers can overload the Cmywindowtraits type definition, but in general this is not necessary, ATL provides several predefined special types, one of which is cframewintraits, a very nice frame window:

[CPP] view plain copy print? typedef Cwintraits<ws_overlappedwindow | Ws_clipchildren | Ws_clipsiblings, Ws_ex_appwindow | Ws_ex_windowedge> cframewintraits;

typedef Cwintraits<ws_overlappedwindow | Ws_clipchildren | Ws_clipsiblings,
                                         Ws_ex_appwindow | Ws_ex_windowedge>  cframewintraits;

fill in the message map chain

The message-map chain of ATL is a less-than-friendly part of the developer and the most WTL for it. The class wizard can at least allow you to add a message response, but ATL has no message-related macros and parameter Auto-expansion functions like MFC, there are only three types of message processing in ATL, one is wm_notify, one is Wm_command, and the third is other window messages, Let's start by adding wm_close and Wm_destroy message corresponding functions for our window.

[CPP] View Plain copy print? Class cmywindow : public cwindowimpl<cmywindow, cwindow, cframewintraits>    {   public:       declare_wnd_class (_t ("My Window  Class ")            begin_msg_map (cmywindow)             message_handler (wm_close, onclose)             message_handler (Wm_destroy, ondestroy)         End_msg_map ()            lresult onclose (uint umsg,  wparam wparam, lparam lparam, bool& bhandled)         {           destroywindow ();            return 0;       }           lresult ondestroy (Uint umsg, wparam wparam,  lparam lparam, bool& bhandled)        {            postquitmessage (0);            return 0;       }  };  

Class Cmywindow:public Cwindowimpl<cmywindow, CWindow, cframewintraits>
{public
:
    declare_wnd_ Class (_t ("My window Class"))
 
    Begin_msg_map (CMyWindow)
        message_handler (Wm_close, OnClose)
        Message_ HANDLER (Wm_destroy, OnDestroy)
    end_msg_map ()
 
    LRESULT OnClose (UINT umsg, WPARAM WPARAM, LPARAM LPARAM, BOOL & bhandled)
    {
        DestroyWindow ();
        return 0;
    }
 
    LRESULT OnDestroy (UINT umsg, WPARAM WPARAM, LPARAM LPARAM, bool& bhandled)
    {
        postquitmessage (0);
        return 0;
    }
};

You may notice that the message response function is to the original wparam and lparam values, and you need to expand it to the appropriate message for the required parameters. There is also a fourth parameter, bhandled, which is set to true for the message corresponding function call, and if ATL calls the default WindowProc () to process the message after your message response has been processed, you can say bhandled set to false. This differs from MFC, which is the display of the call base class's response function to implement the default message handling.

Let's also add a handle to the WM_COMMAND message, assuming our window has an about menu with ID idc_about:

[CPP] view plain copy print? class cmywindow : public cwindowimpl< cmywindow, cwindow, cframewintraits>   {   public:        declare_wnd_class (_t ("My window class"))             begin_msg_map (CMyWindow)            message_handler (WM_ Close, onclose)            message_handler (WM_DESTROY,  ondestroy)            command_id_handler (IDC_ABOUT,  onabout)        end_msg_map ()             lresult onclose (Uint umsg, wparam wparam, lparam lparam, bool

Related Article

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.