分享

Visual Basic 2005新功能——My命名空间

 猛小妖 2011-09-26

 

      Visual Basic不同于Visual C#、Visual C++之处在于它更偏重于快速开发,更针对非专业开发人员和编程新手。Visual Basic 2005这次提供的“My”是一个极为出色的设计,可以帮助开发人员快速利用.NET Framework中的各种功能进行开发。说到My到底是什么,其实它就是一个工程相关的命名空间,其中的内容是由IDE帮助你组织的。

      在My出现以前,.NET Framework已经具有强大而丰富的类库,学习这些类库算不上是一件轻松的事。许多VB或VC的开发者第一次接触到.NET开发时,总是习惯于自己实现或通过调用Windows API实现某些.NET早已准备好的功能。其原因就是.NET类库太庞大太分散了,许多常用的功能与那些不太常用的功能混在一起。比如,获得从当日零点开始的毫秒数的方法(经常被用来做随机数的种子)竟然与设置环境变量功能同在Environment类中,而不是“看上去像是”的System.Timers、TimeSpan或DateTime等命名空间或类型中。许多开发者对类库不熟悉,于是就一遍又一遍地重复开发.NET Framework的功能。Visual Basic Team为了解决这个问题,设计了My命名空间,它将.NET Framework中最常用的功能挑出来,然后按照最容易理解的逻辑结构存放在一起。当你深入My命名空间,你会发现那些功能就在你凭直觉就能想象到的路径中。

      My命名空间在当前版本中主要包含My.Application、My.Computer、My.Resources、My.User、My.Forms和My.Webservices等六个主要部分。你可以输入My关键字找到他们,也可以导入My命名空间,其语法是:Imports 项目名称.My

My.Application

在My命名空间中的所有类或对象中,My.Application是与当前运行的应用程序有关的对象,本次首先来介绍My.Application。My.Application提供的功能非常丰富,比如当前应用程序的主线程、主窗口、版本或公司版权等信息、文化和语言设置、路径及命令行、事件日志甚至Splash Screen的信息。下面的表格列出了My.Application的全部功能。

My.Application 成员 描述
ApplicationContext 应用程序的上下文,包括主线程和主窗体的信息
AssemblyInfo 程序集信息,包括版本、版权、标题、产品名称和可执行名称等
ChangeCurrentCulture 改变应用程序当前文化设置,如货币和时间的格式
ChangeCurrentUICulture 改变应用程序当前的用户界面文化设置,如显示语言和用词
CommandLineArgs 一个只读集合,返回当前应用程序的命令行参数。这些参数已经分隔开,无须像原来那样手工分隔Command函数的值了。
CurrentCulture 返回当前的文化设置
CurrentDirectory 返回应用程序使用的当前目录
CurrentUICulture 返回当前的用户界面文化设置
Deployment 返回按照ClickOnce方法部署的应用程序的Deployment对象
DoEvents 执行储存在Windows消息队列中的所有Windows消息
Exit 退出应用程序
GetEnvironmentVariable 通过环境变量的名字获取环境变量的值
IsNetworkDeployed 返回一个值,指示当前应用程序是否采用了网络部署方式
Log 一个记录应用程序事件日志和异常的日志工具
MainForm 当前应用程序的主窗体
OpenForms 当前应用程序中所有已经打开窗体的集合,与VB6的Forms集合功能相同
Run 启动Visual Basic的启动/关闭应用程序模式
SplashScreen 返回当前应用程序作为Splash Screen的窗口

可以注意到,My.Application中的某些功能和Application对象是一样的,但是My.Application不仅仅能用于Windows Form的应用程序,许多功能在控制台应用程序照样能够使用。下面举几个简单的例子来使用My.Application:

1、显示一个简单的关于窗口。

