2009-04-16 7 views
58

Czytałem dużo o uruchamianiu aplikacji z poziomu programu C# (Process.Start()), ale nie udało mi się znaleźć żadnych informacji o tym, jak uruchomić tę nową aplikację w panelu mojego Program C#. Na przykład chciałbym kliknąć przycisk, aby otworzyć plik notepad.exe w mojej aplikacji, a nie na zewnątrz.Jak mogę uruchomić inną aplikację w panelu mojego programu C#?

Odpowiedz

12

Nie wiem, czy nadal jest to zalecane, ale struktura "Łączenie i osadzanie obiektów" pozwala osadzać pewne obiekty/kontrolki bezpośrednio w aplikacji. Prawdopodobnie działa to tylko w przypadku niektórych aplikacji, nie jestem pewien, czy Notepad jest jednym z nich. W przypadku naprawdę prostych rzeczy, takich jak notatnik, najprawdopodobniej będzie Ci łatwiej pracować z formantami pola tekstowego dostarczonymi przez dowolne medium, z którego korzystasz (np. WinForm).

Oto link do informacji OLE zacząć:

http://en.wikipedia.org/wiki/Object_Linking_and_Embedding

-1
Krótka odpowiedź:

Nie

shortish Odpowiedź:

Tylko wtedy, gdy inna aplikacja jest przeznaczona na to pozwolić, dostarczając komponenty, aby dodać do własnej aplikacji.

+2

@PaulSonier - nawet gdy krótka odpowiedź jest całkowicie błędne? ;-) Krótka odpowiedź brzmi: Tak –

1

Jeśli chcesz uruchomić notes wewnątrz aplikacji to prawdopodobnie być lepiej ze składnikiem edytora tekstu. Oczywiście jest to podstawowe pole tekstowe dołączone do WinForm, ale podejrzewam, że w interwebie można znaleźć bardziej zaawansowane komponenty, które oferują funkcjonalność Notatnika (lub lepiej).

+0

Notatnik był tylko przykładem do celów testowych! –

1

Wiem, że jest to możliwe, jeśli druga aplikacja może dołączyć się do uchwytu okna win32. Na przykład mamy oddzielną aplikację C#, która obsługuje aplikację DirectX w jednym ze swoich okien. Nie wiem dokładnie, w jaki sposób jest to zaimplementowane, ale myślę, że wystarczy, że przeniesiemy win32 Handle twojego panelu do drugiej aplikacji, aby ta aplikacja mogła dołączyć swoją powierzchnię DirectX.

86

Korzystanie z API win32 umożliwia "zjedzenie" innej aplikacji. Zasadniczo dostajesz górne okno dla tej aplikacji i ustawiasz, że to rodzic jest uchwytem panelu, w którym chcesz go umieścić. Jeśli nie chcesz efektu stylu MDI, musisz również dostosować styl okna, aby był zmaksymalizowany i usuń pasek tytułu.

Oto prosty przykładowy kod gdzie mam formularz z przycisku i panelu:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Threading; 

namespace WindowsFormsApplication2 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      Process p = Process.Start("notepad.exe"); 
      Thread.Sleep(500); // Allow the process to open it's window 
      SetParent(p.MainWindowHandle, panel1.Handle); 
     } 

     [DllImport("user32.dll")] 
     static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); 
    } 
} 

Widziałem tylko kolejny przykład, w którym nazwali WaitForInputIdle zamiast spania. Więc kod byłoby tak:

Process p = Process.Start("notepad.exe"); 
p.WaitForInputIdle(); 
SetParent(p.MainWindowHandle, panel1.Handle); 

Kodeks Projekt ma dobry artykuł jeden cały proces: Hosting EXE Applications in a WinForm project

+14

Super pomocny! łącze nie pokazuje importu dll dla ich funkcji, więc myślę, że id udostępniają je tutaj [DllImport ("user32.dll")] Statyczny zewnętrzny IntPtr SetParent (IntPtr hWndChild, IntPtr hWndNewParent); [DllImport ("user32.dll")] static extern int SetWindowLong (IntPtr hWnd, int nIndex, int dwNewLong); [DllImport ("user32.dll")] statyczna zewnętrzna bool MoveWindow (IntPtr Handle, int x, int, int, int h, bool repaint); – hrh

+0

ten kod jest również uruchamiany w wpf –

+0

Kiedy używam tego w IE lub Chrome, górna część przeglądarki wyświetla się jako czarna. Czy istnieje sposób, aby zmienić to na przezroczyste, tak aby pokazywało kolor mojego głównego okna? – user21479

2
  • Dodawanie jakieś rozwiązanie w odpowiedzi .. **

