目前 Web 已成了街谈巷议的话题。"> 目前 Web 已成了街谈巷议的话题。" />
科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道NET Frameworks创建基于Windows应用程序

NET Frameworks创建基于Windows应用程序

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

   简介 目前 Web 已成了街谈巷议的话题。

作者:中国IT实验室 来源:中国IT实验室 2007年9月30日

关键字: 程序 编程

  

简介

 

目前 Web 已成了街谈巷议的话题,看起来好像 Microsoft? Visual Studio? 开发系统对创建基于 Microsoft Windows? 的传统应用程序的支持有所减弱。实际上,Microsoft 对基于 Windows 的应用程序开发方面的投资在不断加大。

 

Win 表单是一个新的窗体程序包,借助这一程序包,开发人员能够充分利用 Microsoft Windows? 操作系统所提供的丰富的用户界面功能,创建基于 Windows 的应用程序。Win Forms 是新的 Microsoft?.NET 平台的一个组成部分,它提供了许多新技术,包括通用的应用程序框架、可管理的执行环境、一体化的安全性以及面向对象的设计原则。而且,Win Forms 全面支持快速简便地接入 Web Services 以及建立丰富的基于 ADO+ 数据模型的数据感知应用程序。得益于 Visual Studio 中新的共享开发环境,开发人员能够使用包括 Microsoft Visual Basic? C# 在内的任何支持 .NET 平台的语言创建 Win Forms 应用程序。

 

介绍 Win Forms

 

就像刚才所说的,Win Forms 是专用于 Windows 客户机 UI 编程的 .NET Framework 的命名空间。它与 ASP+ UI 程序包(即 Web Forms)共享同样的设计原则,但其类和实现却全然不同。在 Microsoft Win32? API Web 组件之间没有魔术般变形的类。就像所有的 .NET Frameworks 一样,一致性已成为优先考虑的问题。其目的是为了 Win Forms 开发人员能够迅速适应在 Web Forms 中编写代码,反之亦然。例如,所有命名空间都有 Button 类,每一个都有文本、默认的 OnClick 事件以及 ForeColorBackColor Font 属性。

 

Win Forms 的所有控件都基于 System.WinForms.Control 类。Control 已内置了所有基本的 HWND 功能,并且它能处理我们已经熟悉并喜爱的绝大多数通用 WM_xxxx 消息。RichControl Control 派生而来,其中添加了布局逻辑和绘图代码。System.WinForms 命名空间中的绝大多数控件实际上都由 RichControl 派生而来。ScrollableControl 能够支持窗口客户区域的滚动。一般情况下,对滚动功能的支持是通过 ContainerControl 实现的,后者由 ScrollableControl 派生而来,并增加了对管理子控件、焦点问题和跨栏的支持。Form ContainerControl 派生而来,是 Win Form 的顶级控件,它带有控制标题栏、系统菜单、非矩形窗口和默认控件的属性。UserControl 也由 ContainterControl 派生而来,是开发人员能够创建的控件的基本类。UserControl 一般用于托管其它子控件,但对于外部客户机来说,它又是作为单个单元出现的。UserControl Form Microsoft? Visual Studio.NET 中都有可视设计器,您会找到用于添加和设计由其所派生的类的项。

 

既然我们已了解 Win Forms 的(最)基本方面,让我们揭开它的面纱,看看其表面下的一些相当不错的功能。

 

更好的易学易用性

 

Win Forms 的主要目的是尽可能地提高定位到 Win32 平台的开发人员的工作效率。无论是图形设备界面 (GDI) 还是窗口状态管理,为 Win32 编程通常都是很困难的。例如,类似 WS_BORDER WS_CAPTION 的一些窗口样式只能在创建窗口时指定或修改。而 WS_VISIBLE WS_CHILD 等其它窗口样式则可以对已创建的窗口进行修改。Win Forms 尽力消除了这些细微的差别,并确保操作过程始终保持一致性。可以随时地、不限次序地对 Win Forms 控件的属性进行设置,总能产生预期效果。如果改动过程需要创建新的 HWNDWin Forms 框架能够自动地、透明地重新生成窗口,并为其应用相适宜的所有设置。

 

