Mon,
ich habe die Anforderung erhalten, das ich aus einem C# Programm heraus externe Programme aufrufen soll. Allerdings sollen diese nicht wie "normal" auf der Windows-Oberfläche laufen, sondern in einem C# Fenster.
Hat jemand von Euch schon mal was mit einem solchen Problem zu tuen gehabt und kann mir Anhaltspunkte nennen?
Danke
Hallo,
ja sowas würde gehen, aber es ist total unsauber, weil man nie weiß wie sich die Programme verhalten, wenn diese einen anderen Parent als erwartet erhalten.
Das Fenster innerhalb von c# muss dazu ein MdiContainer sein. Das Fremdfenster musst du dann per SetParent umbiegen. Aber wie gesagt, schön ist was anderes.
"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)
Okay,
ich habe nun also ein neues Fenster und hole mir dort aus der user32.dll das SetParent. So weit so gut.
Wie geht es jetzt weiter? Ich erstelle derzeit einen Process und übergebe das zu startende Programm.
Und da häng ich jetzt .... Hast Du noch etwas Hilfe für mich?
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr child, IntPtr newParent);
public ProgrammStarter()
{
InitializeComponent();
}
private void ProgrammStarter_Load(object sender, EventArgs e)
{
Process proc = new Process();
proc.StartInfo.FileName = ProgToStart;
proc.StartInfo.UseShellExecute = true;
//proc.Start();
}
Muss ich das Programm zunächst jetzt starten, mir dann die Process ID holen und das dann wieder auf das C# Fenster verbiegen?
Nein. Du musst dir das Mainwindow des Prozesses Holen, nachdem es gestartet ist und dann musst du mit SetParent sagen, das das Fremde Fenster das Childfenster deines Fensters ist. Das geht alles über den Windowhandle (intptr)
Super, danke.
Das läuft und ich habe die Programme jetzt im Fenster.
Bleibt nur noch eine Frage:
Wie kann ich das auszuführende Programm im Fenster korrekt positionieren?
Ich mach das derzeit so, um das Programm zunächst nicht anzuzeigen:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr child, IntPtr newParent);
Process proc = new Process();
public ProgrammStarter()
{
InitializeComponent();
}
private void ProgrammStarter_Load(object sender, EventArgs e)
{
proc.StartInfo.FileName = Sidebar.ProgToStart;
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.Start();
}
protected override void OnShown(EventArgs e)
{
System.Threading.Thread.Sleep(1000);
IntPtr processWindowHandle = proc.MainWindowHandle;
SetParent(processWindowHandle, this.Handle);
base.OnShown(e);
}
Das Program wird also Hidden gestartet und ist somit auch im Fenster nciht mehr sichtbar 😦
Über ShowWindow
"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)
Naja, damit wird das Fenster wieder sichtbar. Aber leider nciht maximiert.
Ich möchte dies aber maximiert anzeigen!
Hast du du ShowWIndow auch mit SW_SHOWMAXIMIZED aufgerufen?
"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)
Sorry, mein Fehler.
Jetzt geht es. Ich poste nachher mal den Code, wenn ich fertig bin.
Danke für die Hilfe.
Ich habe nun nur noch das Problem, das nicht jedes Programm im Fenster dargstellt wird. Ist anscheinend abhängig von der Ladezeit des Programms.
Hat noch jemand eine kurze Idee, wie man das umgehen kann?
Hallo!
Es gibt in der Process-Klasse die Methode WaitForInputIdle, die könnte dein Problem lösen.
Nobody is perfect. I'm sad, i'm not nobody 🙁
Hallo!
Reiner Egoismus: Binn gespannt auf die Lösung.
Nobody is perfect. I'm sad, i'm not nobody 🙁
Da der Code nicht mehr gepostet wurde, stellt sich für mich noch die Frage wie der Prozess angezeigt werden kann.
Soviel ich verstanden habe (MSDN) muss ich mit ShowWindow die Form aufrufen. Leider ist dies aber nicht verfügbar (steckt das nicht in der user32 ?!).
Anbei mein Code zum Aufrufen des Prozesses:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr child, IntPtr newParent);
Process proc = new Process();
private void Form1_Load(object sender, EventArgs e)
{
proc.StartInfo.FileName = FILENAME;
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.Start();
proc.WaitForInputIdle();
IntPtr processWindowHandle = proc.MainWindowHandle;
SetParent(processWindowHandle, this.Handle);
ShowWindow(SW_SHOWMAXIMIZED, 3); //FEHLER
}
Danke schon mal 😃
Gruß
cyn
Hallo cyntonix,
das DllImport für ShowWindow fehlt ja auch.
In welcher DLL sich die Funktion befindet, steht in der Win32-Doku.
herbivore