With My.Application.AssemblyInfo
    Dim msg As New System.Text.StringBuilder
    msg.AppendLine("Protuct Name: " & .ProductName)
    msg.AppendLine("Company Name: " & .CompanyName)
    msg.AppendLine("Version: " & .Version.ToString)
    msg.AppendLine("Description: " & .Description)

    MsgBox(msg.ToString, MsgBoxStyle.Information, "About " & .Title)
End With

2、将当前打开的所有窗口的标题都改为环境变量%TITLE%的值

For Each f As Form In My.Application.OpenForms
    f.Text = My.Application.GetEnvironmentVariable("TITLE")
    DoEvents() '也可以写成My.Application.DoEvents()
Next

3、检查如果从网络上部署,修改当前用户界面文化设置为英语-美国

If My.Application.IsNetworkDeployed Then
    My.Application.ChangeCurrentUICulture("en-US")
End If

My.Computer

My.Computer可能是My命名空间中最有趣的部分了,这一部分封装了大量访问系统和硬件信息的功能,操作起来比直接使用.NET Framework或Windows API都方便得多。My.Computer中有很多对象,下面我们分别来介绍。

My.Computer.Audio

Audio对象提供了播放音频的功能,它既可以从wav等文件播放,也可以从音频数据流来播放,就是说你可以用它轻松播放储存在资源文件中或者数据库中的音频。播放时还可以指定后台播放或等待结束等多种设置。结合My.Resources来使用,更显得方便无穷。这是一个简单的播放wav文件的例子:

My.Computer.Audio.Play("c:/ding.wav", AudioPlayMode.BackgroundLoop)

 

My.Computer.Clipboard

Clipboard对象提供了以强类型方式读写剪贴板的功能,比Windows.Forms里面的剪贴板更加好用。使用Clipboard对象可以直接从剪贴板读写音频、图像、文本甚至我的电脑中的文件拖放信息。此外,由VB6升级的项目现在将直接使用My.Computer.Clipboard对象升级以前的Clipboard对象,这将解决VB.NET不能升级原先剪贴板功能的缺陷。下面的例子将文本框内的内容复制到剪贴板:

My.Computer.Clipboard.SetText(TextBox1.Text)

My.Computer.Clock

Clock对象是一个获取时间的工具,它可以直接获取当地时间、中时区的时间和从当时子时开始的毫秒计数。

My.Computer.FileSystem

这是微软Visual Basic Team在My.Computer中倾注最多精力的对象,使用它可以充分改善文件操作的复杂程度。FileSystem对象提供了易于理解的操作方式。FileSystem对象中复制文件的方法不但只需要指定目标路径,还可以帮助你建立目标目录中不存在的级别。它还特别提供了CopyDirectory的功能,可以复制整个目录!这正是目前.NET Framework缺乏的功能。同时FileSystem还能提供搜索上级目、子目录或根目录的功能,非常体贴。下面例子展示了如何在动画演示下将文件放入回收站。

My.Computer.FileSystem.DeleteFile("c:/mybigfile.big", True, True)

FileSystem对象还提供了只用一行代码就可以读取文本文件内容,或者将所需内容写入文本文件的功能,现在你不需要再用迷惑人的StreamReader、StreamWriter来读写文件了,还不用担心资源释放的问题。如下面的例子:

s = My.Computer.FileSystem.ReadAllText("c:/a.txt")

除了可以通过My访问以外,通过System.IO.FileSystem类也可以完成FileSystem对象的大多数功能,这种方式似乎更适合于使用C#或C++的开发者。

My.Computer.Info

看名字就知道了,这个对象的属性都是系统信息。如果你想获得本机物理内存或虚拟内存的总数,剩余量、操作系统名称、当前用户名、本机安装的文化设置等等,都可以轻松使用Info对象,它让你对应用程序所在的系统了如指掌。

My.Computer.Keyboard和My.Computer.Mouse

通过这两个对象,你可以快速获得用户键盘的信息,如大写锁定、数字键盘锁定等是否打开,以及鼠标有几个按键,是否配备滚轮等。如果你希望你的应用程序能够做到最体贴用户,那这些信息是少不了了。下面例子演示获取用户的鼠标左右键功能是否交换(这样你就可以知道用户是不是左撇子,从而提供更体贴的界面,多爽)

