Как я могу запустить другое приложение на панели моей программы на C#?
Я много читал о том, как запустить приложение из программы на C# (Process.Start()), но я не смог найти никакой информации о том, как запустить это новое приложение на панели моей программы на C#, Например, я бы хотел, чтобы щелчок по кнопке открывал notepad.exe В МОЕМ приложении, а не внешне.
8 ответов
Я не знаю, рекомендуется ли это использовать, но инфраструктура "Связывание и внедрение объектов" позволяет вам встраивать определенные объекты / элементы управления непосредственно в ваше приложение. Это, вероятно, будет работать только для определенных приложений, я не уверен, является ли Блокнот одним из них. Для действительно простых вещей, таких как блокнот, вам, вероятно, будет легче работать с элементами управления текстовым полем, предоставляемыми любым используемым средством (например, WinForms).
Вот ссылка на информацию OLE, чтобы начать:
Используя 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.
нет
Короткий ответ:Только если другое приложение предназначено для этого, предоставляя компоненты для добавления в ваше собственное приложение.