跳到主要内容

菜单栏 MenuBar

菜单栏是桌面软件的经典导航方式:顶部一条横杆,点击后下拉出一层层选项。HiEasyX 的 MenuBar 支持无限级嵌套、分隔线和禁用项,足以撑起一个正经的编辑器或 IDE。

函数原型

菜单栏由三层 API 组成:栏本身、菜单、以及菜单项。

// 菜单栏容器
void BeginMenuBar();
void EndMenuBar();

// 下拉菜单(可嵌套)
bool BeginMenu(const HXString &Label);
void EndMenu();

// 菜单里的具体选项
bool MenuItem(const HXString &Title, bool Selected = false, bool Enabled = true);

// 分隔线
void MenuSeparator();

参数说明

菜单栏的外观由这个资料结构体统一控制:

字段类型默认值说明
BarHeightint28顶部菜单栏的高度。
ItemHeightint28每个菜单项(一行文字)的高度。
FontSizeint20菜单文字字体大小。
SeparatorHeightint8分隔线占据的垂直空间。

各函数参数

函数参数说明
BeginMenuLabel菜单名称,例如 HXStr("文件")。返回 bool 表示该菜单是否正被展开。
MenuItemTitle菜单项显示的文本,例如 HXStr("打开")
Selected是否显示左侧勾选标记,用于“开关型”选项。
Enabled是否可用。设为 false 时文字变灰,不可点击。
BeginMenu 的返回值

BeginMenu 返回 bool:只有当用户点击或悬停展开该菜单时,才返回 true。和 TabItem 一样,你可以把菜单内容包在 if 里,没展开的菜单不会执行内部逻辑。

返回值

函数返回值说明
BeginMenubool该菜单当前是否展开。
MenuItembool该菜单项在本帧被点击。是则执行业务逻辑。
其他void

完整示例

#include <include/hex.h>
#include <include/impl/EasyX/hex_impl_easyx.h>

// 全局配置(可选,通常用默认即可)
static HX::MenuBarProfile g_menuBarProfile;

int main() {
static HX::WindowProfile wp;
while (true) {
HX::HXBegin();
ExMessage msg;
while (peekmessage(&msg)) {
HX::PushMessage(HX::GetHXMessage(&msg));
}

HX::Window(HXStr("MenuBar 示例"), wp);

HX::BeginMenuBar();
{
// ---- 文件菜单 ----
if (HX::BeginMenu(HXStr("文件"))) {
if (HX::MenuItem(HXStr("新建"))) {
// 用户点击了“新建”
MessageBoxW(nullptr, L"新建文件", L"提示", MB_OK);
}
if (HX::MenuItem(HXStr("打开"))) {
// 处理打开...
}
if (HX::MenuItem(HXStr("保存"), false, false)) {
// Enabled = false,这里不会触发
}

HX::MenuSeparator();

if (HX::MenuItem(HXStr("退出"))) {
return 0;
}
HX::EndMenu();
}

// ---- 编辑菜单(带勾选) ----
if (HX::BeginMenu(HXStr("编辑"))) {
static bool showGrid = true;
if (HX::MenuItem(HXStr("显示网格"), showGrid)) {
showGrid = !showGrid; // 切换勾选状态
}
HX::EndMenu();
}

// ---- 帮助菜单(嵌套子菜单) ----
if (HX::BeginMenu(HXStr("帮助"))) {
if (HX::MenuItem(HXStr("文档"))) {
// 打开文档...
}

if (HX::BeginMenu(HXStr("更多"))) {
if (HX::MenuItem(HXStr("关于"))) {
// 弹出关于对话框...
}
HX::EndMenu();
}

HX::EndMenu();
}
}
HX::EndMenuBar();

// 菜单栏下面的主内容区
HX::Text(HXStr("这里是主窗口内容..."));

HX::End();
HX::Render();
}

return 0;
}
嵌套菜单

BeginMenu 可以套在另一个 BeginMenu 里,形成无限级联菜单。不过为了用户体验,建议不要超过两级。三级以上的菜单用户找起来会很痛苦。

菜单栏必须在 Window 内最顶部

BeginMenuBar / EndMenuBar 应该紧跟在 Window 之后、其他控件之前。如果你先放了一个 Button,再调 BeginMenuBar,菜单栏可能会和按钮重叠,视觉效果会很糟糕。

禁用项与勾选项

MenuItem 的后两个参数非常实用:

// 禁用项:灰色,不可点击
HX::MenuItem(HXStr("保存"), false, false);

// 勾选项:左侧有一个小勾,点击后会取消勾选
static bool isChecked = true;
if (HX::MenuItem(HXStr("自动保存"), isChecked)) {
isChecked = !isChecked;
}

常见疑问

Q:可以做右键菜单吗? MenuBar 是固定在窗口顶部的水平菜单。如果你需要右键弹出的上下文菜单,请使用 PopupMenu 控件,它的 API 更适合浮动菜单场景。

Q:菜单栏的高度被占用了,我的布局需要手动偏移吗? 不需要。HiEasyX 的 BeginMenuBar 会自动向下推移后续控件的布局基线,你像平常一样放控件即可,它们会自然地出现在菜单栏下方。