Windows11更新KB5060829/KB5062553后Delphi中TTouchKeyboard抢占TChromium焦点问题
针对Windows 11 KB更新后TChromium与TTouchKeyboard触摸焦点冲突的解决方案思路
问题核心
Windows 11安装KB5060829/KB5062553更新后,触摸点击同一窗体中的TTouchKeyboard会夺走TChromium内网页输入元素的焦点,仅触摸操作受影响,常规VCL控件无此问题,拦截WM_MOUSEACTIVATE无效。
可行解决方案思路
1. 拦截TTouchKeyboard的触摸专属消息,阻止控件激活
触摸操作触发的是WM_POINTERDOWN/WM_TOUCH系列消息(而非传统鼠标消息),可以通过自定义TTouchKeyboard子类拦截这些消息,避免控件获得激活:
type TCustomTouchKeyboard = class(TTouchKeyboard) protected procedure WndProc(var Message: TMessage); override; end; procedure TCustomTouchKeyboard.WndProc(var Message: TMessage); begin // 拦截触摸按下消息,阻止控件激活 case Message.Msg of WM_POINTERDOWN, WM_TOUCH: begin // 先执行原按键逻辑(保留键盘功能) inherited; // 阻止控件获得焦点激活 Message.Result := 0; Exit; end; WM_ACTIVATE: begin // 拦截激活消息,拒绝成为活动控件 if WA_ACTIVE = Message.WParam then begin Message.Result := 0; Exit; end; end; end; inherited; end;
将原TTouchKeyboard替换为这个自定义类使用。
2. 按键触发后强制恢复TChromium焦点
在TTouchKeyboard的按键事件中,先处理输入传递,再强制将焦点切回TChromium或网页输入元素:
procedure TMainForm.TouchKeyboardKeyPress(Sender: TObject; var Key: Char); begin // 1. 将按键事件直接发送给TChromium(通过CEF API) if Chromium1.Browser <> nil then begin var KeyEvent := TCefKeyEvent.Create; try KeyEvent.windows_key_code := Ord(Key); KeyEvent.type_ := KEYEVENT_CHAR; Chromium1.Browser.GetHost.SendKeyEvent(KeyEvent); finally KeyEvent.Free; end; end; // 2. 恢复TChromium控件焦点 Chromium1.SetFocus; // 3. 可选:执行JS让网页原输入框重新聚焦 if Chromium1.Browser <> nil then Chromium1.Browser.MainFrame.ExecuteJavaScript('document.activeElement.focus();', '', 0); end;
3. 修改TChromium窗口属性,增强焦点锁定
在Chromium初始化后,修改窗口样式以强化焦点保持:
procedure TMainForm.FormCreate(Sender: TObject); begin // 在Chromium初始化后,添加控件父窗口样式增强焦点优先级 if Chromium1.HandleAllocated then begin SetWindowLongPtr(Chromium1.Handle, GWL_EXSTYLE, GetWindowLongPtr(Chromium1.Handle, GWL_EXSTYLE) or WS_EX_CONTROLPARENT); end; end;
也可在CEF的OnAfterCreated事件中强制锁定焦点:
procedure TMainForm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin browser.GetHost.SetFocus(True); end;
4. 拦截主窗体的焦点变更消息
在主窗体的WndProc中拦截WM_SETFOCUS消息,当目标控件是TTouchKeyboard时,强制将焦点切回TChromium:
procedure TMainForm.WndProc(var Message: TMessage); begin if Message.Msg = WM_SETFOCUS then begin // 判断即将获得焦点的是TTouchKeyboard if TWinControl(Message.WParam) = TouchKeyboard1 then begin // 强制将焦点切回TChromium Chromium1.SetFocus; Message.Result := 0; Exit; end; end; inherited; end;
内容的提问来源于stack exchange,提问作者Koen
相关产品推荐
相关产品推荐

