在winform上内嵌入其它的程序

这段代码很有意义,用于把一个程序的界面嵌入到我们自己程序的某个指定窗体上.

比如在某个项目里,我需要把基恩士的激光扫描轮廓显示给客户看,但是激光的DLL中并没有这种功能提供. 于是我想先启动激光的官方程序用以显示轮廓, 然后再把这种显示界面嵌入到我自己程序的界面上指定的位置上.

在笔者构想的PLC仿真器由梯形图编辑器, 3D仿真组态环境两部分组成, 这两部分就可以考虑开发成独立的软件,然后嵌入到我需要的另外的一款PLC仿真教学软件中去.

源代码如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 using System.Runtime.InteropServices;
 10 using System.Diagnostics;
 11 using System.Threading;
 12 
 13 namespace WindowsFormsApplication1
 14 {
 15     public partial class Form1 : Form
 16     {
 17         Process p;
 18 
 19         public Form1()
 20         {
 21             InitializeComponent();
 22         }
 23 
 24         #region API
 25         [DllImport("user32.dll")]
 26         private static extern int SetParent(IntPtr hWndChild, IntPtr hWndParent);
 27 
 28         [DllImport("user32.dll")]
 29         private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
 30 
 31         [DllImport("user32.dll", SetLastError = true)]
 32         private static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
 33 
 34         [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
 35         private static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter,
 36                     int X, int Y, int cx, int cy, uint uFlags);
 37 
 38         [DllImport("user32.dll")]
 39         private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
 40 
 41         [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 42         private static extern uint SetWindowLong(IntPtr hwnd, int nIndex, uint newLong);
 43 
 44         [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 45         private static extern uint GetWindowLong(IntPtr hwnd, int nIndex);
 46 
 47         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 48         private static extern bool ShowWindow(IntPtr hWnd, short State);
 49 
 50         private const int HWND_TOP = 0x0;
 51         private const int WM_COMMAND = 0x0112;
 52         private const int WM_QT_PAINT = 0xC2DC;
 53         private const int WM_PAINT = 0x000F;
 54         private const int WM_SIZE = 0x0005;
 55         private const int SWP_FRAMECHANGED = 0x0020;
 56         public enum ShowWindowStyles : short
 57         {
 58             SW_HIDE = 0,
 59             SW_SHOWNORMAL = 1,
 60             SW_NORMAL = 1,
 61             SW_SHOWMINIMIZED = 2,
 62             SW_SHOWMAXIMIZED = 3,
 63             SW_MAXIMIZE = 3,
 64             SW_SHOWNOACTIVATE = 4,
 65             SW_SHOW = 5,
 66             SW_MINIMIZE = 6,
 67             SW_SHOWMINNOACTIVE = 7,
 68             SW_SHOWNA = 8,
 69             SW_RESTORE = 9,
 70             SW_SHOWDEFAULT = 10,
 71             SW_FORCEMINIMIZE = 11,
 72             SW_MAX = 11
 73         }
 74         #endregion
 75 
 76         private void Form1_Load(object sender, EventArgs e)
 77         {
 78             p = new Process();
 79             //需要启动的程序
 80             p.StartInfo.FileName = @"calc.exe";
 81             //为了美观,启动的时候最小化程序
 82             p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
 83             //启动
 84             p.Start();
 85 
 86             //这里必须等待,否则启动程序的句柄还没有创建,不能控制程序
 87             Thread.Sleep(10000);
 88             //最大化启动的程序
 89             ShowWindow(p.MainWindowHandle, (short)ShowWindowStyles.SW_MAXIMIZE);
 90             //设置被绑架程序的父窗口
 91             SetParent(p.MainWindowHandle, this.Handle);
 92             //改变尺寸
 93             ResizeControl();
 94         }
 95 
 96         //控制嵌入程序的位置和尺寸
 97         private void ResizeControl()
 98         {
 99             SendMessage(p.MainWindowHandle, WM_COMMAND, WM_PAINT, 0);
100             PostMessage(p.MainWindowHandle, WM_QT_PAINT, 0, 0);
101 
102             SetWindowPos(
103             p.MainWindowHandle,
104               HWND_TOP,
105               0 - 10,//设置偏移量,把原来窗口的菜单遮住
106                0 - 32,
107               (int)this.Width + 32,
108               (int)this.Height + 32,
109               SWP_FRAMECHANGED);
110 
111             SendMessage(p.MainWindowHandle, WM_COMMAND, WM_SIZE, 0);
112         }
113 
114         private void Form1_SizeChanged(object sender, EventArgs e)
115         {
116             ResizeControl();
117         }
118 
119         private void Form1_FormClosing(object sender, FormClosingEventArgs e)
120         {
121             p.Kill();
122             p.Dispose();
123         }
124     }
125 }

 

核心功能利用了windows API中的SetParent()

程序运行后, 先启动calc.exe(windows计算器), 然后等待10秒后再显示本程序自己的窗体, 这时你会发现这个窗体已经把calc.exe的界面包含进来的.

这样你就可以清楚的看到嵌入的效果是怎么样的.

 

效果如上图所示. 但是你的程序在退出前,要自己"杀掉"计算器的进程, 否则你的程序退出它还在.

 

本文源代码

  原创文章,出处 : http://www.cnblogs.com/hackpig/

 

posted @ 2016-08-18 13:30  猪悟能  阅读(4645)  评论(1编辑  收藏  举报