.Net开发笔记(九)自定义窗体设计器

简介:

其实本文标题说得有点大,一个窗体设计器包含的功能实在是太多而且非常复杂,网上有很多地方也讲到这方面的内容,不过基本上都是E文,http://www.codeproject.com/Articles/24385/Have-a-Great-DesignTime-Experience-with-a-Powerful该处作者实现了一个简单的Form Designer,而且附有源码,不过也只是点到为止,功能不多,还有一个老外的开源项目http://www.icsharpcode.net/OpenSource/SD/,基本上涵盖了界面设计、生成代码、编译、调试等功能,能和VS IDE有一拼,源码压缩包有几十M,复杂度可想而知,我大概看了一下这两个的源码结构,基本上都是利用微软FCL中提供的接口、类来实现的,它们主要存在System.ComponentModel,Design命名空间中,比如DesignSurface、IDesignerHost、ISelectionService等,诸位也知道,微软的东西用起来很方便,理解起来嘛,那是相当的困难,因为你根本不知道为啥要那么搞,所以本篇文章我打算试着从底层来说明“窗体可视化设计”到底是个什么东西,诸位看官如果之前了解也不妨看看,不了解的话也没事,基本上涉及到的都是平时用到的技术,不涉及到System.ComponentModel,Design中的任何东西。文章最后附带Demo源码下载地址。

我不知道窗体设计器对诸位来说是个什么样的概念,从开始学习可视化编程时,我们就开始接触了它,就我来说,用过VC6.0、VB以及现在的VS,基本上都是一样,在界面上拖拖控件,写写事件处理程序,编译后就能运行一个简单功能的Windows桌面应用程序了,但是,有以下疑问(Winform为例):

  1. 在新建一个Windows窗体时,设计器中默认出现的窗体是个什么东西?是真实实例化的一个Form(或其派生类)对象,还是其他替代品?
  2. 从工具箱中向窗体上拖一个Button控件,是一个什么样的过程?
  3. 类似1,拖进的Button控件是个什么东西?是真是实例化的一个Button类对象,还是其他替代品?
  4. 在设计器中选中一个控件(或者窗体),周围出现的方框是什么东西?鼠标又是怎么改变控件的位置和大小?
  5. 怎样选中多个控件,让其按照某一规则自动对齐?怎样实现设计器中的“剪切”、“粘贴”等菜单?

暂时先列这么几个问题,其实还有很多,只是其他的本文没有给出解释,比如双击Button按钮时,怎么自动生成事件代码?最重要的是,怎样根据设计的界面生成代码?这些问题其实利用.net中提供的类都能实现,只是不太容易去探究它底层的具体实现细节。下面我就来原汁原味地解释一下以上提出的疑问,Demo中我用自己的方法从底层开始实现了跟常用设计器效果基本一样的功能,当然我不保证.net类库中的类底层就是像我解释的这样去实现的,因为我也没看该部分类的源码,呵呵。

以下就是解释:

  1. 设计器中的默认窗体是真实实例化的一个Form(或其派生类)对象,也就是说,它跟桌面左下角“开始”按钮一样,是一个真实存在的控件(窗体即控件,控件即窗体,详见我前面的博客),至于为什么,这个很好解释,因为如果不是真实存在的控件,是不可能通过属性窗口(一般为PropertyGrid控件)来动态显示和修改它的属性。另外,诸位可以用Spy++查看设计器中的窗体和控件,你会发现能看到他们的句柄(Handle)。
  2. 当用户(Programmer)从工具箱向窗体中拖一个Button控件时,对于设计器来说,做的事情很简单:实例化一个控件,将其加到设计器中的默认窗体中,设置属性窗口中的PropertyGrid.SelectedObject = 实例化的控件。
  3. 跟1相同。其实这时候出现了一个问题,既然1中3中说到,设计器中的窗体和控件都是像桌面左下角“开始”按钮一样真实存在的,那么它应该能接受用户输入吧?!比如鼠标点击、键盘输入等,可是如我们所见,所有的设计器中的窗体和控件几乎都不能按照正常方式去响应用户输入,这是为什么?其实,我们的眼睛骗了我们,因为设计器中不只是窗体和控件,在它们上面还有一个透明的遮罩层,看一幅图:

