您的位置:首页 > 其它

将外部应用程序嵌入WinForm中

2010-05-26 10:37 393 查看
如何用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

运行效果见图片

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: