Implementation window in ATL

Source: Internet
Author: User
ATL provides some tool classes to implement windows, so that you can easily create windows without relying on MFC In the ATL component.

  1. Implementation dialog box

There are three template classes in ATL for creating a dialog box:

(1) csimpledialog: Create mode dialog box, which can be host Windows controls

Template <word t_wdlgtemplateid, bool t_bcenter = true>
Class csimpledialog: Public cdialogimplbase

(2) cdialogimpl: Create mode or non-mode dialog box. You can host Windows controls.

Template <class T, class tbase = cwindow>
Class atl_no_vtable cdialogimpl: Public cdialogimplbaset <tbase>

(3) caxdialogimpl: Create mode or non-mode dialog box. You can host Windows controls and ActiveX controls.

Template <class T, class tbase = cwindow>
Class atl_no_vtable caxdialogimpl: Public cdialogimplbaset <tbase>

Use csimpledialog and cdialogimpl to display a dialog box containing ActiveX controls. Only caxdialogimpl can be used. To process ActiveX control events in the dialog box, add atladvisesinkmap (this, true) to oninitdialog ). Add atladvisesinkmap (this, false) When exiting ). The dialog box generated by insert/new ATL Object/miscellaneous/dialog is inherited from caxdialogimpl by default.

The usage of these three classes is similar. Are derived from a new class, and make sure that there is a resource ID specified by an IDD member. For example:

Class cmydialog: Public cdialogimpl ,...
{
Public:
Enum {IDD = idd_mydialog}; // you must have the "IDD" member. Generally, it is in the "Enum" type.

Begin_msg_map (cmydialog)
Message_handler (wm_initdialog, oninitdialog)
End_msg_map ()

Lresult oninitdialog (uint umsg, wparam, lparam, bool & bhandled)
{
Return 1;
}
};
Cmydialog DLG;
DLG. domodal ();

Csimpledialog is easier to use, as shown below:

Csimpledialog <idd_mydialog> DLG;
DLG. domodal ();

In addition, csimpledialog provides internal support for idok and idcancel, that is, the enddialog is automatically called and its definition includes the following code:

Begin_msg_map (thisclass)
Message_handler (wm_initdialog, oninitdialog)
Command_range_handler (idok, IDNO, onclosecmd)
End_msg_map ()

......

Lresult onclosecmd (word/* wnotifycode */, word WID, hwnd/* hwndctl */, bool &/* bhandled */)
{
: Enddialog (m_hwnd, WID );
Return 0;
}

However, cdialogimpl and caxdialogimpl do not have internal support. Therefore, you must add a message processing function to call enddialog. For example:

Command_id_handler (idok, onok)
Command_id_handler (idcancel, oncancel)

Lresult onok (word wnotifycode, word WID, hwnd hwndctl, bool & bhandled)
{
Enddialog (WID );
Return 0;
}

Lresult oncancel (word wnotifycode, word WID, hwnd hwndctl, bool & bhandled)
{
Enddialog (WID );
Return 0;
}

 Ii. subclass and superclass

Subclass intercepts messages and points to its own container process functions. There are two types of subclass.
(1) instance subclass: subclass an existing container object instance. Each window object instance is allocated with a memory space (hwnd refers to this memory block) by the system, which stores various information about the window, including the wndproc address. Therefore, you can rewrite this address to your own wndproc address to intercept message processing. (Of course, you must retain the original wndproc address to pass the message)
(2) Global subclass: subclass A window class. Keep the wndproc address in wndclass, so you can change it to your own wndproc address. In this way, all object instances created based on this new wndclass will point to the new wndproc address. :

Instance subclass Global subclass

There are two differences between superclass and subclass: (1) There is no instance superclass and only superclass window class. (2) subclass cannot intercept messages created by wm_create, wm_nccreate, and superclass can intercept messages, but it must pass the original wndproc to complete initialization.

  3. Use csf-wimpl to implement a window

Csf-wimpl is a template class, which is defined as follows:

Template <class T, class tbase = cwindow, class twintraits = ccontrolwintraits>
Class atl_no_vtable c1_wimpl: Public cwindowimplbaset <tbase, twintraits>

Template <class tbase = cwindow, class twintraits = ccontrolwintraits>
Class atl_no_vtable cwindowimplbaset: Public cwindowimplroot <tbase>

