ASP.NET可交互式位图窗体设计(3)

asp.net|交互|设计

构造函数
    构造函数传递三个参数:包含圆的中心坐标的点、圆的半径以及一个 System.Drawing.Color 结构(包含用于绘制圆轮廓的颜色)。
  
    然后我们根据中心和半径计算边框,并将笔颜色项设置为我们传递的颜色对象。
  
    绘图代码
    Draw 方法重载实际上非常简单:它根据我们保存在构造函数中的颜色对象创建一个笔对象,然后使用该笔,调用 Graphics.DrawEllipse 方法绘制圆,同时传递了我们早先创建的边框。
  
    图形、笔和画笔
    这里我们需要解释一下 Graphics、Pen 和 Brush 对象。(在开始填充我们的可填充对象时,就会看到 Brush 对象。)
  
    Graphics 对象代表一个与某个真实绘图空间相关联的虚拟化的绘图空间。虚拟化是指,通过在 Graphics 对象上绘图,我们可以使用相同的 Graphics 方法在与该对象相关联的任何类型的实际表面上绘图。对于那些习惯于使用 MFC 或 Microsoft Windows? SDK 编程的用户,Graphics 对象相当于 Windows 中称为“设备上下文”(或 DC)的 .NET 版本。
  
    在此 Windows 窗体应用程序中,传递到 Draw 方法的 Graphics 对象将与屏幕上的一个窗口相关联 -- 这里是 PictureBox。在我们的 Microsoft ASP.NET 应用程序中使用这一代码时,传递给 Draw 方法的 Graphics 对象将与一个位图图像相关联。它也可以和打印机或其他设备相关联。
  
    这个方案的优点是我们可以使用相同的绘图代码在不同的表面上绘图。在我们的绘图代码中,我们不需要知道任何有关屏幕、位图、打印机等等之间的不同 -- .NET Framework(以及底层的操作系统)可以为我们处理所有细节。
  
    利用相同的标记,笔和画笔成为虚拟化的绘图工具。笔代表线条属性 -- 颜色、宽度、样式,甚至可以是用来绘制线的位图。画笔代表一个填充区域的属性 -- 颜色、样式,甚至可以是用来填充区域的位图。
  
    在使用 Using 后清除(或至少 Dispose)
    Graphics、Pen 和 Brush 对象都与相似类型的 Windows 对象相关联。这些 Windows 对象分配在操作系统的内存中 -- 这些内存尚未被 .NET 运行时管理。长时间将这些对象驻留在内存中会导致性能问题,并且在 Microsoft Windows 98 下,当图形堆填满时会导致绘图问题。因此,我们应尽快释放这些 Windows 对象。
  
    当相应的 .NET Framework 对象完成操作并回收内存后,.NET 运行时会自动释放 Windows 对象。但回收内存的时间会很长 -- 如果我们不迅速释放这些对象,所有不幸的事情(包括填满 Windows 堆)都可能发生。在该应用程序的 ASP.NET 版本中,由于很多用户在同一台服务器上访问该应用程序,所以这种现象会更加严重。
  
    因为这些对象与未管理的资源相关联,所以它们实现 IDisposable 接口。该接口有一个方法,即 Dispose,它将 .NET Framework 对象从 Windows 对象中分离出来,并释放 Windows 对象,从而使计算机处于良好的状态。
  
    这时您只需完成一项任务:确保在使用完该对象后,调用 Dispose 方法。
  
    Visual Basic .NET 代码中显示了这一内容的经典形式:首先创建对象,然后在一个 Try 块中使用该对象,最后在 Finally 块中清理该对象。Try/Finally 能够确保即使出现异常也会清理对象。(在本例中,我们调用的绘图方法可能不会引发异常,所以可能并不需要 Try/Finally 块。但掌握这些技巧很有用,因此 Dr. GUI 也希望向您演示这一正确方法。)
  
    这种形式很常见,因此 C# 为其提供了一个私有语句:using。C# 代码中的 using 语句等同于 Visual Basic .NET 代码中的声明和 Try/Finally -- 但更为简洁、方便,并减少了发生错误的可能性。(Dr. GUI 不清楚为什么 Visual Basic .NET 不包含一些诸如 using 的语句。)
  
    接口
    有些(但不是全部)可绘制对象可以被填充。某些对象(如点和线)不能被填充,因为它们不是封闭的区域,而矩形和圆等对象可以是中空的,或者被填充。
  
    另一方面,就象将所有可绘制对象作为多态处理一样,我们也可以将所有可填充对象作为多态处理,这会很方便。例如,如同我们将所有可绘制对象放到一个集合中,通过遍历集合并在每个对象上调用 Draw 来绘制对象一样,我们可以将所有可填充对象放到一个集合中,而不考虑这些可填充对象的实际类型。因此,我们使用某种机制(如继承)来获得真正的多态。
  
    因为不是所有的可绘制对象都可以被填充,因此不能将 Fill 方法的声明放在抽象基类中。.NET Framework 不允许类的多重继承,所以也不能将其放在另一个抽象基类中。并且如果我们从不是非可填充类的其他基类中派生出可填充对象,则不能将所有可绘制对象作为多态处理。
  
    但 .NET Framework 支持接口 -- 并提供了一个可实现任意数量的接口的类。接口不具有任何实现 -- 没有代码,也没有任何数据。因此,实现接口的类必须提供所有内容。
  
    接口所能包含的只有声明。以下是我们在 C# 中的接口 IFillable。单击此处在新窗口中查看全部源文件。
  
  
  
    C#
  public interface IFillable {
  void Fill(Graphics g);
  Color FillBrushColor { get; set; }
  }
  
  
    以下是等同的 Visual Basic .NET 代码。单击此处在新窗口中查看全部源文件。
  
    Visual Basic .NET
  
  Public Interface IFillable
  Sub Fill(ByVal g As Graphics)
  Property FillBrushColor() As Color
  End Interface
  
    我们不需要声明方法或者 virtual/Overridable 或 abstract/MustOverride 属性以及任何其他项,因为接口中的所有方法和属性都自动设置为公开的和 abstract/MustOverride。
  
    使用一个属性:不能在接口中包含数据
    请注意,虽然我们不能在接口中声明字段,但可以声明一个属性,因为属性实际上是作为方法实现的。
  
    但这样做会给接口的实现者带来负担,下面就会看到。实现者必须实现 get 和 set 方法,以及实现该属性所必需的任何数据。如果实现非常复杂,则可以编写一个 helper 类以封装某些部分。在本文稍后我们将就一个略微不同的上下文环境显示如何使用 helper 类。
  
    实现接口
    我们已经定义了接口,现在可以在类中实现它了。请注意,我们必须提供所实现接口的完整实现:不能只从中选取一部分。
  
    下面我们看看 C# 中 DFilledRectangle 类的代码。
  
  
    C#
  public class DFilledCircle : DHollowCircle, IFillable
  {
  public DFilledCircle(Point center, int radius, Color penColor,
  Color brushColor) : base(center, radius, penColor) {
  this.brushColor = brushColor;
  }
  
  public void Fill(Graphics g) {
  using (Brush b = new SolidBrush(brushColor)) {
  g.FillEllipse(b, bounding);
  }
  }
  protected Color brushColor;
  public Color FillBrushColor {
  get {
  return brushColor;
  }
  set {
  brushColor = value;
  }
  }
  public override void Draw(Graphics g) {
  Fill(g);
  base.Draw(g);
  }
  }
  
  
    以下是 Visual Basic .NET 中 DFilledRectangle 类的代码。
  
  
    Visual Basic .NET
  Public Class DFilledRectangle
  Inherits DHollowRectangle
  Implements IFillable
  Public Sub New(ByVal rect As Rectangle, _
  ByVal penColor As Color, ByVal brushColor As Color)
  MyBase.New(rect, penColor)
  Me.brushColor = brushColor
  End Sub
  Public Sub Fill(ByVal g As Graphics) Implements IFillable.Fill
  Dim b = New SolidBrush(FillBrushColor)
  Try
  g.FillRectangle(b, bounding)
  Finally
  b.dispose()
  End Try
  End Sub
  Protected brushColor As Color
  Public Property FillBrushColor() As Color _
  Implements IFillable.FillBrushColor
  Get
  Return brushColor
  End Get
  Set(ByVal Value As Color)
  brushColor = Value
  End Set
  End Property
  Public Overrides Sub Draw(ByVal g As Graphics)
  Dim p = New Pen(penColor)
  Try
  Fill(g)
  MyBase.Draw(g)
  Finally
  p.Dispose()
  End Try
  End Sub
  End Class
  
  
    以下是有关这些类的注意事项。
  
    从 HollowRectangle 中派生
    我们从这个类的空心版本中派生出填充类。这个类中的多数内容都发生了改变:Draw 方法和构造函数都是新的(但两者都调用基类的版本),并且为 IFillable 接口的 Fill 方法以及 FillBrushColor 属性添加了实现。
  
    需要新构造函数的原因是我们在这个类中包含了需要初始化的其他数据,即填充画笔。(您可以回顾我们前面讨论的画笔。)请注意此构造函数是如何调用基类构造函数的:在 C# 中,该调用被内置到声明 (: base(center, radius, penColor)) 中;在 Visual Basic .NET 中,我们将它明确放在 New 方法(即构造函数)的第一行 (MyBase.New(rect, penColor))。
  
    因为我们已经向基类构造函数中传递了三个参数中的两个,现在只需初始化最后的字段即可。

