5Button的click消息流程(notify消息)
来源:互联网 发布:thinkphp投票系统源码 编辑:程序博客网 时间:2024/06/08 15:32
1.简介
本节研究下当一个 Button 按钮被点击时,消息是如何一步步传输的,并最终被主窗口中的 Notify() 函数处理掉。 通过此,可以清晰的了解 Notify 消息的产生过程及传递过程。
本节基于需要了解的一点是:在自定义窗口中的,如果 HandleMessage() 不对消息进行处理,则最终会走向 CPaintManagerUI::MessageHandler() 函数中,此函数对多种系统消息进行了处理。
2.鼠标左键按下
当鼠标左键按下时,系统会向窗口发送 WM_LBUTTONDOWN 消息,经过一系列传递后,WM_LBUTTONDOWN 到达 CPaintManagerUI::MessageHandler() 函数中。CPaintManagerUI中有成员变量 m_pEventClick 用于记录点击事件由哪个控件处理,在此处进行赋值,方便在鼠标左键抬起时使用。
bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes){ //异步消息处理...... //消息过滤...... switch( uMsg ) { //此处省略了其他各种case处理 case WM_LBUTTONDOWN: //系统消息:左键按下 { //窗口获得焦点 ::SetFocus(m_hWndPaint); //根据鼠标位置判断是哪个控件被左键按下 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; m_ptLastMousePos = pt; CControlUI* pControl = FindControl(pt); if( pControl == NULL ) break; if( pControl->GetManager() != this ) break; //将焦点设置在控件上(当然会有关于焦点的一系列消息发生) m_pEventClick = pControl; pControl->SetFocus(); //捕获鼠标 SetCapture(); //初始化event事件 TEventUI event = { 0 }; event.Type = UIEVENT_BUTTONDOWN; event.pSender = pControl; event.wParam = wParam; event.lParam = lParam; event.ptMouse = pt; event.wKeyState = (WORD)wParam; event.dwTimestamp = ::GetTickCount(); //处理按下事件:按钮变换背景颜色等 pControl->Event(event); } break; default: break; } //异步消息处理...... return false;}
接着简介下 pControl->Event(event) 这句。由于 CButtonUI 未重载 Event() 函数,故调用父类 CControlUI 的,如下:
void CControlUI::Event(TEventUI& event){ if( OnEvent(&event) ) DoEvent(event);}
CButtonUI 并没有给 OnEvent 设置代理(后续再介绍),故会返回true,接着会直接调用 DoEvent() 函数。DoEvent() 会对多种event事件进行处理,在这里仅将对 UIEVENT_BUTTONDOWN 的处理贴出来:
void CButtonUI::DoEvent(TEventUI& event){ //其他各种event处理 if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_DBLCLICK ) { if( ::PtInRect(&m_rcItem, event.ptMouse) && IsEnabled() ) { m_uButtonState |= UISTATE_PUSHED | UISTATE_CAPTURED; //更改状态样式 Invalidate(); //刷新控件 } return; } CLabelUI::DoEvent(event);}
3.鼠标左键抬起
左键抬起的消息 WM_LBUTTONUP 的处理流程跟按下左键基本相同,bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes) 中对 WM_LBUTTONUP 消息的处理过程如下:
case WM_LBUTTONUP: { POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; m_ptLastMousePos = pt; if( m_pEventClick == NULL ) break; //释放鼠标捕获 ReleaseCapture(); //初始化event事件 TEventUI event = { 0 }; event.Type = UIEVENT_BUTTONUP; event.pSender = m_pEventClick; event.wParam = wParam; event.lParam = lParam; event.ptMouse = pt; event.wKeyState = (WORD)wParam; event.dwTimestamp = ::GetTickCount(); //处理松开鼠标事件 m_pEventClick->Event(event); m_pEventClick = NULL; } break;
之后便会进入 CButtonUI::DoEvent, 如下:
void CButtonUI::DoEvent(TEventUI& event){ //其他各种event处理 if( event.Type == UIEVENT_BUTTONUP ) { if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) { if( ::PtInRect(&m_rcItem, event.ptMouse) ) Activate(); m_uButtonState &= ~(UISTATE_PUSHED | UISTATE_CAPTURED); Invalidate(); } return; } CLabelUI::DoEvent(event);}
如果按下鼠标与松开鼠标的过程中没有移动鼠标,则鼠标位置仍在Button中,PtInRect()返回true,进入 Activate() 函数,如下:
bool CButtonUI::Activate(){ if( !CControlUI::Activate() ) return false; if( m_pManager != NULL ) m_pManager->SendNotify(this, DUI_MSGTYPE_CLICK); return true;}
4.进入 SendNotify 函数
从上面代码中可以看出,会执行 m_pManager->SendNotify(),而且是同步消息,消息会立即被执行。执行的过程简化如下:
void CPaintManagerUI::SendNotify(TNotifyUI& Msg, bool bAsync /*= false*/){ Msg.ptMouse = m_ptLastMousePos; Msg.dwTimestamp = ::GetTickCount(); if( m_bUsedVirtualWnd ) { Msg.sVirtualWnd = Msg.pSender->GetVirtualWnd(); } if( Msg.pSender != NULL ) { //控件本身处理此消息 if( Msg.pSender->OnNotify ) Msg.pSender->OnNotify(&Msg); } for( int i = 0; i < m_aNotifiers.GetSize(); i++ ) { //同步消息,被立即执行 static_cast<INotifyUI*>(m_aNotifiers[i])->Notify(Msg); }}
故窗口的 Notify() 函数将会直接被执行。至于你要对按钮点击做出什么响应,在Notify()中实现就可以了。
5.结束
印证了一点,所有的notify消息都是通过 CPaintManagerUI::SendNotify() 产生的。
- 5Button的click消息流程(notify消息)
- 4.Notify消息流程
- NOTIFY消息
- notify-listview-的消息处理
- 关于 notify 消息的 介绍
- Delphi中Click消息的实质?
- powerplant中view的click消息处理
- PostMessage发送click消息
- windows 消息的流程
- 消息的处理流程
- notify–消息中间件
- 消息中间件Notify
- Notify.js 消息管理
- 关于button的MOUSEMOVE消息的添加
- ImageButton 屏蔽掉父类click消息
- DELPHI消息的处理流程
- DELPHI消息处理的流程
- zigbee消息的处理流程
- Linux中umask函数/命令的用法
- 机器视觉-结构光测量之三角测量原理
- Laravel安装后访问空白
- 数据库和数据表的操作
- 数据结构和算法(C语言)
- 5Button的click消息流程(notify消息)
- Android分割特殊字符
- eclipse中Java连接sql server数据库
- "Calendars" and "DateFormats" should not be static
- GO语言的环境搭建
- Java_线程-Thread
- 常用类和集合框架
- RTB实时竞价
- VS 常见快捷键有哪些,