xuiHitTest:坐标 → 控件查找、标志位控制、层优先级、穿透与裁剪。
命中测试(HitTest)将屏幕坐标映射到控件:
• xuiHitTest:给定 (x, y) 返回最上层命中控件
• 层优先:从最高层(DEBUG)向最低层(NORMAL)搜索
• 标志位:控制是否穿透透明区域、是否包含禁用控件
• 裁剪:被父控件裁剪的区域不命中
• 用途:拖拽 Drop 判定、右键菜单定位、调试拾取
| 函数 | 说明 |
|---|---|
xui_widget xuiHitTest(pCtx, fX, fY, iFlags) | 坐标命中测试 |
gcc -O2 -I. -o ch198.exe ch198_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch198.exe
// 鼠标右键按下时
void OnRightClick(float fX, float fY) {
// 命中测试:找到鼠标下的控件
xui_widget pHit = xuiHitTest(pCtx,
fX, fY, 0);
if (pHit) {
// 根据控件类型弹出不同菜单
int iType = xuiWidgetGetType(pHit);
if (iType == xuiListViewGetType(pCtx)) {
ShowListContextMenu(pHit, fX, fY);
} else if (iType ==
xuiCanvasGetType(pCtx)) {
ShowCanvasContextMenu(pHit, fX, fY);
}
}
}
// 拖拽 Drop 判定
void OnDragEnd(float fX, float fY) {
xui_widget pTarget = xuiHitTest(pCtx,
fX, fY, 0);
if (pTarget && CanAcceptDrop(pTarget)) {
PerformDrop(pTarget);
}
}将以下代码保存为 ch198_main.c,编译后运行即可看到命中测试与控件拾取效果:
#include "xge.h"
#include "xui.h"
#include <stdio.h>
static xui_context g_pCtx;
static xui_widget g_pInfo;
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);
/* 实时命中测试 */
xui_widget pHit = xuiHitTest(g_pCtx, pos.x, pos.y, 0);
char buf[128];
sprintf(buf, "Hit: %s", pHit ? "widget" : "none");
xuiLabelSetText(g_pInfo, buf);
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 = "ch198 - HitTest";
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});
xui_widget pBtn;
xuiButtonCreate(g_pCtx, &pBtn, NULL);
xuiWidgetAddChild(pRoot, pBtn);
xuiLabelSetText(pBtn, "Target");
xuiWidgetSetRect(pBtn, (xui_rect_t){240, 140, 160, 48});
xuiWidgetSetRect(pBtn, (xui_rect_t){0, 0, 160, 48});
g_pInfo = xuiLabelCreate(g_pCtx, &g_pInfo, NULL);
xuiWidgetAddChild(pRoot, g_pInfo);
xuiLabelSetText(g_pInfo, "Move mouse over button");
xuiWidgetSetRect(g_pInfo, (xui_rect_t){200, 240, 240, 32});
xuiWidgetSetRect(g_pInfo, (xui_rect_t){0, 0, 240, 32});
xgeRun(onFrame, NULL);
xuiDestroy(g_pCtx);
xgeUnit();
return 0;
}