时间: 2024-08-01 09:58:48

ASP.NET可交互式位图窗体设计(3)的相关文章

ASP.NET可交互式位图窗体设计(9)

asp.net|交互|设计 在页面和请求之间传递状态    为使应用程序能够工作,它需要能够维护请求之间的状态并将状态传递给绘图页面(如下所示).       维护和传递状态有多种方式.如果应用程序是严格的单页面应用程序(和以前的应用程序一样),则可以使用视图状态,其中数据被编码存储在 Web 页的隐藏输入字段中.       但是我们的图像控件是在单独的页面中进行绘图的,因此需要某些更灵活的东西.最好的选择就是 cookie 和会话状态.会话状态非常灵活,但要求使用服务器资源.浏览器可以保留

ASP.NET可交互式位图窗体设计(4)

asp.net|交互|设计  绘图如何改变    您会注意到,Draw 方法与基类基本相同 -- 主要差别在于它调用了 Fill 方法,因为要完成绘制一个填充对象,所以需要对其进行填充.我们没有为绘制轮廓重写代码,而是再次调用了基类的方法:Visual Basic .NET 中的 MyBase.Draw(g) 或 C# 中的 base.Draw(g);.       因为我们正在指派用于绘制轮廓的笔,因此需要使用 using 或 Try/Finally 和 Dispose 以确保迅速释放 Win

