我为我的gamedev项目制作了一个非常小的游戏内GUI库,但我找不到处理焦点的干净方法。
我的库支持嵌套的ListBoxes和小部件层次结构,但在处理小部件焦点时,我似乎无法找到防止奇怪行为的方法。示例表格:
|------------|
| Form [X] |
|------------|
| |
| [Button01] |
| |
| [List1][v] |
| |
| [Button02] |
| |
|------------|
我的设计有一个Context
对象,用于存储Widget
个对象的列表。 Widget
可以有任意数量的孩子。我有设施来递归迭代Widget
的所有孩子/父母。
目前我的焦点逻辑是:
如果上下文繁忙(拖动,调整大小,编辑......),请不要更改焦点
如果在上下文之外按下鼠标或上下文未聚焦,请将所有内容取消聚焦
找到最受压迫的孩子,如果有的话
找到"最深的"在层次结构中按下了孩子
将小部件以外的所有内容展开,与最深的孩子一样深,然后关注上下文
然而,这在许多情况下都失败了,特别是对于嵌套列表和TextBoxes。我试图在网上找到一个好的解决方案,但无法找到任何文章/教程。我不确定是否应该专注于特殊小部件,或者是否有一个好的"算法在任何情况下都能正常工作。
GUI库如何处理小部件焦点?
是否有特殊说明可以专门关注ListBoxes或ComboBoxes等小部件?
这是我的GUI库的source code和video here。
答案 0 :(得分:2)
我建议定义一个像数据结构一样的树,它将节点定义为数据(窗口句柄,bool isFocus和一些额外的数据)以及几个指向节点的指针 - 父节点,第一个子节点,左兄弟节点,右兄弟节点。此外,将节点指针存储在窗口数据区域中,以便从给定的窗口句柄中检索节点指针。从节点指针,无论如何数据都会给你窗口句柄。现在,只要根窗口失去焦点,因为您在其他应用程序上单击了鼠标或按下alt + tab或其他内容,主窗口就会失去焦点并且您会获得相应的kill focus消息。处理窗口句柄,重置节点树的所有isFocus。无论何时单击某个窗口,都会获得gainfocus消息,从窗口句柄中找出节点,将isFocus设置为true。并将其所有父nide的isFocus设置为true,直到到达顶级节点(root)。这有帮助吗?
答案 1 :(得分:1)
我不知道任何UI算法或UI的正确方法,但是很久以前我确实实现了一个通用的UI库(不是最好的但它服务于它的目的) ),也许使用的方法可以满足您的需求。
为了处理从父母到孩子的事件,使用了两个函数,其中包含以下原型:
int handleEventReceived(int eventType, void* data);
int getEventConsumers(int eventType, vector<IConsumers*>& consumers);
在枚举中找到了Ofc eventTypes。
在所有子节点中实现第一个函数时,可以使用递归函数将事件分派给每个子节点和子节点(所以广播)。 当孩子回答事件时,它返回0,否则返回一些错误代码(例如ERRROR_EVENT_NOT_TREATED)。
但是,如果您只希望UI的特定部分响应某个事件,则使用第二个功能。
第二个函数返回&#34;最大响应优先级&#34; ,以及与此优先级相关的消费者。例如,如果您的包含3个优先级为5的按钮和优先级为6的2个按钮,它将返回6和包含两个按钮的数组,您可以将该事件发送到该按钮。
在您的情况下,您说您需要处理子组件的焦点。使用上述方法,我将创建一个事件ET_FOCUS_RECEIVED,并根据需要在每个UI元素上为此事件添加不同的优先级。
在您的情况下,如果您将事件优先级随着元素在层次结构中更深入而增加,则来自相同深度的元素将具有相同的优先级(因此,与最深的子项一样深的小部件都将处理该事件)。