XUI 快捷键:Command 统一命令、菜单 Shortcut 绑定、修饰键组合、命令分发。
XUI 热键系统基于 Command 统一命令模型:
• Command:抽象命令(保存/复制/粘贴),与触发源解耦
• Shortcut:菜单项绑定快捷键字符串("Ctrl+S")
• CommandDispatch:统一分发入口,菜单/热键/按钮触发同一命令
• 修饰键:Ctrl/Shift/Alt/Win 组合
• 焦点链:命令沿焦点链传播,直到被处理
| 函数 | 说明 |
|---|---|
int xuiCommandDispatch(pCtx, pTarget, iCmd, sCmd, pData) | 命令分发 |
int xuiDispatchEvent(pCtx, pEvent) | 键盘事件注入 |
MenuItem.sShortcut | 菜单项快捷键字符串 |
gcc -O2 -I. -o ch197.exe ch197_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch197.exe
// 命令 ID 定义
enum {
CMD_SAVE = 1001,
CMD_COPY,
CMD_PASTE,
CMD_UNDO
};
// 菜单项绑定快捷键
xui_menu_item_t tSave = { 0 };
tSave.sText = "保存";
tSave.sShortcut = "Ctrl+S";
tSave.iCommand = CMD_SAVE;
// 键盘事件 → 命令分发
void OnKeyDown(int iKey, int iMods) {
if (iKey == 'S' &&
(iMods & XGE_KEY_MOD_CTRL)) {
xuiCommandDispatch(pCtx,
NULL, CMD_SAVE, "file.save", NULL);
}
if (iKey == 'Z' &&
(iMods & XGE_KEY_MOD_CTRL)) {
xuiCommandDispatch(pCtx,
NULL, CMD_UNDO, "edit.undo", NULL);
}
}将以下代码保存为 ch197_main.c,编译后运行即可看到命令分发与快捷键系统效果:
#include "xge.h"
#include "xui.h"
#include <stdio.h>
static xui_context g_pCtx;
static xui_widget g_pLog;
static int g_iCmd = 0;
enum { CMD_SAVE = 1001, CMD_UNDO };
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x1a1a2e);
xui_vec2_t pos;
xgeMouseGet(&pos.x, &pos.y);
xuiInputPointerMove(g_pCtx, pos.x, pos.y);
if (xgeMouseDown(XGE_MOUSE_LEFT))
xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
else
xuiInputPointerUp(g_pCtx, pos.x, pos.y, 0);
/* 键盘快捷键检测 */
if (xgeKeyDown('S') && (iMods & XGE_KEY_MOD_CTRL))
xuiCommandDispatch(g_pCtx, NULL, CMD_SAVE, "file.save", NULL);
if (xgeKeyDown('Z') && (iMods & XGE_KEY_MOD_CTRL))
xuiCommandDispatch(g_pCtx, NULL, CMD_UNDO, "edit.undo", NULL);
xuiUpdate(g_pCtx, xgeGetDelta());
xuiLayout(g_pCtx);
xuiRender(g_pCtx, NULL, NULL, 0);
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 640; d.iHeight = 480;
d.sTitle = "ch197 - Shortcuts";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xuiCreate(&g_pCtx);
extern const xui_proxy_t tXgeProxy;
xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
xuiSetViewportSize(g_pCtx, 640, 480);
xui_widget pRoot;
xuiPanelCreate(g_pCtx, &pRoot, NULL);
xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 640, 480});
g_pLog = xuiLabelCreate(g_pCtx, &g_pLog, NULL);
xuiWidgetAddChild(pRoot, g_pLog);
xuiLabelSetText(g_pLog, "Press Ctrl+S / Ctrl+Z");
xuiWidgetSetRect(g_pLog, (xui_rect_t){200, 220, 240, 32});
xuiWidgetSetRect(g_pLog, (xui_rect_t){0, 0, 240, 32});
xgeRun(onFrame, NULL);
xuiDestroy(g_pCtx);
xgeUnit();
return 0;
}