我想在WinForm中加载一个.exe的可执行文件,但是我想让他嵌入一个控件中显示,而不是新打开一个窗口来显示exe文件,请问应该怎么实现这个功能呢?分数真的不多。。只为求教。。

解决方案 »

  1.   

    打开那个exe后。获取那个进程的主窗口。然后用setparent这个api把你的控件作为那个窗口的你窗口。
    这些都必须使用win api来做。这些个api 网上都有。
      

  2.   

    可是我直接把这些代码打进去没效果啊。。怎么回事?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;namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            #region WIN API---引入系统API,用于把程序打开的窗口整合到SHOW页面中
            #region  宏定义
            private const int SWP_NOOWNERZORDER = 0x200;
            private const int SWP_NOREDRAW = 0x8;
            private const int SWP_NOZORDER = 0x4;
            private const int SWP_SHOWWINDOW = 0x0040;
            private const int WS_EX_MDICHILD = 0x40;
            private const int SWP_FRAMECHANGED = 0x20;
            private const int SWP_NOACTIVATE = 0x10;
            private const int SWP_ASYNCWINDOWPOS = 0x4000;
            private const int SWP_NOMOVE = 0x2;
            private const int SWP_NOSIZE = 0x1;
            private const int GWL_STYLE = (-16);
            private const int WS_VISIBLE = 0x10000000;
            private const int WM_CLOSE = 0x10;
            private const int WS_CHILD = 0x40000000;
            #endregion
            [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
                 CharSet = CharSet.Unicode, ExactSpelling = true,
                 CallingConvention = CallingConvention.StdCall)]
            private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);        [DllImport("user32.dll", SetLastError = true)]
            private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);        [DllImport("user32.dll", SetLastError = true)]
            private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);        [DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
            private static extern long GetWindowLong(IntPtr hwnd, int nIndex);        [DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
            private static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
            //private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
            [DllImport("user32.dll", SetLastError = true)]
            private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);        [DllImport("user32.dll", SetLastError = true)]
            private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);        [DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
            private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
            #endregion
            Process process = null;
            IntPtr appWin;
            private string exeName = "";        private void splitContainer1_Panel2_Resize(object sender, EventArgs e)
            {
                if (this.appWin != IntPtr.Zero)
                {
                    MoveWindow(appWin, 0, 0, this.splitContainer1.Panel2.Width, this.splitContainer1.Panel2.Height, true);
                }
                base.OnResize(e);
            }        private void Form1_Load(object sender, EventArgs e)
             {
                 exeName = "否定.exe";
                try
                {
                    // Start the process 
                    process = System.Diagnostics.Process.Start(this.exeName);                // Wait for process to be created and enter idle condition 
                    process.WaitForInputIdle();                // Get the main handle
                    appWin = process.MainWindowHandle;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "Error");
                }            // Put it into this form
                SetParent(appWin, this.splitContainer1.Panel2.Handle);            // Remove border and whatnot
                // SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);
                // Move the window to overlay it on this window
                MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
            }        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            {
                if (process != null && !process.HasExited)
                    process.Kill();
            }
        }
    }
      

  3.   

    这个代码基本可用,如果没效果,一个可能的原因是有些exe取不到MainWindowHandle,我的解决办法是先运行这个exe,然后用autoit这个工具,找到它的窗口的class,然后用appWin = FindWindow("className", null);来取得句柄。手头有个Alexsys Team 2 Pro的软件,用MainWindowHandle没效果,用class可行。
      

  4.   

    我试了你的方法,可是窗口还是在另一个窗口中打开了。。没有嵌入我的窗体。我对Win API不是很熟悉,请问这是为什么呢?private void Form1_Load(object sender, EventArgs e)
             {
                 exeName = "否定.exe";
                try
                {
                    // Start the process 
                    process = System.Diagnostics.Process.Start(this.exeName);                // Wait for process to be created and enter idle condition 
                    process.WaitForInputIdle();                // Get the main handle
                    appWin = FindWindow("WindowsForms10.Window.8.app.0.2bf8098_r13_ad1", null);
                    //appWin = process.MainWindowHandle;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "Error");
                }            // Put it into this form
                SetParent(appWin, this.splitContainer1.Panel2.Handle);            // Remove border and whatnot
                // SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);
                // Move the window to overlay it on this window
                MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
            }
      

  5.   


    在你的示例 的代码中。我加了一个button 
    button的点击事件。
            private void button1_Click(object sender, EventArgs e)
            {
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Filter = "*.exe|*.exe";
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    string filename = dlg.FileName;
                    Process proc = Process.Start(filename);
                    IntPtr inp = FindWindow(null, "Form1");
                    while (inp == IntPtr.Zero)
                    {
                        System.Threading.Thread.Sleep(100);
                        Application.DoEvents();
                    }
                    long i = SetParent(proc.MainWindowHandle, this.Handle);
                }
            }
    测试过可以用。
      

  6.   

    我明白你的意思了,是可以打开exe文件,但是是在新窗口中打开的,不是吗?
    我的想法其实是嵌入我的一个控件内显示(例如在tabControl的一个子页面中)
      

  7.   

     long i = SetParent(proc.MainWindowHandle, this.Handle);
    替换为this.tabControl.Handle
      

  8.   

    大哥,我真的照你的方法试了,可是为什么是这种效果?代码如下:      private void button1_Click(object sender, EventArgs e)
          {
             OpenFileDialog dlg = new OpenFileDialog();
             dlg.Filter = "*.exe|*.exe";
             if (dlg.ShowDialog() == DialogResult.OK)
             {
                string filename = dlg.FileName;
                Process proc = Process.Start(filename);
                IntPtr inp = FindWindow(null,"否定");
                while (inp == IntPtr.Zero)
                {
                   System.Threading.Thread.Sleep(100);
                   Application.DoEvents();
                }
                long i = SetParent(proc.MainWindowHandle, this.tabPage1.Handle);
             }
      

  9.   

    进程打开之后先sleep几秒 等程序窗口显示出来了再setparent就可以了。
    Process.Start之后先sleep
      

  10.   

    你的思路就不大对,应该反射取.exe的程序集,然后再接着用常规方法实现,你这样做有点怪.