ATL window source code learning notes

xiaoxiao2021-03-06  73

ATL window source code learning notes

This article is a summary of learning source code. When writing the process and checking the code, find some articles.

Reference:

WTL process analysis - premium

THUNK mechanism learning in ATL

1. CWindow ATL has a basic class specifically designed to be a window, you can do all window operations, which is CWindow. It is actually a package class for HWND operations, encapsulated almost all window APIs with the HWND handle as the first parameter, such as SETWINDOWTEXT () and DESTROYWINDOW (). The CWindow class has a public member m_hwnd that allows you to operate directly to the window, CWindow has an operator HWnd, which can pass the CWindow object to a function of HWND as a parameter.

CWindow is an ordinary C class. Creating a CWindow object takes a lot of resources because there is only one data member.

2. The implementation of the CWINDOWIMPL inherited tree in the ATL class is CWindowImpl. CWINDOWIMPL contains all windows implementation code, such as the registration of the window, the subclass of the window, the message mapping, and the basic WindowProc () function.

Let's pursue the source and look at its inheritance process:

In general, we need to define your own window, first inherit from CWindowImpl.

Class CMYWND: PUBLIC CWINDOWIMPL

;

Template

Class ATL_NO_VTABLE CWINDOWIMPL: Public CWINDOWIMPLBASET

Template

Class ATL_NO_VTABLE CWINDOWIMPLBASET: PUBLIC CWINDOWIMPLROOT

Template

Class ATL_NO_VTABLE CWINDOWIMPLROOT: PUBLIC TBASE, PUBLIC CMESSAGEMAP

Class ATL_NO_VTABLE CMESSAGEMAP