由控件获得通知或事件在 Win Forms 中也要容易得多。Win Forms 事件都基于称为 Delegates 的一个通用语言运行时功能。Delegates 从本质上讲是对类型安全的、可靠的函数指针。对于任一控件的任一事件,都可以添加代理处理程序;绝不会强迫您创建派生类以通过替代处理事件,创建事件映射,或仅为处理一个事件而为类的所有事件实施一个接口。也可以通过替代派生类处理事件,但这种方式一般用于控件创建者或更为高级的应用。汇集某一按钮的 Click 事件相当简单:

 

public class ButtonClickForm: System.WinForms.Form {

private System.WinForms.Button button1;

public ButtonClickForm() {

// 创建按钮

button1 = new System.WinForms.Button();

// 添加处理程序

button1.AddOnClick(new System.EventHandler(button1_Click));

// 将按钮添加到窗体中

this.Controls.Add(button1);

  }

 

private void button1_Click(object sender, EventArgs e) {

MessageBox.Show("button1 clicked!");

  }

    }

 

这里,我们创建了一个按钮,并添加了一个名为 button1_Click 的处理程序方法,通过短短几行代码,在单击该按钮后,将调用这一方法。请注意,即使处理程序方法被标记为专用,创建这一挂钩的代码仍可以使用该方法,单击按钮后,按钮将能够激活这一方法的事件。

 

启动 Win Forms 项目的过程也得到了简化。使用 Visual Studio.NET 创建 Win Forms 项目的过程只会创建一个要编译的项目文件:Form1.cs。没有头文件,没有接口定义文件,没有引导程序文件,没有资源文件,没有库文件。项目所需的所有信息都包含在窗体的代码中。这样做有一个好处:项目由一个简单的单窗体应用程序扩展到复杂的、带有多个代码文件的多窗体应用程序要方便得多。链接过程不需要中间对象文件,只有代码和已构建的、受管理的所有 DLL。只要您习惯了这一方法,就能明显地感觉到创建 .NET Framework 应用程序和创建 C/C++ 应用程序之间复杂性的不同。因为信息仅仅包含在代码文件中,在 Visual Studio.NET 环境外创建版本的过程也非常容易,无论是 Visual Basic 代码、C# 代码,还是任何其它语言编写的针对 .NET Framework 的代码。

 

因为 Win Forms 建立在通用语言运行时的基础之上,开发人员可以任选目前针对通用语言运行时的众多语言中的一种,构建 Win32 应用程序。开发人员现在可以使用多种语言编写 Win Forms 应用程序(或 Web Forms 应用程序或 Data 应用程序):从 C# COBOL Eiffel 再到 Perl 等等,中间还有很多种(上一次计数是 17 种)。方便易用再加上广泛的应用场合相得益彰,为开发人员提供了深厚的基础,使他们能够迅速有效地使用 Win Forms 构建实用的应用程序。

 

布局

 

如果您曾尝试创建能够正常调整大小的窗体,您就会知道这一过程有多么困难。Microsoft Foundation Classes (MFC) 或早期的 Visual Basic 版本没有对这一功能提供内置的支持。然而现在只需几行代码(通常情况下您甚至不需要编写这些代码,因为在设计时就能通过 Property Browser 实现这些功能!),即可创建能够正常调整大小的对话框。

 

基本布局由两条组成:Anchoring DockingRichControl 有一个 Anchor 属性,它是一种枚举类型,可以用“或”操作将这些值组合在一起,以说明控件将与其父控件的某一边保持恒定距离。例如,如果您将一个按钮置于窗体上,并将 Anchor 属性设置为 AnchorStyles.BottomRight,则在调整按钮的大小时,按钮将与窗体的底边和右边保持同一距离。此外,如果将 Anchor 设置为 AnchorStyles.All,则按钮的各个边都与窗体的对应边保持同一距离,在调整按钮大小时仍要满足这些约束条件。

 

Docking 实际上是 Anchoring 的一个特殊情况。RichControl Dock 属性说明控件要将自身固定到其父控件的哪一边。Docking 可以是 TopLeftRightBottom Fill。在每种情况下,控件都将移动到尽量靠近指定边,并调整其大小,以填满那一边。如果父控件的大小有所调整,这一状况仍将保持。将一个控件移动到父控件的底端,并将 Anchor 设置为 AnchorStyle.BottomLeftRight,可以模拟 Docking Bottom。在此处的示例中,列表框是 Docked Left,按钮与窗体的顶端、左边和右边保持恒定距离,由此它们保持了相对位置和大小。下面的示例对话框(图 2)完全使用 Visual Studio.NET 中的 Win Forms 设计器创建,只花了两分钟的时间,没有编写一行代码。

 

