TChromium Events - обработка событий

TChromium Events - обработка событий

Рассмотрим и потестируем некоторые события компонента TChromium.
На момент тестов (август 2016) автор использовал конфигурацию: Lazarus IDE v1.6.0, fpc 3.0.0, fpCEF3 3.2526, win7 64.
В сентябре 2016 автор сменил версию fpCEF3 на 3.2704, изменения дописываются (если они замечены).

В новых версиях fpCEF3 (например в 3.2924 - Chromium 56.0.2924.76), некоторые события удалены, новые добавлены.

Обработка событий позволяет отслеживать и контролировать работу веб-страницы.
Например, мы сможем отследить, когда пользователь наводит курсор мыши на URL-ссылку,
или можем вызвать диалог сохранения загружаемого файла, и т.д.
Все передаваемые в обработчики текстовые параметры имеют кодировку UTF-8 (ustring).

Если Вы заметили ошибку или неточность, просьба сообщить об ошибке.

Описание событий будет постепенно расширяться, как только руки автора дойдут до мелочей.

Создайте произвольное тестовое приложение, например как здесь: TChromium Options - опции в инспекторе объектов
(для проверки некоторых событий, потребуется загружать произвольную веб-страницу вместо локальной).

Для навигации по всем страницам этого раздела сайта используйте иконку меню или ссылку Навигация в строке навигации.

В таблице ниже перечислены события TChromium в инспекторе объектов, ещё ниже Подробное описание

Событие и локальная ссылкаКраткое описание и официальная ссылка
OnAddressChangeПри смене URL-адреса. CefDisplayHandler
OnAfterCreatedСразу после создания объекта браузера. CefLifeSpanHandler
OnBeforeBrowseПри попытке открыть любую веб-страницу. CefRequestHandler
OnBeforeCloseИнформирование о закрытии окна. CefLifeSpanHandler
OnBeforeContextMenuПеред показом контекстного меню.
OnBeforeDownloadПеред попыткой загрузить файл.
OnBeforePluginLoad--- Удалено в новых версиях fpCEF3 ---
OnBeforePopupПри попытке создать новый объект браузера (окно). CefLifeSpanHandler
OnBeforeResourceLoadCefRequestHandler
OnBeforeUnloadDialogВывод подтверждающего диалога при попытке покинуть веб-страницу.
OnCancelGeolocationPermissionCefGeolocationHandler.
OnCertificateErrorCefRequestHandler Prompt to choose client certificate
OnCloseПри попытке закрыть окно с объектом браузера.
OnConsoleMessageПри выводе сообщения в консоль браузера. CefDisplayHandler
OnContextMenuCommandВыбор команды контекстного меню.
OnContextMenuDismissedИнформирование о закрытии контекстного меню.
OnDialogClosedCefJSDialogHandler
OnDownloadUpdatedМногократный вызов обработчика при загрузке файла.
OnDragEnterПри перемещении объекта над веб-страницей. CefDragHandler
OnDraggableRegionsChangedCefDragHandler
OnFaviconUrlchangeCefDisplayHandler
OnFileDialogНепосредственно перед открытием стандартного диалога сохранения файла.
OnFindResultCefFindHandler
OnFullscreenModeChangeCefDisplayHandler
OnGetAuthCredentialsCefRequestHandler
OnGetCookieManager--- Удалено в новых версиях fpCEF3 ---
OnGetResourceHandlerCefRequestHandler
OnGetResourceResponseFilter--- Появилось в новых версиях fpCEF3 ---
OnGotFocusПри получении фокуса объектом браузера.
OnJsdialogПопытка вывести диалог из JavaScript ( CefJSDialogHandler )
OnKeyEventСобытие клавиатуры объекта браузера. CefKeyboardHandler
OnLoadEndЗавершение загрузки каждого фрейма веб-страницы. CefLoadHandler
OnLoadErrorОшибка загрузки фрейма. CefLoadHandler
OnLoadingStateChangeПри начале и завершении загрузки. CefLoadHandler
OnLoadStartНачало загрузки каждого фрейма. CefLoadHandler
OnOpenUrlFromTabКлик по ссылке средней кнопкой мыши (или удерживая <Ctrl>).
OnPluginCrashedCefRequestHandler
OnPreKeyEventПеред событием OnKeyEvent объекта браузера.
OnProcessMessageReceivedCefRenderProcessHandler
OnProtocolExecutionCefRequestHandler
OnQuotaRequestCefRequestHandler --- Обзор File API
OnRenderProcessTerminatedCefRequestHandler
OnRenderViewReadyCefRequestHandler
OnRequestGeolocationPermissionCefGeolocationHandler
OnResetDialogStateCefJSDialogHandler
OnResourceLoadComplete--- Появилось в новых версиях fpCEF3 ---
OnResourceRedirectCefRequestHandler
OnResourceResponse--- Появилось в новых версиях fpCEF3 ---
OnRunContextMenuCefContextMenuHandler
OnRunModalCefLifeSpanHandler --- Удалено в новых версиях fpCEF3 ---
OnSelectClientCertificate--- Появилось в новых версиях fpCEF3 ---
OnSetFocus CefFocusHandler
OnStatusMessageИнформирование о выделении и отмены выделения URL - ссылок. CefDisplayHandler
OnTakeFocus CefFocusHandler
OnTitleChangeИнформирование о смене TITLE веб-страницы. CefDisplayHandler
OnTooltipНе работает. CefDisplayHandler --- CefRenderWidgetHostViewOSR :: SetTooltipText

