用Easyx图形库实现类似windows下拉菜单系统
编译环境:Vs2019 + Easyx图形库
DropDownMenu.h
const int MenuBarHeight = 24; // 菜单栏高度
const int MenuBarWidth = 60; // 菜单栏宽度
struct MenuItem {
std::string text; // 菜单文本
std::vector<MenuItem> subItems; // 二级菜单项
RECT rect; // 菜单项位置和尺寸
bool isSubMenu; // 是否为二级菜单
};
class DropdownMenu {
private:
std::vector<MenuItem> mainMenu; // 主菜单项
int activeMainMenu; // 当前激活的主菜单索引
int activeSubMenu; // 当前激活的二级菜单索引
bool showSubMenu; // 是否显示二级菜单
bool m_enable; // 菜单是否能操作
COLORREF backgroundColor;
COLORREF textColor;
COLORREF mainhoverbkColor;
COLORREF mainhovertextColor;
COLORREF subhoverbkColor;
COLORREF subhovertextColor;
COLORREF borderColor;
// 检查鼠标是否在菜单区域内(包括主菜单和二级菜单)
bool isMouseInMenuArea(int mouseX, int mouseY) {
// 检查主菜单
for (size_t i = 0; i < mainMenu.size(); ++i) {
if (InSide(mouseX, mouseY, mainMenu[i].rect)) {
return true;
}
}
// 检查当前显示的二级菜单
if (showSubMenu && activeMainMenu >= 0) {
RECT r = mainMenu[activeMainMenu].subItems[0].rect;
r.bottom = r.bottom + ((int)mainMenu[activeMainMenu].subItems.size() - 1) * MenuBarHeight;
if (InSide(mouseX, mouseY, r)) {
return true;
}
}
return false;
}
public:
DropdownMenu() :activeMainMenu(-1), activeSubMenu(-1), showSubMenu(false), m_enable(true) {
// 初始化颜色
backgroundColor = RGB(222, 227, 243);
textColor = BLUE;
mainhoverbkColor = RGB(75,0,96);
mainhovertextColor = RGB(82,255,255);
subhoverbkColor = RGB(159,0,90);
subhovertextColor = WHITE;
borderColor = RGB(213, 194, 176);
// 主菜单项
mainMenu = {
{"游戏(G)", {{"开局 F2"}, {"撤销 "}, {"提示 F1"}, {"退出 ESC"}}, {0, 0, MenuBarWidth, MenuBarHeight}, true},
{"设置(S)", {{"播放音乐 "},{"显示动画 "}, {"显示辅助 "}},{MenuBarWidth,0,2 * MenuBarWidth,MenuBarHeight},true},
{"帮助(H)", {{"游戏说明 "}, {"关于FreeCell "}}, {2 * MenuBarWidth, 0, 3 * MenuBarWidth, MenuBarHeight}, true},
};
for (int i = 0; i < (int)mainMenu.size(); i++) {
for (int j = 0; j < (int)mainMenu[i].subItems.size(); j++) {
mainMenu[i].subItems[j].rect = { mainMenu[i].rect.left + 10,mainMenu[i].rect.bottom + j * MenuBarHeight - 1, //偏移一点以免从一级菜单移动到二级菜单时检测不到
mainMenu[i].rect.left + 120,mainMenu[i].rect.bottom + (j + 1) * MenuBarHeight - 1 };
}
}
}
void Draw()
{
settextstyle(20, 0, "微软雅黑");
setbkmode(TRANSPARENT);
// 绘制主菜单
for (size_t i = 0; i < mainMenu.size(); i++) {
setlinecolor(borderColor);
// 绘制背景
if (activeMainMenu == i) {
setfillcolor(mainhoverbkColor);
settextcolor(mainhovertextColor);
}
else {
setfillcolor(backgroundColor);
settextcolor(textColor);
}
fillrectangle(mainMenu[i].rect.left, mainMenu[i].rect.top, mainMenu[i].rect.right, mainMenu[i].rect.bottom);
// 绘制文字
drawtext((LPCSTR)mainMenu[i].text.c_str(), &mainMenu[i].rect, DT_VCENTER | DT_SINGLELINE | DT_CENTER);
}
// 绘制二级菜单
if (showSubMenu && activeMainMenu >= 0) {
for (size_t i = 0; i < mainMenu[activeMainMenu].subItems.size(); i++) {
if (activeSubMenu == i) {
setfillcolor(subhoverbkColor);
settextcolor(subhovertextColor);
}
else {
setfillcolor(backgroundColor);
settextcolor(textColor);
}
fillrectangle(mainMenu[activeMainMenu].subItems[i].rect.left, mainMenu[activeMainMenu].subItems[i].rect.top, mainMenu[activeMainMenu].subItems[i].rect.right, mainMenu[activeMainMenu].subItems[i].rect.bottom);
drawtext((LPCSTR)(" " + mainMenu[activeMainMenu].subItems[i].text).c_str(), &mainMenu[activeMainMenu].subItems[i].rect, DT_VCENTER | DT_SINGLELINE);
}
}
}
// 处理事件
void handleEvent(ExMessage& msg) {
if (!m_enable) return;
if (msg.message == WM_LBUTTONDOWN && activeMainMenu >= 0 && activeSubMenu >= 0)
{
msg.x = 0; msg.y = 0;
int i = activeMainMenu;
int j = activeSubMenu;
activeMainMenu = -1;
activeSubMenu = -1;
showSubMenu = false;
FlushBatchDraw();
// 运行回调函数,可能需要i,j,上面的代码放下面画面会延迟更新
callback(i, j);
}
if (msg.message == WM_MOUSEMOVE) {
// 检查鼠标是否在菜单区域内
bool mouseInMenu = isMouseInMenuArea(msg.x, msg.y);
if (!mouseInMenu)
{
activeMainMenu = -1;
activeSubMenu = -1;
showSubMenu = false;
return;
}
for (int i = 0; i < (int)mainMenu.size(); i++) {
if (InSide(msg.x, msg.y, mainMenu[i].rect))
{
activeMainMenu = i;
showSubMenu = true;
}
}
if (showSubMenu && activeMainMenu >= 0) {
for (int i = 0; i < (int)mainMenu[activeMainMenu].subItems.size(); i++) {
if (InSide(msg.x, msg.y, mainMenu[activeMainMenu].subItems[i].rect)) {
activeSubMenu = i;
}
}
}
}
if (msg.message == WM_KEYDOWN) {
if (msg.vkcode == VK_ESCAPE) callback(0, 3);
if (msg.vkcode == VK_F1) callback(0, 2);
if (msg.vkcode == VK_F2) callback(0, 0);
}
}
// 修改子菜单的标题文字
void ChangeSubMenuText(int MainID, int SubID, const string& text)
{
mainMenu[MainID].subItems[SubID].text = text;
Draw();
}
// 设置菜单启用状态
void SetEanble(bool isEnable) {
m_enable = isEnable;
backgroundColor = m_enable ? RGB(222, 227, 243) : RGB(222, 222, 222);
textColor = m_enable ? RGB(0, 0, 0) : RGB(213, 194, 176);
}
void(*callback)(int MainID, int SubID);
};

浙公网安备 33010602011771号