在Duilib学习笔记《04》中已经知道了如何将窗体显示出来,而如何处理窗体上的事件、消息呢?
一. 系统消息
窗体显示的时候我们就已经说了,窗体是继承CWindowWnd类的,对于窗体的部分消息的处理,需要重载该类的LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); 函数。在显示窗体部分我们创建窗体WM_CREATE消息以及屏蔽标题栏WM_NCACTIVATE、WM_NCCALCSIZE、WM_NCPAINT等消息 都是在HandleMessage中进行处理:
1 |
LRESULT CMainWndDlg::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) |
8 |
case WM_CREATE: lRes = OnCreate(uMsg, wParam, lParam, bHandled); break ; |
9 |
case WM_NCACTIVATE: lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break ; |
10 |
case WM_NCCALCSIZE: lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break ; |
11 |
case WM_NCPAINT: lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break ; |
12 |
case WM_NCHITTEST: lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break ; |
13 |
case WM_CLOSE: lRes = OnClose(uMsg, wParam, lParam, bHandled); break ; |
14 |
case WM_DESTROY: lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break ; |
15 |
case WM_SIZE: lRes = OnSize(uMsg, wParam, lParam, bHandled); break ; |
16 |
case WM_GETMINMAXINFO: lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); break ; |
17 |
case WM_SYSCOMMAND: lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); break ; |
18 |
case WM_KEYDOWN: PostQuitMessage(0); break ; |
23 |
if ( bHandled ) return lRes; |
24 |
if ( m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes; |
26 |
return CWindowWnd::HandleMessage(uMsg, wParam, lParam); |
如同代码中所示,如果消息不需要框架再处理了则直接返回。如果还需要框架处理该消息,则交由父类的HandleMessge中去处理。
二. 事件消息
对于系统消息我们直接重载了HandleMessage来处理,而对于鼠标点击一类的消息呢?为此,我们的窗体除了要继承CWindowWnd外,还需要继承INotifyUI,同样的重载INotifyUI类中的void Notify(TNotifyUI& msg); 函数,由该函数来处理控件操作产生的消息。但仅仅只是继承重载了还不够,我们怎么才能确保事件消息能正常传递呢?因此,在窗体创建OnCreate的时候,我们还需要添加如下m_PaintManager.AddNotifier(this); 这样,控件消息就可以传达大duilib的消息循环中,我们也就可以通过Notify函数对消息进行处理:
1 |
void CMainWndDlg::Notify( TNotifyUI& msg ) |
3 |
if ( msg.sType == _T( "windowinit" ) ) { |
6 |
else if ( msg.sType == _T( "click" ) ) { |
7 |
if ( msg.pSender == m_pCloseBtn ) { |
11 |
else if ( msg.pSender == m_pMinBtn ) { |
12 |
SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0); return ; } |
13 |
else if ( msg.pSender == m_pMaxBtn ) { |
14 |
SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0); return ; } |
15 |
else if ( msg.pSender == m_pRestoreBtn ) { |
16 |
SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0); return ; } |
19 |
OnLBtnClick(msg.pSender); |
21 |
else if (msg.sType==_T( "selectchanged" )) |
23 |
CDuiString name = msg.pSender->GetName(); |
24 |
CTabLayoutUI* pTabSwitch = static_cast <CTabLayoutUI*>(m_PaintManager.FindControl(_T( "tab_switch" ))); |
25 |
CTabLayoutUI* pDemoListSwitch = static_cast <CTabLayoutUI*>(m_PaintManager.FindControl(_T( "demo_list_tab_switch" ))); |
27 |
if (name.CompareNoCase(_T( "demo_tab" )) == 0) |
28 |
pTabSwitch->SelectItem(0); |
29 |
else if (name.CompareNoCase(_T( "web_tab" )) == 0) |
30 |
pTabSwitch->SelectItem(1); |
32 |
if (name.CompareNoCase(_T( "demo_list_basic_ctrl" )) == 0) |
33 |
pDemoListSwitch->SelectItem(0); |
34 |
else if (name.CompareNoCase(_T( "demo_list_rich_ctrl" )) == 0) |
35 |
pDemoListSwitch->SelectItem(1); |
在Notify函数中针对消息的不同进行不同的操作处理,比如click、selectchanged等等。对于这类duilib针对相关操作自定义的消息类型可以在duilib工程中的UIDefine.h文件中查看:
4 |
#define DUI_MSGTYPE_MENU (_T("menu")) |
5 |
#define DUI_MSGTYPE_LINK (_T("link")) |
7 |
#define DUI_MSGTYPE_TIMER (_T("timer")) |
8 |
#define DUI_MSGTYPE_CLICK (_T("click")) |
10 |
#define DUI_MSGTYPE_RETURN (_T("return")) |
11 |
#define DUI_MSGTYPE_SCROLL (_T("scroll")) |
13 |
#define DUI_MSGTYPE_DROPDOWN (_T("dropdown")) |
14 |
#define DUI_MSGTYPE_SETFOCUS (_T("setfocus")) |
16 |
#define DUI_MSGTYPE_KILLFOCUS (_T("killfocus")) |
17 |
#define DUI_MSGTYPE_ITEMCLICK (_T("itemclick")) |
18 |
#define DUI_MSGTYPE_TABSELECT (_T("tabselect")) |
20 |
#define DUI_MSGTYPE_ITEMSELECT (_T("itemselect")) |
21 |
#define DUI_MSGTYPE_ITEMEXPAND (_T("itemexpand")) |
22 |
#define DUI_MSGTYPE_WINDOWINIT (_T("windowinit")) |
23 |
#define DUI_MSGTYPE_BUTTONDOWN (_T("buttondown")) |
24 |
#define DUI_MSGTYPE_MOUSEENTER (_T("mouseenter")) |
25 |
#define DUI_MSGTYPE_MOUSELEAVE (_T("mouseleave")) |
27 |
#define DUI_MSGTYPE_TEXTCHANGED (_T("textchanged")) |
28 |
#define DUI_MSGTYPE_HEADERCLICK (_T("headerclick")) |
29 |
#define DUI_MSGTYPE_ITEMDBCLICK (_T("itemdbclick")) |
30 |
#define DUI_MSGTYPE_SHOWACTIVEX (_T("showactivex")) |
32 |
#define DUI_MSGTYPE_ITEMCOLLAPSE (_T("itemcollapse")) |
33 |
#define DUI_MSGTYPE_ITEMACTIVATE (_T("itemactivate")) |
34 |
#define DUI_MSGTYPE_VALUECHANGED (_T("valuechanged")) |
36 |
#define DUI_MSGTYPE_SELECTCHANGED (_T("selectchanged")) |
三. 消息过滤
在实际中,我们有时候可能需要根据需要对部分消息进行分类处理。比如键盘按键消息等等。对于这类情况,我们的窗体需要继承IMessageFilterUI类,重载LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)函数,同时在窗体OnCreate创建的时候添加m_pm_.AddPreMessageFilter(this)消息通知即可。