Подробное описание событий

Для изучения всех методов и свойств см. файлы cef3gui.pas и cef3intf.pas, а так же cef3own.pas

OnAddressChange

Событие генерируется при смене URL-адреса. Параметр url содержит новый URL в кодировке UTF-8.
Позволяет отслеживать текущий URL страницы или переход по локальным для веб-странице ссылкам-якорям.

В обработчике события OnBeforeBrowse можно запретить смену URL и загрузку другой страницы.
Текущий URL-адрес всегда можно получить через ICefFrame.Url или ICefFrame.GetUrl()
Отличить различные объекты браузера можно через ICefBrowser.GetIdentifier()

OnAfterCreated

Генерируется сразу после создания нового объекта браузера
Приложение может получить уникальный идентификатор объекта браузера ICefBrowser.GetIdentifier()

OnBeforeBrowse

Событие генерируется при попытке открыть любую веб-страницу (перед навигацией объекта браузера).
При установке Result:=false; веб-страница открывается, иначе остаётся текущая.

OnBeforeClose

Генерируется при закрытии окна с объектом браузера. Отменить уничтожение окна можно в OnClose.
Приложение может получить уникальный идентификатор уничтожаемого объекта браузера ICefBrowser.GetIdentifier()

OnBeforeContextMenu

Событие генерируется перед показом контекстного меню.
Дефолтное меню можно очистить через ICefMenuModel.Clear(),
можно добавлять необходимые пункты и разделители ( ICefMenuModel.AddItem() и ICefMenuModel.AddSeparator() )
Можно назначить клавишу быстрого выбора через амперсенд &, например model.AddItem( 131, Utf8Decode('&Print...') );

Автор нашёл в исходных файлах следующие коды операций для меню:

  • 100 (Back)
  • 101 (Forward)
  • 102 (Reload)
  • 103 (Reload NoCache)
  • 104 (Stop load)
  • 113 (Copy)
  • 116 (Select all)
  • 130 (Find)
  • 131 (Print)
  • 132 (View source)
  • 220 (MENU_ID_CUSTOM_FIRST)
  • 250 (MENU_ID_CUSTOM_LAST)

OnBeforeDownload

Генерируется перед началом загрузки файла (например, при клике по ссылке с получением HTTP-заголовков загрузки файла).
По умолчанию (без вызова обратной функции) загрузка будет отменена.
Для сохранения файла нужно вызвать ICefBeforeDownloadCallback.Cont(suggestedName, True);
При передаче True будет вызван диалог сохранения, при передаче False файл будет сохраняться без диалога.

procedure TFormMain.Chromium1BeforeDownload(Sender: TObject;
    const Browser: ICefBrowser; const downloadItem: ICefDownloadItem;
    const suggestedName: ustring; const callback: ICefBeforeDownloadCallback);
begin
    { Сохранимм файл без диалога как "D:\myfolder\file.txt" }
    callback.Cont('D:\myfolder\file.txt', false);
end;

Отслеживать процесс загрузки файла можно в обработчике OnDownloadUpdated
Дополнительно см. OnFileDialog

