什么';在VB6中使用按钮标题作为变量有什么不好?
我在上一个问题()中收到了一些合理的批评性反馈,因为我使用了命令按钮的标题作为状态变量。我这样做是因为它效率高,只需很少的代码就可以同时满足两到三个目的,但我理解它如何也会导致问题,特别是我最初介绍它的方式有点马虎 我觉得这值得自己讨论,所以这里有一个相同的想法,经过一些清理和修改,以“正确地”完成它(这基本上意味着在一个地方定义字符串,这样您的代码就不会因为更改命令按钮的文本而开始失败)。我知道我的变量和控件命名约定很差(好的,不存在),所以请提前道歉。但我想把重点放在状态变量讨论的标题上 现在我们开始:什么';在VB6中使用按钮标题作为变量有什么不好?,vb6,Vb6,我在上一个问题()中收到了一些合理的批评性反馈,因为我使用了命令按钮的标题作为状态变量。我这样做是因为它效率高,只需很少的代码就可以同时满足两到三个目的,但我理解它如何也会导致问题,特别是我最初介绍它的方式有点马虎 我觉得这值得自己讨论,所以这里有一个相同的想法,经过一些清理和修改,以“正确地”完成它(这基本上意味着在一个地方定义字符串,这样您的代码就不会因为更改命令按钮的文本而开始失败)。我知道我的变量和控件命名约定很差(好的,不存在),所以请提前道歉。但我想把重点放在状态变量讨论的标题上 现
' Global variables for this form
Dim DoTheThingCaption(1) As String
Dim UserCancel, FunctionCompleted As Boolean
Private Sub Form_Initialize()
' Define the possible captions (is there a #define equivalent for strings?)
DoTheThingCaption(0) = "Click to Start Doing the Thing"
DoTheThingCaption(1) = "Click to Stop Doing the Thing"
' Set the caption state when form initializes
DoTheThing.Caption = DoTheThingCaption(0)
End Sub
Private Sub DoTheThing_Click() ' Command Button
If DoTheThing.Caption = DoTheThingCaption(0) Then
UserCancel = False ' this is the first time we've entered this sub
Else ' We've re-entered this routine (user clicked on button again
' while this routine was already running), so we want to abort
UserCancel = True ' Set this so we'll see it when we exit this re-entry
DoTheThing.Enabled = False 'Prevent additional clicks
Exit Sub
End If
' Indicate that we're now Doing the Thing and how to cancel
DoTheThing.Caption = DoTheThingCaption(1)
For i = 0 To ReallyBigNumber
Call DoSomethingSomewhatTimeConsuming
If UserCancel = True Then Exit For ' Exit For Loop if requested
DoEvents ' Allows program to see GUI events
Next
' We've either finished or been canceled, either way
' we want to change caption back
DoTheThing.Caption = DoTheThingCaption(0)
If UserCancel = True Then GoTo Cleanup
'If we get to here we've finished successfully
FunctionCompleted = True
Exit Sub '******* We exit sub here if we didn't get canceled *******
Cleanup:
'We can only get to here if user canceled before function completed
FunctionCompleted = False
UserCancel = False ' clear this so we can reenter later
DoTheThing.Enabled = True 'Prevent additional clicks
End Sub '******* We exit sub here if we did get canceled *******
就是这样。这样做还有什么不好的地方吗?这只是一个风格问题吗?有没有其他东西能让我以更理想或更易于维护的方式实现这四点
我可以看到一个问题可能是代码和GUI之间的紧密耦合(以多种方式),因此我可以看到这对于大型项目(或者至少是大型GUI)来说是一个大问题。这恰好是一个较小的项目,只有2或3个按钮可以接受这种“处理”。这种技术最大的一个问题是它使用字符串作为布尔值。根据定义,布尔变量只能有两个状态,而字符串可以有任意数量的状态 现在,您已经通过依赖预定义字符串数组来定义命令按钮文本的允许值,在某种程度上缓解了这种情况下固有的危险。这就留下了一些较小的问题:
- 关于当前和可用状态,逻辑不够明确(表单实际上有四种可能的状态:未启动、已启动、已完成、已启动但正在取消)-维护需要仔细观察按钮文本和布尔变量状态之间的潜在交互,以确定当前状态是/应该是什么。单个枚举将使这些状态显式,使代码更易于阅读和理解,从而简化维护
- 您依赖控件属性(按钮文本)的行为来保持与公开属性值类型(字符串)的行为一致。这种假设使得将旧的VB6代码迁移到新的语言/平台变得非常困难
- 字符串比较比布尔变量的简单测试慢得多。在这种情况下,这无关紧要。一般来说,避免它同样容易
- 您正在使用DoEvents来模拟多线程(与问题没有直接关系……但是,呃)
- 我在处理(非常旧的)代码(按钮标题作为变量)时遇到的最大问题是全球化是一场噩梦。。。。我不得不移动一个旧的vb6应用程序来使用英语和德语。。。这花了几个星期,甚至几个月
你也在使用goto's。。。。。也许需要一些重构来使代码可读
**根据评论进行编辑
我只会在每个进程的顶部使用vb6中的goto;
错误转到myErrorHandler
然后在程序的最底层,我会有一个将err传递给全局处理程序的单行程序来记录错误。我认为最好将标题文本与处理状态分离。此外,后藤也让人难以阅读。这是我的重构版本
Private Const Caption_Start As String = "Click to Start Doing the Thing"
Private Const Caption_Stop As String = "Click to Stop Doing the Thing"
Private Enum eStates
State_Initialized
State_Running
State_Canceled
State_Completed
End Enum
Private Current_State As eStates
Private Sub Form_Initialize()
DoTheThing.Caption = Caption_Start
Current_State = State_Initialized
End Sub
Private Sub DoTheThing_Click()
If Current_State = State_Running Then
'currently running - so set state to canceled, reset caption'
'and disable button until loop can respond to the cancel'
Current_State = State_Canceled
DoTheThing.Caption = Caption_Start
DoTheThing.Enabled = False
Else
'not running - so set state and caption'
Current_State = State_Running
DoTheThing.Caption = Caption_Stop
'do the work'
For i = 0 To ReallyBigNumber
Call DoSomethingSomewhatTimeConsuming
'at intervals check the state for cancel'
If Current_State = State_Canceled Then
're-enable button and bail out of the loop'
DoTheThing.Enabled = True
Exit For
End If
DoEvents
Next
'did we make it to the end without being canceled?'
If Current_State <> State_Canceled Then
Current_State = State_Completed
DoTheThing.Caption = Caption_Start
End If
End If
End Sub
Private Const Caption\u Start As String=“单击开始操作”
Private Const Caption_Stop As String=“单击以停止操作”
私人地产
状态u已初始化
国家运行
州政府取消
州政府已完成
结束枚举
作为不动产的私有当前状态
私有子表单_初始化()
DoTheThing.Caption=Caption\u Start
当前状态=已初始化状态
端接头
私有子点点击()
如果当前状态=运行状态,则
'当前正在运行-因此将状态设置为已取消,重置标题'
'和禁用按钮,直到循环可以响应取消'
当前状态=已取消状态
DoTheThing.Caption=Caption\u Start
DoTheThing.Enabled=False
其他的
'未运行-因此设置状态和标题'
当前状态=运行状态
DoTheThing.Caption=Caption\u Stop
“完成工作”
对于i=0到ReallyBigNumber
呼叫DoSomethingSomewhatTimeConsuming
'每隔一段时间检查取消状态'
如果当前状态=已取消状态,则
'重新启用按钮并退出循环'
DoTheThing.Enabled=True
退出
如果结束
多芬特
下一个
“我们没有被取消就完成了吗?”
如果当前状态已取消,则
当前状态=状态完成
DoTheThing.Caption=Caption\u Start
如果结束
如果结束
端接头
除了像DJ在中那样删除GOTos外,您的方法没有任何错误。按钮标题只能有两种状态,您可以使用这两种状态来定义代码中的流
然而,我有两个原因可以解释为什么我会采取不同的做法: