2009-04-28 9 views
11

W Delphi używałem ShellExecute od lat do uruchamiania (i opcjonalnie oczekiwania) innych aplikacji. Teraz jednak muszę mieć jedną z tych aplikacji w jednym z moich formularzy aplikacji Delphi. Próbowałem kodu poniżej jako prosty test, aby otworzyć notatnik (co robi) i wyświetlić wynik w formularzu PAnel1 na moim formularzu (co nie robi). Czy jakaś dobra osoba może postawić mnie na właściwej drodze? DziękiJak uzyskać dostęp do innej aplikacji i wyświetlić ją w formularzu delphi

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

Co chcesz zrobić z głównym menu Notatnika? – Alex

Odpowiedz

15

Wszystko sprawdzanie błędów pominięte, ale to powinno Ci zacząć:

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; 

Co powinno się zrobić, to wymienić okna nowego procesu, zamiast po prostu stosując dowolny uchwyt okna, które FindWindow() zwraca.

+0

Świetne, dzięki. Chciałbym tylko zrozumieć, co się dzieje .....! Wyłącz teraz, aby usunąć niektóre bity, aby zobaczyć, co się dzieje. Dzięki jeszcze raz. Bri –

+0

Jestem ciekawy - czy to zminimalizuje, zmaksymalizuje zmianę z porządku i takie? Czy może do tego dodać więcej funkcji TForm1.Form *? Wygląda całkiem nieźle. – paxdiablo

+0

Jedynym problemem jest to, że przyciski paska napisów Notatnika są zachowane, więc nadal można zminimalizować, zmaksymalizować lub zamknąć Notatnik.Dla właściwego rozwiązania prawdopodobnie cały pasek napisów powinien zostać usunięty. W zależności od wymagań może być konieczne więcej, ale problem w pytaniu rozwiązany jest powyższym kodem. – mghie

0

To będzie trudne, o ile to możliwe.

Widziałem podejścia, które będą działać w aplikacjach tekstowych - zwykle przechwytują standardowe wyniki procesu i przechodzą do kontroli tekstu.

Ale to, o czym mówisz, to w pełni rozwinięta aplikacja graficzna (Notatnik, pomimo pracy nad tekstem, pikselami ekranowymi, a nie kodami znaków).

Więc chyba Notepad zapewnia interfejs, gdzie można:

  • żądań dowolnych znaków w buforze; i
  • wysyłaj dowolne naciśnięcia klawiszy do programu, Powiedziałbym, że nie masz szczęścia.

Zdecydowanie kundel, ale jedną z opcji jest ciągłe monitorowanie okien Notatnika i zapewnienie, że zawsze jest nałożony na obszar klienta formularzy. To okropne, ponieważ musisz powstrzymać ruch, zmianę rozmiaru, minimalizowanie itd., i utrzymywanie porządku zera, aby znajdować się tuż nad twoimi aplikacjami. Nie życzyłbym sobie tych wymagań wobec mojego najgorszego wroga.

Czy myślałeś o użyciu formantu edytora zbudowanego specjalnie dla Delphi (lub edytora ActiveX, który można osadzić)? To może być lepsze podejście.

+0

Uważam, że Notatnik jest tylko symbolem zastępczym dla innych programów, które mogą wypróbować tę technikę. I chociaż zgadzam się z ogólną opinią, że nie robimy tego, jeśli jest inny sposób, po prostu ustawienie rodzica HWND i wykonanie pozycjonowania nie jest takie trudne. – mghie

+0

Sterowanie ActiveX/OLE zdecydowanie byłoby lepsze. Jednak z pewnością możliwe jest umieszczenie okna innej aplikacji w aplikacji. Zrobiłem coś takiego w VB, ale myślę, że użyłem formularza MDI. Należy również względnie łatwo przechwytywać i wysyłać sekwencje klawiszy do innej postaci okna poprzez podklasy. Ale minęło już prawie dziesięć lat, odkąd zaprzątałem sobie głowę takimi rzeczami. – Calvin

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); 
Powiązane problemy