// ResizableSample.cs

namespace ResizableSampleNamespace {

 

using System;

using System.Drawing;

using System.ComponentModel;

using System.WinForms;

 

/// <summary>

///    ResizableSample 的摘要说明。

/// </summary>

public class ResizableSample : System.WinForms.Form {

/// <summary>

///    Win Forms 设计器所要求

/// </summary>

private System.ComponentModel.Container components;

private System.WinForms.Button button3;

private System.WinForms.Button button2;

private System.WinForms.Button button1;

private System.WinForms.ListBox listBox1;

public ResizableSample() {

// Win Form 设计器支持所要求

InitializeComponent();

 

        }

 

/// <summary>

///    释放正在使用的所有资源

/// </summary>

public override void Dispose() {

base.Dispose();

components.Dispose();

        }

 

/// <summary>

///    应用程序的主入口点。

/// </summary>

public static void Main(string[] args) {

Application.Run(new ResizableSample());

        }

 

/// <summary>

        ///    设计器支持所要求的方法 不要用编辑器

        ///    修改这一方法的内容

/// </summary>

private void InitializeComponent()

   {

this.components = new System.ComponentModel.Container();

this.button2 = new System.WinForms.Button();

this.button3 = new System.WinForms.Button();

this.button1 = new System.WinForms.Button();

this.listBox1 = new System.WinForms.ListBox();

//@design this.TrayLargeIcon = false;

//@design this.TrayHeight = 0;

this.Text = "Resizable Dialog";

this.IMEMode = System.WinForms.IMEMode.Off;

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(256, 173);

button2.Location = new System.Drawing.Point(152, 60);

button2.Size = new System.Drawing.Size(92, 32);

button2.TabIndex = 2;

button2.Anchor = System.WinForms.AnchorStyles.TopLeftRight;

button2.Text = "Cancel";

button3.Location = new System.Drawing.Point(152, 120);

button3.Size = new System.Drawing.Size(92, 44);

button3.TabIndex = 3;

button3.Anchor = System.WinForms.AnchorStyles.All;

button3.Text = "Filler";

button1.Location = new System.Drawing.Point(152, 8);

button1.Size = new System.Drawing.Size(92, 32);

button1.TabIndex = 1;

button1.Anchor = System.WinForms.AnchorStyles.TopLeftRight;

button1.Text = "OK";

listBox1.Size = new System.Drawing.Size(120, 173);

listBox1.Dock = System.WinForms.DockStyle.Left;

listBox1.TabIndex = 0;

listBox1.Items.All = new object[] {"Item One",

"Item Two",

"Item Three",

"Item Four"};

this.Controls.Add(button3);

this.Controls.Add(button2);

this.Controls.Add(button1);

this.Controls.Add(listBox1);

   }

 

    }

}

 

GDI+

 

Win Forms 全面利用了 GDI+ 这一 Microsoft 下一代的二维图形系统。Win Forms 中的图形编程模式完全是面向对象的,各式各样的画笔、笔刷、图像和其它图形对象与 .NET Framework 的其它部分一样,遵循了简单易用的指导方针。开发人员目前可以使用相当不错的一些绘图新功能,如 alpha 混色、渐变色、纹理、消除锯齿以及采用除位图外的其它图像格式。与 Windows 2000 操作系统分层和透明的窗口功能配合使用,开发人员能够毫不费力地创建丰富的、更为图形化的 Win32 应用程序。

 

如果触发了控件的 OnPaint 事件,能够由 PaintEventArgs 访问的 System.Drawing.Graphics 对象就成为一个 GDI+ 图形对象。图形对象能够执行的所有操作都通过 GDI+ 实施。作为一个示例,使用 GDI+ 创建一个绘制渐变背景的按钮。

 

以下是实现这一按钮的代码:

 