Dim f As Boolean = My.Computer.Mouse.ButtonsSwapped

My.Computer.Name

不用多说,这就是本机操作系统安装时输入的名称

My.Computer.Network

这个Network对象充分简化了最常用的网络任务,只需要一行代码,就可以Ping一个地址,或者检测网络是否接通。还能用一行代码下载或上传文件。比如这个例子就完成了一个下载文件的任务:

If My.Computer.Network.IsAvailable Then
    My.Computer.Network.DownloadFile("
http:///x.zip", _
        "C:/download")
End If

My.Computer.Port

提供了用一行代码打开本机串口的功能,还能立刻绑定一个事件监视串口的变化。现在串口编程出奇的简单,再也不需要MSComm控件了。

My.Computer.Printers

这个Printers对象能够遍历本机所安装的所有打印机,还能找出默认的打印机。通过向默认打印机画图一样的操作,就能开始打印了。这样的操作会让你想起VB6时代便利而简洁的打印操作。下面的例子将在默认打印机上打印一个椭圆。从VB6升级项目时,原来的Printer对象将自动升级为My.Computer.Printers中的相关操作,升级的用户可以更加放心了。

My.Computer.Printers.DefaultPrinter.DrawEllipse( _
    New RectangleF(2, 2, 50, 150), 1)
My.Computer.Printers.DefaultPrinter.Print()

My.Computer.Registry

这个注册表对象可比Microsoft.Win32空间中的那个版本简单多了,他提供强类型的路径支持,还能非常方便地读写注册表。下面的例子是一段内置的代码片断,演示了如何判断某一键值是否存在。

Dim exists As Boolean = True

Dim path As String = "Software/Microsoft/TestApp/1.0"

If My.Computer.Registry.CurrentUser.OpenSubKey(path) Is Nothing Then
    exists = False
End If

My.Computer.Screen

Screen对象可以获取屏幕的可视范围,像素的位数等。比VB6的Screen对象更强的是,它现在支持两个显示器。

 

My.Resources和My.User

从原理上来说,My.Resources与前面介绍的My.Computer或My.Application是完全不同的,他带来的是另一种方便。My.Resource不是一个类库,而是My命名空间中唯一一个子命名空间。他的功能是什么呢?我们先回忆一下在.NET Framework1.1时代使用资源的情形。首先我们得通过工具,将图片、文本或声音等资源添加到资源列表中,编译成资源文件,再嵌入到我们的程序集中。当我们要使用资源的时候,必须通过System.Resources.ResourceManager从程序集中提取资源,然后自行判断资源的类型,做适当的转化并使用。比如从Form1的资源中取出ID为Greeting的字符串,需要写这么多代码:

Dim manager As New System.Resources.ResourceManage( _
    "MyApp.Form1", Me.GetType().Assembly)
Dim s As String = manager.GetString("Greeting")

而且那个编辑resx的界面不太直观,只添加字符串资源就不太方便,要想添加图片、音乐等文件到资源文件并在程序中取用就更麻烦了。到现在,许多Visual Basic .NET程序员还总是询问将图片音乐嵌入到EXE文件中去的方法。.NET Framework 2.0为解决这个问题引入了一个新特性——强类型资源。首先ResourceManager增加了一个GetStream()方法,方便获取图片、声音类的资源,其次Resgen工具可以根据资源的内容生成一个包装类,通过它可以直接强类型地读些程序集内的资源。而Visual Basic 2005将强类型资源与VB的IDE的特性结合在一起,就成了方便无比的My.Resources。

在实际使用My.Resources之前,我们先看看Visual Basic 2005新的资源编辑器,它现在已经继承到了项目属性中。打开项目属性并切换到Resources选项卡,我们可以看到如下的资源编辑器。

