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

72 篇文章 87 订阅
21 篇文章 10 订阅

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

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


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

duilib是一个基于C++的轻量级GUI库,它提供了丰富的控件和界面开发工具,方便开发者快速构建界面。其中,duilib提供了自绘标题栏的功能,使得开发者可以自定义标题栏的样式和交互行为。 要实现duilib的自绘标题栏,首先需要在XML布局文件中定义标题栏控件。通过设置标题栏的位置、大小和属性等,将其嵌入到主窗口的布局中。 然后,需要在代码中继承duilib提供的类,并重写标题栏的绘制函数。在绘制函数中,可以使用GDI+或者其他绘图工具进行自定义的绘制。例如,可以根据设计需求绘制背景图案、按钮、文本等。 同时,还可以为标题栏添加交互行为。通过重写相应的事件处理函数,实现对标题栏的拖拽、最小化、最大化、关闭等操作。可以根据需要添加点击、移动、释放等事件的处理逻辑,实现标题栏的交互功能。 最后,在主窗口的代码中,通过调用duilib提供的API将标题栏控件与相应的绘制类和事件处理类进行关联。这样,当主窗口加载时,duilib会自动调用对应的绘制函数和事件处理函数,完成自绘标题栏的效果。 总之,使用duilib自绘标题栏可以灵活定制应用程序的界面风格,提升用户体验。开发者可以根据需要自定义标题栏的样式和交互行为,以满足不同项目的需求。同时,通过duilib提供的API和工具,实现自绘标题栏也是相对简单和高效的。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值