word2003/VBA Repainting a form

User avatar
ChrisGreaves
PlutoniumLounger
Posts: 16801
Joined: 24 Jan 2010, 23:23
Location: brings.slot.perky

word2003/VBA Repainting a form

Post by ChrisGreaves »

Code: Select all

Private Sub cmdFind_Click()
    Dim lngOldBackground  As Long <<<<<<<<<<<<<<<<
    lngOldBackground = Me.cmdFind.BackColor <<<<<<<<<<<<<<<<
    Me.cmdFind.BackColor = RGB(255, 0, 0) <<<<<<<<<<<<<<<<
    Me.Repaint  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    Me.lbFoundStrings.Clear
    Me.lbProcedure.Clear
    If Len(Trim(Me.tbFind)) > 0 Then
        Dim strAr() As String
        Dim lngComparisonConstant As Long
        If frmLocator.cbCaseSensitive Then
            lngComparisonConstant = vbBinaryCompare
        Else
            lngComparisonConstant = vbTextCompare ' find a given string
        End If
        Call LoadFoundArrays(strLib, Me.tbFind, strAr, lngComparisonConstant)
        If UBound(strAr, 2) > 0 Then
            Dim lng As Long
            For lng = LBound(strAr, 2) To UBound(strAr, 2) - 1
                Dim strListItem As String
                strListItem = ""
                Dim i As Long
                For i = LBound(strAr, 1) To UBound(strAr, 1)
                    strListItem = strListItem & strAr(i, lng) & " "
                Next i
                Me.lbFoundStrings.AddItem (strListItem)
            Next lng
        Else
        End If
    Else
    End If
    Me.cmdFind.BackColor = lngOldBackground  <<<<<<<<<<<<<<<<
    Me.Repaint  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
End Sub
My GUI form now does what I want it to do ("It Works"), but since I can't remember using .Repaint before, I am mildly curious if there is a better way to flip colours on a command button.
Empty4x4.jpg
Here is the GUI form as it searches a 64 MB string of source code looking for the string "function convert"; if I searched for "End Function" the search would take over three minutes; if I searched for "sdfgthyjukilotyuiop" the search would finish in whatever time it takes INSTR() to look for "sdfgthyjukilotyuiop" in a 64 MB string, and the Find button would blink to red and then back to grey in less than an eyelid.

To all the VB{A} experts out there, is there an alternate way to effect this short-term change to a GUI form?

Without those two Me.Repaint commands, the change to RGB(255,0,0) doesn't show up at all. I suspect that the GUI form retains control.

Thanks, Chris
You do not have the required permissions to view the files attached to this post.
Fill your face with laughter, then there will be no room for tears.

User avatar
HansV
Administrator
Posts: 80088
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: word2003/VBA Repainting a form

Post by HansV »

Yes, you do need to repaint a userform if you want to update it while code is running, because that is suspended by default.
Best wishes,
Hans

User avatar
SpeakEasy
5StarLounger
Posts: 742
Joined: 27 Jun 2021, 10:46

Re: word2003/VBA Repainting a form

Post by SpeakEasy »

>is there an alternate way to effect this short-term change to a GUI form?

DoEvents - but DoEvents can have knock on effects, such as allowing reentrancy.

User avatar
ChrisGreaves
PlutoniumLounger
Posts: 16801
Joined: 24 Jan 2010, 23:23
Location: brings.slot.perky

Re: word2003/VBA Repainting a form

Post by ChrisGreaves »

SpeakEasy wrote:
14 Jan 2025, 00:04
DoEvents - but DoEvents can have knock on effects, such as allowing reentrancy.
Speakeasy, thank you for this alternatives. My understanding of "DoEvents" is that immediately allows control back to at least some part of the Windows O/S, and that it allows some VBA processes (vaguely undefined here) to start or complete.
In terms of my GUI forms this all suggests that VBA code be be started, or resumed, that allows a logical re-starting of this GUI form, re-entrant in that sense?
Thanks, Chris
Fill your face with laughter, then there will be no room for tears.

User avatar
SpeakEasy
5StarLounger
Posts: 742
Joined: 27 Jun 2021, 10:46

Re: word2003/VBA Repainting a form

Post by SpeakEasy »

DoEvent causes the current thread to be suspended while all waiting window messages are processed, which includes user input like mouse clicks or keyboard presses.

So in your case it would be possible for cmdFind to be clicked again whilst cmdFind_Click is already running (albeit currently paused) ...

User avatar
StuartR
Administrator
Posts: 12949
Joined: 16 Jan 2010, 15:49
Location: London, Europe

Re: word2003/VBA Repainting a form

Post by StuartR »

