FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour How to optimize xbrowse (on incremental search)
Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
How to optimize xbrowse (on incremental search)
Posted: Mon Mar 30, 2026 01:44 PM

On an incremental search

   CASE IsRange( nKey, 32, 127 ) .AND. cFilterKey != NIL .AND. cnSQL:RecordCount() != 0
      IF Chr( nKey ) $ ['/*]
         nKey := 32
      ENDIF
      cFilter += Upper( Chr( nKey ) )
      IF ! ADOFilter( cnSQL, cFilterKey, cFilter, aADOFilterList, nADOFilterPos )
         cFilter := Left( cFilter, Len( cFilter ) - 1 )
         IF Len( cFilter ) == 0
            cnSQL:Filter( "" )
         ELSE
            ADOFilter( cnSQL, cFilterKey, cFilter, aADOFilterList, nADOFilterPos )
         ENDIF
      ENDIF
      oBrowse:SetArray( Array( cnSQL:RecordCount() ) )
      oLabel:Varput( cFilter )
      oLabel:Refresh()
      oBrowse:Refresh()
   ENDCASE

If I type 2 or more letters, a unique refresh at the end speed up screen update.

On a harbour GT tbrowse, I can do this:

      oBrowse:RefreshCurrent()
      nkey := 0
      DO WHILE nkey == 0 .AND. ! oBrowse:Stable
         oBrowse:Stabilize()
         nkey := Inkey()
      ENDDO

On this way, I update only if no more keys pressed, or update later on ENTER or Click.

How I can optimize xbrowse update on same situation?

Note: array is used only to have size, with Nil elements.

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: How to optimize xbrowse (on incremental search)
Posted: Mon Mar 30, 2026 02:44 PM

Dear José,

The key idea is the same as your TBrowse approach: skip the expensive operations while keys are still pending. In
FiveWin you can check NextKey() or peek the Windows message queue.

Simple approach: check NextKey() before refreshing

  CASE IsRange( nKey, 32, 127 ) .AND. cFilterKey != NIL .AND. cnSQL:RecordCount() != 0
     IF Chr( nKey ) $ ['/*]
        nKey := 32
     ENDIF
     cFilter += Upper( Chr( nKey ) )
     IF ! ADOFilter( cnSQL, cFilterKey, cFilter, aADOFilterList, nADOFilterPos )
        cFilter := Left( cFilter, Len( cFilter ) - 1 )
        IF Len( cFilter ) == 0
           cnSQL:Filter( "" )
        ELSE
           ADOFilter( cnSQL, cFilterKey, cFilter, aADOFilterList, nADOFilterPos )
        ENDIF
     ENDIF

 // Update label always (cheap)
 oLabel:Varput( cFilter )
 oLabel:Refresh()

 // Only do the expensive browse refresh if no more keys pending
 IF NextKey() == 0
    oBrowse:SetArray( Array( cnSQL:RecordCount() ) )
    oBrowse:Refresh()
 ENDIF
  ENDCASE

NextKey() returns 0 when the keyboard buffer is empty - meaning the user has stopped typing, so it's worth doing the
full refresh now.

Alternative: small Inkey() wait (like your TBrowse pattern)

If NextKey() alone isn't enough (e.g. keys arrive slightly delayed), you can add a tiny wait:

     oLabel:Varput( cFilter )
     oLabel:Refresh()

 // Give a tiny window for the next keystroke to arrive
 IF Inkey( 0.05 ) == 0   // 50ms, no key arrived
    oBrowse:SetArray( Array( cnSQL:RecordCount() ) )
    oBrowse:Refresh()
 ELSE
    // A key arrived - it stays in the buffer for the next iteration
    // Skip the expensive refresh, the next keystroke will handle it
 ENDIF

The 0.05 (50ms) is a good balance - fast enough to feel instant, long enough to catch fast typing.

Important detail

When you finally do the refresh (on the last keystroke or on Enter/click), make sure SetArray() + Refresh() always
runs. You could add a flag:

LOCAL lNeedsRefresh := .F.

  // Inside the CASE:
     lNeedsRefresh := .T.
     IF NextKey() == 0
        oBrowse:SetArray( Array( cnSQL:RecordCount() ) )
        oBrowse:Refresh()
        lNeedsRefresh := .F.
     ENDIF

  // After the DO WHILE (or on Enter/Escape/Click):
     IF lNeedsRefresh
        oBrowse:SetArray( Array( cnSQL:RecordCount() ) )
        oBrowse:Refresh()
     ENDIF

This guarantees the browse is always correct when the user stops typing or takes an action, even if NextKey() skipped
some intermediate refreshes.

The NextKey() == 0 approach is the closest equivalent to your TBrowse stabilize pattern and should give you
significant speedup when typing multiple characters quickly.

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
Re: How to optimize xbrowse (on incremental search)
Posted: Mon Mar 30, 2026 09:17 PM

Many thanks.

      IF NextKey() == 0 .OR. NextKey() == K_ENTER
         oBrowse:Refresh()
      ENDIF

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Continue the discussion