public class GradientButton : Button {

// 保留颜色设置的成员

private Color startColor;

private Color endColor;

 

// 书写文字时我们将需要它

private static StringFormat format = new StringFormat();

public GradientButton() : base() {

// 初始化颜色

startColor = SystemColors.InactiveCaption;

endColor = SystemColors.ActiveCaption;

format.Alignment = StringAlignment.Center;

format.LineAlignment = StringAlignment.Center;

    }

 

/// <summary>

/// 渐变色的终止颜色

// </summary>

public Color EndColor {

get {

return this.endColor;

         }

set {

this.endColor = value;

// 如有必要,则导致重新绘制

if (this.IsHandleCreated && this.Visible) {

Invalidate();

            }

         }

   }

 

/// <summary>

/// 渐变色的起始颜色

// </summary>

public Color StartColor {

get {

return this.startColor;

         }

set {

this.startColor = value;

// 如有必要,则导致重新绘制

if (this.IsHandleCreated && this.Visible) {

Invalidate();

           }

        }

   }

 

protected override void OnPaint(PaintEventArgs pe) {

// 绘制按钮的常规背景以形成

// 边框,等等。

base.OnPaint(pe);

Graphics g = pe.Graphics;

Rectangle clientRect = this.ClientRectangle;

// 缩小矩形,以免绘制时出界

clientRect.Inflate(-1,-1);

// 创建渐变笔刷,从

// 左上角运行到右下角。

Brush backgroundBrush = new LinearGradientBrush(

new Point(clientRect.X,clientRect.Y),

new Point(clientRect.Width, clientRect.Height),

startColor,

endColor);

// 以渐变色填充背景....

g.FillRectangle(backgroundBrush, clientRect);

// 在客户机区域的中间书写文字。

g.DrawString(this.Text,

this.Font,

new SolidBrush(this.ForeColor),

clientRect,

format);

   }

}

 

就像您所看到的,这并不是非常困难。得益于 Win Forms GDI+ 面向对象的设计,无需编写任何复杂的代码,即可实现我们的 GradientButton,并且在设计器中,可以通过 Property Browser 操作 TextFontStartColor EndColor

 

访问底层系统

 

许多框架的一个缺点就是:如果人们编写的应用程序类型与示例和演示中的严格一致,则这些框架的效果相当不错,但有时开发人员发现,一旦他们希望用框架进行一些有创造性的工作,某些情况下就会碰到障碍或遭到失败。如果遇到这一情况,Win Forms 框架自始至终都能够允许开发人员访问系统基础结构。当然,希望 Win Forms 这样一个设计优良的框架不会使用户遭遇这种情况,但可能发生的情况几乎是无限的。所有的控件都有 Handle 属性,允许访问控件的窗口句柄 (HWND)GDI 对象也提供了类似的句柄访问过程。而且,Control 实际上拥有一个名为 WndProc 的受保护的虚拟方法,对于少数 Win Forms 尚不能支持的消息,可以替代该方法,添加处理方式。

 

例如,假设您的应用程序是资源密集型的,需要响应 WM_COMPACTING。如果系统检测到内存不足,会向所有高层窗口广播 WM_COMPACTING,您就会知道 Win Forms 框架对这一消息没有提供内置支持,由此,可以添加如下处理过程:

 

/// <summary>

///    Win32Form1 的摘要说明。

/// </summary>

public class CompactableForm : System.WinForms.Form {

private EventHandler handler;

public void AddOnCompacting(EventHandler h) {

handler = (EventHandler) Delegate.Combine(handler, h);

}

 

protected override void OnCompacting(EventArgs e) {

// 查看运行时系统能否释放任何东西

System.GC.Collect();

// 调用任一处理程序。

if (handler != null) handler(this, e);

   }

 

public void RemoveOnCompacting(EventHandler h) {

handler = (EventHandler) Delegate.Remove(handler, h);

}

 

protected override void WndProc(ref Message m) {

case (m.msg) {

case win.WM_COMPACTING:

OnCompacting(EventArgs.Empty);

break;

      }

base.WndProc(m);

   }

 

    }

 

只需数行代码,当系统试着收集未用资源时,利用新的 CompactableForm 类或由此派生的类即可得到通知,并作出响应。

 

结论

 

尽管在许多开发人员的计划中,针对 Web 的开发是当前工作的重点,而定位于熟悉的 Win32 平台仍然是一个不得不面对的情况。有了 Win FormsWindows 开发人员无论是新手还是老手,都会发现使用丰富的接口创建复杂的应用程序是一个很方便的过程,而这些接口与 .NET Framework 中具有 Web 和数据功能的许多技术配合良好。

 

通过利用跨语言继承、碎片收集和安全性等通用语言运行时提高工作效率的优秀功能,开发人员将从 .NET Framework Win Forms 中获益。

查看本文来源

    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章