ten kod pomógł mi zadokować niektóre pliki wykonywalne w postaci okien. jak NotePad, Excel, word, Acrobat reader n wiele więcej ...

Ale to nie będzie działać dla niektórych aplikacji. Jak czasami, gdy zaczynasz proces jakiejś aplikacji .... czekaj na czas bezczynności ... i spróbuj uzyskać jego głównąWindowHandle ....do czasu okno główne uchwyt staje się zerowa .....

więc zrobiłem jedną sztuczkę, aby rozwiązać ten

Jeśli pojawi się okno główne uchwyt za nieważną ... następnie przeszukać wszystkie procesy runnning na sytem i znajdź, że przetwarzasz ... potem zdobądź główną część procesu i panel zestawu jako jego rodzic.

 ProcessStartInfo info = new ProcessStartInfo(); 
     info.FileName = "xxxxxxxxxxxx.exe"; 
     info.Arguments = "yyyyyyyyyy"; 
     info.UseShellExecute = true; 
     info.CreateNoWindow = true; 
     info.WindowStyle = ProcessWindowStyle.Maximized; 
     info.RedirectStandardInput = false; 
     info.RedirectStandardOutput = false; 
     info.RedirectStandardError = false; 

     System.Diagnostics.Process p = System.Diagnostics.Process.Start(info); 

     p.WaitForInputIdle(); 
     Thread.Sleep(3000); 

     Process[] p1 ; 
    if(p.MainWindowHandle == null) 
    { 
     List<String> arrString = new List<String>(); 
     foreach (Process p1 in Process.GetProcesses()) 
     { 
      // Console.WriteLine(p1.MainWindowHandle); 
      arrString.Add(Convert.ToString(p1.ProcessName)); 
     } 
     p1 = Process.GetProcessesByName("xxxxxxxxxxxx"); 
     //p.WaitForInputIdle(); 
     Thread.Sleep(5000); 
     SetParent(p1[0].MainWindowHandle, this.panel2.Handle); 

    } 
    else 
    { 
    SetParent(p.MainWindowHandle, this.panel2.Handle); 
    } 
1

Zauważyłem, że wszystkie wcześniejsze odpowiedzi wykorzystują starsze funkcje biblioteki użytkownika Win32, aby to osiągnąć. Myślę, że zadziała to w przypadku większości przypadków, ale z czasem będzie działać niezawodnie.

Teraz, nie robiąc tego, nie mogę powiedzieć, jak dobrze to będzie działać, ale wiem, że obecna technologia Windows może być lepszym rozwiązaniem: Desktop Windows Manager API.

DWM to ta sama technologia, która pozwala wyświetlać podgląd miniatur na żywo aplikacji przy użyciu paska zadań i interfejsu przełącznika zadań. Uważam, że jest to ściśle związane z usługami zdalnego terminalu.

Myślę, że prawdopodobnym problemem, który może się zdarzyć, gdy zmuszasz aplikację do bycia dzieckiem okna nadrzędnego, które nie jest oknem pulpitu, jest to, że niektórzy twórcy aplikacji przyjmą założenia dotyczące kontekstu urządzenia (DC), wskaźnika (myszy), szerokości ekranu itd., które mogą powodować błędne lub problematyczne zachowanie, gdy jest "osadzone" w głównym oknie.

Podejrzewam, że można w dużej mierze wyeliminować te problemy, opierając się na DWM, aby pomóc w zarządzaniu tłumaczeniami niezbędnymi do niezawodnego wyświetlania okien aplikacji i interakcji z nimi w oknie kontenera innej aplikacji.

Dokumentacja zakłada programowanie w C++, ale znalazłem osobę, która wyprodukowała to, co twierdzi, jest biblioteką otworkową C# o otwartym kodzie źródłowym: https://bytes.com/topic/c-sharp/answers/823547-desktop-window-manager-wrapper. Post jest stary, a źródło nie znajduje się na dużym repozytorium, takim jak GitHub, bitbucket lub sourceforge, więc nie wiem, jak aktualne jest.

1

Innym ciekawym rozwiązaniem Lüch się exeternal stosowania z pojemnikiem WinForm jest następujący:

[DllImport("user32.dll")] 
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); 


private void Form1_Load(object sender, EventArgs e) 
{ 
    ProcessStartInfo psi = new ProcessStartInfo("notepad.exe"); 
    psi.WindowStyle = ProcessWindowStyle.Minimized; 
    Process p = Process.Start(psi); 
    Thread.Sleep(500); 
    SetParent(p.MainWindowHandle, panel1.Handle); 
    CenterToScreen(); 
    psi.WindowStyle = ProcessWindowStyle.Normal; 
} 

Etap do ProcessWindowStyle.Minimized z ProcessWindowStyle.Normal usunąć przykry opóźnienia.

enter image description here