C#实现从dll程序集中动态加载窗体

 

昨天晚上花了一晚上时间写了一个从程序集中动态加载窗体的程序.将任何包含窗体的代码编译成 dll 文件,再把 dll 文件拷贝到本程序的目录下,本程序运行时即可动态检查到 dll 文件中的窗体,将窗体类的类型在程序菜单中显示出来,点击菜单即可运行对应的窗体.

  本程序主要用到了 Assembly 类动态加载程序集,再得到程序集中包含类的 Type 类型,动态生成类实例,动态调用类方法.个人觉得这是一种提供高度松耦合,可随意扩展的程序结构框架,希望和大家探讨一下这种框架的应用前景!

  关键性代码如下:

 

 

 

using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsFormTest
{
    /** <summary>
    /// Form1 的摘要说明。
    /// </summary>
    public class FrmMain : System.Windows.Forms.Form
    {
        private int formNum;
        private ArrayList formTypes = new ArrayList();
        private ArrayList formObjects = new ArrayList();

        private System.Windows.Forms.MainMenu mnuMain;
        private System.Windows.Forms.MenuItem mnuItmRun;
        private System.Windows.Forms.MenuItem mnuItemWindow;
        private System.Windows.Forms.MenuItem mnuItmHelp;
        private System.Windows.Forms.MenuItem mnuItmCascade;
        private System.Windows.Forms.MenuItem mnuItmTileHorizontal;
        private System.Windows.Forms.MenuItem mnuItmTileVertical;
        private System.Windows.Forms.MenuItem menuItem1;
        private System.Windows.Forms.MenuItem mnuItmAbout;
        private System.Windows.Forms.StatusBar staBarMain;
        private System.Windows.Forms.StatusBarPanel pnlInfo;
        private System.Windows.Forms.StatusBarPanel pnlNum;
        /** <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.Container components = null;

        public FrmMain()
        {
            //
            // Windows 窗体设计器支持所必需的
            //
            InitializeComponent();

            //
            // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
            //
        }

        /** <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        Windows 窗体设计器生成的代码#region Windows 窗体设计器生成的代码
        /** <summary>
        /// 设计器支持所需的方法 - 不要使用代码编辑器修改
        /// 此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.mnuMain = new System.Windows.Forms.MainMenu();
            this.mnuItmRun = new System.Windows.Forms.MenuItem();
            this.mnuItemWindow = new System.Windows.Forms.MenuItem();
            this.mnuItmCascade = new System.Windows.Forms.MenuItem();
            this.mnuItmTileHorizontal = new System.Windows.Forms.MenuItem();
            this.mnuItmTileVertical = new System.Windows.Forms.MenuItem();
            this.menuItem1 = new System.Windows.Forms.MenuItem();
            this.mnuItmHelp = new System.Windows.Forms.MenuItem();
            this.mnuItmAbout = new System.Windows.Forms.MenuItem();
            this.staBarMain = new System.Windows.Forms.StatusBar();
            this.pnlInfo = new System.Windows.Forms.StatusBarPanel();
            this.pnlNum = new System.Windows.Forms.StatusBarPanel();
            ((System.ComponentModel.ISupportInitialize)(this.pnlInfo)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pnlNum)).BeginInit();
            this.SuspendLayout();
            // 
            // mnuMain
            // 
            this.mnuMain.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                                                                                    this.mnuItmRun,
                                                                                    this.mnuItemWindow,
                                                                                    this.mnuItmHelp});
            // 
            // mnuItmRun
            // 
            this.mnuItmRun.Index = 0;
            this.mnuItmRun.Text = "运行窗体(&R)";
            // 
            // mnuItemWindow
            // 
            this.mnuItemWindow.Index = 1;
            this.mnuItemWindow.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                                                                                          this.mnuItmCascade,
                                                                                          this.mnuItmTileHorizontal,
                                                                                          this.mnuItmTileVertical,
                                                                                          this.menuItem1});
            this.mnuItemWindow.Text = "窗口(&W)";
            // 
            // mnuItmCascade
            // 
            this.mnuItmCascade.Index = 0;
            this.mnuItmCascade.Text = "层叠窗口";
            this.mnuItmCascade.Click += new System.EventHandler(this.mnuItmCascade_Click);
            // 
            // mnuItmTileHorizontal
            // 
            this.mnuItmTileHorizontal.Index = 1;
            this.mnuItmTileHorizontal.Text = "横向平铺窗口";
            this.mnuItmTileHorizontal.Click += new System.EventHandler(this.mnuItmTileHorizontal_Click);
            // 
            // mnuItmTileVertical
            // 
            this.mnuItmTileVertical.Index = 2;
            this.mnuItmTileVertical.Text = "纵向平铺窗口";
            this.mnuItmTileVertical.Click += new System.EventHandler(this.mnuItmTileVertical_Click);
            // 
            // menuItem1
            // 
            this.menuItem1.Index = 3;
            this.menuItem1.Text = "-";
            // 
            // mnuItmHelp
            // 
            this.mnuItmHelp.Index = 2;
            this.mnuItmHelp.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                                                                                       this.mnuItmAbout});
            this.mnuItmHelp.Text = "帮助(&H)";
            // 
            // mnuItmAbout
            // 
            this.mnuItmAbout.Index = 0;
            this.mnuItmAbout.Shortcut = System.Windows.Forms.Shortcut.F1;
            this.mnuItmAbout.Text = "关于(&A)";
            this.mnuItmAbout.Click += new System.EventHandler(this.mnuItmAbout_Click);
            // 
            // staBarMain
            // 
            this.staBarMain.Location = new System.Drawing.Point(0, 343);
            this.staBarMain.Name = "staBarMain";
            this.staBarMain.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {
                                                                                          this.pnlInfo,
                                                                                          this.pnlNum});
            this.staBarMain.ShowPanels = true;
            this.staBarMain.Size = new System.Drawing.Size(584, 22);
            this.staBarMain.TabIndex = 1;
            // 
            // pnlInfo
            // 
            this.pnlInfo.Width = 300;
            // 
            // pnlNum
            // 
            this.pnlNum.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring;
            this.pnlNum.Width = 268;
            // 
            // FrmMain
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
            this.ClientSize = new System.Drawing.Size(584, 365);
            this.Controls.Add(this.staBarMain);
            this.IsMdiContainer = true;
            this.Menu = this.mnuMain;
            this.Name = "FrmMain";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "动态加载窗体";
            this.Load += new System.EventHandler(this.FrmMain_Load);
            ((System.ComponentModel.ISupportInitialize)(this.pnlInfo)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pnlNum)).EndInit();
            this.ResumeLayout(false);

        }
        #endregion

        private void FrmMain_Load(object sender, System.EventArgs e)
        {
            Assembly assembly = null;
            string windowsPath = Path.Combine(Application.StartupPath, "Windows");

            foreach (string dllFile in Directory.GetFiles(windowsPath, "*.dll"))
            {
                assembly = Assembly.LoadFile(dllFile);
                Type[] types = assembly.GetTypes();
                
                foreach (Type t in types)
                {
                    if (t.BaseType == typeof(Form))
                    {
                        this.formTypes.Add(t);
                        MenuItem item = this.mnuItmRun.MenuItems.Add(t.FullName);
                        item.Click += new EventHandler(menuItemNewItem_Click);
                    }
                }
            }
        }

        private void menuItemNewItem_Click(object sender, EventArgs e)
        {
            MenuItem item = (MenuItem)sender;

            Type t = (Type)(this.formTypes[item.Index]);

            Object obj = Activator.CreateInstance(t);
            this.formObjects.Add(obj);
            formNum += 1;

            t.InvokeMember("MdiParent", BindingFlags.SetProperty, null, obj, new object[] {this});
            t.InvokeMember("Text", BindingFlags.SetProperty, null, obj, new object[] {t.FullName+"  窗体:"+formNum});
            t.InvokeMember ("Show", BindingFlags.InvokeMethod, null, obj, new object [] {});

            ((Form)obj).Closing += new CancelEventHandler(FrmWindow_Closing);
            ((Form)obj).Activated += new EventHandler(FrmWindow_Activated);
            MenuItem menuItem = this.mnuItemWindow.MenuItems.Add(((Form)obj).Text);
            menuItem.Click += new EventHandler(menuItemWindow_Click);

            this.pnlNum.Text = "当前装载了"+this.formObjects.Count+"个窗体";
            this.pnlInfo.Text = "当前活动窗体:"+this.ActiveMdiChild.Text;
        }

        private void menuItemWindow_Click(object sender, System.EventArgs e)
        {
            MenuItem item = (MenuItem)sender;

            ((Form)(this.formObjects[item.Index-4])).Activate();

            this.pnlNum.Text = "当前装载了"+this.formObjects.Count+"个窗体";
            this.pnlInfo.Text = "当前活动窗体:"+this.ActiveMdiChild.Text;
        }

        private void FrmWindow_Activated(object sender, System.EventArgs e)
        {
            this.pnlNum.Text = "当前装载了"+this.formObjects.Count+"个窗体";
            this.pnlInfo.Text = "当前活动窗体:"+this.ActiveMdiChild.Text;
        }

        private void FrmWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            for (int i=0; i<this.formObjects.Count; i++)
            {
                if (((Form)this.formObjects[i]).Text == ((Form)sender).Text)
                {
                    this.formObjects.RemoveAt(i);
                    this.mnuItemWindow.MenuItems.RemoveAt(i+4);

                    this.pnlNum.Text = "当前装载了"+this.formObjects.Count+"个窗体";
                    this.pnlInfo.Text = "当前活动窗体:"+this.ActiveMdiChild.Text;
                    break;
                }
            }
        }

        private void mnuItmCascade_Click(object sender, System.EventArgs e)
        {
            this.LayoutMdi(MdiLayout.Cascade);
        }

        private void mnuItmTileHorizontal_Click(object sender, System.EventArgs e)
        {
            this.LayoutMdi(MdiLayout.TileHorizontal);
        }

        private void mnuItmTileVertical_Click(object sender, System.EventArgs e)
        {
            this.LayoutMdi(MdiLayout.TileVertical);
        }

        private void mnuItmAbout_Click(object sender, System.EventArgs e)
        {
            new FrmAbout().ShowDialog(this);
        }
    }
}


 

 

程序截图:

单个 dll 文件包含一个窗体时:

 
 

当程序目录下的所有程序集中包含一个窗体类时,程序运行界面:
 


 

多个 dll 文件包含多个窗体时:
 


 

当程序目录下的所有程序集中包含多个窗体类时,程序运行界面:
 

 

 

程序源码下载http://files.cnblogs.com/Infinity/WindowsForm.rar

 

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
要在C# Winform中嵌入基恩士应用程序exe,可以使用Process类来启动应用程序,并将其嵌入到窗体中。以下是实现步骤: 1. 打开Visual Studio中的Winform项目,并在工具箱中添加一个Panel控件。 2. 在代码中使用Process类的Start方法来启动基恩士应用程序exe,并将其嵌入到Panel控件中。 3. 设置基恩士应用程序exe的属性和方法,以便与其进行交互。 以下是代码示例: ```csharp using System.Diagnostics; using System.Windows.Forms; namespace WinformApp { public partial class Form1 : Form { private Process process; public Form1() { InitializeComponent(); // 启动基恩士应用程序exe process = new Process(); process.StartInfo.FileName = "KeenShine.exe"; process.StartInfo.Arguments = ""; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.Start(); // 将基恩士应用程序exe嵌入到Panel控件中 process.WaitForInputIdle(); SetParent(process.MainWindowHandle, panel1.Handle); // 设置窗体大小和位置 process.StartInfo.WindowStyle = ProcessWindowStyle.Normal; process.WaitForInputIdle(); MoveWindow(process.MainWindowHandle, 0, 0, panel1.Width, panel1.Height, true); // 设置基恩士应用程序exe的属性和方法 process.StandardInput.WriteLine("Command1"); var result = process.StandardOutput.ReadLine(); // ... } protected override void OnFormClosing(FormClosingEventArgs e) { base.OnFormClosing(e); // 关闭基恩士应用程序exe process.Kill(); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); [DllImport("user32.dll")] private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int width, int height, bool repaint); } } ``` 在上面的代码中,panel1是Winform中的一个Panel控件,用来显示基恩士应用程序exe。你需要根据实际情况设置基恩士应用程序exe的属性和方法。需要注意的是,在关闭窗体时,需要使用Process类的Kill方法来关闭基恩士应用程序exe。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值