从顶端的下拉列表框中,可以选择资源的类型——声音、图像、文本、文件、图标或其他自定义内容。选择相应的类别,下面的编辑器就会发生变化,以适应当前类型的资源。每种类别都可以添加任意数量的资源。比如我们添加一个名称为Greeting的字符串,并让它的值等于"Hello",然后切换到代码窗口,输入My.Resource.看到什么了?Greeting弹出来了。现在我们使用这个资源之需要一行代码了。对比刚才所述的旧方法,你感到方便之处了吗?

Dim s As String = My.Resources.Greeting

如果我们添加了图片资源,那么也可以直接使用My.Resources来访问,而且就是BitMap类型,你想怎样用它就可以怎样用它,比如:

BackgroundImage = My.Resources.MyPic

一行代码就可以轻轻松松将窗口背景设置为资源中的图片。如果储存了声音资源,那么结合My.Computer.Audio的功能,播放资源中的声音也变得如此简单:

My.Computer.Audio.PlaySound(My.Resources.MySound)

想象一下以前要多少代码才能完成这样一个任务!有了My.Resource,资源的使用变得非常简单,你一定会改变对使用资源的看法,而爱上在自己的程序中使用资源的。

My.User是My命名空间中最小的成员,但是别看他小,功能对于.NET新手来说却不简单。如果你初次接触.NET开发,要获取当前登陆用户的用户名和用户组怎么办呢?谁会想到它其实是和Thread.CurrentPrincipal属性有关呢?My.User简单地将用户名和角色信息提供给你,要想获得当前登录的用户名,只需要输入My.User.Identity就行了。

 

My.Forms和My.WebServices

如果说My.Application、My.Computer和My.User是VB2005提供的汇集常用功能的类库,My.Resources是一个对项目资源的强类型封装,那么My.Forms和My.WebServices就是一个窗体和Web服务使用模式的绝佳范例。从VB6升级至Visual Basic .NET的程序员往往对VB.NET新的窗体编程模式不适应。因为VB.NET的窗体是类,必须要创建实例才能使用,而VB6的窗体则既是类又是对象,无须创建实例就能使用。在VB.NET中,往往要用这样的语法来使用窗体:

Dim frmForm2 As New Form1()
frmForm2.Show

然而用这样的语法显示窗体,各个窗体之间的通信或数据传递就十分困难。比如新生成的frmForm2要想访问另一个窗体Form1就难以做到,因为frmForm2无法获得Form1实例的引用。许多初学者在使用窗体的时候弄不清类、实力和引用之间的关系因此常常遇到苦难。即使熟悉了这些概念,有时仍不能用正确的方法解决窗体互相访问的问题。许多解决方案,如通过构造函数传递数据,通过全局变量或者静态变量,甚至在模块中生成项目中所有窗体的实例等等都不是十分理想,他们会增加窗体之间的耦合性,或者浪费内存。为了彻底解决窗体创建和互相访问的问题,Visual Basic 2005引入了My.Forms。My.Forms虽然在My命名空间中,但是使用它不需要输入My.Forms。假设你有两个窗体——Form1和Form2,Form1是启动窗体,现在你要用代码显示Form2,新的语法是这样的:

Form2.Show

这种用法和VB6几乎一样。Form2是窗体的类,怎么可以直接使用了呢?因为My.Forms为项目中每一个窗体维护了一个默认实例,其实现方法很像Singleton模式——每个窗体都有一个默认实例,而且有一个全局访问点,就通过窗体的类名即可访问到。这种方式彻底解决了窗体互相访问的问题,因为每个窗体都可以随时访问到任何其它的窗体的默认实例。比如要在Form2中修改Form1中一个TextBox的文字,只需要这样:

Form1.textBox1.Text = "Hello"

不在需要任何传递参数的构造函数或者静态/全局变量。一个项目中多数窗体都是只需要一个实例的,所以这种模式适合任何项目使用。无论是新手或老手,我都建议尽情使用My.Forms的功能,他是解决窗体互访的最佳模式,同时不会浪费内存,因为它只有在第一次访问所需窗体的时候才建立它。