SpeakEasy wrote:
15 Jan 2025, 12:22
So in your case it would be possible for cmdFind to be clicked again whilst cmdFind_Click is already running (albeit currently paused) ...
The usual way to deal with this is to define a static Boolean variable in the procedure, give it a name like "IsRunning". Every time you start the procedure check the value of IsRunning: if True then immediately exit, if False then set to True. At the end of the procedure set it back to False again.
StuartR


User avatar
SpeakEasy
5StarLounger
Posts: 742
Joined: 27 Jun 2021, 10:46

Re: word2003/VBA Repainting a form

Post by SpeakEasy »

Sure, not saying you cannot code defensively against reentrancy. Just saying you need to be aware that DoEvents can have unexpected side effects.

User avatar
ChrisGreaves
PlutoniumLounger
Posts: 16801
Joined: 24 Jan 2010, 23:23
Location: brings.slot.perky

Re: word2003/VBA Repainting a form

Post by ChrisGreaves »

StuartR wrote:
15 Jan 2025, 12:56
The usual way to deal with this is to define a static Boolean variable in the procedure, give it a name like "IsRunning". Every time you start the procedure check the value of IsRunning: if True then immediately exit, if False then set to True. At the end of the procedure set it back to False again.
Stuart, thanks for this; a technique I can say I have not yet used in VBA, and probably never used at all in any of the platforms that has engaged my attention.

My early VBA applications were essentially batch processing - press Start and then walk away. My later creations involved interactive GUI forms which, as you and Speakeasy point out, come equipped with land-mines.

In my Copious Free™ I might retrofit a few GUI forms ...
Cheers, Chrus
Fill your face with laughter, then there will be no room for tears.

User avatar
ChrisGreaves
PlutoniumLounger
Posts: 16801
Joined: 24 Jan 2010, 23:23
Location: brings.slot.perky

Re: word2003/VBA Repainting a form

Post by ChrisGreaves »

SpeakEasy wrote:
15 Jan 2025, 13:43
Sure, not saying you cannot code defensively against reentrancy. Just saying you need to be aware that DoEvents can have unexpected side effects.
Thank you SpeakEasy.
Cheers, Chris
Fill your face with laughter, then there will be no room for tears.

snb
5StarLounger
Posts: 678
Joined: 14 Nov 2012, 16:06

Re: word2003/VBA Repainting a form

Post by snb »

Unless I misundeerstand your question

When I use:

Code: Select all

Private Sub UserForm_Click()
    CommandButton1.BackColor = 5 * Val(CommandButton1.Tag)
    CommandButton1.Tag = 100
End Sub
The colour of the commandbutton changes by the second click in the UF without any 'repaint'

User avatar
SpeakEasy
5StarLounger
Posts: 742
Joined: 27 Jun 2021, 10:46

Re: word2003/VBA Repainting a form

Post by SpeakEasy »

>The colour of the commandbutton changes by the second click

Because you are not comparing like for like. Try the following instead, and see what happens:

Code: Select all

Private Sub UserForm_Click()
    Dim lp As Long
    Dim a As String
    
    CommandButton1.BackColor = 5 * Val(CommandButton1.Tag)
    CommandButton1.Tag = 100
    
    ' Time consuming tight loop
    For lp = 0 To 100000000
        a = CStr(0)
    Next
End Sub

snb
5StarLounger
Posts: 678
Joined: 14 Nov 2012, 16:06

Re: word2003/VBA Repainting a form

Post by snb »

@speak

I see what you mean.
But this does what it should do without repaint.

Code: Select all

Private Sub UserForm_Click()
    With CommandButton1
       .BackColor = IIf(.BackColor = RGB(255, 0, 0), RGB(0, 0, 255), RGB(255, 0, 0))
    End With
    
    Application.Wait DateAdd("s", 3, Now)
    
    With CommandButton1
       .BackColor = IIf(.BackColor = RGB(255, 0, 0), RGB(0, 0, 255), RGB(255, 0, 0))
    End With
End Sub

User avatar
SpeakEasy
5StarLounger
Posts: 742
Joined: 27 Jun 2021, 10:46

Re: word2003/VBA Repainting a form

Post by SpeakEasy »

Yep. Mainly because Application.Wait basically does a DoEvents when it is called

snb
5StarLounger
Posts: 678
Joined: 14 Nov 2012, 16:06

Re: word2003/VBA Repainting a form

Post by snb »

To prevent clicking again:

Code: Select all

Private Sub UserForm_Click()
  With CommandButton1
    .Visible = False
   
    Application.Wait DateAdd("s", 3, Now)
    .BackColor =  RGB(0, 0, 255)

    .Visible = True
  End With
End Sub