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



使用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. 高级I/O函数

    给套接口上的I/O设置超时 1.调用alarm,在调用超过指定时间时产生SIGALARM信号,这涉及到信号处理,而且可能和进程中其他的alarm冲突 2.使用select阻塞在等待I/O上,selec ...

  2. window窗口操作

    打开新窗口 window.open([url],[窗口名称],[参数字符串]) window.open("http://baidu.com","_balnk", ...

  3. 什么是J2EE的集群?

    1. 前言         现在有越来越多的关键应用和大型应用是基于J2EE 来创建的,像银行系统和帐单系统这些关键应用要求有很高的可用性,而Google 和Yahoo 这样的大型应用就需要很好的可扩 ...

  4. MySQL数据表查询操

    准语法结构:编写DQL时一定要严格按照此语法的顺序来实现!/* SELECT [ALL | DISTINCT] ALL表示查询出所有的内容 DISTINCT 去重 {* | 表名.* | 表名.字段名 ...

  5. background及background-size

    background有以下几种属性: background-color background-position background-size background-repeat background ...

  6. 自己对WEBGL坐标系的转换过程的理解【如图】

  7. HDU-6217 BBP Formula 脑洞

    题目链接:https://cn.vjudge.net/problem/HDU-6217 题意 已知: \[ \pi = \sum_{k=0}^{\infty }\frac{1}{16^{k}}(\fr ...

  8. 猫狗分类--Tensorflow实现

    贴一张自己画的思维导图  数据集准备 kaggle猫狗大战数据集(训练),微软的不需要FQ 12500张cat 12500张dog 生成图片路径和标签的List step1:获取D:/Study/Py ...

  9. Ubuntu启动流程

    网上很多Linux的启动流程图,也有Ubuntu早期版本的启动流程介绍,却少有近期版本的启动流程介绍(16.04).这里作出总结归纳. Linux系统采用的是RedHat启动方式,启动流程如下: Ub ...

  10. sso 登录业务逻辑