Как я могу запустить другое приложение на панели моей программы на C#?

Я много читал о том, как запустить приложение из программы на C# (Process.Start()), но я не смог найти никакой информации о том, как запустить это новое приложение на панели моей программы на C#, Например, я бы хотел, чтобы щелчок по кнопке открывал notepad.exe В МОЕМ приложении, а не внешне.

8 ответов

Решение

Я не знаю, рекомендуется ли это использовать, но инфраструктура "Связывание и внедрение объектов" позволяет вам встраивать определенные объекты / элементы управления непосредственно в ваше приложение. Это, вероятно, будет работать только для определенных приложений, я не уверен, является ли Блокнот одним из них. Для действительно простых вещей, таких как блокнот, вам, вероятно, будет легче работать с элементами управления текстовым полем, предоставляемыми любым используемым средством (например, WinForms).

Вот ссылка на информацию OLE, чтобы начать:

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

Используя win32 API, можно "съесть" другое приложение. По сути, вы получаете верхнее окно для этого приложения и задаете его родительский дескриптор панели, в которую хотите поместить его. Если вам не нужен эффект стиля MDI, вам также нужно настроить стиль окна, чтобы сделать его максимально развернутым и удалить строку заголовка.

Вот простой пример кода, где у меня есть форма с кнопкой и панелью:

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

Я только что видел другой пример, где они вызывали WaitForInputIdle вместо сна. Таким образом, код будет выглядеть так:

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

У Code Project есть хорошая статья, посвященная всему процессу: размещение EXE-приложений в проекте WinForm.

Еще одно интересное решение для внешнего приложения с контейнером WinForm заключается в следующем:

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

Шаг к ProcessWindowStyle.Minimized из ProcessWindowStyle.Normal удалить раздражающую задержку.

  • Добавление решения в ответ.**

Этот код помог мне закрепить исполняемый файл в форме Windows. например NotePad, Excel, Word, Acrobat Reader и многие другие...

Но это не будет работать для некоторых приложений. Как иногда, когда вы запускаете процесс какого-то приложения.... ждите простоя... и попробуйте получить его mainWindowHandle.... до тех пор, пока дескриптор главного окна не станет нулевым.....

поэтому я сделал один трюк, чтобы решить это

Если вы получаете дескриптор главного окна как ноль..., тогда ищите все запущенные процессы в sytem и находите ваш процесс... затем получите главный хэдл процесса и панель set в качестве его родителя.

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

Я заметил, что все предыдущие ответы используют для этого более старые функции библиотеки пользователей Win32. Я думаю, что это будет работать в большинстве случаев, но со временем будет работать менее надежно.

Теперь, не сделав этого, я не могу сказать вам, насколько хорошо это будет работать, но я знаю, что текущая технология Windows может быть лучшим решением: API-интерфейс Desktop Manager для Windows.

DWM - это та же технология, которая позволяет просматривать живые эскизы приложений в реальном времени с помощью панели задач и интерфейса переключателя задач. Я считаю, что это тесно связано со службами удаленного терминала.

Я думаю, что вероятная проблема, которая может возникнуть, когда вы заставляете приложение быть дочерним по отношению к родительскому окну, которое не является окном рабочего стола, состоит в том, что некоторые разработчики приложений делают предположения относительно контекста устройства (DC), положения указателя (мыши), ширины экрана и т. д., что может привести к ошибочному или проблематичному поведению, когда он "встроен" в главное окно.

Я подозреваю, что вы можете в значительной степени устранить эти проблемы, полагаясь на DWM, который поможет вам управлять переводами, необходимыми для надежного представления окон приложения и взаимодействия с ними внутри окна контейнера другого приложения.

Документация предполагает программирование на C++, но я нашел одного человека, который создал то, что, как он утверждает, является библиотекой с открытым исходным кодом C#: https://bytes.com/topic/c-sharp/answers/823547-desktop-window-manager-wrapper, Сообщение старое, и источник не находится в большом репозитории, таком как GitHub, bitbucket или sourceforge, поэтому я не знаю, насколько он актуален.

Если вы хотите запустить блокнот внутри своего приложения, вам, вероятно, лучше использовать компонент текстового редактора. Очевидно, что есть базовое текстовое поле, которое поставляется с WinForms, но я подозреваю, что более сложные компоненты, которые предлагают функциональность Notepad (или лучше), могут быть найдены на веб-сайте.

Я знаю, что это возможно, если другое приложение может присоединиться к дескриптору окна win32. Например, у нас есть отдельное приложение C#, которое размещает приложение DirectX в одном из своих окон. Я не знаком с точными деталями того, как это реализовано, но я думаю, что просто передать win32 Handle вашей панели к другому приложению достаточно для этого приложения, чтобы прикрепить свою поверхность DirectX.

Короткий ответ:

нет

Короткий ответ:

Только если другое приложение предназначено для этого, предоставляя компоненты для добавления в ваше собственное приложение.

Другие вопросы по тегам