CEF4Delphiについて


 2022-12-04 11:32:36  No: 150703  IP: 192.*.*.*

おばんさまです。
D7を利用しCEF4Delphiを試しています。

そこで、質問なんですが、リンクタグをクリックするとリンク先のページに移動しますが、それを移動させずに
リンク先を新しいwindowsで開いたり、別のCEFWindowParent1に表示したりはできないでしょうか?

と、いう事を思っていていろいろ試していて、疑問に思っていることがいろいろあるんですが
下記のMr.XRAYさんのページを見て、
http://mrxray.on.coocan.jp/Delphi/plSamples/934_GoogleChrome_CEF4Delphi.htm

GlobalCEFApp_OnProcessMessageReceived構文のところにprocedureの下にprocedureという構文があり
検索していてもよく見かけるのですが、D7だとprocedureの下にprocedureを置くことができないようです。

これの対策はございますでしょうか?

またChromium1AfterCreatedやChromium1BeforeCloseの構文ですが、
これも中でPOSTをしている記述を検索も気かけるのですが、これがなくてもproc内の処理はされるのに
なんの為にPSOTをしているかが不思議です。

それと、破棄時の構文が、これもよく検索で見かけるのですが

    Chromium1.CloseBrowser(True); のようなものを利用していますが、
たとえば、パネルに張り付けたときにpanelをnilすると、BeforeCloseイベントが発生するので、破棄はされていると思うのですが
Chromium1.CloseBrowser(True);をかける意味はどのようなものなのでしょうか?

という事を思いました。
急いではいませんので、お手すきの時にでもコメントをつけていただければ嬉しいです。






Mr.XRAYさんのページを拝見していて

編集 削除
HFUKUSHI  2022-12-06 07:27:17  No: 150705  IP: 192.*.*.*

さすがにDelphi 6/7あたりの話になると回答が付きにくいですね…無償版で、ということであればDelphi 10.4 RioのCommunity Editionにされたほうがいいとは思いますが…

それはさておき、
> GlobalCEFApp_OnProcessMessageReceived構文のところにprocedureの下にprocedureという構文があり
> 検索していてもよく見かけるのですが、D7だとprocedureの下にprocedureを置くことができないようです。
これはDelphi 2009で導入された無名メソッドですね。

Delphi での無名メソッド - RAD Studio
https://docwiki.embarcadero.com/RADStudio/ja/Delphi_%E3%81%A7%E3%81%AE%E7%84%A1%E5%90%8D%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89

で質問にあったGlobalCEFApp_OnProcessMessageReceivedのところを見ると、ICefFrame.VisitDomProcの呼び出しのパラメータとして無名メソッドを渡しているのですが、ここでCEF4Delphiのソースコード(uCEFInterfaces.pas)を見ると、ICefFrame.VisitDomProcは

  ICefFrame = interface(ICefBaseRefCounted)
    ...
    procedure VisitDomProc(const proc: TCefDomVisitorProc);

となっていて、パラメータの型はTCefDomVisitorProcで、これは

  TCefDomVisitorProc                   = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const document: ICefDomDocument);

と定義されています。なのでDelphi 2007およびそれ以前のバージョンでは(reference toがなく)単にprocedure(const document: ICefDomDocument);と解釈されるので、無名メソッドをサポートしていないバージョンのDelphiでは、単にどこかで定義したprocedureを渡せばいい、ということになります(ただしここにはof objectがついていないので、フォームなどクラスのメンバメソッドは渡すことができず、普通のprocedureである必要があります)。
単なるfunction/procedureと無名メソッドの違いは、無名メソッドでは、その置かれた場所からアクセスできる概ねすべてのものに無名メソッド内部からアクセスできる、というところにあって、このコードでいうと無名メソッドの最後にある
      browser.SendProcessMessage(PID_BROWSER, LMsg);
で、呼び出し元のGlobalCEFApp_OnProcessMessageReceivedの仮引数browserがそれにあたります。これを正しく回避するのはちょっと難しいように思います。
とりあえず、ということであれば、たとえば
var
  gbrowser: ICefBrowser;

procedure VisitDom(const doc: ICefDomDocument);
var
  LMsg  : ICefProcessMessage;
  LText : ustring;
begin
  //メインプロセスに送信するメッセージの文字列
  //ここでは受け取った値と同じにしている
  LMsg := TCefProcessMessageRef.New(message.Name);

  LText := doc.Title;
  //送信内容のセット(ここでは文字列)
  LMsg.ArgumentList.SetString(0, LText);
  //送信(メインプロセスで受け取る必要がなければ不要)
  gbrowser.SendProcessMessage(PID_BROWSER, LMsg);
end;

procedure GlobalCEFApp_OnProcessMessageReceived(const browser: ICefBrowser;
  sourceProcess: TCefProcessId; const message: ICefProcessMessage;
  var aHandled: boolean);
var
  LIFrame : ICefFrame;
begin
  ...
  if (message.Name = 'get_doctitle') then begin
    gbrowser := browser;
    LIFrame.VisitDomProc(VisitDom);
    ...
のようにして、コンテキストに相当するもの(この場合はbrowser)をファイルローカルのgbrowser経由でコールバック関数VisitDomに渡すような感じで行けるかな、とは思いますが…。

編集 削除
HFUKUSHI  2022-12-06 07:33:42  No: 150706  IP: 192.*.*.*

> またChromium1AfterCreatedやChromium1BeforeCloseの構文ですが、
> これも中でPOSTをしている記述を検索も気かけるのですが、これがなくてもproc内の処理はされるのに
> なんの為にPSOTをしているかが不思議です。
これはスレッドコンテキストの問題(イベントがメインスレッド以外のスレッドで呼ばれている)か、もしくは当該イベント内でやってはいけないような処理を遅延して実行しているか、ですね。実際のところはわかりませんが…。

編集 削除