按钮 Button
按钮大概是 GUI 里最"老熟人"的控件了。点击它,就会发生一些事情。在 HiEasyX 中,按钮的使用非常简单——调用 Button(),如果返回值是 true,说明这一帧用户刚刚点击了它。
Button() 返回 true 的那一帧,意味着用户完成了"按下并松开"的完整点击动作。如果用户只是按住不放,或者鼠标滑过,返回值都是 false。
函数原型
bool Button(const HXString &Title, ButtonProfile &Profile);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
Title | const HXString & | 按钮上显示的文字。使用 HXStr("文字") 或 L"文字"。 |
Profile | ButtonProfile & | 按钮的配置结构体。必须是 static 或全局变量。 |
返回值
| 类型 | 说明 |
|---|---|
bool | true —— 用户刚刚点击了按钮(按下并释放)。false —— 没有发生点击。 |
ButtonProfile 结构体
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
OnHover | bool | false | 鼠标是否正悬停在按钮上。由框架自动维护。 |
OnPressed | bool | false | 鼠标是否正在按钮上按下(未释放)。由框架自动维护。 |
OnHold | bool | false | 按钮是否处于"按住"状态。由框架自动维护。 |
OnFocus | bool | false | 按钮是否拥有焦点。由框架自动维护。 |
Size | HXPoint | {-1, -1} | 按钮尺寸。{-1, -1} 表示自动根据文字内容计算大小。 |
FontSize | int | 20 | 按钮文字的字体大小。 |
ContentGap | int | 4 | 文字与按钮边缘的内边距(仅影响自动大小)。 |
RepeatOnHold | bool | false | 是否开启长按连续触发模式。 |
RepeatInitialDelayMs | float | 400.0f | 长按后首次重复触发的延迟(毫秒)。 |
RepeatIntervalMs | float | 100.0f | 重复触发的间隔(毫秒)。 |
当 Size = {-1, -1} 时,框架会根据文字长度和 FontSize 自动计算出一个合适的宽高,并在四周留出 ContentGap 像素的内边距。如果你希望所有按钮都一样大,手动设置 Size 即可。
基本用法
最朴素的用法,就是判断返回值,然后执行逻辑:
static HX::ButtonProfile btnProfile;
if (HX::Button(HXStr("点击我"), btnProfile)) {
// 用户点击了按钮!
count++;
}
ButtonProfile 必须是 static 或全局变量。如果写成局部变量,按钮的悬停、按下、焦点状态会在每一帧重置,按钮将完全无法交互!
自动大小 vs 自定义大小
自动大小(推荐)
static HX::ButtonProfile btn;
// Size 保持默认 {-1, -1},框架自动计算
HX::Button(HXStr("自动大小"), btn);
固定大小
static HX::ButtonProfile btn;
btn.Size = {160, 50}; // 宽 160,高 50
HX::Button(HXStr("固定大小"), btn);
如果你想让所有按钮的宽高统一,建议设置一个全局的固定尺寸;如果按钮文字长短不一,自动大小会让界面看起来更自然。
长按重复触发
有时候我们需要"按住不放就持续触发"的效果,比如音量调节、滚动加速、连发攻击等。HiEasyX 的按钮原生支持这个特性:
static HX::ButtonProfile btn;
btn.RepeatOnHold = true;
btn.RepeatInitialDelayMs = 300.0f; // 按住 0.3 秒后开始连发
btn.RepeatIntervalMs = 50.0f; // 每 0.05 秒触发一次
if (HX::Button(HXStr("连发按钮"), btn)) {
// 首次点击 + 按住后的每次重复触发都会走进这里
fireBullet();
}
开启 RepeatOnHold 后,用户按下并松开的那一次会计为第一次触发,随后如果按住不放,就会按照设定的间隔持续触发。你不需要区分"单击"和"长按"——所有触发都走同一个 if 分支。
读取交互状态
如果你只是想做 UI 反馈(比如按钮被按下时变个颜色),通常不需要手动处理,因为框架会根据 HXTheme 自动渲染不同状态下的样式。
但如果你想在按钮外部根据它的状态做点什么,可以直接读 Profile 的字段:
static HX::ButtonProfile btn;
HX::Button(HXStr("状态检测"), btn);
if (btn.OnHover) {
// 鼠标正悬停在这个按钮上
}
if (btn.OnPressed) {
// 鼠标正按住这个按钮
}
if (btn.OnFocus) {
// 按钮拥有焦点(按 Tab 可以切换)
}
完整示例代码
下面是一个完整的示例,展示了普通按钮、固定大小按钮、以及长按重复触发按钮的用法。
#include <include/hex.h>
#include <include/impl/EasyX/hex_impl_easyx.h>
int main() {
initgraph(800, 600);
setbkcolor(WHITE);
cleardevice();
HX::HXInitForEasyX();
HX::SetBuffer(GetWorkingImage());
BeginBatchDraw();
// ===== 必须是 static 或全局变量 =====
static HX::WindowProfile wp;
wp.Size = {500, 400};
wp.Position = {150, 100};
static HX::ButtonProfile btnNormal;
static HX::ButtonProfile btnFixed;
btnFixed.Size = {200, 60};
static HX::ButtonProfile btnRepeat;
btnRepeat.RepeatOnHold = true;
btnRepeat.RepeatInitialDelayMs = 400.0f;
btnRepeat.RepeatIntervalMs = 100.0f;
static int clickCount = 0;
static int repeatCount = 0;
while (true) {
HX::HXBegin();
ExMessage msg;
while (peekmessage(&msg)) {
HX::PushMessage(HX::GetHXMessage(&msg));
}
HX::Window(HXStr("Button 演示"), wp);
// 普通按钮
if (HX::Button(HXStr("点我计数"), btnNormal)) {
clickCount++;
}
// 固定大小的按钮
if (HX::Button(HXStr("固定大小按钮"), btnFixed)) {
clickCount += 10;
}
// 显示计数
HX::Text(HXStr("普通点击计数: ") + std::to_wstring(clickCount));
// 长按连发按钮
if (HX::Button(HXStr("按住连发"), btnRepeat)) {
repeatCount++;
}
HX::Text(HXStr("连发计数: ") + std::to_wstring(repeatCount));
HX::End();
HX::Render();
FlushBatchDraw();
Sleep(16);
}
closegraph();
return 0;
}
新手常犯的错误是:在 Button() 返回 true 之后,又去检查 Profile.OnPressed 来做额外逻辑。其实返回值本身就告诉你"点击已发生"了,直接用 if (Button(...)) 就够了,简单清晰。
运行效果
截图占位符:请补充 $name 控件的运行效果截图。
截图占位符:请补充
Button 运行效果的运行效果截图,保存为./assets/Button_view.png。`n