{

PUBLIC:

Virtual Bool ProcessWindowMessage (HWND HWND, UINT UMSG, WPARAM WPARAM, LPARAM LPARAM,

LRESULT & LRESULT, DWORD DWMSGMAPID = 0;

}

2.1, CMessageMap This class is a pure virtual class that is the main purpose to provide a processing interface for Windows messages. All subclasses inherited from this class have functions that handle Windows messages.

2.2, CWindowImplroot Template

Class ATL_NO_VTABLE CWINDOWIMPLROOT: PUBLIC TBASE, PUBLIC CMESSAGEMAP

First look at TBASE, what is this guy? Just when we define your own window classes, it is incoming CWindow.

Class CMYWND: PUBLIC CWINDOWIMPL

;

TBASE illustrates what the ancestors of our own defined window classes are. So can we inherit a class from CWindow, then pass this subclass as a type parameter? absolutely okay. With this TBASE, we can control from what the base class inheritage from yourself when writing the program.

CWindowImplRoot defines these members, all public.

CWNDPROCTHUNK M_THUNK;

Const _tl_msg * m_pcurrentmsg;

DWORD M_DWSTATE; Its member function is mainly for M_PCurrentMSG. Such as:

// Current Message

Const _TL_MSG * getCurrentMessage () Const

// "Handled" Management for Cracked Handlers

Bool ismsghandled () const

Void setmsghand (bool bhandled)

There is also a support for the advancement and reflection of messages.

// Message Forwarding and Reflection Support

Lresult ForwardNotifications (Uint UMSG, WPARAM WPARAM, LPARAM LPARAM, BOOL & BHANDED);

Lresult ReflectNotifications (UINT UMSG, WPARAM WPARAM, LPARAM LPARAM, BOOL & BHANDED);

Static Bool DefaultReflectionHandler (HWND HWND, UINT UMSG, WPARAM WPARAM, LRESULT & LRESULT);

It seems to do what to do with M_DWState, M_thunk.

About CWNDPROCTHUNK, you need to see:

Thunk mechanism in ATL learning,

http://dev.9cbs.net/develop/Article/20532.shtm

2.3, CWindowImplbaset Template

Class ATL_NO_VTABLE CWINDOWIMPLBASET: PUBLIC CWINDOWIMPLROOT

Take a look at CControlwintraits.

/

// Cwintraits - Defines Various default value for a window

Template

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

Ccontrolwintraits;

Typedef Cwintraits

CframewinTraits;

Typedef Cwintraits

Cmdichildwintraits;

Typedef Cwintraits <0, 0> CNULTRAITS;

Template

Class Cwintraitsor

{

PUBLIC:

Static DWORD GETWNDSTYLE (DWORD DWSTYLE)

{

Return DWStyle | T_DWStyle | Twintraits :: GetWndStyle (DWStyle);

}

Static DWORD GETWNDEXSTYLE (DWORD DWEXStyle)

{

Return DwexStyle | T_DwexStyle | Twintraits :: getWndexStyle (dwexstyle);

}

}

It turns out that it is a package for window properties. Definitions are static functions. So after the creation window needs to fill in the window attribute parameters, we can write:

CControlwintraits :: getWndStyle (0); thereby got an attribute of a similar child control. Or we can define your own:

Typedef Cwintraits

CMYWINDOWTRAITS;

CWindowImplbaset is mainly packaged for window processes.

Its secretary member is a window process function pointer:

WndProc M_PFNSUPERWINDOWPROC;

This function pointer points to the system default window process when constructing, and the same as Win32 API.

CWindowImplbaset (): m_pfnsuperwindowproc (:: defWindowproc)

{}

The window attribute has been supported at this time.

GetWndStyle

GetWndexStyle

There are two static functions, that is, the window process function, it should belong to a more secret technology, skip it first.

Windowproc

StartWindowProc

2.4, CWindowImpl

Template

Class ATL_NO_VTABLE CWINDOWIMPL: Public CWINDOWIMPLBASET

A macro appeared in the class:

Declare_Wnd_Class (NULL)

What did you represent? --->

#define declare_wnd_class (wndclassname) /

Static atl :: CWndClassInfo & getWndClassInfo ()

{

Static atl :: CWNDClassInfo wc =

{

{SIZEOF (WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, STARTWINDOWPROC,

0, 0, NULL, NULL, NULL, (HBRUSH) (Color_Window 1), NULL, WNDCLASSNAME, NULL},

NULL, NULL, IDC_ARROW, TRUE, 0, _T ("")

}

Return WC;

}

That is to define a static member function.

Typedef struct tagwndclassexw {

Uint CBSIZE;

/ * Win 3.x * /

Uint style;

WndProc lpfnwndproc;

Int cbclsextra;

Int Cbwndextra;

Hinstance hinstance;

Hicon Hicon;

Hcursor hcursor;

Hbrush Hbrbackground;

LPCWSTR LPSZMENUNUNUNAME;

LPCWSTR LPSZCLASSNAME;

/ * WIN 4.0 * /

Hicon HiconSM;

} WNDCLASSEXW, * PWNDCLASSEXW, NEAR * NPWNDCLASSEXW, FAR * LPWNDCLASSEXW;

The definition of the window class is implemented via the Declare_Wnd_Class macro or Declare_Wnd_Class_ex macro. This macro defines a CWndClassInfo structure that encapsulates the WNDCLASSEX structure. DECLARE_WND_CLASS Macro makes you specify the class name of the window class, other parameters use the default setting, and the declare_wnd_class_ex macro also allows you to specify the type of window and the background color of the window, you can also use null as class name, ATL will automatically generate one Class name.

In fact, when we define your own window classes, we also defined such a macro.

Class CMYWND: PUBLIC CWINDOWIMPL

{

...

PUBLIC:

Declare_wnd_class (_t ("My Window Class") ...

}

In addition to this macro, there is a CREATE function.

HWND CREATE (HWND HWNDPARENT, _U_RECT RECT = null, lpctstr szwindowname = NULL,

DWORD DWSTYLE = 0, DWORD DWEXSTYLE = 0,

_U_Menuorid Menuorid = 0u, LPVOID LPCREATEPARAM = NULL)

2.5, the message processing function Next is the definition of the message processing in the custom class, mainly using the following macros:

Begin_MSG_MAP (CMYWINDOW)

Message_handler (WM_Close, OnClose)

Message_handler (WM_DESTROY, ONDESTROY)

END_MSG_MAP ()

As for these macros, as well as their specific relationship, I am ready to write a note. The above macro base can be sure that it defines a function:

Bool ProcessWindowMessage (HWND HWND, UINT UMSG, WPARAM WPARAM, LRESULT & LRESULT, DWORD DWMSGMAPID = 0)

{

}

That is, the message processing function, this function is a virtual function, defined in CMessageMap, inherited by CWindowImplroot.

Who calls this function? Think about it will know in WindowProc. After registering the window class, successfully created a window, the operating system will call our window procedure. The window process should be processed in the CWindowImplbaset class.

Template

LResult Callback CWindowImplbaset :: WindowProc (HWND HWND, UINT UMSG, WPARAM WPARAM, LPARAM LPARAM)

{

CWindowImplbaset * Pthis = (CWindowImplbaset *) hwnd;

// set a ptr to this message and save the old value

_TL_MSG MSG (PTHIS-> M_HWND, UMSG, WPARAM, LPARAM);

Const _tl_msg * Poldmsg = pthis-> m_pcurrentmsg;

PTHIS-> M_PCURRENTMSG = & msg;

// Pass to the message map to process

LRESULT LRES;

Bool Bret = Pthis-> ProcessWindowMessage (PTHIS-> M_HWND, UMSG, WPARAM, LPARAM, LRES, 0);

// Restore Saved Value for The Current Message

Atlassert (pthis-> m_pcurrentmsg == & msg);

PTHIS-> M_PCURRENTMSG = POLDMSG;

// do the default processing if message was not handled

IF (! bret)

{

IF (UMSG! = WM_NCDESTROY)

Lres = Pthis-> DefWindowProc (UMSG, WPARAM, LPARAM); ELSE

{

// unsubclass, if nesered

Long_ptr pfnwndproc = :: getwindowlongptr (pthis-> m_hwnd, gwlp_wndproc);

Lres = pthis-> DefWindowProc (UMSG, WPARAM, LPARAM);

IF (pthis-> m_pfnsuperwindowproc! = :: DefWindowProc &&: getWindowlongPtr (pthis-> m_hwnd, gwlp_wndproc) == PfnWndProc)

:: setwindowlongptr (pthis-> m_hwnd, gwlp_wndproc, (long_ptr) pthis-> m_pfnsuperwindowproc);

// Mark Window As Des Destryed

PTHIS-> M_DWSTATE | = WINSTATE_DESTROYED;

}

}

IF ((PTHIS-> M_DWSTATATATE & WINSTATE_DESTROYED & WINSTATE_DESTROYED) && pthis-> m_pcurrentmsg == null)

{

// Clear Out Window Handle

HWND HWND = PTHIS-> M_HWND;

PTHIS-> M_HWND = NULL;

PTHIS-> M_DWSTATATE & = ~ WINSTATE_DESTROYED;

// Clean Up After Window Is Destroyed

PTHIS-> OnfinalMessage (hwnd);

}

Return Lres;

}

CWindowImplbaset * Pthis = (CWindowImplbaset *) hwnd;

This sentence has to pay attention to why you can get a class instance pointer from a handle? I haven't figured it out for a while. Not pursued first.

In this function, the main points are:

(1) Save the original message

(2) Call ProcessWindowMessage, which is the source of the message processing function we compare.

(3) If there is no message in a custom window class, ATL is processed.

(4) If you need to destroy the window, the ending process is made, call the virtual function: onfinalMessage.

Summary: Through the interpretation of the original code above, we can find that the ATL is essentially the creation of the window, the message loop, and the like. Nothing is to use a template mechanism, and ultimately the call to the Win32 API.

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

New Post(0)