Mit der win32-API ist es möglich, eine andere Anwendung zu "essen". Grundsätzlich erhalten Sie das oberste Fenster für diese Anwendung und legen fest, dass das übergeordnete Fenster das Handle des Bedienfelds ist, in dem Sie es platzieren möchten. Wenn Sie den MDI-Stileffekt nicht möchten, müssen Sie auch den Fensterstil anpassen, um ihn zu maximieren und zu maximieren Entfernen Sie die Titelleiste.
Hier ist ein einfacher Beispielcode, in dem ich ein Formular mit einer Schaltfläche und einem Bedienfeld habe:
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);
SetParent(p.MainWindowHandle, panel1.Handle);
}
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
}
}
Ich habe gerade ein anderes Beispiel gesehen, in dem WaitForInputIdle aufgerufen wurde, anstatt zu schlafen. Der Code würde also so aussehen:
Process p = Process.Start("notepad.exe");
p.WaitForInputIdle();
SetParent(p.MainWindowHandle, panel1.Handle);
Das Code-Projekt enthält einen guten Artikel über den gesamten Prozess: Hosten von EXE-Anwendungen in einem WinForm-Projekt
Dieser Code hat mir geholfen, einige ausführbare Dateien in Windows-Form anzudocken. wie NotePad, Excel, Word, Acrobat Reader n viele mehr ...
Bei einigen Anwendungen funktioniert dies jedoch nicht. Wie manchmal, wenn Sie den Prozess einer Anwendung starten ... warten Sie auf die Leerlaufzeit ... und versuchen Sie, das mainWindowHandle abzurufen ... bis das Handle des Hauptfensters null wird .....
Also habe ich einen Trick gemacht, um das zu lösen
Wenn Sie das Hauptfenster-Handle als null erhalten ... dann durchsuchen Sie alle laufenden Prozesse auf dem System und finden Sie Ihren Prozess ... dann erhalten Sie die Haupt-Hadle des Prozesses und das Set-Panel als übergeordnetes Element.
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); }
quelle
Eine weitere interessante Lösung für eine externe Anwendung mit einem WinForm-Container ist die folgende:
[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; }
Der Schritt
ProcessWindowStyle.Minimized
von ProcessWindowStyle.Normal entfernt die störende Verzögerung.quelle
Ich stelle fest, dass alle vorherigen Antworten ältere Funktionen der Win32-Benutzerbibliothek verwenden, um dies zu erreichen. Ich denke, dass dies in den meisten Fällen funktionieren wird, aber im Laufe der Zeit weniger zuverlässig.
Nachdem ich dies nicht getan habe, kann ich Ihnen nicht sagen, wie gut es funktionieren wird, aber ich weiß, dass eine aktuelle Windows-Technologie eine bessere Lösung sein könnte: die Desktop Windows Manager-API .
DWM ist dieselbe Technologie, mit der Sie mithilfe der Taskleiste und der Task-Switcher-Benutzeroberfläche eine Live-Vorschau von Apps anzeigen können. Ich glaube, es hängt eng mit den Diensten des Remote-Terminals zusammen.
Ich denke, dass ein wahrscheinliches Problem, das auftreten kann, wenn Sie eine App dazu zwingen, ein untergeordnetes Element eines übergeordneten Fensters zu sein, das nicht das Desktop-Fenster ist, darin besteht, dass einige Anwendungsentwickler Annahmen über den Gerätekontext (DC), die Zeigerposition (Maus) treffen. Bildschirmbreiten usw., die zu unregelmäßigem oder problematischem Verhalten führen können, wenn sie in das Hauptfenster "eingebettet" werden.
Ich vermute, dass Sie diese Probleme weitgehend beseitigen können, indem Sie sich auf DWM verlassen, um die Übersetzungen zu verwalten, die erforderlich sind, damit die Fenster einer Anwendung zuverlässig im Containerfenster einer anderen Anwendung dargestellt und mit ihnen interagiert werden.
Die Dokumentation geht von C ++ - Programmierung aus, aber ich habe eine Person gefunden, die eine Open-Source-C # -Wrapper-Bibliothek erstellt hat: https://bytes.com/topic/c-sharp/answers/823547-desktop-window-manager-wrapper . Der Beitrag ist alt und die Quelle befindet sich nicht in einem großen Repository wie GitHub, Bitbucket oder Sourceforge. Daher weiß ich nicht, wie aktuell sie ist.
quelle
Wenn Sie den Editor in Ihrer App ausführen möchten, ist eine Texteditor-Komponente wahrscheinlich besser geeignet. Es gibt natürlich ein grundlegendes Textfeld, das mit WinForms geliefert wird, aber ich vermute, dass im Internet erweiterte Komponenten mit Notepad-Funktionalität (oder besser) zu finden sind.
quelle
Ich weiß, dass dies möglich ist, wenn sich die andere Anwendung an ein Win32-Fensterhandle anhängen kann. Zum Beispiel haben wir eine separate C # -Anwendung, die eine DirectX-Anwendung in einem ihrer Fenster hostet. Ich bin nicht mit den genauen Details der Implementierung vertraut, aber ich denke,
Handle
dass es ausreicht , nur die win32 Ihres Panels an die andere Anwendung zu übergeben, damit diese Anwendung ihre DirectX-Oberfläche anbringt.quelle
Nein
Kurze Antwort:Nur wenn die andere Anwendung dies zulässt, indem Sie Komponenten bereitstellen, die Sie zu Ihrer eigenen Anwendung hinzufügen können.
quelle