Template <class tbase = cwindow>
Class atl_no_vtable cwindowimplroot: Public tbase, public cmessagemap

It can be seen that for csf-wimpl <cmywindow>, the final base class is still cwindow (by default ). The template parameter twintraits is used to specify the style of the window to be created. ATL has built-in types: ccontrolwintraits, cframewintraits, cmdichildwintraits, and so on. The default type is ccontrolwintraits. The style includes wm_child | wm_visible | ws_clipchildren | ws_clipsiblings. You can also define the style and extended styles of the window.

Template <DWORD t_dwstyle = 0, DWORD t_dwexstyle = 0>
Class cwintraits
{
Public:
Static DWORD getwndstyle (DWORD dwstyle)
{
Return dwstyle = 0? T_dwstyle: dwstyle;
}
Static DWORD getwndexstyle (DWORD dwexstyle)
{
Return dwexstyle = 0? T_dwexstyle: dwexstyle;
}
};

Typedef cwintraits <ws_child | ws_visible | ws_clipchildren | ws_clipsiblings, 0>
Ccontrolwintraits;
Typedef cwintraits <ws_overlappedwindow | ws_clipchildren | ws_clipsiblings, ws_ex_appwindow | ws_ex_1_wedge>
Cframewintraits;
Typedef cwintraits <ws_overlappedwindow | ws_child | ws_visible | ws_clipchildren | ws_clipsiblings, ws_ex_mdichild>
Cmdichildwintraits;

(1) Use superclass

Class cmywindow: Public c1_wimpl <cmywindow> ,...
{
Public:
Declare_wnd_superclass (null, "edit ")
// Message ing macro
// Message Processing Function
};

Cmywindow WND;
WND. Create (...);

(2) Use instance subclass

Class cmywindow: Public c1_wimpl <cmywindow> ,...
{
Public:
// Message ing macro
// Message Processing Function
};
Cmywindow WND;
WND. subclasswindow (hsomewnd); // handle of an existing window

(3) create a new window

Class cmywindow: Public c1_wimpl <cmywindow> ,...
{
Public:
Declare_wnd_class ("mywindow") // defines only one class name, which can also be null. The system automatically generates a class name.
// Message ing macro
// Message Processing Function
};

Cmywindow WND;
WND. Create (...);

  Iv. Message ing macro

ATL defines a set of message ing macros. A typical example is as follows:

Begin_msg_map (cmyclass)
Message_handler (wm_paint, onpaint)
Chain_msg_map (cmybaseclass) // cmybaseclass indicates the base class
Alt_msg_map (1) // atl_msg_map is mainly used for "contained window"
Chain_msg_map (cmybaseclass)
Alt_msg_map (2)
Message_handler (wm_char, onchar)
Chain_msg_map_alt (cmybaseclass, 1)
End_msg_map ()

The macro expansion results are roughly as follows:

Bool cmyclass: processwindowmessage (hwnd, uint, wparam, lparam, lresult & lresult, DWORD dwmsgmapid)
{
Bool bhandled = true; // This variable is used to determine whether the message has been processed
...
Switch (dwmsgmapid) // The default value is 0.
{
Case 0:
If (umsg = wm_paint)
{
Bhandled = true;
Lresult = onpaint (umsg, wparam, lparam, bhandled); // bhandled is a reference parameter.
If (bhandled) return true;
}
If (cmybaseclass: processwindowmessage (hwnd, umsg, wparam, lparam, lresult ))
Return true;
Break;
Case 1: // alt_msg_map (1), function of Branch
If cmybaseclass: processwindowmessage (hwnd, umsg, wparam, lparam, lresult ))
Return true;
Break;
Case 2: // alt_msg_map (1)
If (umsg = wm_char)
{
Bhandled = true;
Lresult = onchar (umsg, wparam, lparam, bhandled );
If (bhandled) return true;
}
If cmybaseclass: processwindowmessage (hwnd, umsg, wparam, lparam, lresult, 1) // select branch 1
Return true;
Break;
Default:
...
}
Return false;
}

ProcessWindowMessage () is a virtual function. Its root cause is defined in CMessageMap. CMessageMap is one of the base classes of csf-wimpl (the other is CWindow ). ProcessWindowMessage is generally called in WindowProc. If the call fails, that is, FALSE is returned, DefWindowProc is called, and DefWindowProc calls the Window Process pointed to by the member variable m_pfnSuperWindowProc, this variable is used to retain the original Window Process pointer when subclass and superclass are used.

