VMP Home
Product Information
Testimonials
Message Board
Download VMP
Training and Demos
Support
Previous versions
User Contributions
VFP Tools & Downloads
Subscription Policy
Order Now
  Faster <Add all> mover with cursors

I have a mover listbox container in which the lists can be quite large, with 400 items or more. I couldn't get satisfactory speed with arrays, but cursors worked fine except for <Add all>. I was able to get <Add all> to work faster by using two cursors and taking advantage of the native VFP DELETE/RECALL behavior with SET DELETED ON. Here are the modifications I made:

1) Create cursors in the Form.DataEnvironment.Init() or Form.Load()

* create cursors for CIP Mover
SELECT SUBSTR(rv_cip.cip,1,5)+' '+rv_cip.acronym AS
CIPAcronym ;
FROM rv_cip INTO CURSOR cip_temp

SELECT cip_temp
=AFIELDS(laFields)

CREATE CURSOR t_CIPAvail FROM ARRAY laFields
CREATE CURSOR t_CIPSelect FROM ARRAY laFields

SELECT t_CIPAvail
APPEND FROM DBF('cip_temp')
*delete all

SELECT t_CIPSelect
APPEND FROM DBF('cip_temp')
delete all

USE IN cip_temp

2) Set ctrMover properties

icavailablecursorname = t_CIPAvail
icselectedcursorname = t_CIPSelect

lstAvailable.RowSourceType = 2
lstAvailable.RowSource = "t_CIPAvail.CIPAcronym"
lstAvailable.Name = "lstAvailable"

lstSelected.RowSourceType = 2
lstSelected.RowSource = "t_CIPSelect.CIPAcronym"
lstSelected.MoverBars = .F.
lstSelected.Name = "lstSelected"
3) Add code to ctrMover.PreAddAction(), RETURNing .F. to prevent the default AddAction()
* Default VMFP AddAction() is not performed when
* PreAddAction() returns .F.  This code is intended to
* override the default VMFP action and applies to
* cursors only.

LOCAL llLockScreenHere, llAnySelected
llLockScreenHere = THISFORM.LockScreenHere()

WITH THISFORM.pgfrsbase1.page1.ctrrsmover1

SET DELETED OFF

FOR lnLoopCount = 1 TO .lstAvailable.LISTCOUNT
  IF .lstAvailable.SELECTED(lnLoopCount)
    *
    * For each lstAvailable item that is selected, DELETE and Deselect. 
    * Locate the corresponding record in the .icSelectedCursorName alias 
    * and recall it.
    * llAnySelected = .T.

    SELECT (.icAvailableCursorName)
    recnum = RECNO()
    DELETE
    .lstAvailable.SELECTED(lnLoopCount) = .F.

    SELECT (.icSelectedCursorName)
    GO recnum
    RECALL
  ENDIF
NEXT

SET DELETED ON

IF llAnySelected
  .BoundControlsInteractiveChange()
ENDIF

.ilAnyAvailableSelected = .F.
.lstSelected.REFRESH()
.lstAvailable.REFRESH()
.lstSelected.SETFOCUS()
.lstAvailable.SETFOCUS()
*   .cmdAdd.REFRESH()
*   .cmdAddALL.REFRESH()
*   .cmdRemove.REFRESH()
*   .cmdRemoveAll.REFRESH()
.REFRESH()  && only refreshes lstAvailable ?
ENDWITH

THISFORM.LockScreenHere(llLockScreenHere)

RETURN .F.  && DO NOT execute default cmd Action
4) Add code to ctrMover.PreAddAllAction(), RETURNing .F. to prevent the default AddAllAction()
* Default VMFP AddAllAcion() action is not performed
* when PreAddAllAction() returns .F.  This code is
* intended to override the default VMFP action and
* applies to curosrs only.

LOCAL llLockScreenHere
llLockScreenHere = THISFORM.LockScreenHere()

WITH THISFORM.pgfrsbase1.page1.ctrrsmover1

.BoundControlsInteractiveChange()

SET DELETED OFF

*
* Recall all records in the .icSelectedCursorName
alias. * DELETE and Deselect each
.iclAvailableCursorName item. * SELECT
(.icSelectedCursorName) RECALL ALL

