В FMX-приложении при использовании компонента TWebBrowser с движком WindowsEngine.EdgeOnly возникает проблема с потерей фокуса у элемента <input> на веб-странице, отображаемой внутри браузера. При клике на поле ввода оно получает фокус, но немедленно его теряет, что делает невозможным ввод текста. Проблема проявляется на Windows и исчезает при подключении второго монитора или переключении на WindowsEngine.IEOnly.
Пример кода для воспроизведения проблемы:
procedure TForm1.FormCreate(Sender: TObject);
begin
var browser := TWebBrowser.Create(Self);
browser.WindowsEngine := TWindowsEngine.EdgeOnly;
browser.Align := TAlignLayout.Client;
browser.URL := 'http://localhost:8000/test.html';
Self.AddObject(browser);
end;
Проблема заключается в ошибке в реализации FMX.WebBrowser.Win. В обработчике события GotFocus для WebView2 вызывается SetFocus, что приводит к нежелательной потере фокуса.
Предложенное решение:
Закомментировать вызов SetFocus в следующем коде:
FWebViewController.Add_GotFocus(
Callback<ICoreWebView2, IUnknown>
.CreateAs<ICoreWebView2FocusChangedEventHandler>(
function(const WebView: ICoreWebView2; const Args: IUnknown): HResult; stdcall
begin
Result := S_OK;
FWebViewFocusEventActive := True;
//SetFocus; // ЗАКОММЕНТИРОВАТЬ ЭТУ СТРОКУ
FWebViewFocusEventActive := False;
end
),
FGotFocusToken);
В VCL версии компонента TEdgeBrowser используется другой подход:
FWebViewController.Add_GotFocus(
Callback<ICoreWebView2, IUnknown>
.CreateAs<ICoreWebView2FocusChangedEventHandler>(
function(const WebView: ICoreWebView2; const Args: IUnknown): HResult; stdcall
begin
Result := S_OK;
FWebViewFocusEventActive := True;
DoEnter;
FWebViewFocusEventActive := False;
end
), FGotFocusToken);
где DoEnter вызывает WebViewController.MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC), а FWebViewFocusEventActive используется для предотвращения рекурсивного изменения фокуса.
Альтернативное решение (предложенное в ответах):
Этот вариант предполагает поиск HWND рендера WebView и принудительную установку на него фокуса при клике мышью.
unit Unit13;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.WebBrowser,
FMX.Platform,
FMX.Platform.Win,
Winapi.Windows,
Winapi.Messages;
type
TForm13 = class(TForm)
procedure FormCreate(Sender: TObject);
private
FBrowser: TWebBrowser;
FWebViewRenderHandle: HWND;
procedure BrowserDidFinishLoad(ASender: TObject);
procedure WMParentNotify(var Message: TWMParentNotify); message WM_PARENTNOTIFY;
public
end;
var
Form13: TForm13;
implementation
{$R *.fmx}
procedure TForm13.FormCreate(Sender: TObject);
begin
FBrowser := TWebBrowser.Create(Self);
FBrowser.Parent := Self;
FBrowser.Align := TAlignLayout.Client;
FBrowser.OnDidFinishLoad := BrowserDidFinishLoad;
FBrowser.URL := 'http://localhost:8000/test.html';
end;
procedure TForm13.BrowserDidFinishLoad(ASender: TObject);
var
WinService: IFMXWindowService;
ParentHandle: HWND;
begin
if (FBrowser <> nil) and (FWebViewRenderHandle = 0) then
begin
if TPlatformServices.Current.SupportsPlatformService(IFMXWindowService, IInterface(WinService)) then
begin
ParentHandle := WindowHandleToPlatform(Self.Handle).Wnd;
if ParentHandle <> 0 then
begin
FWebViewRenderHandle := FindWindowEx(ParentHandle, 0, 'Chrome_RenderWidgetHostHWND', nil);
end;
end;
end;
end;
procedure TForm13.WMParentNotify(var Message: TWMParentNotify);
begin
if (Message.Event = WM_LBUTTONDOWN) and (FWebViewRenderHandle <> 0) then
begin
Winapi.Windows.SetFocus(FWebViewRenderHandle);
end;
inherited;
end;
end.
Обсуждение:
Первое решение (закомментирование SetFocus) является более простым и, вероятно, более правильным, так как оно устраняет причину проблемы. Второе решение (принудительная установка фокуса) является обходным путем и может иметь нежелательные побочные эффекты.
Рекомендации:
Попробуйте закомментировать SetFocus в исходном коде FMX.WebBrowser.Win.
Если это не возможно, используйте второй вариант, но будьте готовы к возможным проблемам.
Сообщите об этой ошибке разработчикам Embarcadero, чтобы они исправили ее в будущих версиях Delphi.
Дополнительные замечания:
Убедитесь, что HTML-код вашей веб-страницы валиден.
Рассмотрите возможность использования компонента WebView4Delphi, который, по словам автора вопроса, не имеет этой проблемы.
Эта статья предоставляет информацию о проблеме с фокусом ввода в TWebBrowser при использовании WindowsEngine.EdgeOnly в FMX, а также предлагает два возможных решения. Первое решение является более предпочтительным, так как оно устраняет причину проблемы. Не забудьте сообщить об этой ошибке разработчикам Embarcadero.
В FMX-приложении при использовании TWebBrowser с WindowsEngine.EdgeOnly возникает проблема с потерей фокуса ввода на веб-странице, вызванная ошибкой в FMX.WebBrowser.Win, которую можно решить, закомментировав вызов SetFocus или принудительно установив фо
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.