菜单栏 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();
参数说明
MenuBarProfile
菜单栏的外观由这个资料结构体统一控制:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
BarHeight | int | 28 | 顶部菜单栏的高度。 |
ItemHeight | int | 28 | 每个菜单项(一行文字)的高度。 |
FontSize | int | 20 | 菜单文字字体大小。 |
SeparatorHeight | int | 8 | 分隔线占据的垂直空间。 |
各函数参数
| 函数 | 参数 | 说明 |
|---|---|---|
BeginMenu | Label | 菜单名称,例如 HXStr("文件")。返回 bool 表示该菜单是否正被展开。 |
MenuItem | Title | 菜单项显示的文本,例如 HXStr("打开")。 |
Selected | 是否显示左侧勾选标记,用于“开关型”选项。 | |
Enabled | 是否可用。设为 false 时文字变灰,不可点击。 |
BeginMenu 的返回值
BeginMenu 返回 bool:只有当用户点击或悬停展开该菜单时,才返回 true。和 TabItem 一样,你可以把菜单内容包在 if 里,没展开的菜单不会执行内部逻辑。
返回值
| 函数 | 返回值 | 说明 |
|---|---|---|
BeginMenu | bool | 该菜单当前是否展开。 |
MenuItem | bool | 该菜单项在本帧被点击。是则执行业务逻辑。 |
| 其他 | 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 会自动向下推移后续控件的布局基线,你像平常一样放控件即可,它们会自然地出现在菜单栏下方。