SELECT (.icAvailableCursorName)
DELETE ALL

FOR i = 1 TO .lstAvailable.LISTCOUNT
.lstAvailable.SELECTED(i) = .F.
NEXT

SET DELETED ON

.ilAnyAvailableSelected = .F.
.lstSelected.REFRESH()
.lstAvailable.REFRESH()
.lstSelected.SETFOCUS()
.lstAvailable.SETFOCUS()
* .cmdAdd.REFRESH()
* .cmdAddALL.REFRESH()
* .cmdRemove.REFRESH()
* .cmdRemoveAll.REFRESH()
.REFRESH() && onll refreshes lstAvailable ?
ENDWITH

THISFORM.LockScreenHere(llLockScreenHere)

RETURN .F. && DO NOT execute default cmd Action
5) Add code to ctrMover.PreRemoveAction(), RETURNing .F. to prevent the default RemoveAction()
* Default VMFP RemoveAction() is not performed when
PreRemoveAction() returns .F. * This code is intended
to override the default VMFP action * and applies to
curosrs only.

LOCAL llLockScreenHere, llAnySelected
llLockScreenHere = THISFORM.LockScreenHere()

WITH THISFORM.pgfrsbase1.page1.ctrrsmover1

SET DELETED OFF

FOR lnLoopCount = 1 TO .lstSelected.LISTCOUNT
IF .lstSelected.SELECTED(lnLoopCount)
*
* For each lstSelected item that is selected,
DELETE and Deselect. * Locate the
corresponding record in the
.icAvailableCursorName alias * and recall it.
* llAnySelected = .T.

SELECT (.icSelectedCursorName)
recnum = RECNO()

DELETE
.lstSelected.SELECTED(lnLoopCount) = .F.

SELECT (.icAvailableCursorName)
GO recnum
RECALL
ENDIF
NEXT

SET DELETED ON

IF llAnySelected
.BoundControlsInteractiveChange()
ENDIF

.ilAnySelectedSelected = .F.
.lstSelected.REFRESH()
.lstAvailable.REFRESH()
.lstSelected.SETFOCUS()
.lstAvailable.SETFOCUS()
* .cmdAdd.REFRESH()
* .cmdAddALL.REFRESH()
* .cmdRemove.REFRESH()
* .cmdRemoveAll.REFRESH()
.REFRESH() && only refreshes lstAvailable ?
ENDWITH

THISFORM.LockScreenHere(llLockScreenHere)

RETURN .F. && DO NOT execute default cmd Action
6) Add code to ctrMover.PreRemoveAllAction(), RETURNing .F. to prevent the default RemoveAllAction()
* Default VMFP RemoveAllAction() is not performed when
PreRemoveAllAction() returns .F. * This code is
intended to override the default VMFP action * and
applies to curosrs only.

LOCAL llLockScreenHere
llLockScreenHere = THISFORM.LockScreenHere()

WITH THISFORM.pgfrsbase1.page1.ctrrsmover1

.BoundControlsInteractiveChange()

SET DELETED OFF

*
* Recall all records in the .icAvailableCursorName
alias. * DELETE and Deselect each
.icSelectedCursorName item. * SELECT
(.icAvailableCursorName) RECALL ALL

SELECT (.icSelectedCursorName)
DELETE ALL

FOR i = 1 TO .lstSelected.LISTCOUNT
.lstSelected.SELECTED(i) = .F.
NEXT

SET DELETED ON

.ilAnySelectedSelected = .F.
.lstSelected.REFRESH()
.lstAvailable.REFRESH()
.lstSelected.SETFOCUS()
.lstAvailable.SETFOCUS()
* .cmdAdd.REFRESH()
* .cmdAddALL.REFRESH()
* .cmdRemove.REFRESH()
* .cmdRemoveAll.REFRESH()
.REFRESH() && only refreshes lstAvailable ?
ENDWITH

THISFORM.LockScreenHere(llLockScreenHere)

RETURN .F. && DO NOT execute default cmd Action

7) Bypass the default UpdateMoverOnNew() code by adding a NODEFAULT

nodefault

 

Patrick Godfrey