Come posso eseguire un’altra applicazione all’interno di un pannello del mio programma C #?

Ho letto molto su come triggersre un’applicazione da un programma C # (Process.Start ()), ma non sono stato in grado di trovare alcuna informazione su come far funzionare questa nuova applicazione all’interno di un pannello del mio programma C # . Ad esempio, mi piacerebbe un clic del pulsante per aprire un notepad.exe ENTRO la mia applicazione, non esternamente.

Non so se questa sia ancora la cosa consigliata da usare ma il framework “Object Linking and Embedding” ti permette di incorporare determinati oggetti / controlli direttamente nella tua applicazione. Probabilmente questo funzionerà solo per determinate applicazioni, non sono sicuro che il Blocco note sia uno di questi. Per cose davvero semplici come il blocco note, probabilmente avrai un tempo più semplice semplicemente lavorando con i controlli della casella di testo forniti da qualsiasi supporto (ad esempio WinForms).

Ecco un collegamento alle informazioni OLE per iniziare:

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

Utilizzando l’API win32 è ansible “mangiare” un’altra applicazione. Fondamentalmente si ottiene la finestra superiore per quell’applicazione e si imposta il genitore come l’handle del pannello in cui si desidera inserirlo. Se non si desidera l’effetto di stile MDI, è inoltre necessario regolare lo stile della finestra per renderlo massimizzato e rimuovere la barra del titolo.

Ecco alcuni semplici esempi di codice in cui ho un modulo con un pulsante e un pannello:

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); } } 

Ho appena visto un altro esempio in cui hanno chiamato WaitForInputIdle invece di dormire. Quindi il codice sarebbe come questo:

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

Il Code Project ha un buon articolo uno l’intero processo: Hosting di applicazioni EXE in un progetto WinForm

  • Aggiunta di una soluzione in risposta .. **

Questo codice mi ha aiutato ad agganciare alcuni eseguibili in forma di windows. come NotePad, Excel, word, Acrobat reader n molti altri …

Ma non funzionerà per alcune applicazioni. Come a volte quando si avvia il processo di qualche applicazione …. attendi il tempo di inattività … e prova a ottenere il suo MainWindowHandle …. fino al momento in cui l’handle della finestra principale diventa nullo …..

quindi ho fatto un trucco per risolvere questo

Se ottieni l’handle della finestra principale come null … quindi cerca tutti i processi runnning su sytem e scopri come processare … quindi ottieni l’aspetto principale del processo e il pannello dell’insieme come genitore.

  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 arrString = new List(); 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); } 

Un’altra soluzione interessante per recuperare un’applicazione esterna con un contenitore WinForm è la seguente:

 [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; } 

Il passaggio a ProcessWindowStyle.Minimized da ProcessWindowStyle.Normal rimuove il fastidioso ritardo.

inserisci la descrizione dell'immagine qui

Se vuoi eseguire il blocco note all’interno della tua app probabilmente starai meglio con un componente di editor di testo. C’è ovviamente una casella di testo di base che viene fornito con WinForms, ma sospetto che i componenti più avanzati che offrono funzionalità di Blocco note (o meglio) possono essere trovati su interweb.

So che questo è ansible se l’altra applicazione può collegarsi a un handle di finestra Win32. Ad esempio, abbiamo un’applicazione C # separata che ospita un’applicazione DirectX in una delle sue windows. Non ho familiarità con i dettagli esatti di come questo è implementato, ma penso che passare l’ Handle win32 del pannello all’altra applicazione sia sufficiente per quell’applicazione per colbind la sua superficie DirectX.

Ho notato che tutte le risposte precedenti utilizzano le vecchie funzioni della libreria utente Win32 per ottenere ciò. Penso che funzionerà nella maggior parte dei casi, ma funzionerà in modo meno affidabile nel tempo.

Ora, non avendo fatto questo, non posso dirti quanto bene funzionerà, ma so che una tecnologia Windows attuale potrebbe essere una soluzione migliore: l’ API di Windows Manager Desktop .

DWM è la stessa tecnologia che consente di visualizzare anteprime in miniatura delle app utilizzando la barra delle applicazioni e l’interfaccia utente del commutatore di attività. Credo che sia strettamente correlato ai servizi di Remote Terminal.

Penso che un probabile problema che potrebbe accadere quando imponi a un’app di essere figlio di una finestra genitore che non è la finestra del desktop è che alcuni sviluppatori di applicazioni faranno ipotesi sul contesto del dispositivo (DC), sulla posizione del puntatore (mouse), larghezze dello schermo, ecc., che possono causare un comportamento irregolare o problematico quando è “incorporato” nella finestra principale.

Ho il sospetto che tu possa in gran parte eliminare questi problemi affidandoti a DWM per aiutarti a gestire le traduzioni necessarie ad avere windows di un’applicazione presentate e interagite in modo affidabile all’interno della finestra del contenitore di un’altra applicazione.

La documentazione presuppone la programmazione in C ++, ma ho trovato una persona che ha prodotto ciò che afferma essere una libreria di wrapper C # open source: https://bytes.com/topic/c-sharp/answers/823547-desktop-window-manager-wrapper . Il post è vecchio e la fonte non è su un grande repository come GitHub, bitbucket o sourceforge, quindi non so quanto sia attuale.

Risposta breve:

No

Risposta breve:

Solo se l’altra applicazione è progettata per consentirlo, fornendo componenti da aggiungere alla propria applicazione.