Não tem nada de extraordinário nela, tem até parte que pode ser eliminada, do tempo que eu não usava SET SCOPE.
Uso duas rotinas genéricas de tbrowse, e talvez 1 ou 2 muito especÃficas, mas que nem olhei ainda se dá pra passar pra genérica.
Só lembrando que em produtos de pedidos não precisa pesquisar em ordem alfabética, filtrar iniciais conforme digita, etc.
São os produtos que entraram em um pedido.
FUNCTION DbView( nTop, nLeft, nBottom, nRight, oTBrowse, bUserFunction, nFixToCol, mSkipVar, bSkipCpo, aHotKeys )
LOCAL oBrowse, nkey, lmore, col, mRecNo
LOCAL nMRow, nMCol, nCont, oElement
IF oTBrowse == NIL
oTBrowse := {}
FOR nCont = 1 TO FCount()
AAdd( oTBrowse, { FieldName( nCont ), FieldBlock( FieldName( nCont ) ) } )
NEXT
ENDIF
oBrowse := tbrowsedb( nTop, nLeft, nBottom + 1, nRight )
oBrowse:HeadSep := " "
oBrowse:FootSep := " "
oBrowse:ColSep := " "
IF mSkipvar != NIL .AND. bSkipcpo != NIL
oBrowse:SkipBlock := { | nSkip | dbViewSkip( nSkip, mSkipvar, bSkipcpo ) }
oBrowse:GoBottomBlock := { || dbViewBottom( mSkipvar ) }
oBrowse:GoTopBlock := { || dbViewTop( mSkipvar ) }
ENDIF
FOR EACH oElement IN oTBrowse
Col := TbColumnNew( oElement[ 1 ], oElement[ 2 ] )
IF Len( oElement ) > 2
col:ColorBlock := oElement[ 3 ]
ENDIF
oBrowse:AddColumn( col )
NEXT
oBrowse:ColorSpec := SetColorTBrowse()
IF nFixToCol != NIL
oBrowse:freeze := nFixToCol
ENDIF
IF aHotKeys == NIL
aHotKeys := {}
ELSE
FOR EACH oElement IN aHotKeys
@ oElement[ 1 ], oElement[ 2 ] SAY oElement[ 5 ]
NEXT
ENDIF
DO WHILE .NOT. oBrowse:Stable
oBrowse:Stabilize()
ENDDO
lmore := .T.
DO WHILE lmore
oBrowse:RefreshCurrent()
nkey := 0
DO WHILE .NOT. oBrowse:Stable // // Problemas ao acelerar dbview
oBrowse:Stabilize()
// nkey := Inkey()
ENDDO
IF oBrowse:Stable
oBrowse:ColorRect( { oBrowse:RowPos, 1, oBrowse:RowPos, oBrowse:ColCount }, { 3, 3 } ) // linha está com o cursor
oBrowse:ColorRect( { oBrowse:RowPos, oBrowse:ColPos, oBrowse:RowPos, oBrowse:ColPos }, { 2, 2 } ) // linha/coluna está com cursor
nkey := Inkey(600)
IF nKey == 0
KEYBOARD Chr( K_ESC )
LOOP
ENDIF
ENDIF
nMRow := MROW()
nMCol := MCOL()
DO CASE
CASE SetKey( nKey ) != NIL
Eval( SetKey( nKey ), ProcLine(), ProcName(), ReadVar() )
CASE nKey > 999
DO CASE
CASE mBrzMove( oBrowse, nMRow, nMCol, nTop + 2, nLeft + 1, nBottom, nRight - 1 ) // Move cursor
CASE mBrzClick( oBrowse, nMRow, nMCol ) // click no tbrowse atual
KEYBOARD Chr( K_ENTER )
Inkey(0)
nKey := 13
CASE nKey == K_LBUTTONDOWN
FOR EACH oElement IN aHotKeys
IF nMRow >= oElement[ 1 ] .AND. nMRow <= oElement[ 3 ] .AND. nMCol >= oElement[ 2 ] .AND. nMCol <= oElement[ 4 ]
nKey := oElement[ 6 ]
EXIT
ENDIF
NEXT
ENDCASE
CASE nkey == K_DOWN ; oBrowse:Down() ; LOOP
CASE nkey == K_PGDN ; oBrowse:PageDown() ; LOOP
CASE nkey == K_PGUP ; oBrowse:PageUp() ; LOOP
CASE nkey == K_CTRL_PGDN ; oBrowse:GoBottom() ; LOOP
CASE nkey == K_UP ; oBrowse:Up() ; LOOP
CASE nkey == K_CTRL_PGUP ; oBrowse:GoTop() ; oBrowse:RefreshAll() ; LOOP
CASE nkey == K_HOME ; oBrowse:GoTop() ; LOOP
CASE nkey == K_END ; oBrowse:GoBottom() ; LOOP
CASE nkey == K_RIGHT ; oBrowse:Right() ; LOOP
CASE nkey == K_LEFT ; oBrowse:Left() ; LOOP
CASE nKey == Asc( "0" ); hb_KeyPut( K_INS ); LOOP
CASE nKey == Asc( "." ); hb_KeyPut( K_DEL ); LOOP
CASE nKey == Asc( "7" ); hb_KeyPut( K_HOME ); LOOP
CASE nKey == Asc( "8" ); hb_KeyPut( K_UP ); LOOP
CASE nKey == Asc( "2" ); hb_KeyPut( K_DOWN ); LOOP
CASE nKey == Asc( "9" ); hb_KeyPut( K_PGUP ); LOOP
CASE nKey == Asc( "3" ); hb_KeyPut( K_PGDN ); LOOP
ENDCASE
IF nkey == K_ESC .OR. ( nkey == K_ENTER .AND. bUserFunction == NIL ) // ENTER só sai se não existir função definida
lmore := .F.
ENDIF
IF bUserFunction # NIL
DO WHILE .NOT. oBrowse:Stable
oBrowse:Stabilize()
ENDDO
WSave( MaxRow() - 1, 0, MaxRow(), MaxCol() )
mRecno := RecNo()
IF ValType( bUserFunction ) == "C"
&bUserFunction( oBrowse, nKey )
ELSE
Eval( bUserFunction, oBrowse, nKey )
ENDIF
nKey := 0 // Testar se resolve saÃda indesejavel
IF mRecno != RecNo() .OR. Deleted()
Eval( oBrowse:SkipBlock, 1 )
ENDIF
oBrowse:RefreshAll()
WRestore()
ENDIF
ENDDO
//SetCursor( SC_NORMAL )
RETURN ( nkey == K_ENTER )
FUNCTION dbViewSkip( nSkip, cScopeValue, bScopeMacro )
LOCAL nSkipped := 0, nRecNo // Para ADO
IF .NOT. Eof()
IF Eval( bScopeMacro ) != cScopeValue
GOTO LastRec() + 1
ENDIF
IF ( nSkip == 0 )
SKIP 0
ELSEIF ( nSkip > 0 .AND. Eval( bScopeMacro ) = cScopeValue .AND. .NOT. Eof() )
DO WHILE nSkipped < nSkip
SKIP
IF Eof() .OR. Eval( bScopeMacro ) > cScopeValue
SKIP -1
EXIT
ENDIF
nSkipped++
ENDDO
ELSEIF ( nSkip < 0 ) .AND. Eval( bScopeMacro ) = cScopeValue
DO WHILE ( nSkipped > nSkip )
nRecNo := RecNo() // alterado aqui pra ADO
SKIP -1
IF Bof() .OR. nRecNo == RecNo() .OR. Eval( bScopeMacro ) < cScopeValue // alterado aqui pra ADO
IF Eval( bScopeMacro ) < cScopeValue
SKIP
ENDIF
EXIT
ENDIF
nSkipped--
ENDDO
ENDIF
ENDIF
RETURN ( nSkipped )
FUNCTION dbViewBottom( cScopeValue )
SEEK cScopeValue + Replicate( Chr(255), 10 ) SOFTSEEK
SKIP -1
RETURN NIL
FUNCTION dbViewTop( cScopeValue )
SEEK cScopeValue SOFTSEEK
RETURN NIL
No uso mais simples:
USE arquivo
dbView()
USE