My.WebServices的原理与My.Forms如出一辙,因为原来WebService的代理类都需要手工创建对象才能使用。而WebService对于项目全局应该有一个一致的访问点,所以VB2005将代替你创建代理类的实例,并维护于My.WebServices中,你可以随时访问他。比如你的项目添加了一个Web引用到Service1服务,它提供了一个方法叫Method1,以前的Visual Basic你必须写成:

Dim myService1 As New Service1()
Dim myResult As Integer = myService1.Method1()

而现在,无论在何地,你都可以直接写:

myResult = My.WebServices.Service1.Method1()

而无须手工创建代理类的对象了。

 

My命名空间之高级用法

但是对于一些高级用户来说,这些功能还显得有所欠缺。老手们有时也编写了类似My功能的类或函数,要是能把他们放到My命名空间中多好。My就像一个可随时访问的工具箱,除了里面已经有的工具以外,当然允许我们将自己的东西放进去。下面我们就来看看怎么扩展My命名空间。

添加自定义的类或模块

如果我们想要放进My中的函数都是静态的,那么直接把类或模块放入My命名空间是个方便的方法,做法非常简单,只要将类或模块定义在My命名空间中即可

Namespace My
    Public Module
Tools
        Public Sub DoSomething()
            'Some code here
        End Sub
    End Module
End Namespace

现在就可以直接用My.Tools来访问自定义的模块,很方便。

添加自定义类的实例

如果我们观察Visual Basic所提供的My命名空间成员,将发现他们都不是类本身,而是对象。因为所有的方法都做成静态毕竟不是最佳方法,我们有时候需要将一些自定义类的实例放到My命名空间中,这样不用的时候就比较节省内存,而且易于控制资源释放的问题。首先我们要定义自定义类,可以放在任何地方,而不必放到My命名空间中,这样就可以避免类名直接显示在My关键字后。然后,在My命名空间下,定义一个带有HideModuleNameAttribute的模块,名称可以随便起;最后在模块中设定访问自定义类实例的属性。假设我们的自定义类叫ToolsProxy,而自定义属性叫Tools,那么可以这样写:

'Namespace My

