目的
次のコードを使用して、Windowsフォームにいくつかのアプリケーションをロードすることができました。
コード
この関数が行うことは...
- プロセスを述べる
- プロセスを私のフォームのパネルに埋め込む
- 埋め込まれたプロセスを最大化する
- パネルにサイズ変更イベントハンドラーを追加して、パネルサイズ変更時に埋め込まれたプロセスのサイズを更新します
- フォームに閉じたイベントハンドラーを追加して、フォームを閉じるときに埋め込みプロセスを終了します
使用法
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
定数
const int GWL_STYLE = -16;
const long WS_VISIBLE = 0x10000000,
WS_MAXIMIZE = 0x01000000,
WS_BORDER = 0x00800000,
WS_CHILD = 0x40000000;
働き
IntPtr LoadExtern(Control Panel, string Path)
{
try
{
Process Process = Process.Start(Path);
Process.WaitForInputIdle();
IntPtr Handle = Process.MainWindowHandle;
SetParent(Handle, Panel.Handle);
SetWindowLong(Handle, GWL_STYLE, (int)(WS_VISIBLE+(WS_MAXIMIZE|WS_BORDER)));
MoveWindow(Handle, 0, 0, Panel.Width, Panel.Height, true);
Panel.Resize += new EventHandler(
delegate(object sender, EventArgs e)
{
MoveWindow(Handle, 0, 0, Panel.Width, Panel.Height, true);
}
);
this.FormClosed += new FormClosedEventHandler(
delegate(object sender, FormClosedEventArgs e) {
SendMessage(Handle, 83, 0, 0);
Thread.Sleep(1000);
Handle = IntPtr.Zero;
}
);
return Handle;
}
catch (Exception e) { MessageBox.Show(this, e.Message, "Error"); }
return new IntPtr();
}
DLLのインポート
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr Handle, int x, int y, int w, int h, bool repaint);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr Handle, int Msg, int wParam, int lParam);
結果
このコードは、Windowsのメモ帳などの一部のアプリケーションでうまく機能します。メモ帳が起動し、フォームのパネルに含まれています。キャプションはなく、境界線もありません。
LoadExtern(panel1, "notepad.exe");
フォームを閉じた後、埋め込まれたプロセスは期待どおりに終了します。
問題
残念ながら、私のコードは、Firefoxやsublimetextなどの他の(より大きな)アプリケーションでは機能しません。
LoadExtern(panel2, @"C:\Program Files (x86)\Mozilla Firefox\firefox.exe");
何が起こるかというと、私のフォームが始まり、Firefoxが始まりますが、それはそれ自身のウィンドウです。アプリケーションにsublimetextまたはfirefoxを含めるのを手伝ってもらえますか?
ソリューションの一部
Sheng Jiangの回答のおかげで、さらにいくつかのアプリケーションで機能するようになりました。私がしたことは、メインウィンドウのハンドルを待つことです。
Process.WaitForInputIdle();
IntPtr Handle = new IntPtr();
for (int i = 0; Handle == IntPtr.Zero && i < 300; i++)
{
Handle = Process.MainWindowHandle;
Thread.Sleep(10);
}
しかし、それでもWindowsエクスプローラーのようなアプリケーションを埋め込むことはできません。