it-swarm.com.ru

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

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

66
Alex

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

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

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

14
Andy White

Используя 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

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

Этот код помог мне закрепить исполняемый файл в форме 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);
     }
4
Saurabh Raoot

Еще одно интересное решение для внешнего приложения с контейнером 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 удалить раздражающую задержку.

enter image description here

3
daniele3004

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

1
Steve Haigh

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

1
Anthony Brien

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

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

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

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

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

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

1
Alan McBee - MSFT