ASP.NET可交互式位图窗体设计(6)

asp.net|交互|设计 使我们的对象可序列化    为在 ASP.NET 中使用可绘制对象类,我们需要对其再进行一项更改.这些类需要是可序列化的,以便能够在主要的 Web 页和生成该图像的 Web 页之间传递数据(后面将详述).序列化是这样的过程:将某个类的数据以某种方式写入存储介质,以便存储和/或传递数据并在以后反序列化.反序列化是从序列化数据中重新创建对象的过程.我们会在将来的专栏中深入讨论这个问题.       Dr. GUI 最开始作为 Windows 窗体应用程序编写此应用程序时,

ASP.NET可交互式位图窗体设计(7)

asp.net|交互|设计 在 Windows 窗体应用程序中使用可绘制对象    我们已经讨论了可绘制对象类,下面谈谈如何在 Windows 窗体应用程序中使用这些类.首先谈一下 Windows 窗体应用程序是怎样工作的.       Windows 窗体应用程序的主要部分    简单的 Windows 窗体应用程序包含一个主窗口(或窗体),其中包含控件子项.如果您是一位 Visual Basic 程序员,就会发现这个模型非常熟悉.       主窗口    任何 Windows 窗体应用程序

ASP.NET可交互式位图窗体设计(8)

asp.net|交互|设计 按钮单击事件处理程序    接下来就是每个按钮的按钮单击事件处理程序.多数仅仅是向绘图列表中添加一个新的可绘制对象,然后调用 PictureBox 上的 Invalidate,从而使用更新的绘图列表进行重绘.典型的按钮事件处理程序代码如下所示:          C#   private void AddPoint_Click(object sender, System.EventArgs e) {   drawingList.Add(new DPoint(GetRa

ASP.NET可交互式位图窗体设计(2)

asp.net|交互|设计 我们的任务    这个程序的基本思想如下:我们有一个 abstract 基类(在 Microsoft Visual Basic? 中是 MustInherit),其中包含公共数据(如边框)和一套虚拟方法,虚拟方法多数是抽象的(在 Visual Basic 中是 MustOverride),例如 Draw.请注意,Draw 的多态性很重要,因为每个可绘制对象类型(如点.线.矩形.圆等)都是用完全不同的代码绘制的.       虽然方法可以是多态的,但数据不能.因此,我们

ASP.NET可交互式位图窗体设计(5)

asp.net|交互|设计 维护两个列表    因为我们要改变对象的填充颜色以实现 Change fill to hot pink 按钮,因此维护了两个可绘制对象列表:一个列表是全部对象,另一个列表是可填充对象.我们为这两个列表都使用了 ArrayList 类.ArrayList 对象包含一组 Object 引用 -- 这样一个 ArrayList 可以包含系统中任何类型的混合.       这实际上并没有什么帮助 -- 我们希望 ArrayList 仅仅包括可绘制/可填充对象.为此,我们将 A

ASP.NET创建Web服务之设计方针

asp.net|web|web服务|创建|设计 使用ASP.NET构造一个简单的XML Web服务是相对容易的,然而,XML Web服务的真正的强大的功能只有等你研究了基础结构以后才能领悟.XML Web服务是建立在.NET框架和公共语言运行时间基础上的.一个XML Web服务可以利用这些技术.例如,ASP.NET支持的性能.状态管理和验证全都可被用来构造XML Web服务. XML Web服务的基础结构是构建来符合象SOAP.XML和WSDL这样的行业标准,并且它允许其他的平台的客户端与XML

怎样在asp.net中嵌套winform窗体?

问题描述 怎样在asp.net中嵌套winform窗体?然后通过winform窗体来连接RFID来实现对读卡器进行读卡和写卡 解决方案 解决方案二: 解决方案三:两种方式1.ActiveX前提是浏览器认为你的控件是安全的2.WebBrowser自制浏览器用ObjectForScripting赋予脚本读写卡的方法然后Asp.Net里用脚本的external调用解决方案四:怎样在asp.net中嵌套winform窗体?答:不能.解决方案五:在server端引用之后调用部分功能是可以的.但在serve