中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Visual C++ > .NET平台
Z-order 和集合拷贝
作者:未知 时间:2005-07-20 14:21 出处:VC知识库 责编:chinaitpower
              摘要:Z-order 和集合拷贝

Z-order 和集合拷贝


原著:ken spencer

翻译:tjq_tang


原文出处:MSDN Magazine Jan 2004(AdvancedBasics)

原代码下载:AdvancedBasics0401.exe (131KB)

SendToBack 和 BringToFront 方法是改变 Windows® 窗体控件 z-order 的唯一选项吗?
 
解决这个难题采纳了在微软工作的一个哥们的建议,当然,一旦你知道了如何做,解决方法非常简单。
  Windows 窗体控件没有象以前 Visual Basic (ZOrder)那样具备处理 z-order 的属性。碰到类似的处理时,可以在控件集合中找到方法。SetChildIndex 方法允许你设置控件的 z-index 。下面这行代码出自 Figure 1中的单击事件,它改变 Label2 的 z-index 值:

      Me.Controls.SetChildIndex(Me.Label2, Label2NewIndex)       
为了获取某个控件当前的索引,调用 GetChildIndex方法,如 Figure 1中 ShowIndex 方法所示。

如何用 Windows 窗体控件集的 CopyTo 方法将控件拷贝到一个数组中?

CopyTo 方法将控件集拷贝到一个数组。为了使用它,你务必指定一个数组以及它的起始点。例如,下面的代码从第一个元素开始将控件拷贝到 MyArrayOfControls 数组。
      Me.Controls.CopyTo(MyArrayOfControls, 0)
  下面我举例来说明一下,首先,我创建叫 frmControlsToArrayMaster 的窗体,它包含一组 Label/textbox 控件和三个按钮。接着我创建第二个窗体, 叫做 frmArrayClient, 它与前面创建的窗体大小相同,但没有控件。 于是,我准备好编写一些代码。
  我最初写的代码是cmdCopy_Click事件(参见Figure 2)。该事件定义MyArrayOfControls数组大小为集合中控件的数目。然后,用 CopyTo 从第一个元素位置开始将控件拷贝到这个数组。我将这些代码放在按钮的 click 事件中,以便更加容易观察到它的运行。

接着我创建 cmdNew_Clieck 事件,第一个版本的代码就像这样:
	Private Sub cmdNew_Click(ByVal sender As System.Object, _
	   ByVal e As System.EventArgs) Handles cmdNew.Click
	   Dim frm As New frmArrayClient
	   frm.ShowDialog()
	End Sub      
然后,我在 frmArrayClient 中添加下面的代码:
	Dim ct As Control
	If MyArrayOfControls.GetUpperBound(0) > 0 Then
	   Me.Controls.AddRange(MyArrayOfControls)
	For Each ct In Me.Controls
	   If ct.GetType.ToString = "System.Windows.Forms.Button" Then
	   ct.Visible = False
	   End If
	Next
	End If      
  通过调用 Controls.AddRange 添加来自第一个窗体的控件。因为在这个窗体上我不想要相同命令的按钮,于是将任何按钮的Visible 属性都设置为 False。很 Cool 吧?
效果参见 Figure 3:


Figure 3 Reparented 控件

  上面的窗体是 frmControlsToArrayMaster,它是有控件的。但它们在哪里呢? 实际上,frmArrayClient 中的 AddRange 被调用时,这些控件从我的数组中被加载到新的窗体上。
因为一个控件仅能有一个父控件,这些控件被重新指定为新窗体( frmArrayClient )里的子控件。也就是说这些控件不会再出现在第一个窗体( frmControlsToArrayMaster )上。
  Figure 2 中的代码cmdNew_Click在进行上面的处理时是有隐痛的。它 会将控件放回到 frmControlsToArrayMaster。你可以自己运行例子程序来证明这一点,将数据放进两个控件,然后单击新按钮。现在将数据添加 到两个以上的控件并且关闭新的窗体。所有输入的数据现在都在在原来窗体上。大多数情况下这样是很酷,但如果你是想拷贝控件到新的窗体上,而不是移动它们,那会 怎么样呢?
  我对这个问题不是很在行,就向在 NetEdge Software 工作的朋友 Bill Martschenko 请求帮助,他发给我一些经典的代码以解决控件拷贝(克隆)问题。
  它通过 CopyTo 函数将拷贝控件到数组,创建同样属性的控件集合(或者它们的子集),作为原始的控件。接着就可添加新控件而不会影响到原来的控件。
  frmNewArrayClient2 采用了 Bill 建议的方法 . Figure 4 显示了新窗体,正如你所见的,原来的窗体上的控件依然如故,但新 窗体上这些控件被复制出来,几个命令按钮除外。


