2009-04-28 55 views
11

在德爾福,我用ShellExecute多年來啓動(和可選地等待)其他應用程序。但現在,我需要將其中一個應用程序顯示在我的一個Delphi應用程序窗體中。我試過下面的代碼作爲一個簡單的測試來打開記事本(它會這樣做)並在我的表單上顯示PAnel1中的結果(它沒有)。有人能讓我走上正軌嗎? 感謝如何shell到另一個應用程序,並以德爾菲形式出現

var 
    Rec   : TShellExecuteInfo; 
    wnd : HWnd; 
const 
    AVerb = 'open'; 
    AParams = ''; 
    AFileName = 'Notepad.exe'; 
    ADir = ''; 
begin 
    FillChar(Rec, SizeOf(Rec), #0); 

    Rec.cbSize  := SizeOf(Rec); 
    Rec.fMask  := SEE_MASK_NOCLOSEPROCESS; 
    Rec.lpVerb  := PChar(AVerb); 
    Rec.lpFile  := PChar(AfileName); 
    Rec.lpParameters := PChar(AParams); 
    Rec.lpDirectory := PChar(Adir); 
    Rec.nShow  := sw_Show; 

    ShellExecuteEx(@Rec); 

    wnd := Windows.FindWindow('Notepad', nil); 
    Windows.SetParent(Wnd, PAnel1.Handle); 

end; 
+0

你想用記事本的主菜單做什麼? – Alex 2009-04-28 09:08:31

回答

15

所有錯誤檢查省略,但這應該讓你開始:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Rec: TShellExecuteInfo; 
const 
    AVerb = 'open'; 
    AParams = ''; 
    AFileName = 'Notepad.exe'; 
    ADir = ''; 
begin 
    FillChar(Rec, SizeOf(Rec), #0); 

    Rec.cbSize  := SizeOf(Rec); 
    Rec.fMask  := SEE_MASK_NOCLOSEPROCESS; 
    Rec.lpVerb  := PChar(AVerb); 
    Rec.lpFile  := PChar(AfileName); 
    Rec.lpParameters := PChar(AParams); 
    Rec.lpDirectory := PChar(Adir); 
    Rec.nShow  := SW_HIDE; 

    ShellExecuteEx(@Rec); 
    WaitForInputIdle(Rec.hProcess, 5000); 

    fNotepadHandle := Windows.FindWindow('Notepad', nil); 
    Windows.SetParent(fNotepadHandle, Handle); 

    Resize; 
    ShowWindow(fNotepadHandle, SW_SHOW); 
end; 

procedure TForm1.FormResize(Sender: TObject); 
begin 
    if IsWindow(fNotepadHandle) then begin 
    SetWindowPos(fNotepadHandle, 0, 0, 0, ClientWidth, ClientHeight, 
     SWP_ASYNCWINDOWPOS); 
    end; 
end; 

什麼你絕對應該做的是枚舉新進程的窗口,而不是簡單地使用任何窗口句柄FindWindow函數()回報。

0

這將是一個棘手的,如果它甚至有可能。

我已經看到了適用於基於文本的應用程序的方法 - 它們通常捕獲進程的標準輸出,並將其放入文本控件中。

但是你說的是一個完全成熟的圖形應用程序(記事本,儘管在文本,顯示像素,而不是字符代碼)。

所以,除非記事本提供了一種界面,在此:在緩衝

  • 請求任意字符;和
  • 發送任意擊鍵到程序, 我會說你平平運氣。

肯定是一個kludge,但一種選擇是連續監視記事本窗口,並確保它總是疊加在您的窗體客戶區。這是非常可怕的,因爲你必須阻止它移動,調整大小,最小化等等,保持其z-順序在你的應用程序之上。我不希望這些要求對我最大的敵人。

你有沒有想過使用專門爲Delphi構建的編輯器控件(或者你可以嵌入的ActiveX編輯器)?這可能是一個更好的方法。

+0

我認爲記事本只是其他程序的佔位符,可以嘗試使用此技術。雖然我同意你的一般觀點,如果還有其他方法,那麼只需設置父HWND並進行定位並不困難。 – mghie 2009-04-28 09:14:32

+0

ActiveX/OLE控件肯定會更好。但是,將另一個應用程序的窗口放入應用程序當然是可能的。我在VB中做過類似的事情,但我認爲我使用了MDI表單。 而且通過子類捕獲和發送擊鍵到另一個窗體應該相對容易。但是,自從我對這類東西感到厭煩已經有近十年了。 – Calvin 2009-04-28 09:18:02

2
var 
    URL: string; 
begin 
    URL:= DBMemoURL.Text; 
    // ShellExecute(self.WindowHandle,'open', PChar(URL), nil, nil, SW_SHOW); //default browser 
    ShellExecute(self.WindowHandle,'open','chrome.exe', PChar(URL), nil, SW_SHOW);