类似的,你在vb.net中写类似的代码测试,在load事件里也是visible.这下就知道哪种更合理了吧。 Sub MainFormLoad(sender As Object, e As EventArgs) trace("Form_load Text1.Visible: " & textBox1.Visible.ToString()) End Sub
Private Sub trace(ByVal Value As String) 'Debug.Print value listBox1.Items.Add(Value) End Sub
Sub MainFormActivated(sender As Object, e As EventArgs) trace("Form_Activated Text1.Visible: " & textBox1.Visible.ToString()) End Sub
一个 TextBox 控件可以看成一个窗口句柄和一个类的的组成。 VB6 和 VB.Net 的控件设计方式是不一样的: VB6 中句柄和类是强关联的,取 Visible 就是取 hWnd 的对应属性的当前值。 VB.Net 中句柄和类是弱关联的,取 Visible 属性取的是变量值,并不反映当前的真是状态。 '以下为 System.Windows.Forms.Control 的 reflector 代码' Public Property Visible As Boolean Get Return Me.GetVisibleCore End Get Set(ByVal value As Boolean) Me.SetVisibleCore(value) End Set End PropertyFriend Overridable Function GetVisibleCore() As Boolean If Not Me.GetState(2) Then '这个标志位存放的是应该是 Visible 属性' Return False End If '就算递归检查容器也与 hWnd 无关' Return ((Me.ParentInternal Is Nothing) OrElse Me.ParentInternal.GetVisibleCore) End FunctionFriend Function GetState(ByVal flag As Integer) As Boolean Return ((Me.state And flag) <> 0) End FunctionPrivate state As Integer 所以两者没有可比性,设计就是这样的,不存在“缺陷”的说法。
Private Sub Form_Load()
Me.Show
Debug.Print Text1.Visible 'VB6 bug:输出false
End Sub
先有Initialize事件,再有Load事件,再加载显示控件,再Show 再有Resize事件
问题是.有Hwnd的没有Show,那就表示不可见.
Sub MainFormLoad(sender As Object, e As EventArgs)
trace("Form_load Text1.Visible: " & textBox1.Visible.ToString())
End Sub
Private Sub trace(ByVal Value As String)
'Debug.Print value
listBox1.Items.Add(Value)
End Sub
Sub MainFormActivated(sender As Object, e As EventArgs)
trace("Form_Activated Text1.Visible: " & textBox1.Visible.ToString())
End Sub
刚加载没显示的时候就是 Visible = False,这是定性的。
去检测属性值纯属脱裤子放屁——多此一举。
Debug.Print Text1.Visible
至于类似Lable1控件,这些控件没有hwnd属性,它们可以理解为父窗口的一块区域而已。
VB6 和 VB.Net 的控件设计方式是不一样的:
VB6 中句柄和类是强关联的,取 Visible 就是取 hWnd 的对应属性的当前值。
VB.Net 中句柄和类是弱关联的,取 Visible 属性取的是变量值,并不反映当前的真是状态。
'以下为 System.Windows.Forms.Control 的 reflector 代码'
Public Property Visible As Boolean
Get
Return Me.GetVisibleCore
End Get
Set(ByVal value As Boolean)
Me.SetVisibleCore(value)
End Set
End PropertyFriend Overridable Function GetVisibleCore() As Boolean
If Not Me.GetState(2) Then '这个标志位存放的是应该是 Visible 属性'
Return False
End If
'就算递归检查容器也与 hWnd 无关'
Return ((Me.ParentInternal Is Nothing) OrElse Me.ParentInternal.GetVisibleCore)
End FunctionFriend Function GetState(ByVal flag As Integer) As Boolean
Return ((Me.state And flag) <> 0)
End FunctionPrivate state As Integer
所以两者没有可比性,设计就是这样的,不存在“缺陷”的说法。
不是 Bug,是一种设计约定。比如我在某一个控件(比如 ListBox 或 ComBoBox)的 Click 事件中对另一个控件进行操作。如果我在 Form_Load 事件中将对该 ListBox 或 ComBoBox 或 AddItem 并设置了当前 Index,则 Click 事件就被触发。但此时另一个控件还不能进行某些操作,比如 SetFocus(因为还没有完成初始化)。所以,我可以在前一个控件的 Click 事件中这样写:If txtCLS.Visible Then txtCLS.SetFocus这样,由于 FormLoad 中的语句引起的事件触发就不会发生错误,而后续运行中的事件触发就得到正确处理。当然了,如果当初设计时没有对 Visible 这样处理,也还可以再添加一个新的属性,比如较 Initialized 来处理这种情况,也是可以的。但目前的约定更简单一些。不要预先假设微软的设计者比我们更 2。
show 显示窗口
至少,我目前发现了两个在界面处理方面的BUG:
一个是 Windows XP系统的;一个是 VB6的下拉列表控件的。
就好像在load事件中不能xxx.setfocus一样
一般我们要设置某个控件启动后获得焦点都在Initialize事件中处理。
错,你自己在每个事件开关放个Debug.print就看得出来了