转自:http://blog.youkuaiyun.com/llddyy123wq/article/details/5624625
如何用C# WinFrom程序将其他程序激活并让其他程序作为他的子窗体。比如他开个主窗体可以把QQ,游戏什么的作为他的子窗体显示出来?这个问题我在网上看到很多人都提过。但真正解决问题的很难找到。后来终于在网上找到了一个相关方面的知识。我早把这个资源上传到我的下载文件中去了。但是我感觉这样的话,别人搜索到的机率还是很小。所以我现在再不厌其烦的,把代码再贴出来吧,方便大家共同学习。
需要Process.Start()启动外部应用。
还要FindWindow,SetParent等几个API。
C#调用请看
http://www.pinvoke.net/search.aspx?search=FindWindow&namespace=[All]
这个控件封装好了。
- using System;
- using System.Collections;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Drawing;
- using System.Data;
- using System.Windows.Forms;
- using System.Runtime.InteropServices;
- namespace AppControl
- {
- /// <summary>
- /// Application Display Control
- /// </summary>
- [
- ToolboxBitmap(typeof(ApplicationControl), "AppControl.bmp"),
- ]
- public class ApplicationControl : System.Windows.Forms.Panel
- {
- /// <summary>
- /// Track if the application has been created
- /// </summary>
- bool created = false;
- /// <summary>
- /// Handle to the application Window
- /// </summary>
- IntPtr appWin;
- /// <summary>
- /// The name of the exe to launch
- /// </summary>
- private string exeName = "";
- /// <summary>
- /// Get/Set if we draw the tick marks
- /// </summary>
- [
- Category("Data"),
- Description("Name of the executable to launch"),
- DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)
- ]
- public string ExeName
- {
- get
- {
- return exeName;
- }
- set
- {
- exeName = value;
- }
- }
- /// <summary>
- /// Constructor
- /// </summary>
- public ApplicationControl()
- {
- }
- [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);
- [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);
- 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;
- /// <summary>
- /// Force redraw of control when size changes
- /// </summary>
- /// <param name="e">Not used</param>
- protected override void OnSizeChanged(EventArgs e)
- {
- this.Invalidate();
- base.OnSizeChanged(e);
- }
- /// <summary>
- /// Creeate control when visibility changes
- /// </summary>
- /// <param name="e">Not used</param>
- protected override void OnVisibleChanged(EventArgs e)
- {
- // If control needs to be initialized/created
- if (created == false)
- {
- // Mark that control is created
- created = true;
- // Initialize handle value to invalid
- appWin = IntPtr.Zero;
- // Start the remote application
- Process p = null;
- try
- {
- // Start the process
- p = System.Diagnostics.Process.Start(this.exeName);
- // Wait for process to be created and enter idle condition
- p.WaitForInputIdle();
- // Get the main handle
- appWin = p.MainWindowHandle;
- }
- catch (Exception ex)
- {
- MessageBox.Show(this, ex.Message, "Error");
- }
- // Put it into this form
- SetParent(appWin, this.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);
- }
- base.OnVisibleChanged(e);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="e"></param>
- protected override void OnHandleDestroyed(EventArgs e)
- {
- // Stop the application
- if (appWin != IntPtr.Zero)
- {
- // Post a colse message
- PostMessage(appWin, WM_CLOSE, 0, 0);
- // Delay for it to get the message
- System.Threading.Thread.Sleep(1000);
- // Clear internal handle
- appWin = IntPtr.Zero;
- }
- base.OnHandleDestroyed(e);
- }
- /// <summary>
- /// Update display of the executable
- /// </summary>
- /// <param name="e">Not used</param>
- protected override void OnResize(EventArgs e)
- {
- if (this.appWin != IntPtr.Zero)
- {
- MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
- }
- base.OnResize(e);
- }
- }
- }
调用方法 (其实就是把上面生成的控件直接拖放到窗体,改一下路径等相关属性就可以了。)
- this.applicationControl1 = new AppControl.ApplicationControl();
- this.SuspendLayout();
- //
- // applicationControl1
- //
- this.applicationControl1.Anchor = ((System.Windows.Forms.AnchorStyles) ((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
- | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.applicationControl1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- // 在这里设置要嵌入的程序路径,我试验了灵格斯翻译专家成功,QQ没试,据说不成功,我不清楚呵呵。)
- this.applicationControl1.ExeName = @"f:/EditPlus/EDITPLUS.EXE";
- //this.applicationControl1.ExeName = @"f:/Tencent/QQ/QQ.exe";//QQ的没成功
- this.applicationControl1.Location = new System.Drawing.Point(29, 26);
- this.applicationControl1.Name = "applicationControl1";
- this.applicationControl1.Size = new System.Drawing.Size(230, 195);
- this.applicationControl1.TabIndex = 0;
特别申明:本文纯属个人在网上搜索所得。感谢原文网址( http://www.chenjiliang.com/Article/View.aspx?ArticleID=2103)
运行效果见图片