图1

如你们所见,整个设计器可以分为三层,底层的灰色部分可以看作整个设计器的容器,中间层的蓝色部分就是设计器中的默认窗体,所有拖进设计器中的控件都是放在蓝色部分中,在蓝色部分上面,有一层透明的遮罩层(用橘黄色方框表示),大小跟底层的灰色部分一致,在用户(Programer)看来,最上面的遮罩层是“不存在”的,但是事实上,所有的鼠标键盘操作都被遮罩层拦截,由它进行处理,因此,中间层的窗体和控件不会接受任何用户输入。注:中间层的蓝色部分和最上面的橘黄色部分都属于底层灰色部分,如果把它们都看做控件,那么蓝色部分和橘黄色是平行关系,都属于灰色部分的子控件,只是Z轴顺序不同(Demo中的源码有所体现)。

     4.既然最上面有一个透明的遮罩层,那么当选中一个控件时,周围出现的选中方框可以把它画在这个遮罩层上,任何时候遮罩层中的方框跟中间层的选中控件相对应,保持一致,也就是说,无论方框大小还是位置,都跟中间层的选中控件一样,让人看起来,它两重合  ( 虽然不在同一个层面)。鼠标操作的是顶层的方框,中间层的控件跟着移动、变大、变小。

     5.在设计器中,如果选中多个控件,就会出现多个选中方框,道理一样,所有的选中方框都在最顶层,每一个方框都与中间层的某一控件相对应,操作跟4中一样。复制时,可以将选中控件的完整名称、属性、以及属性值收集起来存放在ClipBoard中,粘贴时,根据 完整名称新建控件,将属性值赋予新建控件,将其加到中间层。

以上就是从底层开始解释一个窗体设计器的简单原理,在图1中,底层灰色部分DesignerControl是一个UserControl,HostFrame是一个控件容器(Form),Overlayer也是一个透明的UserControl,Recter为虚线效果的选中框,这些名称分别与Demo中的源码对应,诸位可以对照参考。

另外,我说几个关键点:

  • 透明控件的实现
View Code
  • 当移动或者改变顶层的方框时,不要让中间层的控件刷新的方法,就是过滤掉中间层控件的WM_PAINT消息,用到了System.Windows.Forms.IMessageFilter接口,该接口中有一PreFilterMessage方法,专门用来过滤需要忽略的Windows消息,具体实现如下:
View Code

使用时,用Application.AddMessageFilter()方法就可以,MSDN上对该方法有一个解释,大概意义是说此操作只对当前UI线程有效,也就是说如果一个应用程序有两个或者多个UI线程,只能过滤当前UI线程中的某一消息。当然这个不是重点,我只是简单的提一下,有关Windows消息以及WInform中的消息流动问题,请参考我之前的博客。

  • 选中方框就是一个普通的类,代码如下:
View Code

其余的都很简单,用到的都是简单技术,详细请参考源码。XP .net3.5测试通过,源码下载地址:http://download.csdn.net/detail/xiaozhi_5638/5185939。源码中没有剪切、复制、自动对齐等功能。

上一张Demo效果图:

图2

希望有帮助,O(∩_∩)O~。感觉本文对自己有用的朋友,给个“推荐”或者建议啥的都是可以滴,非常感谢~

 

作者:周见智 
出处:http://www.cnblogs.com/xiaozhi_5638/ 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

标签:  c#Winform

