• 仿酷狗音乐播放器开发日志二十六 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

  • 相关阅读:
    快速查询 jsp页面 和 js方法
    order by 特定字段放在特定的位置
    eclipse中将java项目变成web项目
    Eclipse导入项目:No projects are found to import
    解决【Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modul】报错问题
    ORA-24247:网络访问被访问控制列表(ACL)拒绝器
    Oracle 使用UTL_HTTP发送http请求--转载
    Oracle ACL (Access Control List) 详细介绍
    PLSQL中&符号处理
    windows oracle11gR2安装使用
  • 原文地址:https://www.cnblogs.com/redrainblog/p/3946584.html
Copyright © 2020-2023  润新知