WTL基于ATL,并做了简化和封装
不同点
1.DECLARE_FRAME_WND_CLASS
原ATL:DECLARE_WND_CLASS封装了一个ATL::CWndClassInfo结构
DECLARE_FRAME_WND_CLASS封装了一个WTL::CFrameWndClassInfo,多了一个资源字段,可以加载菜单
2.BEGIN_MSG_MAP_EX
添加IsMsgHandled和SetMsgHandled方法.
3.MSG_WM_CREATE
MSG_WM_CREATE与BEGIN_MSG_MAP_EX连用,其内部会调用SetMsgHandled和IsMsgHandled.
#define MSG_WM_CREATE(func) \
if (uMsg == WM_CREATE) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
if(IsMsgHandled()) \
return TRUE; \
}
默认情况下会直接返回,这样就会阻止基类执行此消息,在必要时调用SetMsgHandled方法传入false参数,这样基类也可以处理此消息.当然前提是不要忘了消息链CHAIN_MSG_MAP
LRESULT OnCreate ( LPCREATESTRUCT lpcs )
{
SetTimer ( 1, 1000 );
SetMsgHandled(false);
return 0;
}
可以注意到OnCreate函数的参数只有一个,进行了简化.
也可以用回原ATL提供的宏,注意BEGIN_MSG_MAP和MESSAGE_HANDLER也是连用的
BEGIN_MSG_MAP(CMainFrame)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
END_MSG_MAP()
4.COMMAND_ID_HANDLER_EX
#define COMMAND_HANDLER_EX(id, code, func) \
if (uMsg == WM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \
{ \
SetMsgHandled(TRUE); \
func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
其内部也会调用SetMsgHandled和IsMsgHandled方法
5.CMessageLoop
CMessageLoop的Run方法封装了消息循环
int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
CMessageLoop theLoop;
_Module.AddMessageLoop(&theLoop);
CMainFrame wndMain;
if(wndMain.CreateEx() == NULL)
{
ATLTRACE(_T("Main window creation failed!\n"));
return 0;
}
wndMain.ShowWindow(nCmdShow);
int nRet = theLoop.Run();
_Module.RemoveMessageLoop();
return nRet;
}
int Run()
{
BOOL bDoIdle = TRUE;
int nIdleCount = 0;
BOOL bRet;
for(;;)
{
…
if(!PreTranslateMessage(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}
…
}
return (int)m_msg.wParam;
}
6.CMessageFilter
重写PreTranslateMessage方法返回TRUE时用于过滤消息,
7.CIdleHandler
重写OnIdle方法,空闲时执行