Hosting EXE Application บน .Net Windows form

เมื่อไม่นานมานี้ผมได้มีโอกาสได้เขียนโปรแกรมแปลกๆ ตัวหนึ่งนะครับโดย Requirement ก็คือจะต้องเขียนโปรแกรม Windows Form โดยที่จะต้อง Host ตัวโปรแกรม Exe ตัวหนึ่งเอาไว้ใน Windows Form หลักด้วยนะซิ เป็นเรื่องเลยครับเพราะปกติ ผมก็เขียนโดยรัน Exe นั่นแยกอีก Process หนึ่งโดยการใช้พวก Process class ใน .Net สำหรับให้รันโปรแกรม Exe ตัวนั่นๆ นี้ละครับจึงเป็นที่มาของบทความนี้ละครับ

ก่อนอื่นเลยเรามาเริ่มดูกันก่อนเลยครับ หลักการก็ไม่มีอะไรมากมายครับเพียงแค่เราจะต้องเรียกใช้งานฟั่งชั่น SetParent และ MoveWindow จาก user32.dll ที่ซึ่งจะมีมาให้ในทุกๆ Window อยู่แล้วครับ โดยเริ่มจากตัวอย่างที่ผมจะกล่าวต่อไปนะครับ จะเป็นการ Host ให้ Notepad ทำงานอยู่บน Window Formที่เราจะสร้างขึ้นมานะครับ เรามาเริ่มดูโคดกันก่่อนเลยดีกว่าครับ

ขั้นตอนเริ่มแรกเลยเราต้องสร้าง Form ที่มี Button และ Panel ก่อนนะครับ


รูปหลังจากเราเพิ่มทั้ง Button และ Panel แล้วควรจะได้ประมาณนี้นะครับ


ตอไปเราดูโค็ดกันนะครับ

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 WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll")]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

        private Process pDocked;
        private IntPtr hWndDocked;
        private IntPtr hWndOriginalParent;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            pDocked = Process.Start(@"notepad");
            while (hWndDocked == IntPtr.Zero)
            {
                hWndDocked = pDocked.MainWindowHandle;
            }
            hWndOriginalParent = SetParent(hWndDocked, panel1.Handle);
            panel1.SizeChanged += new EventHandler(Panel1_Resize);
            Panel1_Resize(new Object(), new EventArgs());
        }

        private void Panel1_Resize(object sender, EventArgs e)
        {
            MoveWindow(hWndDocked, 0, 0, panel1.Width, panel1.Height, true);
        }
    }
}

จากตัวอย่างในโค็ดส่วนที่น่าจะต้องอธิบายหน่อยน่าจะเป็นส่วนที่เป็น while นะครับเพราะในส่วนตรงนันจะมีการวนลูปเช๊กตลอดเวลา ถ้าตัว hWndDocked ยังคงเป็น 0 หรือ Zero นั่นหมายความว่าตัว pDocked ยังคงรันโปรแกรม Notepad ยังไม่เสร็จนะครับต้องวนลูปรอจนกว่าตัวโปรแกรม Notepad จะรันเสร๊จก่อนถึงจะค่อยทำการ Host ตัว Notepad โปรแกรมไปยัง Form หลักของเรานะครับ

โดยคำสั่งที่เราใช้ในการ Host ตัวโปรแกรม Notepad ก็คือ SetParent ครับส่วนฟั่งชั่น MoveWindow นี้เราใช้สำหรับการปรับให้โปรแกรม Notepad แสดงในกรอบของ Panel พอดีนะครับ ถ้าเราทำถูกวิธีเราจะได้ผลลัพธ์ประมาณรูปด้านล่างนะครับ


เห็นมั้ยครับไม่ได้ยากอะไรเลยครับ เพียงเท่านี้เราก็สามารถใส่โปรแกรมอะไรที่เราต้องการลงในโปรแกรมของเราได้แล้วละครับ ง่ายมากๆ
ถ้าอ่านแล้วชอบอย่าลืมช่วยกด Like ที่ http://www.facebook.com/PStudioDev ด้วยนะครับ ขอบคุณครับ
Reference: http://stackoverflow.com/questions/5836176/docking-window-inside-another-window