1 Duilib原有列表子项鼠标点击消息的弊端
Duilib中原有的列表控件UIList中的子项CListContainerElementUI
、CListLabelElementUI
的鼠标左键消息和右键消息全部都是发送的DUI_MSGTYPE_ITEMCLICK
消息,也就是说我们只能知道列表项被点击,并不能分清是左键点击还是右键点击,这在源码中也有体现,比如
if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_RBUTTONDOWN )
{
if( IsEnabled() ) {
m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMCLICK);
Select();
Invalidate();
}
return;
}
在现实的开发需求中,我们经常需要对列表中的子项进行操作,而这就经常设计为右键点击列表中的子项然后弹出菜单,如果我们不能分清是鼠标左键还是右键点击消息,就没办法进行开发,所以本文将区分列表中子项的鼠标左键和鼠标右键点击消息。
2 源码修改
2.1 修改Core/UIDefine.h
修改Core/UIDefine.h文件,在该文件中增加列表子项点击的右键消息,如下
#define DUI_MSGTYPE_ITEMRCLICK (_T("itemrclick"))
我们将这个消息定义为DUI_MSGTYPE_ITEMRCLICK
。
2.2 修改UI/UIList.cpp
修改UI/UIList.cpp,原有的子项CListContainerElementUI
的DoEvent(TEventUI& event)
函数源码如下,
void CListContainerElementUI::DoEvent(TEventUI& event)
{
if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {
if( m_pOwner != NULL ) m_pOwner->DoEvent(event);
else CContainerUI::DoEvent(event);
return;
}
if( event.Type == UIEVENT_DBLCLICK )
{
if( IsEnabled() ) {
Activate();
Invalidate();
}
return;
}
if( event.Type == UIEVENT_KEYDOWN )
{
if (IsKeyboardEnabled() && IsEnabled()) {
if( event.chKey == VK_RETURN ) {
Activate();
Invalidate();
return;
}
}
}
if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_RBUTTONDOWN )
{
if( IsEnabled() ) {
m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMCLICK);
Select();
Invalidate();
}
return;
}
if( event.Type == UIEVENT_BUTTONUP )
{
return;
}
if( event.Type == UIEVENT_MOUSEMOVE )
{
return;
}
if( event.Type == UIEVENT_MOUSEENTER )
{
if( ::PtInRect(&m_rcItem, event.ptMouse ) ) {
if( IsEnabled() ) {
if( (m_uButtonState & UISTATE_HOT) == 0 ) {
m_uButtonState |= UISTATE_HOT;
Invalidate();
}
}
}
}
if( event.Type == UIEVENT_MOUSELEAVE )
{
if( !::PtInRect(&m_rcItem, event.ptMouse ) ) {
if( IsEnabled() ) {
if( (m_uButtonState & UISTATE_HOT) != 0 ) {
m_uButtonState &= ~UISTATE_HOT;
Invalidate();
}
}
if (m_pManager) m_pManager->RemoveMouseLeaveNeeded(this);
}
else {
if (m_pManager) m_pManager->AddMouseLeaveNeeded(this);
return;
}
}
// An important twist: The list-item will send the event not to its immediate
// parent but to the "attached" list. A list may actually embed several components
// in its path to the item, but key-presses etc. needs to go to the actual list.
if( m_pOwner != NULL ) m_pOwner->DoEvent(event); else CControlUI::DoEvent(event);
}
我们将鼠标左键消息与鼠标邮件消息进行分离,修改后的DoEvent(TEventUI& event)
函数如下:
void CListContainerElementUI::DoEvent(TEventUI& event)
{
if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {
if( m_pOwner != NULL ) m_pOwner->DoEvent(event);
else CContainerUI::DoEvent(event);
return;
}
if( event.Type == UIEVENT_DBLCLICK )
{
if( IsEnabled() ) {
Activate();
Invalidate();
}
return;
}
if( event.Type == UIEVENT_KEYDOWN )
{
if (IsKeyboardEnabled() && IsEnabled()) {
if( event.chKey == VK_RETURN ) {
Activate();
Invalidate();
return;
}
}
}
if( event.Type == UIEVENT_BUTTONDOWN)
{
if( IsEnabled() ) {
m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMCLICK);
Select();
Invalidate();
}
return;
}
if (event.Type == UIEVENT_RBUTTONDOWN)
{
if (IsEnabled()) {
m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMRCLICK);
Select();
Invalidate();
}
return;
}
if( event.Type == UIEVENT_BUTTONUP )
{
return;
}
if( event.Type == UIEVENT_MOUSEMOVE )
{
return;
}
if( event.Type == UIEVENT_MOUSEENTER )
{
if( ::PtInRect(&m_rcItem, event.ptMouse ) ) {
if( IsEnabled() ) {
if( (m_uButtonState & UISTATE_HOT) == 0 ) {
m_uButtonState |= UISTATE_HOT;
Invalidate();
}
}
}
}
if( event.Type == UIEVENT_MOUSELEAVE )
{
if( !::PtInRect(&m_rcItem, event.ptMouse ) ) {
if( IsEnabled() ) {
if( (m_uButtonState & UISTATE_HOT) != 0 ) {
m_uButtonState &= ~UISTATE_HOT;
Invalidate();
}
}
if (m_pManager) m_pManager->RemoveMouseLeaveNeeded(this);
}
else {
if (m_pManager) m_pManager->AddMouseLeaveNeeded(this);
return;
}
}
// An important twist: The list-item will send the event not to its immediate
// parent but to the "attached" list. A list may actually embed several components
// in its path to the item, but key-presses etc. needs to go to the actual list.
if( m_pOwner != NULL ) m_pOwner->DoEvent(event); else CControlUI::DoEvent(event);
}
通过上述代码我们为Duilib扩展了列表子项的右键点击消息响应函数。
2.3 如何使用
在List控件的主窗口的Notify(TNotifyUI& msg)
函数中增加对消息的响应,
else if (_tcsicmp(msg.sType, _T("itemrclick")) == 0)
{
ProcessItemrclickMessage(msg);
}
然后在ProcessItemrclickMessage
函数中判断msg.pSender
的父控件是哪个List控件,然后弹出相应的菜单即可。
参考链接
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:Duilib – 为列表控件UIList添加列表子项右键点击消息响应功能
原文链接:https://www.stubbornhuang.com/2389/
发布于:2022年10月18日 10:12:36
修改于:2023年06月21日 17:57:37
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
50