Question

J'ai lu beaucoup sur la façon de déclencher une application à partir d'un programme C # (Process.Start ()), mais je n ai pas été en mesure de trouver des informations sur la façon d'avoir cette nouvelle exécution de l'application dans un panneau de mon programme C #. Par exemple, je voudrais un bouton cliquez pour ouvrir un notepad.exe dans mon application et non à l'extérieur.

Était-ce utile?

La solution

Je ne sais pas si cela est encore la chose recommandée à utiliser, mais le « Object Linking and Embedding » cadre vous permet d'intégrer certains objets / contrôles directement dans votre application. Ce sera probablement ne fonctionnera que pour certaines applications, je ne sais pas si le Bloc-notes est l'un d'entre eux. Pour des choses très simples comme le bloc-notes, vous aurez probablement un temps plus facile de travailler avec les contrôles de zone de texte quel que soit le moyen que vous utilisez (par exemple WinForms).

Voici un lien vers les informations OLE pour commencer:

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

Autres conseils

En utilisant l'API win32 il est possible de "manger" une autre application. Fondamentalement, vous obtenez la fenêtre supérieure pour cette application et de définir son parent d'être la poignée du panneau que vous souhaitez placer. Si vous ne voulez pas l'effet de style MDI vous devez également ajuster le style de fenêtre pour la rendre maximisée et retirer la barre de titre.

Voici un code simple exemple où j'ai un formulaire avec un bouton et un panneau:

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

Je viens de voir un autre exemple où ils ont appelé WaitForInputIdle au lieu de dormir. Ainsi, le code serait comme ceci:

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

Le Code du projet a un bon article un ensemble du processus: Hébergement Applications EXE dans un WinForm projet

  • Ajout d'une solution dans réponse .. **

Ce code m'a aidé à arrimer certains exécutables sous forme de fenêtres. comme NotePad, Excel, Word, Acrobat reader n beaucoup plus ...

Mais cela ne fonctionnera pas pour certaines applications. Comme parfois, quand vous commencez processus d'une application .... attendre que le temps de repos ... et essayer d'obtenir son mainWindowHandle .... jusqu'au moment où la principale poignée de fenêtre devient nulle .....

donc je l'ai fait un truc pour résoudre ce

Si vous obtenez principale poignée de fenêtre nulle ... recherche alors tous les processus de runnning sur sytem et vous trouverez ... puis traiter obtenir le principal hadle du processus et le panneau de jeu comme parent.

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

Une autre solution intéressante à Luch une application exeternal avec un conteneur de WinForm est le suivante:

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

L'étape de ProcessWindowStyle.Minimized de ProcessWindowStyle.Normal supprimer le retard gênant.

Si vous voulez exécuter le bloc-notes dans votre application, vous seriez probablement mieux avec un composant éditeur de texte. Il y a de toute évidence une zone de texte de base qui vient avec WinForms, mais je soupçonne que des composants plus avancés qui offrent des fonctionnalités Bloc-notes (ou mieux) se trouve sur l'interweb.

Je sais que cela est possible si l'autre application peut se joindre à une poignée de fenêtre win32. Par exemple, nous avons une demande distincte C # qui héberge une application DirectX dans l'une de ses fenêtres. Je ne connais pas les détails exacts de comment cela est mis en œuvre, mais je pense que passer le Handle win32 de votre panneau à l'autre application est suffisante pour que l'application d'attacher sa surface DirectX.

Je remarque que toutes les réponses précédentes utilisent Win32 fonctions de bibliothèque utilisateur âgées pour y parvenir. Je pense que cela va fonctionner dans plus cas, mais fonctionnera moins fiable au fil du temps.

Maintenant, ne pas avoir fait cela, je ne peux pas vous dire à quel point cela va fonctionner, mais je ne sais qu'une technologie Windows actuelle pourrait être une meilleure solution: windows desktop Manager API .

DWM est la même technologie qui vous permet de voir les vignettes de prévisualisation des applications en utilisant le commutateur barre des tâches et des tâches interface utilisateur. Je crois qu'il est étroitement lié aux services Terminal Server à distance.

Je pense qu'il ya un problème probable qui pourrait se produire lorsque vous forcer une application à être un enfant d'une fenêtre parent qui n'est pas la fenêtre du bureau est que certains développeurs d'applications faire des hypothèses sur le contexte de périphérique (DC), pointeur (souris ) la position, la largeur d'écran, etc., ce qui peut causer un comportement erratique ou problématique quand il est « intégré » dans la fenêtre principale.

Je pense que vous pouvez éliminer en grande partie ces problèmes en se fondant sur DWM pour vous aider à gérer les traductions nécessaires pour que les fenêtres d'une application sont présentées de manière fiable et interagi avec l'intérieur de la fenêtre conteneur d'une autre application.

La documentation suppose la programmation C ++, mais je l'ai trouvé une personne qui a produit ce qu'il prétend est une open source C # bibliothèque wrapper: https://bytes.com/topic/c-sharp/answers/823547-desktop-window-manager-wrapper . Le poste est vieux, et la source n'est pas sur un grand dépôt comme GitHub, bitbucket ou sourceforge, donc je ne sais pas comment il est courant.

Réponse courte:

Non

Shortish Réponse:

Seulement si l'autre application est conçue pour lui permettre, en fournissant des composants pour vous d'ajouter dans votre propre application.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top