1. 개요
임베딩된 크롬 웹브라우저에 사용자 정의 자바스크립트(JavaScript)를 강제로 실행 시킬수 있고, 자바스크립트 내에 델파이코드로 작성된 델파이 객체를 직접 호출할 수 있으며, 실행 결과를 어플리케이션에서 받아서 적절한 처리를 할 수 있다.
2. 주요 기능 정의
- 임베딩된 웹브라우저의 Context Menu(팝업메뉴)에 사용자 정의 메뉴 항목을 추가한다.
- 추가된 Context Menu 항목에 해당하는 실행 코드를 작성할 수 있다.
- 자바스크립트 내에서 호출 가능한 델파이 확장 객체를 정의 하고 웹브라우저에 등록 할 수 있다.
- 사용자 정의 자바스크립트를 지정된 웹브라우저 프레임에 실행시킬 수 있다.
- 실행된 자바스크립트의 결과를 받아서 델파이 코드 내에서 처리할 수 있다.
3. 구현하기
가. 델파이 확장 객체 정의
자바스크립트에서 호출 가능한 확장 객체는 일반 클래스로 정의하되 호출할 함수 및 프로시저는 class 함수 및 프로시저로 작성되어야 한다.
또한 자바스크립트 내에서 실행 되어야 하기 때문에 Visual Component에 대한 사용은 제한 된다.
확장객체 예제 에서는 자바스크립트에서 호출한 함수 및 프로시저에서는 "ICefProcessMessage" 메시지 객체를 생성하여 웹브라우저에 파라미터를 포함한 처리 메시지를 보내도록 작성 되었다
웹브라우저를 통해 전달된 메시지는 TChromium.OnProcessMessageReceived 이벤트 핸들러에서 해당 메시지 정보를 받아서 처리를 할 수 있다.
uses
{$IFDEF DELPHI16_UP}
Winapi.Windows,
{$ELSE}
Windows,
{$ENDIF}
uCEFRenderProcessHandler, uCEFBrowserProcessHandler, uCEFInterfaces, uCEFProcessMessage,
uCEFv8Context, uCEFTypes, uCEFv8Handler;
const
MOUSEOVER_MESSAGE_NAME = 'mouseover';
CUSTOMNAME_MESSAGE_NAME = ‘customname’;
type
TTestExtension = class
class procedure mouseover(const data: string);
class procedure sendresulttobrowser(const msgtext, msgname : string);
end;
…
class procedure TTestExtension.mouseover(const data: string);
var
msg: ICefProcessMessage;
begin
TRACE('mouseover'); //Visual Component를 사용하지 않는 일반 함수 호출은 동작
ShowMessage('TEST'); //Visual Component를 변경하는 함수 호출시 무시됨.
msg := TCefProcessMessageRef.New(MOUSEOVER_MESSAGE_NAME);
msg.ArgumentList.SetString(0, data);
// 웹브라우저에 되돌려 주기 위한 메시지 생성
// TChromium.OnProcessMessageReceived 에서 이벤트를 수신
// TCefv8ContextRef.Current는 현재 자바스크립트가 실행된 프레임에
// 대한 V8 Context를 리턴함
TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg);
end;
//여기서는 자바스크립트 호출시 메시지 이름을 직접 넣어서 호출할 수 있도록 했다.
class procedure TTestExtension.sendresulttobrowser(const msgtext, msgname : string);
var
msg: ICefProcessMessage;
begin
TRACE('sendresulttobrowser');
msg := TCefProcessMessageRef.New(msgname);
msg.ArgumentList.SetString(0, msgtext);
TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg);
end;
나. 런타임 확장 객체를 웹브라우저에 등록
런타임 확장 객체를 웹브라우저에 등록하기 위해서는 크롬어플리케이션 초기화시에 "GlobalCEFApp.OnWebKitInitialized" 이벤트 핸들러를 만들어 지정하도록 한다.
//이벤트 핸들러
procedure GlobalCEFApp_OnWebKitInitialized;
begin
{$IFDEF DELPHI14_UP}
TCefRTTIExtension.Register('myextension', TTestExtension);
{$ENDIF}
end;
procedure CreateGlobalCEFApp;
begin
GlobalCEFApp := TCefApplication.Create;
GlobalCEFApp.OnWebKitInitialized := GlobalCEFApp_OnWebKitInitialized;//확장객체 이벤트 핸들러 지정
GlobalCEFApp.DisableFeatures := 'NetworkService,OutOfBlinkCors';
end;
다. 웹브라우저 팝업메뉴(Context Menu) 항목 추가 등록
임베딩된 웹브라우저의 Context Menu항목을 지정하기 위해서는 "TChromium.OnBeforeContextMenu"이벤트 핸들러에서 다음과 같이 사용자 메뉴를 추가하는데, 추가될 각 메뉴 항목에 대한 메뉴ID를 지정해 주어야 한다.
추가할 메뉴ID는 기 정의된 "const MENU_ID_USER_FIRST = 26500;" 로 부터 증가되는 번호로 지정하길 권고 한다.
const
MINIBROWSER_CONTEXTMENU_SETJSEVENT = MENU_ID_USER_FIRST + 1;
MINIBROWSER_CONTEXTMENU_JSVISITDOM = MENU_ID_USER_FIRST + 2;
...
procedure TJSRTTIExtensionFrm.Chromium1BeforeContextMenu(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; const model: ICefMenuModel);
begin
// 사용자가 추가하고 싶은 메뉴항목을 추가 한다.
model.AddSeparator;
model.AddItem(MINIBROWSER_CONTEXTMENU_SETJSEVENT, 'Set mouseover event');
model.AddItem(MINIBROWSER_CONTEXTMENU_JSVISITDOM, 'Visit DOM in JavaScript');
end;
라. 추가된 사용자 메뉴(Context Menu) 실행코드 작성
선택된 Context Menu에 대한 실행 코드는 "TChromium.OnContextMenuCommand"에서 commandId 값에 따라 실행 코드를 달리 작성한다.
procedure TJSRTTIExtensionFrm.Chromium1ContextMenuCommand(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; commandId: Integer;
eventFlags: Cardinal; out Result: Boolean);
begin
Result := False;
// Context Menu로 추가된 CommandId별 실행 코드를 등록 한다.
case commandId of
MINIBROWSER_CONTEXTMENU_SETJSEVENT :
if (browser <> nil) and (browser.MainFrame <> nil) then
//자바스크립트 코드를 작성하여 강제로 웹브라우저에게 실행 시켰다.
browser.MainFrame.ExecuteJavaScript(
'document.body.addEventListener("mouseover", function(evt){'+
'function getpath(n){'+
'var ret = "<" + n.nodeName + ">";'+
'if (n.parentNode){return getpath(n.parentNode) + ret} else '+
'return ret'+
'};'+
'myextension.mouseover(getpath(evt.target))}'+ //여기서 델파이로 작성된 확장 객체의 프로시저(mouseover)를 호출 했다.
')', 'about:blank', 0);
MINIBROWSER_CONTEXTMENU_JSVISITDOM :
if (browser <> nil) and (browser.MainFrame <> nil) then
//자바스크립트 코드를 작성하여 강제로 웹브라우저에게 실행 시켰다.
browser.MainFrame.ExecuteJavaScript(
'var testhtml = document.body.innerHTML;' +
'myextension.sendresulttobrowser(testhtml, ' + quotedstr(CUSTOMNAME_MESSAGE_NAME) + ');', //여기서 델파이로 작성된 확장 객체의 프로시저(sendresulttobrowser)를 호출 했다.
'about:blank', 0);
end;
end;
4. 실행 예제
5. 전체 흐름에 대한 도식
'프로그래밍 > Chromium(CEF4Delphi)' 카테고리의 다른 글
[Chromium] CEF4Delphi - DOM탐색을 위한 메시지처리 개념잡기 (0) | 2021.06.16 |
---|---|
[Chromium] CEF4Delphi - Context Menu추가 구현하기 (0) | 2019.10.29 |
[Chromium] CEF4Delphi - 자바스크립트로 델파이 코드 실행 (0) | 2019.09.30 |
[Chromium] CEF4Delphi - 크롬브라우저 팝업메뉴 추가 및 실행 (0) | 2019.09.25 |
[Chromium] CEF4Delphi - Javascript 유효성 체크(Evaluate Javascript) (0) | 2019.09.19 |