<HideModuleName()> _
Friend Module MyCustomModule
    Private syncRoot As New Object

    Private _tools As ToolsProxy

    ''' <summary>
    ''' Contains my custom tools.
    '''
</summary>
    Public ReadOnly Property Tools() As ToolsProxy
        Get
            'Double check lock to ensure thread safty.
            If _tools Is Nothing Then
                SyncLock syncRoot
                    If _tools Is Nothing Then
                        _tools = New ToolsProxy
                    End If
                End SyncLock
            End If


            Return _tools
        End Get
    End Property
End Module

有了HideModuleName这个Attribute,它本身就不会出现在My关键字后面,而它的属性则会显示。完成以后,你会发现My.Tools这次与Visual Basic内置在My中的对象没有任何区别了。此方法为扩展My最佳的方法,推荐使用。

扩展My.Application或My.Computer

有时候,我们不仅要将自定义的类添加到My中,还希望更进一步直接补充My.Application或My.Computer本身的功能。而这完全可以做到。Visual Basic提供了Partial关键字,他可以扩写当前项目中的类或结构,无论原先定义的时候是否加上了Partial关键字。于是我们就可以利用这一特征扩写定义看不见的My.Application或My.Computer。My.Application对应的是MyApplication类,而My.Computer对应的是MyComputer类。比如我们要给My.Computer增加一个新的功能——CdRomDriver属性,用以控制光驱的弹出、缩进与自动运行,就可以直接在My命名空间下扩写MyComputer类,如下:

'Namespace My

Partial Class MyComputer
    Public ReadOnly Property CdRomDriver() As CdRomDriver
        Get
            'Codes here
        End Get
    End Property
End Class

这样就成功地给My.Computer添加了新的属性,你会发现My.Computer.CdRomDriver和其他My.Computer有完全一样的行为。同样,My.Application也可以通过Partial并添加自定义属性的方式进行扩展。

现在我们可以看出,My命名空间是完全开放和可编程的,我们可以自由发挥想象力,创造完全属于自己的My命名空间。

也许说到这里,C#的程序员已经很眼馋了,能不能在C#中使用My命名空间呢?答案是能,又不能。C#的设计者没有提供通过My来访问对象的方法,那么直接使用My是不可能了。但是Visual Basic的设计者已经考虑到了这些问题,将My命名空间中大多数功能开放了出来,让C#和其他语言的程序员可以用到他们。

在C#中使用My.Application

要使用My.Application,必须要继承System.Windows.Forms.WindowsFormsApplicationBase(该类位于Microsoft.VisualBasic.dll中)。继承之后我们要做几件事情,首先书写构造函数初始化MyApplication类,在Visual Basic中这些设置均为IDE生成,而C#则需要手工书写。然后重写OnCreateMainForm方法,这个方法设定了当前应用程序的主窗体。接下来书写My类,让他提供对MyApplication类的全局访问点。最后改写Main,在其中执行My.Application.Run()代替原来的Application.Run(),具体做法如下。

namespace WindowsApplication2.Properties
{
    public class MyApplication : WindowsFormsApplicationBase
    {
        public MyApplication() : base(AuthenticationMode.Windows)
        {
            IsSingleInstance = false;
            EnableVisualStyles = true;
            ShutdownStyle = ShutdownMode.AfterMainFormCloses;
        }


        protected override void OnCreateMainForm()
        {
            //Sepecify the main form of your project
            MainForm = new WindowsApplication2.Form1();
        }

    }

    public static class My
    {
        private static MyApplication _Application;
        private static object syncRoot = new object();

        public static MyApplication Application
        {
            get {
                if (_Application == null)
                {
                    lock (syncRoot)
                    {
                        if (_Application == null)
                        {
                            _Application = new MyApplication();
                        }
                    } // end lock
                } // end if
                return _Application;
            } // end get
        }

    }
}

修改Main函数:

[STAThread]
static void Main()
{
    // Application.EnableVisualStyles();
    // Application.EnableRTLMirroring();
    // Application.Run(new Form1());

    Properties.My.Application.Run();
}

这样我们就充分获得了My.Application的对象模型。但是有些动态生成的内容,如SplashScreen对象等,除非自己书写,否则无法使用。通过这种方法使用My.Application可以获得许多额外的好处,比如获得My.Application的事件支持,他们是跟应用程序运行状态密切相关的事件,非常有用。但是由于缺乏自动代码的支持,不能保证My.Application事件的全部行为都和Visual Basic一样。

在C#中使用My.Computer

要使用My.Computer我们无需像Application那样费劲了。Visual Basic的设计者将大部分供能放到了System的自命名空间中,可以很自然地使用他们:

My中的名称 System中的名称
My.Computer.FileSystem System.IO.FileSystem
My.Application.AssemblyInfo System.Reflection.AssemblyInfo*
My.Computer.KeyBoard System.Windows.Forms.KeyBoard
My.Computer.Mouse Sysetm.Widnows.Forms.Mouse

注:System.Reflecton.AssemblyInfo只是My.Applicaton.AssemblyInfo的类型。

当然这不如Visual Basic中那样丰富,但是一般应用有FileSystem就足够了,其他功能用.NET Framework原本的方法也很简单。要注意,尽管这些类分散在System的各个字命名空间中,但是全部都位于Microsoft.VisualBasic.dll中,需要引用它才能使用。

在C#中使用My.Resources和My.Settings

一个好消息是,C#也内置了这两样功能,只要把My换成Properties就可以使用了,和Visual Basic一样方便。但是My.User、My.Forms和My.WebServices是真的没有了,要实现他们的功能,需要完全手工编码。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多