CHAIN_MSG_MAP provides an opportunity to execute the ProcessWindowMessage function of theChainClass (usually the parent class). It is generally used in the implementation of ActiveX Control, such as CHAIN_MSG_MAP (CComControl <CMyCtl> ). This macro is necessary because the parent class may process some messages. For example, the class definition of CComControl contains the following statements:

Message_handler (wm_paint, ccomcontrolbase: onpaint)
Message_handler (wm_setfocus, ccomcontrolbase: onsetfocus)
Message_handler (wm_killfocus, ccomcontrolbase: onkillfocus)
Message_handler (wm_mouseactivate, ccomcontrolbase: onmouseactivate)

It can be seen that CComControl contains the processing of four messages: WM_PAINT, WM_SETFORCE, WM_KILLFOCUS, and WM_MOUSEACTIVE. DefWindowProc should be called only when the parent class cannot process the message.

  5. Use contained window

Contained window is included in other objects. The typical usage is as follows:

Class cmycontainer: Public ccomcontrol <cmycontainer>,... // a full control
{
Public:
Ccontainedwindow m_wndedit, m_wndlist;
Cmycontainer ()
: M_wndedit ("edit", this, 1) // 1 indicates the branch
, M_wndlist ("list", this, 2) // 2 indicates the branch
{...}

Begin_msg_map (cmycontainer)
// Process your own messages
Alt_msg_map (1) // Case 1:
// Process the message of the edit container
Alt_msg_map (2) // Case 2:
// Process the message of the List container
End_msg_map ()

Lresult oncreate (...)
{
M_wndedit.create (...);
M_wndlist.create (...);
}
......
};

Compare the message processing processes of CWindowImpl and CContainedWindow:

(1) csf-wimpl:

(2) CContainedWindow:

It can be seen that the contained window is first processed by the container containing it. If it cannot be processed, it is transferred to its own DefWindowProc.

  6. Implement hosting ActiveX Control

ATL also provides some classes to implement the window that can be hosting ActiveX control. Caxdialogimpl mentioned above is such a class. In addition, caxwindow can be applied to more common windows. Its usage is also very simple. The following is a simple example to implement a window that contains a calendar control.

(1) Declare the class definition in the following form:

Class catlaxwindow
: Public cwindowimpl <catlaxwindow, cwindow, cframewintraits>
, Public idispeventimpl <1, catlaxwindow, & diid_dcalendarevents, & libid_msacal, 7, 0>
{
Public:
// Window message
Begin_msg_map (catlaxwindow)
...
End_msg_map ()

// Event processing
Begin_sink_map (catlaxwindow)
Sink_entry_ex (1, diid_dcalendarevents, 0x1, onafterupdatecalendar)
...
End_sink_map ()
Stdmethod (onafterupdatecalendar )();

PRIVATE:
Caxwindow m_axwnd; // host ActiveX Control

};

Inherit from csf-wimpl to create a parent window containing ActiveX controls. cframewintraits is used to create a frame style window. Inherited from idispeventimpl to accept events containing controls.

(2) There are two methods to create the hosting window:

// Method 1
Rect = {0, 0,400,300 };
M_axwnd.create (m_hwnd, rect, _ T ("mscal. calendar.7 "),
Ws_overlappedwindow | ws_visible | ws_clipsiblings | ws_clipchildren, 0 );
M_axwnd.centerwindow ();
M_axwnd.setwindowtext (_ T ("ActiveX host window "));
Subclasswindow (m_axwnd.m_hwnd );

// Method 2, or m_axwnd is not used. In create, set windowname to "atlaxwin" to directly create
Rect = {0, 0,400,300 };
Create (null, rect, null, ws_overlappedwindow | ws_visible | ws_clipsiblings | ws_clipchildren );
Centerwindow ();
Setwindowtext (_ T ("ActiveX host window "));
M_axwnd.attach (m_hwnd );
M_axwnd.createcontrol (olestr ("mscal. calendar.7 "));

These statements are very simple. For more information about the functions, see msdn.

(3) After creating the hosting window, you need to establish an event connection by using the following code:

// Establish an event connection
Ccomptr <iunknown> spiunknown;
M_axwnd.querycontrol (iid_iunknown, (void **) & spiunknown );
Dispeventadvise (spiunknown, & diid_dcalendarevents );

Effect:

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.