分类: C/C++
2008-08-05 13:56:22
本文使用了以下技术:Visual Basic 2005 和 .NET Framework
我开始着手写这篇关于 Visual Basic
2005 的文章时,我竟然都不知从哪里下笔才好。我在整个特性列表中徘徊,要是给你一大堆 IDE 酷酷的特色,比如编辑/继续,IntelliSense 代码段(Code
Snippets),或异常辅助机制;浏览一下最新的语言增强如泛型,局部类(partial
classes)以及无符号类型;还有不能不说的关于 Windows Forms 的所有酷酷的 Microsoft .NET Framework 增强
特性、数据绑定、ClickOnce 部署及其它。虽然这些都是令人感兴趣的特色,但本文我将挖掘 Visual Basic
2005中最酷的一个特色,即 My 命名空间。
为什么是 My?
程序员遇到的最大问题是 .NET 的博大精深,这意味着想找到一个刚好适合特殊任务的最佳类将是令人望而生畏。我曾读过许多开发者的新闻组邮件,他们很努力地从他们的Visual
Basic .NET 或 C# 代码中调用一个Win32 API函数,而同时在
.NET中正好有所要的函数(function)。为什么他们要调用API?他们没有找到、注意或也许没有理解如何使用已有框架的部分。My通过容易理解的根对象(root
objects)提供一个直观的导航层次以揭示现有的.NET功能,以你在一个有条理的基础上抓住实际任务和概念为目标。
哦,这听起来不错,但它意味着什么呢,为了很快地勾勒出My的好处,让我们看看在GotDotNet的论坛上的一个非常普通的问题:“我怎样才能完全读取一个文本文件的内容到一个字符串中去?”.NET
Framework 1.1的答案是这样的:
Dim sr As New IO.StreamReader("c:\mytextfile.txt") contents = sr.ReadToEnd sr.Close()
它不需要太多的代码,但是它当然也不直观。对许多人来说,使用 StreamReader 途径将导致他们在该代码段结束之前遍历 Stream 类,FileStream 类,及更多的其它类。完全相同的代码在 Visual Basic 2005 中将会运行得很好,但用 My 来获得相同的信息要快得多,象下面这样写:
contents = My.Computer.FileSystem.ReadAllText("c:\mytextfile.txt")
My.Computer.FileSystem 只是包含在 My 语言扩展中许多类中的一个,因此首先我们要熟悉什么是可以利用的?
My 被最恰当地描述成
.NET框架中的一个速度表盘(speed-dial)。这种简化——使其能更加容易地找到并执行正确的操作——在程序设计时是一种普遍惯例。当我或我的开发
团队碰到在某个多步处理中要重复使用的过程时,我一般会创建一个辅助函数(helper function)。该辅助函数通常只是
一个带有若干参数的简单调用,这些参数都是些用法最普通的参数,然后在此环境下完成多步处理,精细化开发过程。绝大多数软件开发商都构建此类辅助函数,并
将它们分组结合成一些代码段集或者形成像 MyCompany.Utilities 或 Duncan.NetworkUtilities
这样的共享库,这是一种相当普遍的做法。
正如许多函数对几乎所有开发团队都很有用,创建这些库存在大量的重复工作。My 将辅助函数的思路提高到了一个全新的层次上,因为它们包含了如此之多的功能
,而且它们与 Visual
Basic 一起交付。就把它看成一个你不必自己去编写的充满生产力的增强的代码库。
My 探索
My 展示了几个完全不同的类,这些类将各种不同的函数分门别类概括地组织成七个范畴之一:
My.Application、My.Computer、My.Forms、My.Resources、My.Settings、My.User 和 My.WebServices。
一般来说,My 中提供的类可以轻松存取两类信息之一,不论是 .NET Framework 底层信息还是当前项目元素。My.Application、My.Computer、和 My.User 都
被聚焦于框架功能,虽然 My.Forms、My.Resources、My.Settings、和 My.WebServices 都处理当前项目的内容。当我
挨个讨论每个类时,都从针对底层框架的内容开始,我将提供一些有针对性的例子,它们都包含相关的属性和类信息。
正如我早先提到的,当你使用 .NET
Framework 时,找到你需要的确切功能有时是很困难的,但你要注意的问题不仅仅是找到它。在一些特殊环境下,即使在你发现了你所需要的类后,特定的步骤
以及搞掂构造函数所需的参数可能要用好几行代码,而且理解起来可能都很困难。My 类(My.Application、My.Computer 和
My.User)针对 Framework 而设计,帮助你直接操纵你需要的类,并让它们就绪以便你能直接使用。
My.Application
My.Application 为开发者提供了一个应用程序信息和服务的直观分组。My.Application下的单个节点包括 AssemblyInfo(应用的版权,标题,描述等等), OpenForms(当前
打开的项目中所有窗体的集合),Log(一个被集成到 System.Diagnostics 类中特性丰富的具备高可配置性日志工具)以及更多。
使用 My.Application.Log 类,记录异常日志或许比原来更容易。当开发者能写出如下代码时,那他们是怎样的一位真正的编码大侠:
Dim winINIFile As String Try winINIFile = My.Computer.FileSystem.ReadText("c:\windows\wind.ini") Catch ex As IO.FileNotFoundException My.Application.Log.WriteException(ex, "Error Accessing INI File") End Try
Visual Basic 6.0 和更早版本的用户当时讨论得出的更普通的特色要求之一便是加入了 OpenForms 集合。在 Visual Basic 6.0 中通过关键字“Forms”这个集合是可获得的,为你提供了一种简单的方法来循环遍历应用程序中当前所有打开的窗体,不用费力去维护自己的全局 窗体清单,如这里所示:
For Each f As Form In My.Application.OpenForms Debug.WriteLine(f.Text) f.WindowState = FormWindowState.Minimized Next
My.Computer 和 My.User
My.Computer 允许你操作与主机有关所服务和数据。这个类的功能可以单独写一篇文章,但我在本文将只讨论其最为精华的部分。
FileSystem 类为使用文件和查询文件提供了一个非常简单的API;这将消除人们仍然对FileSystemObject 库的任何向往。下面的代码使用 FileSystem 类拷贝所有当前用户的 My
Pictures文件夹中的图片到一个新的文件夹(C:\Desktop Wallpaper),如果文件拷贝需要一会儿才能结束则显示一个进度条:
Dim myPics As String = _ My.Computer.FileSystem.SpecialFolders.MyPictures.Path My.Computer.FileSystem.CopyFolderContents( _ "C:\Desktop Wallpaper", myPics, False, True) MsgBox( My.Computer.FileSystem.GetFiles( _ myPics, "*.jpg", "*.bmp").Count)
在.NET Framework 1.1中为了完成相同的文件拷贝将需要更多一些的代码(参见 Figure 1):
''''''''Figure 1 在 .NET Framework 1.1 中拷贝文件''''''''''并且此代码还没有包含显示进度条功能,你要自己创建你自己的进度条。
Dim myPics As String = Environment.GetFolderPath( _ Environment.SpecialFolder.MyPictures) Dim pictureFiles As String() = IO.Directory.GetFiles(myPics) Dim targetDirectory As String = "C:\Desktop Wallpaper" Dim newPath As String Dim jpgAndbmpCount As Integer For Each pic As String In pictureFiles newPath = IO.Path.Combine(targetDirectory, pic) IO.File.Copy(IO.Path.Combine(myPics, pic), newPath, False) If IO.Path.GetExtension(pic) = "jpg" Or _ IO.Path.GetExtension(pic) = "bmp" Then jpgAndbmpCount = 1 End If Next MsgBox(jpgAndbmpCount)
Dim comport As IO.Ports.SerialPort comport = My.Computer.Ports.OpenSerialPort("COM1") AddHandler comport.ReceivedEvent, AddressOf DataReceived
My.Computer.Audio 类允许你播放自定义的或系统的声音,终结了 P/Invoking 的 PlaySound API 的使用,如这里所示:
Dim musicFile As String musicFile = My.Computer.FileSystem. _ GetFiles("C:\WINDOWS\Media", "*.wav")(0).Path My.Computer.Audio.Play(musicFile)
My.Computer.Network 使得各种广泛的网络调用变得容易,包括接收和发送 Pings(试通程序)到远程机器,上传或下载文件,确定是否 联接,如此等等。
If My.Computer.Network.IsConnected Then If My.Computer.Network.Ping("") Then Debug.WriteLine("Site Available") My.Computer.Network.DownloadFile( _ "http:///Articles/", _ My.Computer.FileSystem.SpecialFolders.MyDocuments, _ ShowProgress:=True) End If End If
在 Windows Forms 命名空间中,My.Computer.Printer 和新的 Printing 类一起工作使得打印工作易如反掌。作为一个例子,制作一个如图 Figure 2 所示的报表,以前得动用那些熟悉 GDI 编程的人来实现。这里是开始的几行代码:
With My.Computer.Printers.DefaultPrinter .HorizontalAlignment = HorizontalAlignment.Center .WriteLine("Document Title") .WriteImage(New Bitmap("z:\msdn-logo.gif")) .HorizontalAlignment = HorizontalAlignment.Left .Write("Company Name") .HorizontalAlignment = HorizontalAlignment.Right .WriteLine("Report Title") .WriteHorizontalLine(0.05) .WriteLine() ...
如果你想知道使用 Framework 1.1 制作同样类型的报表要涉及到写什么,你可以看看我在 MSDN 在线上(MSDN®
Online)一篇有关打印的技术文章:“Printing Reports in Windows Forms”。
Figure 2 用 My 创建报表
这里还有一些更多的类我不准备在此赘述了,包括 My.Computer.Keyboard,My.Computer.Registry,和 My.Computer.Screen。希望你能自己体验它们。
通过 My 中 My.Computer 部分公开了如此之多的功能,以致于每当 Visual Studio 2005 新的beta 版和
社区下载(Community Drop)版发布时,其对象模型便成为首先看到的文档之一。
My.User 是 My 中的最为简单一个类,但是不要被它的简单所愚弄;它提供访问应用程序当前用户一些相当有用的信息。这些信息包括属性,比如 DisplayName,UserName
和 DomainName,以及查询角色成员的方法,和 IsAuthenticated 这样的状态函数:
If My.User.IsAuthenticated Then If My.User.IsInRole("BUILTIN\Administrators") Then MsgBox("tsk, tsk... running as Admin are we?") End If End If
注意 My.User 的属性和方法默认使用 Windows 认证,但是它同时也将和自定义的安全低层结构很好地无缝接合,以保持相同编码模式与所使用的认证类型
无关。
从你的项目中公开设置,资源和更多的信息
My 中以项目为中心的类包括 Settings、Resources、WebServices 和 Forms。
当明确指定窗体时,前面两个类处理你的项目相关的数据,WebServices 类提供对窗体以及已经添加到项目中的 Web 服务的直接存取。
Figure 3 设置设计器
使用 Visual Studio
2005 的 IDE,你可以建立多种资源元素以及用户的强类型分组或者应用程序级的设置(通过 Figure 3 所示的设计器接口)。
Figure 4 资源编辑
在两种情况下,你必须在对应的类成为 My 可利用的类之前配置设置或资源,但是一旦它们被添加到你的项目中,My.Resources 和 My.Settings 类(分别地)使
你很容易与任一信息的类型交互。下面的例程获取并修改某个保存的用户设置,这时使用 My.Resources 类来获取一个在消息框中使用的局部字符串(如
Figure 4 所示,用 IDE 工具创建):
Dim lastRun As Date lastRun = My.Settings.LastRun My.Settings.LastRun = Now() Dim myMessage As String = _ String.Format(My.Resources.LastRunMessage, _ lastRun.ToShortDateString) MsgBox(myMessage)
除了刚才描述的两个方面以外,项目中的所有窗体都可以通过 My.Forms 获得,并且任何在项目中引用的 Web 服务都通过 My.WebServices 类 公开。对于 Web 服务,这意味着你具备直接引用它们的选择权而不用手工建立实例。因此,从 xmethods.com 添加一个引用到 TemperatureService 后,你可以用下面的代码 获取当前的温度:
Dim tempService As New net.xmethods.() MsgBox(tempService.getTemp("98052"))这可以更加简单地表示成:
MsgBox(My.WebServices.TemperatureService.getTemp("98052"))
My.Forms 与我早先讨论的 My.Application.OpenForms 集合有所不同,因为 My.Forms 公开每个Form 类的一个默认实例,而不是这些类的当前打开的实例。如果你有 Visual Basic 6.0 或更早版本的编程背景,这些默认实例将对你来说是绝对有用的,因为它们使你能显示、隐藏或使用 Form 类名直接存取窗体:
Private Sub showForm2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles showForm2.Click My.Forms.Form2.Show() End Sub Private Sub updateForm2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles updateForm2.Click My.Forms.Form2.Text = "Updated..." End Sub
这在 .NET 框架发布之前的 Visual Basic 中是标准行为,并且对那些已经熟悉 Visual Basic
6.0 编程方式的开发者来说,它将是一个令人欢迎的回归。
结束语
Visual Basic 2005 中的 My 为访问 .NET Framework 中的某些深层
功能提供了快速轻松的方法,它不会防碍你用任何所选择的方法直接使用
Framework。除了公开 Framework 功能以外,My 的某些方面,比如窗体集合,带回一些 Visual
Basic 早期版本中熟悉和方便的编程概念。用得到的 Visual Studio 2005 试试吧,我相信你会发现它很有用的。