隐藏TextBox的Caret
来源:cww
这个问题有些有趣,我们知道使用HideCaret可以来隐藏Caret,但是只要我们KeyIn任
何字之後,Caret又跑出来了,好像HideCaret没有效用一般。其实,问题可能出在
TextBox内部的运作,TextBox内部在GetFocus与Keyin字时会将Caret重新显示,所以就
算我们HideCaret,只要有Keyin字,那Caret便会再出现。如果说,把HideCaret的指令
放在Text1_KeyUp,那的确也会使Caret不见,不过每次KeyDown字时,Caret会出现,
而KeyUp後才会令Caret消失,这可能不是我们想要的。

解决这个问题,其实有很多困难,那得改变TextBox内部的运作。但是我们可以达到"还
可以"的效果,这个程式是告诉我们,Windows程式设计真的要了解Message出现的顺序,
否则,常会有意想不到的问题。

既然TextBox在KeyDown时会ShowCaret,那我们就先让它Show,之後我们再HideCaret就
好了,所以只要在HideCaret之前加个DoEvents,便可以达到"比较好"的效果,说"比较
好"而不说完全解决的原因是,毕竟系统还是有ShowCaret过,但立即被HideCaret所隐藏
,有时,会看到一下下Caret,但已好多了。注:不加DoEvents的结果是:先执行我们程
式的HideCaret,之後交给Windows处理,又会把Caret show出来,而加了DoEvents後,
是先让Windows ShowCaret後,才执行到我们的HideCaret。我们可以这样想:

TextBox KeyDown的执行

1.Window执行KeyDown的前置动作
2.RasisEvents KeyDown     'vb 产生一个keydown的Event,以便我们在Text1_KeyDow
                          '之内写程式
3.Window 执行KeyDown的後置动作

而Windows内部ShowCaret的动作便是在第3个步骤中做的。我们在第2步中加个Doevents
以便Windows先处理第3步的一些Message。

当然,这只是我们可以这样思考,实际上Window的运作是Messages,而不是Events
'需2个Command Button 一个textbox
Option Explicit
Private Declare Function HideCaret Lib "user32" (ByVal hwnd As Long) As Long

Private CanShow As Boolean

Private Sub Form_Load()
CanShow = True
Command1.Caption = "Hide"
Command2.Caption = "Show"
End Sub

Private Sub Command1_Click()
CanShow = False
End Sub

Private Sub Command2_Click()
CanShow = True
End Sub

Private Sub Text1_GotFocus()
If Not CanShow Then
   DoEvents
   Call HideCaret(Text1.hwnd)
End If
End Sub

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)
If Not CanShow Then
   DoEvents
   Call HideCaret(Text1.hwnd)
End If
End Sub