本文转自周见智博客博客园博客,原文链接:http://www.cnblogs.com/xiaozhi_5638/archive/2013/03/27/2984086.html,如需转载请自行联系原作者
目录
相关文章
|
10天前
|
开发框架 前端开发 .NET
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
集成于VS 2019,EXT.NET前端和ASP.NET后端,搭配MSSQL 2018数据库。系统覆盖样品管理、数据分析、报表和项目管理等实验室全流程。应用广泛,包括生产质检(如石化、制药)、环保监测、试验研究等领域。随着技术发展,现代LIMS还融合了临床、电子实验室笔记本和SaaS等功能,以满足复杂多样的实验室管理需求。
20 3
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
|
3天前
|
前端开发 测试技术 C#
如何开发一套基于C#和.NET 6.0手术麻醉系统? 手术麻醉系统源码
如何开发一套基于C#和.NET 6.0手术麻醉系统?
10 1
|
20天前
|
开发框架 JavaScript 前端开发
分享7个.NET开源、功能强大的快速开发框架
分享7个.NET开源、功能强大的快速开发框架
|
27天前
|
开发框架 .NET C#
使用C#进行.NET框架开发:深入探索与实战
【5月更文挑战第28天】本文探讨了C#在.NET框架中的应用,展示了其作为强大编程语言的特性,如类型安全、面向对象编程。C#与.NET框架的结合,提供了一站式的开发环境,支持跨平台应用。文中介绍了C#的基础知识,如数据类型、控制结构和面向对象编程,以及.NET的关键技术,包括LINQ、ASP.NET和WPF。通过一个实战案例,展示了如何使用C#和ASP.NET开发Web应用,包括项目创建、数据库设计、模型和控制器编写,以及视图和路由配置。本文旨在揭示C#在.NET开发中的深度和广度,激发开发者探索更多可能性。
|
14天前
|
存储 分布式计算 大数据
MaxCompute操作报错合集之自定义udf的函数,引用了import net.sourceforge.pinyin4j.PinyinHelper;但是上传资源后,出现报错,是什么原因
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
|
1月前
|
人工智能 量子技术 C#
【专栏】.NET 开发:开启数字化新时代
【4月更文挑战第29天】.NET开发在数字化新时代中发挥关键作用,借助跨平台能力、高性能和现代编程语言支持,如C#,助力企业实现数字化转型。通过企业级应用开发、移动应用和云计算集成,.NET加速业务流程和提升用户体验。未来,.NET将涉足AI、ML、MR/AR及量子计算,持续推动技术创新和数字化转型。开发者应提升技能,适应高性能需求,把握发展机遇。
|
1月前
|
缓存 监控 算法
【专栏】.NET 开发:实现卓越性能的途径
【4月更文挑战第29天】本文探讨了.NET开发中的性能优化,强调了理解性能问题根源和使用分析工具的重要性。基础优化包括代码优化(如减少计算、避免内存泄漏)、资源管理及选择合适算法。高级策略涉及并行编程、缓存策略、预编译(AOT)和微服务架构。持续性能测试与监控是关键,包括性能测试、监控分析和建立优化反馈循环。开发者应持续学习和实践性能优化,以构建高性能应用。
|
1月前
|
开发框架 .NET C#
【专栏】理解.NET 技术,提升开发水平
【4月更文挑战第29天】本文介绍了.NET技术的核心概念和应用,包括其跨平台能力、性能优化、现代编程语言支持及Web开发等特性。文章强调了深入学习.NET技术、关注社区动态、实践经验及学习现代编程理念对提升开发水平的重要性。通过这些,开发者能更好地利用.NET构建高效、可维护的多平台应用。
|
1月前
|
机器学习/深度学习 vr&ar 开发者
【专栏】.NET 技术:引领开发新方向
【4月更文挑战第29天】本文探讨了.NET技术如何引领软件开发新方向,主要体现在三方面:1) 作为跨平台开发的先锋,.NET Core支持多操作系统和移动设备,借助.NET MAUI创建统一UI,适应物联网需求;2) 提升性能和开发者生产力,采用先进技术和优化策略,同时更新C#语言特性,提高代码效率和可维护性;3) 支持现代化应用架构,包括微服务、容器化,集成Kubernetes和ASP.NET Core,保障安全性。此外,.NET还不断探索AI、ML和AR/VR技术,为软件开发带来更多创新可能。
|
1月前
|
物联网 vr&ar 开发者
【专栏】.NET 技术:为开发注入活力
【4月更文挑战第29天】本文探讨了.NET技术的创新,主要体现在三个方面:1) .NET Core实现跨平台开发革命,支持多种操作系统和硬件,如.NET MAUI用于多平台UI;2) 性能提升与生产力飞跃,C#新特性简化编程,JIT和AOT优化提升性能,Roslyn提供代码分析工具;3) 引领现代化应用架构,支持微服务、容器化,内置安全机制。未来,.NET 7将带来更多新特性和前沿技术整合,如量子计算、AI,持续推动软件开发创新。开发者掌握.NET技术将赢得竞争优势。