跳到主要内容

按钮 Button

按钮大概是 GUI 里最"老熟人"的控件了。点击它,就会发生一些事情。在 HiEasyX 中,按钮的使用非常简单——调用 Button(),如果返回值是 true,说明这一帧用户刚刚点击了它。

返回值的理解

Button() 返回 true那一帧,意味着用户完成了"按下并松开"的完整点击动作。如果用户只是按住不放,或者鼠标滑过,返回值都是 false


函数原型

bool Button(const HXString &Title, ButtonProfile &Profile);

参数说明

参数类型说明
Titleconst HXString &按钮上显示的文字。使用 HXStr("文字")L"文字"
ProfileButtonProfile &按钮的配置结构体。必须是 static 或全局变量

返回值

类型说明
booltrue —— 用户刚刚点击了按钮(按下并释放)。
false —— 没有发生点击。

ButtonProfile 结构体

字段类型默认值说明
OnHoverboolfalse鼠标是否正悬停在按钮上。由框架自动维护
OnPressedboolfalse鼠标是否正在按钮上按下(未释放)。由框架自动维护
OnHoldboolfalse按钮是否处于"按住"状态。由框架自动维护
OnFocusboolfalse按钮是否拥有焦点。由框架自动维护
SizeHXPoint{-1, -1}按钮尺寸。{-1, -1} 表示自动根据文字内容计算大小。
FontSizeint20按钮文字的字体大小。
ContentGapint4文字与按钮边缘的内边距(仅影响自动大小)。
RepeatOnHoldboolfalse是否开启长按连续触发模式。
RepeatInitialDelayMsfloat400.0f长按后首次重复触发的延迟(毫秒)。
RepeatIntervalMsfloat100.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