TWebBrowser: масштабирование + "режим одного окна" несовместимо

Я:

мне нужен TWebBrowser, который всегда увеличен (~140%) и сохраняет все ссылки в одном webbrowser (т. е. Ссылки настроек должен быть открыт в том же браузере).

как я это делаю:

я поставил FEATURE_BROWSER_EMULATION в реестре до 9999, поэтому веб-страницы отображаются с помощью IE9. Я подтвердил, что это работает. Кроме того, я запускаю скомпилированную программу на новой установке Windows 7 с IE9, полностью обновленной через центр обновления Windows.

масштабирование:

procedure TForm1.WebBrowser1DocumentComplete(ASender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
var
  ZoomFac: OLEVariant;
begin
  ZoomFac := 140;
  WebBrowser1.ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, ZoomFac);
end;

это отлично работает.

открывать новое окно в том же браузере:

по умолчанию TWebBrowser открывает новый IE, когда он встречает набор ссылок, который будет открыт в новом окне. Мне нужно, чтобы он оставался в моей программе/webbrowser.

я пробовал много вещей здесь. Это работает для меня:

procedure TFormWeb.WebBrowser1NewWindow3(ASender: TObject;
  var ppDisp: IDispatch; var Cancel: WordBool; dwFlags: Cardinal;
  const bstrUrlContext, bstrUrl: WideString);
begin
  Cancel := True;
  WebBrowser1.Navigate(bstrUrl);
end;

Я отменяю новое окно, а вместо этого просто перейдите к тому же URL.

другие источники на разных страницах в Интернете предполагают, что я не отменяю и вместо этого устанавливаю ppDisp для различных вещей, таких как WebBrowser1.DefaultDispath или WebBrowser1.Application и вариации из них. Это не работает для меня. Когда я нажимаю ссылку _BLANK, ничего не происходит. Это тестируется на двух компьютерах (как Win7, так и IE9). Я не знаю, почему это не работает, потому что это, кажется, работает для других людей в Интернете. Может быть, это решит проблему?

теперь проблема:

когда я объединяю эти 2 части кода, он ломается!

procedure TForm1.Button1Click(Sender: TObject);
begin
  WebBrowser1.Navigate('http://wbm.dk/test.htm');
  // This is a test page, that I created. It just contains a normal link to google.com
end;

procedure TForm1.WebBrowser1DocumentComplete(ASender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
var
  ZoomFac: OLEVariant;
begin
  ZoomFac := 140;
  WebBrowser1.ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, ZoomFac);
end;

procedure TForm1.WebBrowser1NewWindow3(ASender: TObject; var ppDisp: IDispatch;
  var Cancel: WordBool; dwFlags: Cardinal; const bstrUrlContext,
  bstrUrl: WideString);
begin
  Cancel := True;
  WebBrowser1.Navigate(bstrUrl);
end;

при нажатии на ссылку (независимо от того, является ли она нормальной или _BLANK) в webbrowser во время выполнения, она выдает эту ошибку:

First chance exception at F1B9BC. Exception class EOleException with message 'Unspecified error'. Process Project1.exe (3288)

если я удаляю любую часть кода, он работает (без удаленного кода, очевидно).

может кто-нибудь помочь мне получить обе вещи одновременно?

спасибо время!

обновление:

теперь речь идет о правильном захвате нового окна и сохранении его в том же элементе управления браузером. Код масштабирования в OnDocumentComplete, насколько я могу судить, не имеет к этому никакого отношения. Это увеличение в целом. Если элемент управления WebBrowser был увеличен (достаточно одного раза), код в NewWindow3 завершится ошибкой "Unspecified error". Сброс уровня масштабирования до 100% не помогает.

С помощью кода масштабирования (ExecWB) что-то меняется "навсегда" в WebBrowser, что делает его несовместимым с кодом в NewWindow3.

кто-нибудь может понять это?

новый код:

procedure TForm1.Button1Click(Sender: TObject);
var
  ZoomFac: OLEVariant;
begin
  ZoomFac := 140;
  WebBrowser1.ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, ZoomFac);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  WebBrowser1.Navigate('http://www.wbm.dk/test.htm');
end;

procedure TForm1.WebBrowser1NewWindow3(ASender: TObject; var ppDisp: IDispatch;
  var Cancel: WordBool; dwFlags: Cardinal; const bstrUrlContext,
  bstrUrl: WideString);