OnBeforePopup

Событие генерируется при попытке создать новый объект браузера в окне. По-умолчанию объект и окно создаются
(инициировать создание нового окна с объектом браузера можно кликом по ссылке с атрибутом target="_blank").
Чтобы запретить создание нового объекта браузера, нужно выполнить Result:=True;
Параметр targetUrl содержит URL-адрес страницы, которую можно при желании открыть в любом их существующих объектов,
например так: ICefBrowser.MainFrame.LoadUrl(targetUrl); или ICefFrame.LoadUrl(targetUrl);

OnBeforeUnloadDialog

Генерируется при попытке покинуть веб-страницу, если на ней задан JS-обработчик window.onbeforeunload.
Если JS-обработчик не задан, или возвращает null / undefined, то события OnBeforeUnloadDialog нет и веб-страницу можно покинуть без проблем.

/* JavaScript-код на веб-странице */
window.onbeforeunload = function(e) {
  /* alert(...) не сработает, важен return */
  return null; /* return "Мы что-то не то сказали ???"; */
}

Если событие window.onbeforeunload на веб-странице обрабатывается и возвращается значение, отличное от null или undefined, то:
- будет выведен диалог подтверждения, если OnBeforeUnloadDialog не обрабатывается или Result:=False;
- диалога не будет и веб-страницу невозможно покинуть (а так же закрыть окно), если Result:=True;

Можно вызвать обработчик ICefJsDialogCallback.Cont(success: Boolean; const userInput: ustring);
в этом случае никакого подтверждающего окна не будет ни при каких вариантах, поведение зависит от параметра success
при вызове обработчика нельзя трогать Result - будет runtime error (у меня было именно так).

procedure TFormMain.Chromium1BeforeUnloadDialog(Sender: TObject;
    const Browser: ICefBrowser; const messageText: ustring; isReload: Boolean;
    const callback: ICefJsDialogCallback; out Result: Boolean);
begin
    { Код ниже разрешает перезагружать страницу }
    callback.cont(isReload, '');
end;

Попытка закрыть отдельное независимое окно с объектом браузера может привести к генерации данного события.

OnClose

Генерируется при попытке закрыть окно с объектом браузера. Окно приложения по-умолчанию закрывается пользоветелем без подверждения.
Если обработчика этого события нет или Result:=False; то окно закрывается, иначе остаётся открытым.
Приложение может получить уникальный идентификатор уничтожаемого объекта браузера ICefBrowser.GetIdentifier()
Если необходимо лишь получать уведомления об уничтожении объектов браузера, то см. OnBeforeClose

OnConsoleMessage

Генерируется при выводе сообщения в консоль браузера. Параметр message содержит текст сообщения в кодировке UTF-8.

OnContextMenuCommand

Генерируется при выборе команды контекстного меню. Каманда НЕ выполняется при установке Result:=True;
См. описание ICefContextMenuParams в файле cef3intf.pas
См. описание TCefEventFlags в файле cef3types.pas

OnContextMenuDismissed

Информационное событие генерируется после отмены контекстного меню или после события OnContextMenuCommand
См. описание ICefBrowser и ICefFrame в файле cef3intf.pas

OnDownloadUpdated

Многократный вызов обработчика при загрузке файла.

procedure TFormMain.Chromium1DownloadUpdated(Sender: TObject;
    const Browser: ICefBrowser; const downloadItem: ICefDownloadItem;
    const callback: ICefDownloadItemCallback);
begin
    { callback.Cancel | callback.Pause | callback.Resume }
    if (downloadItem.IsComplete) then ShowMessage('Download complete');
end;

В обработчике OnBeforeDownload можно показывать диалог сохранения файла или сразу указать путь.
Дополнительно см. OnFileDialog. См. описание ICefDownloadItem в файле cef3intf.pas

OnDragEnter

Генерируется при перемещении объекта над веб-страницей.
См. описание ICefDragData в файле cef3intf.pas
См. описание TCefDragOperationsMask в файле cef3types.pas

OnFileDialog

Генерируется непосредственно перед открытием стандартного диалога сохранения файла.
Можно отменить диалог, если установить Result:=True;
Можно вызвать произвольный диалог:
ICefFileDialogCallback.Cont(selectedAcceptFilter: Integer; filePaths: TStrings);

