金山卫士开源代码----消息机制浅析 (下)

本文详细解析了ATL框架下窗口创建的过程,包括窗口类的注册、窗口处理函数的设置及窗口的创建流程。深入探讨了CWndClassInfo结构及WNDCLASSEXW的作用。

接上文http://blog.youkuaiyun.com/hw_henry2008/archive/2011/05/22/6438153.aspx

代码地址:http://download.youkuaiyun.com/source/3301518

HWND CBkDialogImpl : public CWindowImpl <T, TBase, TWinTraits> ::Create(HWND hWndParent = ::GetActiveWindow(), LPRECT rect = NULL) { //··· //调用父类的函数创建窗口,窗口标志什么的是从XML中读入的 HWND hWnd = __super::Create(hWndParent, rcWnd, lpszCaption, m_richView.GetDlgStyle(), m_richView.GetDlgExStyle()); //··· return hWnd; } //继续看代码,到父类CWindowImpl中去 HWND CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits > ::Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) { if (T::GetWndClassInfo().m_lpszOrigName == NULL) T::GetWndClassInfo().m_lpszOrigName = GetWndClassName(); ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); //··· return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam); }

/*上面的代码调用GetWndClassInfo得到窗口结构的基本信息,其中即设置了窗口处理函数有必要贴一下的代码GetWndClassInfo,它返回一个窗口类的基本信息。其中就包括了窗口处理函数,这是我们用来向操作系统注册的回调函数。*/
static ATL::CWndClassInfo& CBkDialogImpl::GetWndClassInfo() { static ATL::CWndClassInfo wc = { { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | (IsWinXPAndLater() ? CS_DROPSHADOW : 0), StartWindowProc, 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, NULL, NULL }, NULL, NULL, IDC_ARROW, TRUE, 0, _T("") }; return wc; } //其中 ATL::CWndClassInfo 经过一系列的宏定义,最终等于_ATL_WNDCLASSINFOW struct _ATL_WNDCLASSINFOW {//实际上这个结构基本只用了m_wc,其他初始化为空 WNDCLASSEXW m_wc;//下面看起定义 LPCWSTR m_lpszOrigName; WNDPROC pWndProc; LPCWSTR m_lpszCursorID; BOOL m_bSystemCursor; ATOM m_atom; WCHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT]; ATOM Register(WNDPROC* p) {//这个函数待会会提一下,想操纵系统注册窗口就是通过它的 return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, this, p); } }; typedef struct tagWNDCLASSEXW { UINT cbSize; UINT style; WNDPROC lpfnWndProc;//仔细的读者会发现,这个成员其实就是注册的消息处理函数:StartWindowProc!!!! int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; HICON hIconSm; } WNDCLASSEXW, *PWNDCLASSEXW, NEAR *NPWNDCLASSEXW, FAR *LPWNDCLASSEXW;

/*好了,到这就清楚了这个窗口处理函数是如何向操作系统注册的,为了结个尾,看一下创建窗口的代码吧
窗口的注册是在上述CWindowImpl的Create函数中,一个很隐蔽的地方
ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
这个Register其实就是CWndClassInfo结构的一个成员函数,里面经过了一些繁琐的调用,最终调用了下面的代码
p->m_atom = T::RegisterClassEx(pWinModule, &p->m_wc);
很明显,这就是注册窗口类的地方。那么,创建窗口呢?上述函数中注册后紧接着调用了下面的函数创建窗口
*/

template <class TBase, class TWinTraits> HWND CWindowImplBaseT< TBase, TWinTraits > : public CWindowImplRoot< TBase > ::Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam) { //··· HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu, _AtlBaseModule.GetModuleInstance(), lpCreateParam); ATLASSUME(m_hWnd == hWnd); return hWnd; }

/*不好意思哦,因为刚看金山的代码,所以很多地方都很生疏,
漏掉了许多重要的精彩的地方,写的文笔一塌糊涂,随便在代码中乱注释
影响阅读还忘见谅···前阵子问邹欣老师一个问题,
他说"有些东西不懂的话试着写出来,写个博客也许就懂了",诚然。
理解错的地方(肯定有)还请大家不吝赐教:hw_henry2008@126.com

Todo:ATL::CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap
这句代码好像也能引出一个消息映射的另一种方式,改天看看。
另外XML的实现机制那块改天也得好好看看了
先这样吧···*/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值