2012-04-13 95 views
3

如何以編程方式啓動IE(iexplore.exe)並在當前運行的實例中導航(通過打開新選項卡或替換當前URL)而不是創建新實例。如何強制Internet Explorer打開它的當前運行實例而不是創建新的實例?

我已經搜索了一個命令行開關,並嘗試使用InternetExplorer.Application,無濟於事。

這裏是什麼,我需要(IE6-IE9將是很好的)一個

ShellExecute(Handle, 'open', 'iexplore.exe', 
    '"http://google.com" -single_instance', 
    nil, SW_RESTORE); 

下面是一些代碼來證明我的嘗試。代碼(部分基於How to get IHTMLDocument2 from a HWND):

implementation 

uses ShellApi, ComObj, ActiveX, SHDocVw, MSHTML;   

function GetIEFromHWND(WHandle: HWND; var IE: IWebbrowser2): Boolean; 
type 
    TObjectFromLResult = function(LRESULT: lResult; const IID: TIID; 
    wParam: WPARAM; out pObject): HRESULT; stdcall; 
var 
    hInst: HMODULE; 
    lRes: Cardinal; 
    Msg: UINT; 
    pDoc: IHTMLDocument2; 
    ObjectFromLresult: TObjectFromLresult; 
begin 
    Result := False; 
    hInst := LoadLibrary('oleacc.dll'); 
    if hInst <> 0 then 
    try 
    @ObjectFromLresult := GetProcAddress(hInst, 'ObjectFromLresult'); 
    if @ObjectFromLresult <> nil then 
    begin 
     Msg := RegisterWindowMessage('WM_HTML_GETOBJECT'); 
     if SendMessageTimeOut(WHandle, Msg, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes) <> 0 then 
     if ObjectFromLresult(lRes, IHTMLDocument2, 0, pDoc) = S_OK then 
     begin 
      (pDoc.parentWindow as IServiceprovider).QueryService(
      IWebbrowserApp, IWebbrowser2, IE); 
      Result := IE <> nil; 
     end; 
     end; 
    finally 
    FreeLibrary(hInst); 
    end; 
end; 

function GetActiveIEServerWindow(const Activate: Boolean=True): HWND; 
var 
    Wnd, WndChild: HWND; 
begin 
    Result := 0; 
    Wnd := FindWindow('IEFrame', nil); // top level IE 
    if Wnd <> 0 then 
    begin 
    WndChild := FindWindowEx(Wnd, 0, 'Shell DocObject View', nil); 
    if WndChild <> 0 then 
    begin 
     WndChild := FindWindowEx(WndChild, 0, 'Internet Explorer_Server', nil); 
     if WndChild <> 0 then 
     begin 
     Result := WndChild; 
     if Activate then 
     begin 
      if IsIconic(Wnd) then 
      ShowWindow(Wnd, SW_RESTORE) 
      else 
      SetForegroundWindow(Wnd); 
     end; 
     end; 
    end; 
    end; 
end; 

// Method 1 
procedure TForm1.Button1Click(Sender: TObject); 
const 
    navOpenInNewTab = $800; 
var 
    IEServerWnd: HWND; 
    IE: IWebBrowser2; 
begin 
    IEServerWnd := GetActiveIEServerWindow; 
    if (IEServerWnd <> 0) and GetIEFromHWnd(IEServerWnd, IE) then 
    begin 
    // *** this opens the Default browser, e.g Google Chrome 
    // *** if IE is the Default browser, an empty new window is opened. 
    OleVariant(IE).Navigate('http://www.yahoo.com', Longint(navOpenInNewTab)); 
    end 
    else 
    begin 
    ShellExecute(Handle, 'open', 'iexplore.exe', 
    '"http://google.com"', 
    nil, SW_RESTORE); 
    end; 
end; 

procedure InternetExplorerNavigate(URL: WideString); 
const 
    navOpenInNewTab = $800; 
var 
    IE: OleVariant; 
begin 
    try 
    // *** this always fails (security constraints?) 
    IE := GetActiveOleObject('InternetExplorer.Application'); 
    except 
    IE := CreateOleObject('InternetExplorer.Application'); 
    end; 
    IE.Visible := True; 
    IE.Navigate(URL, Longint(navOpenInNewTab)); 
end; 

// Method 2 
procedure TForm1.Button2Click(Sender: TObject); 
begin 
    InternetExplorerNavigate('http://google.com'); 
end; 
+0

這不應該歸結爲用戶配置嗎?如果我將它設置爲在新窗口中打開,那麼我期望新的窗口。如果我將它設置爲在一個窗口中加載所有選項卡,我也會這麼想。 – Deanna 2012-04-16 14:20:42

回答

4

您的方法'1'實際工作。這個問題至少在這裏是'Shell DocObject View'窗口不是頂層窗口的直接子節點。在IE8中,'Internet Explorer_Server'窗口是'Shell DocObject View'的子項,它是'TabWindowClass'的子項,它是'Frame Tab'的子項。如果您可以確認'方法1中'FindWindowEx'返回0,這就是爲什麼它失敗。下面的是修改爲使用EnumChildWindows的代碼:

function EnumChilds(hwnd: HWND; lParam: LPARAM): BOOL; stdcall; 
const 
    Server = 'Internet Explorer_Server'; 
var 
    ClassName: array[0..24] of Char; 
begin 
    GetClassName(hwnd, ClassName, Length(ClassName)); 
    Result := ClassName <> Server; 
    if not Result then 
    PLongWord(lParam)^ := hwnd; 
end; 

function GetActiveIEServerWindow(const Activate: Boolean=True): HWND; 
var 
    Wnd, WndChild: HWND; 
begin 
    Result := 0; 
    Wnd := FindWindow('IEFrame', nil); // top level IE 
    if Wnd <> 0 then 
    begin 

// WndChild := FindWindowEx(Wnd, 0, 'Shell DocObject View', nil); 
// if WndChild <> 0 then 
// begin 
//  WndChild := FindWindowEx(WndChild, 0, 'Internet Explorer_Server', nil); 

    WndChild := 0; 
    EnumChildWindows(Wnd, @EnumChilds, LongWord(@WndChild)); 

    if WndChild <> 0 then 
    begin 
     Result := WndChild; 
     if Activate then 
     begin 
     if IsIconic(Wnd) then 
      ShowWindow(Wnd, SW_RESTORE) 
     else 
      SetForegroundWindow(Wnd); 
     end; 
    end; 
// end; 
    end; 
end; 

至於方法「2」,我已經看到聲明IE不支持返回其活動對象的參考在網絡上的幾個鏈接,但我對此沒有任何官方參考。

+0

嗨,謝謝你的回答。我正在測試IE6/XP。所以這裏的子窗口可能會有所不同(這不是問題)。什麼是您的默認瀏覽器BTW? – kobik 2012-04-14 15:07:42

+0

但ie6沒有標籤,800美元對ie6沒有意義。我在回答中提到了使用ıe8。 – 2012-04-14 15:44:41

+0

我知道,我希望IE6會忽略這一點(我也試圖通過0作爲標誌),並且由於我獲得了活動的'IHTMLDocument2',我應該能夠'導航'不? – kobik 2012-04-14 17:20:28

相關問題