Дополнительно см. описание OnBeforeDownload
См. описание ICefFileDialogCallback в файле cef3intf.pas
См. описание TCefFileDialogMode в файле cef3types.pas

OnGotFocus

Генерируется при получении фокуса объектом браузера.

OnJsdialog

Генерируется при попытке вывести диалог из JavaScript (alert(), prompt(), confirm())
При установке Result:=true; или suppressMessage:=true; JS-диалог будет проигнорирован.
Можно обработать диалог из приложения, заменив стандартный браузерный диалог.

Поэкспериментируйте с кодом ниже (Pascal и JavaScript), чтобы лучше разобраться в работе обработчика события.

procedure TFormMain.Chromium1Jsdialog(Sender: TObject;
    const Browser: ICefBrowser; const originUrl, acceptLang: ustring;
    dialogType: TCefJsDialogType; const messageText, defaultPromptText: ustring;
    callback: ICefJsDialogCallback;
    out suppressMessage: Boolean; out Result: Boolean);
begin
    case dialogType of

        JSDIALOGTYPE_ALERT: //alert( messageText );
          begin
            ShowMessage('alert: ' + UTF8Encode(messageText)); // закомментировать для теста
            //suppressMessage := true; Exit;    // раскомментировать для теста
          end;

        JSDIALOGTYPE_CONFIRM: //result = confirm( messageText );
          if (MessageDlg('confirm: ' + UTF8Encode(messageText), mtConfirmation, mbOKCancel, 0) = 1)
            and (UTF8Encode( messageText ) = 'Продолжить?')
              then callback.Cont(true, '')
              else callback.Cont(false, '');

        JSDIALOGTYPE_PROMPT: //result = prompt(messageText, defaultPromptText);
          begin
            if (UTF8Encode(messageText) = 'Введите текст') then
              callback.Cont(true, defaultPromptText)
            else
              begin
                Result:=false;
                Exit;
              end;
          end;
    end;
    Result:=true;
end;

/* Локальный файл JavaScript для выполнения */
document.addEventListener("DOMContentLoaded", init, false);
function init() {
    /* Здесь работа с веб-страницей */
    alert( prompt("Введите текст",1) );
    alert( confirm("Продолжить?") );
}

OnKeyEvent

События клавиатуры. В обработчике лучше сразу устанавливать по-умолчанию Result:=False; ,
иначе, когда фокус на объекте браузера, нам придётся самим обрабатывать все нажатия на клавиши.

Пример простой навигации по страницам через клавиши <F5>, <Alt + LeftArrow>, <Alt + RightArrow> :

procedure TFormMain.Chromium1KeyEvent(Sender: TObject;
    const Browser: ICefBrowser; const event: PCefKeyEvent;
    osEvent: TCefEventHandle; out Result: Boolean);
var KeyCode: Integer;
begin
    Result:=False;
    if (event^.kind <> KEYEVENT_KEYUP) then Exit;
    KeyCode:=event^.windows_key_code;
    if (KeyCode=116) then Browser.Reload();
    { ??? Перепутаны наименования флагов ??? }
    if (EVENTFLAG_ALT_DOWN in event^.modifiers) then
    begin
        if (KeyCode=37) and Browser.CanGoBack() then Browser.GoBack();
        if (KeyCode=39) and Browser.CanGoForward() then Browser.GoForward();
    end;
end;

Примечание: под fpCEF3 3.2526 флаги определяются так:
EVENTFLAG_SHIFT_DOWN - левый и правый Ctrl
EVENTFLAG_CONTROL_DOWN - левый и парвый Alt
EVENTFLAG_ALT_DOWN - не определяется :)

Под fpCEF3 3.2704 флаги определяются правильно:
EVENTFLAG_SHIFT_DOWN - левый и правый Shift
EVENTFLAG_CONTROL_DOWN - левый и парвый Ctrl
EVENTFLAG_ALT_DOWN - левый и парвый Alt

Можно обрабатывать клавиатурные события ещё раньше - в обработчике события OnPreKeyEvent

OnLoadEnd

Завершение загрузки каждого фрейма веб-страницы (страница может содержать вложенные фреймы).
Проверить загрузку главного фрейма можно через ICefFrame.IsMain()
Событие OnLoadEnd соответствует событию веб-страницы «DomContentLoaded».

