GUI_emWin 切换控件的焦点
Contents
起因
带键盘的嵌入式设备(工控面板、遥控器操作的界面)没有鼠标和触摸,或者触摸只是辅助——用户在对话框里填完一个编辑框,要靠按键跳到下一个控件。这就要求程序能控制“焦点”:焦点在哪个控件上,按键就作用在哪个控件上。emWin 对此有一套现成机制,这篇把机制和用法整理清楚。
需求
- 在对话框中把焦点设到指定控件(比如开机后默认聚焦第一个输入框)
- 用按键在控件间前后切换焦点(TAB 下一个 / BACKTAB 上一个)
- 判断当前焦点落在哪个控件上,做条件处理
技术实现原理
焦点的本质:键盘消息的路由
emWin 的窗口管理器给每个窗口维护一个“是否拥有输入焦点”的状态,同一时刻一个对话框里只有一个控件持有焦点。键盘消息的目标窗口就是焦点窗口:GUI_SendKeyMsg() 把键值发往当前焦点窗口;如果此刻没有窗口持有焦点,它就退化为 GUI_StoreKeyMsg() 把数据存进键盘缓冲器,等有窗口取键时再消费——这就是下文手册摘录里那两段描述的原理含义。
WM_SetFocus(hItem) 直接把焦点交给指定窗口,WM_HasFocus(hItem) 查询焦点是否在某窗口上,WM_GetDialogItem(hDlg, Id) 用控件 ID 换句柄——三个函数合起来就是“指定焦点、查询焦点”的全部入口。
TAB 切换的原理:窗口管理器代劳遍历
对话框里的控件在窗口管理器里按创建顺序连成链。把 GUI_KEY_TAB 作为一条按键消息发出去,窗口管理器会自动把焦点移到下一个可聚焦控件,GUI_KEY_BACKTAB 反向移动——相当于系统替你做了链表遍历,应用层不用关心控件顺序。注意 Pressed 参数:1 表示按下、0 表示松开,发 1 即可,切换消费的是键值本身。
API 参考(手册摘录)
驱动层API
键盘驱动层处理键盘消息函数。这些程序会在具体键(或组合键)被按下或松开时通知窗口管理器。
下表按字母顺序列出了驱动层键盘程序。详细描述如下。
|GUI_StoreKeyMsg()|把消息存储于指定键。|
|GUI_SendKeyMsg()|把消息发送至指定键。|
GUI_SendKeyMsg()
描述
把键盘数据发送到输入焦点所在窗口。如果没有窗口有输入焦点,则调用GUI_StoreKeyMsg()函
数将数据存储至输入缓冲器之中。
原型
|
|
|参数 |描述 |
|Key |可以是任意扩展 ASCII 字符 (范围为 0x20 至 0xFF)或者任意预定义的 emWin 字符编码。|
|Pressed|1 按下状态。0 松开 (未按下)状态。|
GUI_StoreKeyMsg()
描述
把消息数据 (Key, PressedCnt) 存进键盘缓冲器。
原型
|
|
应用层 API
下表按字母顺序列出了应用层键盘程序。详细描述如下。
| 程序 | 描述 |
|---|---|
| GUI_ClearKeyBuffer() | 清除键缓冲器。 |
| GUI_GetKey() | 返回键缓冲器中的内容。 |
| GUI_StoreKey() | 把键存储于缓冲器中。 |
| GUI_WaitKey() | 等待键被按下 |
实现步骤
ucGui(emWin)的对话框中怎么切换控件的焦点?
- 获得控件的句柄hItem=WM_GetDialogItem(HWin,EditLocateGet());
- 聚焦:WM_SetFocus(hItem);
- 切换控件的焦点,向窗口管理器发 TAB / BACKTAB 键消息即可:
|
|
例如:
|
|
代码说明
WM_GetDialogItem(HWin, ID):用控件 ID 换句柄,句柄是后续一切焦点操作的钥匙;WM_SetFocus(hItem):把输入焦点交给该控件,之后的键盘消息默认路由到它;GUI_SendKeyMsg(GUI_KEY_TAB, 1):向焦点所在窗口发 TAB 键,窗口管理器把焦点移到下一个可聚焦控件;GUI_KEY_BACKTAB 反向;- 例如代码:
WM_HasFocus判断当前焦点是否在“-”按键上,是则发 TAB 跳走——条件切换的典型写法。
踩坑记录与注意事项
- 发了 TAB 界面没反应:GUI_SendKeyMsg 的目标是“当前焦点窗口”,此刻若没有窗口持有焦点,消息会进键盘缓冲而不是触发切换——先 WM_SetFocus 给对话框里任一控件垫底;
- 切换顺序 = 创建顺序:TAB 的下一个/上一个按控件的窗口链顺序走,界面上的视觉排列不影响它;顺序不对要调控件创建顺序,不是挪坐标;
- 纯显示控件不在焦点链里:TEXT 这类只读控件不参与 TAB 遍历,布局里夹着它们不会“空跳”;
- 别在焦点消息处理里再发切换键:焦点变化会触发 WM_SET_FOCUS / WM_KILL_FOCUS,在这些消息的处理里再发 TAB 容易一次按键连环切换;
- 触摸与键盘焦点是两套输入:纯键盘导航的界面要自己用 WM_SetFocus 摆好初始焦点,别指望用户碰一下屏幕帮你把焦点摆对。
Author 软件开发大郭
LastMod 2022-01-08