从 dll 程序集中动态加载窗体

C#学习笔记001——创建并调用DLL项目 **第一章:创建DLL项目** 第一步: 第二步: 右击图中所示——>“添加”——>“窗体(Windows窗体)”——>。。。 第三步: 第四步: 第五步:拖入一个按钮,改个名字 第六步:双击 写入按钮的动作 MessageBox.Show("我是DLL控件测试按钮"); 第七步:生成“解决方案”(PS... 阅读详情

转载:http://www.cnblogs.com/Infinity/archive/2006/10/26/540347.html 感谢原作者。


昨天晚上花了一晚上时间写了一个从程序集中动态加载窗体的程序.将任何包含窗体的代码编译成 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);
}

}

}

程序源码下载:/Files/Infinity/WindowsForm.rar
  
  程序截图:

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

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


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

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



Delphi中DLL窗体调用实践指南 动态链接库(Dynamic Link Library,DLL)是Windows操作系统中的一种实现共享函数库的方式。DLL可以包含可由多个程序同时使用的代码和数据,当多个应用程序使用同一个DLL时,该DLL仅在内存中加载一次,从而节省资源。DLL对于实现模块化编程、代码复用以及软件维护和升级都起着至关重要的作用。创建DLL的第一步是使用Delphi提供的DLL模板。模板是一种预设的代码结构,它为开发人员提供了一个快速启动项目的起点。 阅读详情

相关推荐

DLL窗体的创建与调用

DLL窗体的创建与调用 可在主窗体中调用DLL中的模式窗体、MDIChild子窗体。

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

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

plean的专栏 1757

DLL动态加载 生成窗口的方法

一个大的项目,经常要把程序模块化。 一般的模块化方法,例如把算法类,封装到dll中,再导出类给主EXE使用。或者dll封装函数,供主EXE调用接口函数。 再或者使用COM组件。 但是Windows程序经常有很多窗口,如何把窗口封装到dll中,并且能否动态加载。就不是MFC架构能解决了。 因为要用到扩展MFC导出dll类型,来导出窗口类,但是这样的话,必须用静态加载lib文件方式来实现。降低了灵活性。因为有可能某个窗口还在开发中,而其他的可以用,这时我们想让能用的跑起来,这时,需要动态加载dll。 可是动态加载dll又没有导出窗口类的机制,怎么办? 请看本资料。 由于时间关系,没有太多时间整理现在的代码。只提供了思路,因为我已经实现了,因此思路是可行的。并且很简单。

C# 动态加载Dll

在很多应用程序中有这样的效果,就是某个文件夹下面放入某个dll,这个软件就会把此Dll显示出来。效果图如下这个效果在C#里面实现起来非常简单 foreach (var name in projectsname) { ToolStripMenuItem mi = new ToolStripMenuItem(name); ...

落魂之殇 3087

C# WinForm动态加载DLL通过配置文件

C# WinForm动态加载DLL通过配置文件

从原理到实现:在《图灵完备》中构建一个144*256像素、1536时钟刻/帧的视频播放器

本文详细解析了在《图灵完备》游戏中构建144*256像素、1536时钟刻/帧视频播放器的全过程。从图灵完备原理出发,通过分层架构设计、视频数据预处理和关键电路实现,展示了如何用基础电子元件模拟现代显卡功能。重点介绍了像素坐标定位系统和颜色数据处理流水线的优化方案,为游戏内复杂电子系统设计提供实践指导。

weixin_42520025的博客 445

.net 反射

说明:原文中的代码为vb.net,我本人比较熟悉c#,所以在翻译的过程中,把vb.net代码替换成了c#代码,所以译文中的代码和原文中的代码会稍有出入,但这并不会影响你阅读。何谓反射?反射就是在运行的时候发现对象的相关信息。根据这些信息可以动态的执行对象的方法以及获取对象的属性所储存的值。使用.NET Framework编写的代码是自动反射的,或者说是自我描述的。之所以可以反射,是通过

pengdean的专栏 2872

STM32F103多通道PWM输出避坑指南:TIM1_CH1异常输出的解决方案

本文深入解析STM32F103多通道PWM输出中的TIM1_CH1异常问题,提供从时钟配置到GPIO复用的系统化解决方案。通过黄金法则配置流程和高级调试技巧,帮助开发者快速定位并解决PWM输出不稳定、占空比异常等问题,同时拓展多定时器协同和互补PWM等高级应用场景。

weixin_29194817的博客 117

C# 调试动态库(DLL)

将调用DLL文件的工程中的“引用”上右键,选择“添加引用”,在弹出的对话框中,选择“dll文件的工程生成动态库的路径”下对应的DLL文件即可。

believe的专栏 7682

cadence数模混合仿真反标sdf

数模混合IC设计时经常要调用一些Verilog模块(最简单的例如SPI接口),在前仿时一般直接用rtl代码来仿真,但是后仿时要关注因寄生带来的延迟,避免这些额外的延迟导致时序错误,因此不能简单地采用RTL来仿真。 一般有两种办法:1是采用由RTL综合得到的门级电路来仿真,这种方法比较简单,但是缺点是规模较大,而且只包括门延迟不包括因版图导致的线延迟;如果想要仿真更精细,就要对该这部分门电路提取寄生参数; 另一种方式是利用sdf文件(standard delay format)来进行仿真。后端工具在布局布

长河柱天的博客 7274

从寄存器到驱动:深入解读RFSoC RF-ADC阈值与校准API的底层逻辑

本文深入解析Xilinx RFSoC中RF-ADC的阈值检测与校准API的底层逻辑,涵盖寄存器映射、驱动实现及Gen3增强功能。通过详细代码示例和寄存器操作流程,揭示如何精准控制信号阈值检测与校准时序,提升系统稳定性与性能。特别探讨RF数据转换器在无线通信和雷达信号处理中的关键应用。

weixin_30552811的博客 687

从 dll 程序集中动态加载窗体 [原创]

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

213

转载:YOLOv8改进全新Inner-IoU损失函数:扩展到其他SIoU、CIoU等主流损失函数,带辅助边界框的损失

目标检测是计算机视觉中的基本任务,包括目标分类和定位。边界框回归损失函数是检测器定位分支的重要组成部分,检测器的定位精度在很大程度上取决于边界框回归,在当前的检测器中发挥着不可替代的作用。在BBR中,IoU损失可以准确描述预测边界框与GT框之间匹配的程度,确保模型在训练过程中可以学习到目标的位置信息。作为现有主流边界框回归损失函数的基本部分,IoU定义如下:B和分别代表预测框和GT框。定义IoU之后,相应的损失可以定义如下:至今,基于IoU的损失函数逐渐成为主流并占据主导地位。

wuling129的专栏 4943

转] 从 dll 程序集中动态加载窗体

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

weixin_33940102的博客 167

STM32F407驱动OV2640摄像头全栈解析:DCMI+DMA+SCCB协同设计

图像采集是嵌入式视觉系统的基石,其核心在于传感器与MCU间的数据通路构建。原理上需理解并行接口(如DCMI)的硬件同步捕获机制、串行控制总线(如SCCB/I²C)的寄存器级配置逻辑,以及DMA在高吞吐数据搬运中的关键作用。技术价值体现在解放CPU、保障实时性、降低功耗,并支撑JPEG压缩与RGB565直显等差异化应用。典型场景包括智能终端实时预览、低带宽图像上传、工业现场视频监控及教学实验平台搭建。本文以STM32F407与OV2640集成实践为载体,深入剖析DCMI时序约束、SCCB软件模拟实现及DMA循

weixin_36151775的博客 180

AgentScope Java 2.0 项目实战:从零构建企业级自主Coding Agent

本文基于 AgentScope Java 框架,完整拆解两个生产级 AI Agent 项目的从零开发全过程。其一是企业级自主编码机器人(agentscope-codingagent),支持 Issue→PR 自动实现、PR Code Review、Docker 沙箱隔离执行与多通道接入;其二是个人 AI 助手管理平台(agentscope-paw),采用 Spring Boot + React 全栈架构,支持多 Agent、技能市场与多 IM 通道。

program哲学 839

[转] 从 dll 程序集中动态加载窗体

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

weixin_33834910的博客 109

告别JavaScript!C#通过WebAssembly在浏览器中实现“原生级“性能

C# + WebAssembly:前端开发的革命性替代方案 摘要:本文探讨了C#通过WebAssembly取代JavaScript开发前端应用的新趋势。文章分析了JavaScript的局限性(弱类型、回调地狱等),并详细介绍了C#+WebAssembly组合的优势:强类型系统、高性能、多线程支持和代码重用。技术实现方面,阐述了C#通过Mono/.NET编译为WebAssembly字节码的原理,重点介绍了Blazor框架的两种模式。文章还提供了实战指南,包括项目创建、多线程配置,以及一个与ChatGPT AP

墨夶的博客 946

[转] 从 dll 程序集中动态加载窗体

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

weixin_30249203的博客 106

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

C#,动态加载DLL,通过反射,调用参数,方法,窗体

.net中常会用到动态加载DLL,而DLL中可能包含各种参数、方法、窗体,如何来调用动态加载这些参数、方法、窗体呢? 在C#中,我们要使用反射,首先要搞清楚以下命名空间中几个类的关系: System.Reflection命名空间 (1) AppDomain:应用程序域,可以将其理解为一组程序集的逻辑容器 (2) Assembly:程序集类 (3) Module:模块类 (4) Type:使用反射得到类型信息的最核心的类 他们之间是一种从属关系,也就是说,一个AppDoma...

以梦为马 不负韶华 1613

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C# 动态加载DLL通过反射调用参数、方法、窗体

.net中常会用到动态加载DLL,而DLL中可能包含各种参数、方法、窗体,如何来调用动态加载这些参数、方法、窗体呢? 在C#中,我们要使用反射,首先要搞清楚以下命名空间中几个类的关系: System.Reflection命名空间 (1) AppDomain:应用程序域,可以将其理解为一组程序集的逻辑容器 (2) Assembly:程序集类 (3) Module:模块类 (4) Type:使用反射得到类型信息的最核心的类 他们之间是一种从属关系,也就是说,一个AppDomain可...

钢铁男儿 3870

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

上一篇: ComboBox绑定数据源时触发SelectedIndexChanged事件的处理办法
下一篇: C# DllImport用法和路径问题
蝶恋花雨
博客等级 码龄21年 1290粉丝 147原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值