Важно! При обработке этого события DOM уже построен, поэтому можно выполнить собственный произвольный JavaScript-код. Таким образом, мы можем выполнять свои скрипты для любых или определённых веб-страниц. Это бывает удобно для автоматической авторизации на том или ином сайте/админке, удаления рекламы, изменения оформления, расширения функциональности... и прочих задач, насколько хватит нашей фантазии.

Пример автоматической подстановки логина и пароля для сайта www.sql.ru

procedure TFormMain.Chromium1LoadEnd(Sender: TObject;
    const Browser: ICefBrowser; const Frame: ICefFrame;
    httpStatusCode: Integer);
var s, url: String;
begin
    if (not Frame.IsMain) or (httpStatusCode<>200) then Exit;
    url := 'http://www.sql.ru/forum/login.aspx?action=login';
    if (UTF8Encode(Browser.MainFrame.Url)=url) then
    begin
        s := 'var p=document.getElementById("login_form");';
        s := s + 'p=p.getElementsByTagName("input");';
        s := s + 'p[0].value="myLogin";';
        s := s + 'p[1].value="myPassword";';
        Frame.ExecuteJavaScript(Utf8Decode(s),'about:blank',0);
    end;
end;

Намного удобнее при запуске приложения читать заранее заготовленный JavaScript-файл (в кодировке UTF-8) в переменную и выполнять его при готовности веб-страниц, так мы сможем гибко менять JS-код без перекомпиляции приложения, например:

/* Локальный файл JavaScript для выполнения */
(function() {
  var p, url = window.location.href;
  if (url == 'http://www.sql.ru/forum/login.aspx?action=login') {
    p = document.getElementById('login_form');
    p = p.getElementsByTagName('input');
    p[0].value = 'myLogin';
    p[1].value = 'myPassword';
  }
  ...
  /* прочие действия над любыми страницами */
  ...
})();

OnLoadError

Ошибка загрузки фрейма. Можно проверять главный фрейм через ICefFrame.IsMain(), и другими способами.
См. описание TCefErrorCode в файле cef3types.pas

OnLoadingStateChange

Генерируется при инициации и завершении загрузки. Пераметры:
isLoading - загрузка в процессе (true) или завершена (false)
canGoBack - возможность вернуться на предыдущую страницу (true/false)
canGoForward - возможность перейти на следующую страницу (true/false)

При загрузке файла по ссылке, это событие возникает дважды ДО начала процесса загрузки и/или вывода диалога сохранения.
Процесс скачивания файла не отслеживается этим событием.

OnLoadStart

Начало загрузки каждого фрейма (страница может содержать вложенные фреймы).

OnOpenUrlFromTab

Генерируется в случае, когда пользователь кликает по ссылке средней кнопкой мыши, или кликает, удерживая <Ctrl>
Это событие возникает перед событием OnBeforeBrowse
Дествие разрешено только при установке Result:=False;

OnPreKeyEvent

Генерируется перед событием OnKeyEvent объекта браузера.
Можно обработать или установить Result:=False; для продолжения текущей операции.

OnStatusMessage

Генерируется при наведении курсора мыши на любую URL-ссылку или в момент, когда курсор мыши покидает URL-ссылку.
Клавиша Tab так же позволяет обходить ссылки по порядку (если опция TabToLinks не установлена как STATE_DISABLED).
Параметр value содержит URL-адрес ссылки (возможного перехода) в кодировке UTF-8, или пустое значение (когда курсор покидает ссылку).

OnTitleChange

Смена TITLE веб-страницы (параметр title в кодировке UTF-8). Генерируется каждый раз при смене TITLE веб-страниц(ы).

  • «Lazarus fpCEF3» - Главная страница раздела
  • Учебные проекты
  • project1 - первый запуск
  • project2 - один объект (окно) и контекстное меню
  • project3 - веб-интерфейс для десктопного приложения
  • Справочная информация по fpCEF3
  • TChromium Options - опции компонента TChromium
  • TChromium Events - обработка событий Chromium
  •  
  • Vcorp.ru - Главная страница сайта
  • Тест больших гридов в перемещаемых окнах
  • Тестирование 3D графики в браузерах
  • «VcorpJS» - Главная страница раздела
  • «Vcorp Generator» - Главная страница раздела
  • Открывать окно навигации
    <<<
    Изменить высоту >>