zoukankan      html  css  js  c++  java
  • 仿酷狗音乐播放器开发日志二十六 duilib在标题栏弹出菜单的方法

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

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


           本以为像上一片博客那样,处理标题栏的布局的右键消息就可以了。后来发现在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消息。代码如下:

    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);
    
    		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

  • 相关阅读:
    linux查看python安装位置
    Linux 重命名
    Linux 解压 压缩文件
    linux下文件的复制、移动与删除
    设计模式-命令模式
    设计模式-心得
    设计模式-责任链模式
    ajax跨域问题以及解决方案
    强者运强
    管理者法则
  • 原文地址:https://www.cnblogs.com/redrainblog/p/3946584.html
Copyright © 2011-2022 走看看