내 C # 프로그램의 패널 내에서 다른 응용 프로그램을 어떻게 실행할 수 있습니까?
C # 프로그램 (Process.Start ())에서 응용 프로그램을 트리거하는 방법에 대해 많이 읽었지만이 새 응용 프로그램을 C # 프로그램의 패널에서 실행하는 방법에 대한 정보를 찾을 수 없었습니다. . 예를 들어, 외부가 아닌 내 응용 프로그램 내에서 notepad.exe를 열기 위해 버튼을 클릭하고 싶습니다.
이것이 여전히 사용하는 것이 권장되는 것인지는 모르겠지만 "Object Linking and Embedding"프레임 워크를 사용하면 특정 개체 / 컨트롤을 응용 프로그램에 직접 포함 할 수 있습니다. 이것은 아마도 특정 응용 프로그램에서만 작동하며 메모장이 그중 하나인지 확실하지 않습니다. 메모장과 같은 매우 간단한 작업의 경우 사용중인 매체 (예 : 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);
코드 프로젝트에는 전체 프로세스에 대한 좋은 기사 가 있습니다. WinForm 프로젝트에서 EXE 응용 프로그램 호스팅
- Answer .. **에 솔루션 추가
이 코드는 일부 실행 파일을 Windows 형식으로 도킹하는 데 도움이되었습니다. 메모장, 엑셀, 워드, 아크로뱃 리더 등 더 많은 ...
그러나 일부 응용 프로그램에서는 작동하지 않습니다. 때로는 일부 응용 프로그램의 프로세스를 시작할 때 ... 유휴 시간을 기다립니다 ... 그리고 메인 창 핸들이 null이 될 때까지 mainWindowHandle을 가져 오려고합니다 ....
그래서 나는 이것을 해결하기 위해 한 가지 트릭을했습니다.
메인 창 핸들을 null로 얻는 경우 ... 시스템에서 실행중인 모든 프로세스를 검색하고 프로세스를 찾은 다음 프로세스의 주요 하들과 부모로 설정된 패널을 가져옵니다.
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);
}
WinForm 컨테이너를 사용하여 외부 응용 프로그램을 luch하는 또 다른 흥미로운 솔루션은 다음과 같습니다.
[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에서 단계 는 성가신 지연을 제거합니다.
If you want to run notepad inside your app you would probably be better of with a text editor component. There's obviously a basic text box that comes with WinForms, but I suspect more advanced components that offer Notepad functionality (or better) can be found on the interweb.
I know this is possible if the other application can attach itself to a win32 window handle. For example, we have a separate C# application that hosts a DirectX application inside one of its windows. I'm not familiar with the exact details of how this is implemented, but I think just passing the win32 Handle
of your panel to the other application is enough for that application to attach its DirectX surface.
I notice that all the prior answers use older Win32 User library functions to accomplish this. I think this will work in most cases, but will work less reliably over time.
Now, not having done this, I can't tell you how well it will work, but I do know that a current Windows technology might be a better solution: the Desktop Windows Manager API.
DWM is the same technology that lets you see live thumbnail previews of apps using the taskbar and task switcher UI. I believe it is closely related to Remote Terminal services.
I think that a probable problem that might happen when you force an app to be a child of a parent window that is not the desktop window is that some application developers will make assumptions about the device context (DC), pointer (mouse) position, screen widths, etc., which may cause erratic or problematic behavior when it is "embedded" in the main window.
I suspect that you can largely eliminate these problems by relying on DWM to help you manage the translations necessary to have an application's windows reliably be presented and interacted with inside another application's container window.
문서는 C ++ 프로그래밍을 가정하지만 그가 주장하는 것을 제작 한 한 사람이 오픈 소스 C # 래퍼 라이브러리임을 발견했습니다. https://bytes.com/topic/c-sharp/answers/823547-desktop-window-manager-wrapper . 게시물이 오래되었고 소스가 GitHub, bitbucket 또는 sourceforge와 같은 큰 저장소에 없기 때문에 얼마나 최신인지 모르겠습니다.
짧은 답변:
아니
짧은 답변 :다른 응용 프로그램이이를 허용하도록 설계된 경우에만 사용자가 자신의 응용 프로그램에 추가 할 수있는 구성 요소를 제공합니다.
'developer tip' 카테고리의 다른 글
NVM을 사용하여 기본 노드 버전을 어떻게 설정할 수 있습니까? (0) | 2020.11.11 |
---|---|
순서를 유지하면서 정렬 된 목록을 데이터베이스에 저장하는 가장 좋은 방법 (0) | 2020.11.11 |
Java HashMap keySet () 반복 순서가 일치합니까? (0) | 2020.11.11 |
Javascript / jQuery에서 문자열의 픽셀 길이를 결정합니까? (0) | 2020.11.11 |
Linux 용 예쁘고 기능이 풍부한 Git GUI (0) | 2020.11.11 |