仿酷狗音乐播放器开发日志二十六 duilib在标题栏弹出菜单的方法

来源:互联网 发布:网络规划设计师 论文 编辑:程序博客网 时间:2024/05/29 04:47

转载请说明原出处,谢谢~~

       上篇日志说明了怎么让自定义控件响应右键消息。之后我给主窗体的标题栏增加右键响应,观察原酷狗后可以发现,在整个标题栏都是可以响应右键并弹出菜单的。应该的效果如下:


       本以为像上一片博客那样,处理标题栏的布局的右键消息就可以了。后来发现在duilib的标题栏中无法像在客户区那样自如响应UIEVENT_CONTEXTMENU消息的。所以还得用另外的方法。

      在非客户区处理右击消息对应的是WM_NCRBUTTONUP,WM_NCRBUTTONUP是和WM_NCHITTEST相辅相成的。在WinImplBase.cpp文件中可以看到duilib处理WM_NCHITTEST的代码。在这里可以过滤指定的控件,被过滤的控件不会被duilib当作是非客户区的一部分,如果不过滤的话在标题栏的对应控件是无法响应用户的消息的,我为了适应仿酷狗程序,增加了被过滤的控件,源码如下:

LRESULT WindowImplBase::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);::ScreenToClient(*this, &pt);RECT rcClient;::GetClientRect(*this, &rcClient);if( !::IsZoomed(*this) ){RECT rcSizeBox = m_PaintManager.GetSizeBox();if( pt.y < rcClient.top + rcSizeBox.top ){if( pt.x < rcClient.left + rcSizeBox.left ) return HTTOPLEFT;if( pt.x > rcClient.right - rcSizeBox.right ) return HTTOPRIGHT;return HTTOP;}else if( pt.y > rcClient.bottom - rcSizeBox.bottom ){if( pt.x < rcClient.left + rcSizeBox.left ) return HTBOTTOMLEFT;if( pt.x > rcClient.right - rcSizeBox.right ) return HTBOTTOMRIGHT;return HTBOTTOM;}if( pt.x < rcClient.left + rcSizeBox.left ) return HTLEFT;if( pt.x > rcClient.right - rcSizeBox.right ) return HTRIGHT;}RECT rcCaption = m_PaintManager.GetCaptionRect();if( pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom ) {CControlUI* pControl = static_cast<CControlUI*>(m_PaintManager.FindControl(pt));if( pControl && _tcsicmp(pControl->GetClass(), _T("ButtonUI")) != 0 && _tcsicmp(pControl->GetClass(), _T("OptionUI")) != 0 &&_tcsicmp(pControl->GetClass(), _T("TextUI")) != 0 &&_tcsicmp(pControl->GetClass(), _T("SliderUI")) != 0 &&_tcsicmp(pControl->GetClass(), _T("EditUI")) != 0)return HTCAPTION;}return HTCLIENT;}

         如果要在主窗体的标题栏里响应右击消息,应该让主窗体类继承WindowImplBase类,然后重写HandleMessage函数或者直接修改WindowImplBase类的HandleMessage函数。在函数里处理WM_NCRBUTTONUP消息,我选择的是第一个方法。当发现用户右击了标题栏,就让标题栏布局向主窗体发出menu消息,剩下的就是正常处理menu消息。代码如下:


<pre code_snippet_id="459463" snippet_file_name="blog_20140827_2_9548473" name="code" class="cpp">LRESULT CFrameWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam){if (uMsg == WM_NCRBUTTONUP ){POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);<span></span>::ScreenToClient(*this, &pt);
RECT rcClient;::GetClientRect(*this, &rcClient);RECT rcCaption = m_PaintManager.GetCaptionRect();if( pt.x >= rcClient.left && pt.x < rcClient.right && pt.y >= rcClient.top && pt.y < rcCaption.bottom ) m_PaintManager.SendNotify(m_pWndTitle, DUI_MSGTYPE_MENU, 0, 0);}return __super::HandleMessage(uMsg, wParam, lParam);}

        原本我还在代码里过滤了控件,但是后来发现,在WM_NCHITTEST里面过滤了控件后就不用在WM_NCRBUTTONUP消息里另外过滤了!在WM_NCHITTEST里面过滤的控件,恰好在WM_NCRBUTTONUP消息就是不可以响应右键的,这正是我想要的。就这样可以模仿出酷狗的标题栏右键消息。


   Redrain  2014.8.27

1 0
原创粉丝点击