ATL provides some tool classes to implement windows so that you can create a window without relying on the MFC in an ATL component.
First, implement the dialog
Three template classes in ATL can be used to create a dialog:
(1) CSIMPLEDIALOG: Create a mode dialog, you can host Windows Controls
Template
(2) CDIALOGIMPL: Create a mode or non-Mode dialog, you can host Windows Controls
Template
(3) CAXDIALOGIMPL: Create a mode or non-Mode dialog, you can host Windows Controls and ActiveX Controls
Template
With CSIMPLEDIALOG and CDIALOGIMPL, you cannot display dialogs containing the ActiveX control, only CAXDIALOGIMPL. If you want to handle the event in the dialog, ATLADVISINKMAP (this, true) is added to OnInitDialog (). Add AtladViseSinkMap (this, false) when exiting. The dialog box generated by Insert / New ATL Object / Miscellaneous / Dialog is inherited from CaxDialogIMPL.
The use of these three classes is very similar. They are all derived from a new class and make sure there is a member of the IDD to indicate the resource ID. Such as:
class CMyDialog: public CDialogImpl, ... {public: enum {IDD = IDD_MYDIALOG}; // this member must have IDD, generally enum type BEGIN_MSG_MAP (CMyDialog) MESSAGE_HANDLER (WM_INITDIALOG, OnInitDialog) END_MSG_MAP () LRESULT OnInitDialog (UINT UMSG, WPARAM WPARAM, LPARAM LPARAM, BOOL & BHANDERED) {Return 1;}}; cmydialog dlg; dlg.domodal ();
CSIMpleDialog can be more simple, as follows:
CSIMPLEDIALOG
In addition, CSIMpleDialog has intrinsic support to IDOK and IDCANCEL, which will automatically call EndDialog, which contains the following code in its definition:
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 & / * BHANDED * /) {:: enddialog (m_hwnd, wid); return 0;} However, CDialogIMPL and CAXDialogIMPL do not have intrinsic support, so you must add your message handler to call EndDialog, such as:
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;}
Second, SUBCLASS and SUPERCLASS
Subclass's role is to intercept messages and point to its own container process function. There are two kinds of subclass.
(1) Instance Subclass: Subclassization An instance of existing container objects. Each window object instance is allocated by the system (HWND is this memory block), saving various information with a window, including the address of WndProc. So you can override this address for your own WndProc address, so that the processing of the message can be intercepted. (Of course, I have to retain the original WndProc address, with pass message)
(2) Global Subclass: Subclass a Window Class. The address of WndProc is kept in WNDCLASS, so you can change it for your own WndProc address, so all object instances created based on this new Wndclass will point to the address of the new WndProc. as the picture shows:
Instance Subclass
Global Subclass
Superclass is the same as Subclass, there are two distinction: (1) No instance superclass, only superclass window classes. (2) SUBCLASS cannot intercept the creation of WM_CREATE, WM_NCCREATE, etc., and SuperClass can be intercepted, but it must be PASS to give the original WndProc to complete the initialization work.
Third, use CWINDOWIMPL to implement one window
CWindowIMPL is a template class that is defined as follows:
template
template
(1) Using SuperClass
Class CMYWINDOW: PUBLIC CWINDOWIMPL
Class CMYWINDOW: PUBLIC CWINDOWIMPL
Fourth, message mapping macro
A set of messages are defined in the ATL, and a typical example is as follows:
BEGIN_MSG_MAP (CMyClass) MESSAGE_HANDLER (WM_PAINT, OnPaint) CHAIN_MSG_MAP (CMyBaseClass) // CMyBaseClass base class that represents ALT_MSG_MAP (1) // ATL_MSG_MAP mainly 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 results of the macro show are roughly as follows:
Bool CMYCLASS :: ProcessWindowMessage (HWND, UINT, WPARAM, LPARAM, LRESULT & LRESULT, DWORD DWMSGMAPID) {BOOL BHAND = true; // This variable is used to determine if the message has been processed ... Switch (dwmsgmapid) // default 0 {case 0: if (UMSG == WM_Paint) {bhandled = true; LRESULT = OnPaint (UMSG, WPARAM, LPARAM, BHAND); // 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), the branch action 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 TR UE; break; default: ...} return false;} processWindowMessage () is a virtual function that is defined in CMessageMap in CMessageMap (the other is CWindow). ProcessWindowMessage is usually called in WindowProc, if the invoking failed, then returns false, then DEFWINDOWPROC, and DEFWINDOWPROC calls the member variable M_PFNSUPERWINDOWPROC pointing to the window process, which is used to retain the original window process pointer when Subclass and Superclass.
Chain_msg_map gave an opportunity to execute the ProcessWindowMessage function of ThechainClass (Generally, the parent class), which is generally used in the implementation of ActiveX Control, such as: chain_msg_map (ccomcontrol
It can be seen that CCOMControl contains processing of four messages for WM_Paint, WM_SETFORCE, WM_KILLFOCUS, WM_MOUSEACTIVE. DEFWINDOWPROC should only be called only if the parent class can't handle this message.
V. Use Contained Window
Contained WINDOW is included in other objects, typical usage is as follows:
Class CMYCONTAINER: PUBLIC CCOMCONTROL
Compare the message processing of CWindowImpl and CContainedWindWind: (1) CWindowImpl:
(2) ccontainedwindow:
It can be seen that Contained WINDOW first processes the message that contains its Container, if it cannot be processed to go to its own DefWindowProc. 6. Realizing Hosting ActiveX Control ATL also provides some classes to implement windows that you can Hosting ActiveX Control. The CAXDialogimpl in front of the previously ever is such a class, and the CaxWindow can be applied to a more versatile window. Its use method is also very simple, the following is a simple example, implements a window, including a calendar control. (1) a statement of the form class definition: class CAtlAxWindow: public CWindowImpl
Inheriting from CWindowIMPL, in order to create a parent window that contains ActiveX controls, here CFramewIntraits, indicates that the window creates a Frame style. Inheriting from IdispeventImpl, in order to accept events included in the control.
(2) There are two ways to create a Hosting window, as follows:
@ A method RECT 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 ("ActiveX Host Window"); SubclassWindow (M_AXWnd.m_hWnd); // Method, you can also use m_axwnd, set Windowname to "Atlaxwin" directly in Create directly to create Rect 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 words are very simple, the meaning of specific functions can be investigated MSDN.
(3) After the Hosting window is created, it is necessary to establish an event connection, as follows:
// Establish an event connection ccomptrol (m_axwnd.QueryControl (IID_IUNKNOWN, (Void **) & spiunknown; dispeventadvise (spiunknown, & diid_dcalendarevent);
The effect is as shown in the figure: