本节向大家介绍一下右键弹出菜单是如何实现的。效果如下,在窗口中点击鼠标右键弹出菜单,点击菜单项能够响应菜单点击事件。



使用Duilib库实现的弹出菜单,实际上也是一个Windows窗口,因此我们需要创建两个窗口(主窗口和菜单窗口),然后响应主窗口的鼠标右键点击事件,在主窗口右键点击事件的响应函数中获取鼠标位置,將菜单窗口的位置调整为当前鼠标位置,同时把窗口设置为显示即可。

菜单窗口的xml布局文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<Window bktrans="true" size="120,102">
<Font name="宋体" size="13" bold="false"/>
<Font name="宋体" size="12"/>
<VerticalLayout bkimage="file='menu_bk.png' corner='40,8,8,8'" hole="false">
<List header="hidden" inset="8,8,8,8" itemhotimage="file='menu_hot_bk.png' corner='2,2,2,2'" itemdisabledbkcolor="#20000000">
<ListContainerElement name="menu_Open" height="22" inset="40,0,0,0">
<Label text="打开" mouse="false"/>
</ListContainerElement>
<ListContainerElement name="menu_Mark" height="22" inset="40,0,0,0">
<Label text="标注" mouse="false"/>
</ListContainerElement>
<ListContainerElement name="menu_Delete" height="22" inset="40,0,0,0">
<Label text="删除" mouse="false"/>
</ListContainerElement>
<ListContainerElement name="menu_Test" height="22" inset="40,0,0,0">
<Label text="测试" mouse="false"/>
</ListContainerElement>
</List>
</VerticalLayout>
</Window>

我们需要编写一个菜单窗口类继承WindowImplBase来加载xml界面。和上节不同的是我们把这个类的声明和成员函数的定义放在一个单独的头文件中,这样代码容易维护一些。新建头文件MenuWnd.h:

#ifndef _MENUWND_H__
#define _MENUWND_H__
#include "win_impl_base.hpp"
#include <Windows.h>
class MenuWnd : public WindowImplBase
{
LPCTSTR GetWindowClassName() const
{
return L"MenuWnd";
}
UINT GetClassStyle() const{
return UI_CLASSSTYLE_FRAME|CS_DBLCLKS;
}
tString GetSkinFile(){
return L"tutorial6_menu.xml";
}
void Notify(TNotifyUI& msg)
{
if(msg.sType == L"itemclick")
{
//响应菜单事件
::MessageBox(NULL,L"hello",L"hello",MB_OK);
this->ShowWindow(false);
}
} };
#endif

接下来是主窗口,主窗口的xml界面布局文件内容和上节相同,仅仅是主窗口类的定义有些变化,我们同样把主窗口类的声明和定义放在一个单独的头文件MyWnd.h中:

#ifndef _MYWND_H__
#define _MYWND_H__
#include "win_impl_base.hpp"
#include "MenuWnd.h"
#include <Windows.h>
class MyWnd : public WindowImplBase
{
public:
MyWnd()
{
pMenu = new MenuWnd();
pMenu->Create(m_hWnd,L"Menu",WS_POPUP,WS_EX_TOOLWINDOW);
pMenu->ShowWindow(false);
}
LPCTSTR GetWindowClassName() const
{
return L"MyWnd";
}
UINT GetClassStyle() const{
return UI_CLASSSTYLE_FRAME|CS_DBLCLKS;
}
tString GetSkinFile(){
return L"tutorial6.xml";
}
void Notify(TNotifyUI& msg)
{
if(msg.sType == L"click")
{
if(msg.pSender->GetName() == L"CloseBtn")
{
::PostQuitMessage(0); }else if(msg.pSender->GetName() == L"MinBtn")
{
::SendMessage(m_hWnd,WM_SYSCOMMAND, SC_MINIMIZE, 0);
}
}
}
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_RBUTTONDOWN:
OnRButtonDown(wParam,lParam);
return 0;
default:
return WindowImplBase::HandleMessage(uMsg,wParam,lParam);
}
}
void OnRButtonDown(WPARAM wParam, LPARAM lParam)
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
POINT pt = {xPos,yPos};
ClientToScreen(m_hWnd,&pt);
pMenu->ShowWindow(true);
::SetWindowPos(pMenu->GetHWND(), NULL, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
}
LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
//获取鼠标点击位置
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
//將位置转换为屏幕坐标
POINT pt = {xPos,yPos};
ClientToScreen(m_hWnd,&pt); RECT menuWndRect = {0};
::GetWindowRect(pMenu->GetHWND(),&menuWndRect); if(pt.x <= menuWndRect.left || pt.x >= menuWndRect.right
|| pt.y <= menuWndRect.top || pt.y >= menuWndRect.bottom)
{
pMenu->ShowWindow(false);
}
bHandled = FALSE;
return 0;
} private:
MenuWnd* pMenu; };
#endif

在主窗口类中定义一个MenuWnd指针类型的成员变量,在构造函数中创建菜单窗口设置显示风格为隐藏,重写父类的HandleMessage函数,响应主窗口鼠标右键点击事件,在右键点击事件的响应函数中重新设置菜单位置,并把窗口显示风格设置为显示。

最后在WinMain函数中创建并显示主窗口:

//tutorial6.cpp
#include <Windows.h>
#include "MyWnd.h"
INT WinMain(HINSTANCE hInst,HINSTANCE hPreInst,LPSTR lpCmdLine,INT Show)
{
CPaintManagerUI::SetInstance(hInst);
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetResourcePath());
//创建主窗口
MyWnd* pFrame = new MyWnd();
pFrame->Create(NULL,L"Tutorial6",UI_WNDSTYLE_FRAME,WS_EX_WINDOWEDGE);
pFrame->CenterWindow();
pFrame->ShowWindow(true);
CPaintManagerUI::MessageLoop(); return 0;
}

博文源码:https://github.com/rongbo-j/duilib-tutorial

(参考tutorial6工程)

DirectUI界面编程(六)实现右键弹出菜单的更多相关文章

  1. vc++ 如何添加右键弹出菜单

    一.创建新工程 二.编辑菜单资源 1.添加菜单 按"Ctrl+R",双击"Menu"图标 2.于菜单编辑器内编辑菜单 四.添加代码(红色部分) void CCM ...

  2. win32进阶之路:程序托盘图标+右键弹出菜单

     开场白 本次介绍两个非常棒且实用的技巧:程序托盘图标和右键弹出菜单,效果如下图. 程序托盘图标用了迅雷的图标,右键点击时候会弹出三个选项的菜单. 程序托盘图标设置 我会用尽可能清晰明了的步骤介绍方式 ...

  3. Vue2的右键弹出菜单(vue-contextmenu)

    给大家推荐一个基于Vue2的右键弹出菜单插件,支持单一SPA页面以及可以在循环绑定中使用. 项目地址为:https://github.com/chIIC/vue-...demo1: 父组件绑定右键事件 ...

  4. 关于MFC主菜单和右键弹出菜单

    一.主菜单.弹出菜单和右键菜单的概念: 主菜单是窗口顶部的菜单,一个窗口或对话框只能有一个主菜单,但是主菜单可以被更改(SetMenu()更改): 创建方式:CMenu::CreateMenu(voi ...

  5. SWT中的Tree中 添加右键弹出菜单

    先看一下效果: 如图:在树上单击鼠标右键会弹出 弹出式菜单.做法其实很简单,先做一个树: final TreeViewer treeViewer = new TreeViewer(group, SWT ...

  6. js+css实现带缓冲效果右键弹出菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. QT 右键弹出菜单

    QWidget及其子类都可有右键菜单 1.设置标志 在widget初始化的时候 setContextMenuPolicy(Qt::CustomContextMenu); 设置为自定义菜单模式 2.在需 ...

  8. Win32建立右键弹出菜单(PopMenu)

    自定义右键菜单: #ifndef _CONTEXTMENU_H_ #define _CONTEXTMENU_H_ #include <windows.h> //动态菜单 #define I ...

  9. Qt编程之对QGraphicsItem点击右键弹出菜单

    就是对这个contextMenuEvent 事件重新实现,在这个事件函数中创建菜单,大概就是这样. void MyItem::contextMenuEvent(QGraphicsSceneContex ...

随机推荐

  1. WinRAR 5.60 无广告正式版

    首先明确WinRAR唯一的官网是这个 https://www.rarlab.com/ 其余的都不要相信. 现在的问题是:不要脸的中国代理强行捆绑广告:即使你花钱注册同样要面对弹窗广告!这就不可接受了! ...

  2. 用JS解决Asp.net Mvc返回JsonResult中DateTime类型数据格式的问题

    当用ajax异步时,返回JsonResult格式的时候,发现当字段是dateTime类型时,返回的json格式既然是“/Date(1435542121135)/” 这样子的,当然这不是我们想要的格式. ...

  3. PHP Base64 加密 & 解密

    <?php 加密: $cany = 'getshell.top'; #定义要加密的字符串 echo base64_encode($cany); #输出加密后的字符串 解密: $cany = 'Z ...

  4. Docker镜像的备份和恢复

    备份: docker save -o [tar包真实路径] [镜像名 ] 如:docker save -o /usr/docker_data/mongo-backup.tar mongo   导出: ...

  5. java 1.8 内存告警问题

    Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=512m; support was removed in 8.0 ...

  6. MySQL-----笔记3:存储引擎

    1.存储引擎: https://zhidao.baidu.com/question/1049565846666168579.html MySQL中的数据用各种不同的技术存储在文件(或者内存)中.这些技 ...

  7. git入坑随笔

    一直以来,都喜欢用git做版本管理,主要涉及平台是coding, github以及公司自己搭建的gitlab. 因为一直以来都是自己一个人维护前端的项目,所以基本上很少有冲突的情况.(手动微笑 :) ...

  8. [洛谷 P1967] 货车运输 (最大生成树 lca)

    题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...

  9. adb简单使用

    一.基本命令 1.查看目前连接的设备/虚拟器的状态 adb devices

  10. uni-app 之验证码

    手机APP---验证码 最近公司在开发手机APP,app避不可免的就是登录了,emmmm 登录验证码那必须的是有的,我们公司发给我们的图片是酱紫的~~ 这个要求大家应该都能看懂,做这个手机号啊,验证码 ...