begin
  Cancel := True;
  WebBrowser1.Navigate(bstrUrl);
end;

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

2 ответов


вы можете установить ppDisp до новая экземпляр IWebBrowser2 на OnNewWindow2 событие е.г:

procedure TForm1.Button1Click(Sender: TObject);
begin
  WebBrowser1.Navigate('http://wbm.dk/test.htm');
end;

procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
var
  ZoomFac: OleVariant;
begin
  // the top-level browser
  if pDisp = TWebBrowser(Sender).ControlInterface then
  begin
    ZoomFac := 140;
    TWebBrowser(Sender).ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, ZoomFac);
  end;
end;

procedure TForm1.WebBrowser1NewWindow2(Sender: TObject;
  var ppDisp: IDispatch; var Cancel: WordBool);
var
  NewWindow: TForm1;
begin
  // ppDisp is nil; this will create a new instance of TForm1:
  NewWindow := TForm1.Create(self);
  NewWindow.Show;
  ppDisp := NewWindow.Webbrowser1.DefaultDispatch;
end;

также предложено Microsoft установить RegisterAsBrowser to true.
Вы можете изменить этот код, чтобы открыть TWebBrowser в новой вкладке внутри страницы.

мы не можем установить ppDisp до настоящее экземпляр TWebBrowser - таким образом, используя этот простой код:

ppDisp := WebBrowser1.DefaultDispatch; доза не работа.

нужно "воссоздать" текущий/активный TWebBrowser, если мы хотим сохранить поток пользовательского интерфейса-обратите внимание, что в следующем примере TWebBrowser создается "на лету", например:

const
  CM_WB_DESTROY = WM_USER + 1;
  OLECMDID_OPTICAL_ZOOM = 63;

type
  TForm1 = class(TForm)
    Button1: TButton;        
    Panel1: TPanel;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    function CreateWebBrowser: TWebBrowser;
    procedure WebBrowserDocumentComplete(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant);
    procedure WebBrowserNewWindow2(Sender: TObject; var ppDisp: IDispatch; var Cancel: WordBool);
    procedure CMWebBrowserDestroy(var Message: TMessage); message CM_WB_DESTROY;
  public
    WebBrowser: TWebBrowser;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  WebBrowser := CreateWebBrowser;
end;

function TForm1.CreateWebBrowser: TWebBrowser;
begin
  Result := TWebBrowser.Create(Self);
  TWinControl(Result).Parent := Panel1;
  Result.Align := alClient;
  Result.OnDocumentComplete := WebBrowserDocumentComplete;
  Result.OnNewWindow2 := WebBrowserNewWindow2;
  Result.RegisterAsBrowser := True;
end;

procedure TForm1.WebBrowserDocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
var
  ZoomFac: OleVariant;
begin
  // the top-level browser
  if pDisp = TWebBrowser(Sender).ControlInterface then
  begin
    ZoomFac := 140;
    TWebBrowser(Sender).ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, ZoomFac);
  end;
end;

procedure TForm1.WebBrowserNewWindow2(Sender: TObject; var ppDisp: IDispatch; var Cancel: WordBool);
var
  NewWB: TWebBrowser;
begin
  NewWB := CreateWebBrowser;
  ppDisp := NewWB.DefaultDispatch;
  WebBrowser := NewWB;

  // just in case...
  TWebBrowser(Sender).Stop;
  TWebBrowser(Sender).OnDocumentComplete := nil;
  TWebBrowser(Sender).OnNewWindow2 := nil;

  // post a delayed message to destory the current TWebBrowser
  PostMessage(Self.Handle, CM_WB_DESTROY, Integer(TWebBrowser(Sender)), 0);
end;

procedure TForm1.CMWebBrowserDestroy(var Message: TMessage);
var
  Sender: TObject;
begin
  Sender := TObject(Message.WParam);
  if Assigned(Sender) and (Sender is TWebBrowser) then
    TWebBrowser(Sender).Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  WebBrowser.Navigate('http://wbm.dk/test.htm');
end;

Я думаю, проблема в том, что иногда OnDocumentComplete может запускать несколько раз при загрузке документа (страницы с фреймами).

вот способ реализовать его должным образом.