古い情報です、現在メンテナンスされていません

Delphiでウェブタブブラウザを作る

Delphiでウェブタブブラウザを作る際にハマった事や参照した場所等をメモしていきます。


ソフト公開

まだ内容は秘密です!
今使ってるブラウザから移行するようなものではなく、一緒に使う感じになると思います。

はまり雑記

参考にしたページ

  • TUIWebBrowser TDomEvent
    TWebBrowserを拡張したTUIWebBrowserが公開されています。 ちょこちょこっといじればDelphi7Proで使えるみたいです。

リターンキーやショートカットキー等の一部のキーが効かない

TWebBrowserそのままでは、ブラウザ内のリターンキー等が効きません。
TUIWebBrowserはリターンキーは効きますが、その他のDelphiなどで設定したショートカットキー等が効きません。

この解決法は以下のページに書かれています。
幻想遺電子観測地点-Dolphin技術情報→IEコンポーネント使用時の注意点

  • テストコード 幻想遺電子観測地点-Dolphin技術情報と同じもの
    //~省略~
    
      private
        { Private 宣言 }
        FOleInPlaceActiveObject: IOleInPlaceActiveObject;
    
    //~省略~
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Application.OnMessage := AppMessages;
    end;
    
    procedure TForm1.AppMessages(var Msg: TMsg; var Handled: Boolean);
    var
      Re: HRESULT;
    begin
      if Msg.message = WM_KEYDOWN then
      begin
        //WebBrowserにメッセージが送られてきたかを判定
        if IsChild(UIWebBrowser1.Handle, Msg.hwnd) then
        begin
          FOleInPlaceActiveObject :=
            UIWebBrowser1.ControlInterface as IOleInPlaceActiveObject;
    
          //メッセージをアクティブなWebBrowser(の子ウインド)に転送
          Re := FOleInPlaceActiveObject.TranslateAccelerator(Msg);
    
          if Re = S_OK then
          begin
            Handled := True;
          end
          else begin
            Handled := False;
          end;
        end;
      end;
    end;
  • テストコード タブブラウザにした際のコード
    タブブラウザにする際もメインフォームに1つはダミーでTUIWebBrowserを置いておく(使わないので他のコンポーネントの影にでも隠しておく)
    こうしないとApplicationのメッセージループが全く来なくなる問題があるからです…なぜこれで直るかは謎。
    「TFrame」を継承した「TIEFrame」上に「CliantUIWebBrowser: TUIWebBrowser」を置き、「FOleInPlaceActiveObject: IOleInPlaceActiveObject」を用意して外部からプロパティで見えるようにする。

    後記1:あ…これだとタブをフリーした瞬間にタイミング悪いとAppMessagesでエラー起きるしー良い方法思案中…とりあえず外道処理を入れてみる(汗)
    //~省略~
        CliantUIWebBrowser: TUIWebBrowser;
      private
        { Private 宣言 }
        FOleInPlaceActiveObject: IOleInPlaceActiveObject;
      public
        { Public 宣言 }
        property OleInPlaceActiveObject: IOleInPlaceActiveObject
          read FOleInPlaceActiveObject write FOleInPlaceActiveObject;
    
        property WebBrowser: TUIWebBrowser
          read CliantUIWebBrowser write CliantUIWebBrowser;
    //~省略~
    そのフレームをメインフォームの「WebBrowserPageControl:TPageControl」に乗せる。
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Application.OnMessage := AppMessages;
    end;
    
    function TForm1.AddIEFrameTab: TTabSheet;
    var
      WkTabSheet: TTabSheet;
      WkIEFrame: TIEFrame;
    begin
      // タブ(TTabSheet)を増やしてそこにフレーム(TIEFrame)を生成する。
      // 生成したタブシートを返す。
      WkTabSheet := TTabSheet.Create(WebBrowserPageControl);
      WkIEFrame := TIEFrame.Create(WkTabSheet);
      WkIEFrame.Parent := WkTabSheet;
      WkIEFrame.Name := '';
      WkIEFrame.Align := alClient;
      WkTabSheet.PageControl := WebBrowserPageControl;
    
      result := WkTabSheet;
    end;
    
    function TForm1.GetTabSheetToIEFrame(ATabSheet: TTabSheet): TIEFrame;
    var
      WkControlCount: Integer;
      WkControl: TControl;
    begin
      // タブシートの中からフレーム(TIEFrame)を探して返す。
      result := nil;
    
      if ATabSheet = nil then
      begin
        Exit;
      end;
    
      for WkControlCount := 0 to ATabSheet.ControlCount - 1 do
      begin
        WkControl := ATabSheet.Controls[WkControlCount];
        if WkControl.ClassName = 'TIEFrame' then
        begin
          result := TIEFrame(WkControl);
          Exit;
        end;
      end;
    end;
    
    function TForm1.GetActiveIEFrame: TIEFrame;
    begin
      // アクティブになっているTTabSheetのフレーム(TIEFrame)を取得
      result := GetTabSheetToIEFrame(WebBrowserPageControl.ActivePage);
    end;
    
    procedure TForm1.AppMessages(var Msg: TMsg;
      var Handled: Boolean);
    var
      Re: HRESULT;
      WkIEFrame: TIEFrame;
    begin
      begin
        try
          WkIEFrame := GetActiveIEFrame;
    
          // フレームおよびWebBrowserがnilなら通常のイベントとして回す
          if WkIEFrame = nil then
          begin
            Exit;
          end;
          if WkIEFrame.WebBrowser = nil then
          begin
            Exit;
          end;
    
          //WebBrowserにメッセージが送られてきたかを判定
          if IsChild(WkIEFrame.WebBrowser.Handle, Msg.hwnd) then
          begin
            WkIEFrame.OleInPlaceActiveObject :=
              WkIEFrame.WebBrowser.ControlInterface as IOleInPlaceActiveObject;
    
            //メッセージをアクティブなWebBrowser(の子ウインド)に転送
            Re := WkIEFrame.OleInPlaceActiveObject.TranslateAccelerator(Msg);
    
            if Re = S_OK then
            begin
              Handled := True;
            end
            else begin
              Handled := False;
            end;
          end;
        except
          // この処理をしている途中でフリーされたらエラーになるので
          // そうなったらメッセージを処理しないようにする
          // 外道な保険コード?
          Handled := False;
          Exit;
        end;
      end;
    end;

TUIWebBrowserをDelphi7Proで使いたい

USESの「MSHTML_TLB」を「MSHTML」にするだけです。