Figure 4 拷贝的控件

这个窗体加载 frmNewArrayClient2 事件:
	Dim ctNew As Control
	Dim i As Integer

	If MyArrayOfControls.GetUpperBound(0) > 0 Then
	    For i = 0 To MyArrayOfControls.GetUpperBound(0)
	        ctNew = CloneControl(MyArrayOfControls(i))
	        If ctNew.GetType.ToString <> "System.Windows.Forms.Button" Then
	            Me.Controls.Add(ctNew)
	        End If
	    Next
	End If  
  上面这段代码循环访问 MyArrayOfControls 中所有控件,然后只要不是按钮,便每次都创建一个新的控件并添加到窗体上。新控件是通过调用 CloneControl 函数创建的。此代码十分简单并实现了控件的拷贝。现在,让我们进一步深入代码看看它是如何工作的 (参见 Figure 5 ) 。首先, CloneControl 函数执行 下面这行代码,创建与当前控件类型相同的新控件:
	Dim newControl As Control = CType(NewAs(c), Control)      
从CType 调用中可以看出,它有一个 NewAs 方法调用。该函数的这个参数就是你要拷贝的控件。NewAs 的具体细节请参见 Figure 5
  如果你检查 NewAs 的定义( Figure 5 里有两个),就会发现它们看起来就像是自己在做递归调用,其实他们仅仅是被重载。这个小诀窍使你将参数作为对象来传递, 使得第一个函数调用干净利落。然后函数便可以对参数使用一些诸如 GetType 之类的操作,这样使开发人员更容易使用这个函数,因为他们不必知道如何调用私有函数的细节。第二个 NewAs 函数调用了程序集类的 CreateInstance,该方法根据控件 的类型创建控件实例。可以用它创建你想要克隆的控件实例。
  CloneProperties 函数的第二行拷贝控件的属性并且将属性映射到新控件中,参见如下代码:
	CloneProperties(newControl, c, "Visible", "Size", "Font", _
	    "Text", "Location", "BackColor", "ForeColor", "Enabled", _
	    "BackgroundImage")      
  CloneControl以一个If语句块结束,这个语句块允许你对特定的控件类型进行专门的处理。例子程序中有一个If语句块,当控件为按钮或链接标签时拷贝特定的属性。此外,它还二次调用
CloneProperties以获取附加属性。
  CloneProperties 函数实现代码也在 Figure 5 中,该函数有一个你想要设置的属性数组参数。然后,它为每一个控件创建一个 PropertyAccessor 类实例。最后,代码循环参数 名数组,将目标控件的属性设为源控件的属性。从而将源控件的属性一个一个拷贝到新控件属性中。
  让我们来看一下 PropertyAccessor 类(参见 Figure 6 )。该类的构造函数带了一个参数 --- 源或目的控件的引用,该引用设置到目标变量上。目标变量可继承引用控件的属性。
  有意思的是代码定义了子项属性,有缺省值。可以看到子项属性:
   Default Public Property Item(ByVal propertyName As String) As Object      
Get 方法返回属性值。接着创建 PropertyInfo 类的实例并设置需要的属性 :
      Dim prop As PropertyInfo = Me.Target.GetType().GetProperty(propertyName) 
一旦获得了属性,就可通过 GetValue 方法获得它的值。 Set 方法也是这样直接使用的。新值被忽略,你需创建 PropertyInfo 类实例:
      Dim prop As PropertyInfo = Me.Target.GetType().GetProperty(propertyName)
可调用 SetValue 设置属性值:
      prop.SetValue(Me.Target, value, Nothing)  
这就是所有的东西了。从一个 Form 拷贝控件到另一个 Form 的代码:
  这个月的二个问题初看比较困难。但 Microsoft® .NET Framework 都为它们提供了直接的方式来解决。有时候自己就得坚持不懈以找寻解决问题的方案。
对 Ken 所写有什么问题或者评论,与 basics@microsoft.com 联系。
  Ken Spencer 为 32X Tech 工作( http://www.32X.com ),提供培训,软件开发,微软技术质询。
 
本文出自 MSDN MagazineJanuary 2004 期刊,可通过当地 报摊获得,或者最好是 订阅

本文由 VCKBASE MTT 翻译
关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有