Subject Re: Select multiple records in a grid
From Mervyn Bick <invalid@invalid.invald>
Date Thu, 20 Sep 2018 14:45:09 +0200
Newsgroups dbase.getting-started
Attachment(s) test_multigridselect1.wfm

On 2018-09-19 10:40 PM, Mervyn Bick wrote:

> The attached example emulates holding down the control key and clicking
> on the first record to de-select it when the grid opens.  The user can
> then select the required records.

That was written just before bedtime.  In the cold light of day (and
after the second cup of coffee :-) ) I realise I could have gone a step
further and shown how to deal with the selected records.

Selecting a record in a grid saves a bookmark.  Where multiple records
are selected the bookmarks are saved to an array.  To process the
records one needs to use each bookmark to set the rowpointer to the
appropriate record.  Unfortunately doing this destroys the array.  The
solution is to copy the array returned by oGrid.selected() to a new
array before moving the rowpointer.

A revised example is attached.

Mervyn.








if file('test_multiselect.dbf')
   // drop table test_multiselect
endif

if not file('test_multiselect.dbf')
   create table test_multiselect (id autoinc,data character(10))

   use test_multiselect
   generate 10
   use

endif

** END HEADER -- do not remove this line
//
// Generated on 2018-09-20
//
parameter bModal
local f
f = new test_multigridselect1Form()
if (bModal)
   f.mdi = false // ensure not MDI
   f.readModal()
else
   f.open()
endif

class test_multigridselect1Form of FORM
   with (this)
      onOpen = class::FORM_ONOPEN
      onClose = class::FORM_ONCLOSE
      height = 30.3636
      left = 68.4286
      top = 1.5909
      width = 45.5714
      text = ""
   endwith

   this.CHILDTEST1 = new QUERY()
   this.CHILDTEST1.parent = this
   with (this.CHILDTEST1)
      width = 8.0
      height = 1.0
      sql = 'select * from "test_multiselect.DBF"'
      active = true
   endwith

   this.GRID1 = new GRID(this)
   with (this.GRID1)
      onOpen = class::GRID1_ONOPEN
      onMouseOver = class::GRID1_ONMOUSEOVER
      onMouseOut = class::GRID1_ONMOUSEOUT
      dataLink = form.childtest1.rowset
      multiSelect = true
      height = 10.6364
      left = 3.0
      top = 5.5
      width = 36.5714
   endwith

   this.PUSHBUTTON1 = new PUSHBUTTON(this)
   with (this.PUSHBUTTON1)
      onClick = class::PUSHBUTTON1_ONCLICK
      height = 1.7727
      left = 14.0
      top = 17.5
      width = 18.0
      text = "Clear selection"
   endwith

   this.RADIOBUTTON1 = new RADIOBUTTON(this)
   with (this.RADIOBUTTON1)
      height = 1.0909
      left = 2.0
      top = 1.5
      width = 42.0
      text = "Use Ctrl-key to select multiple records"
      group = true
      value = true
   endwith

   this.RADIOBUTTON2 = new RADIOBUTTON(this)
   with (this.RADIOBUTTON2)
      height = 1.0909
      left = 2.0
      top = 3.0
      width = 42.0
      text = "Select multiple records without  using Ctrl-key"
   endwith

   this.RADIOBUTTON3 = new RADIOBUTTON(this)
   with (this.RADIOBUTTON3)
      height = 1.0909
      left = 2.0
      top = 20.5
      width = 42.0
      text = "Clear selection after processng"
      group = true
      value = true
   endwith

   this.RADIOBUTTON4 = new RADIOBUTTON(this)
   with (this.RADIOBUTTON4)
      height = 1.0909
      left = 2.0
      top = 22.5
      width = 42.0
      text = "Retain selection after processing"
   endwith

   this.PUSHBUTTON2 = new PUSHBUTTON(this)
   with (this.PUSHBUTTON2)
      onClick = class::PUSHBUTTON2_ONCLICK
      height = 1.7727
      left = 14.0
      top = 26.0
      width = 18.0
      text = "Process selection"
   endwith

   this.rowset = this.childtest1.rowset

   function GRID1_onMouseOut(flags, col, row)
      if form.radiobutton2.value == true
         class::setcontrolkey(0,1)   //release control key
      endif
      form.grid_selected = this.selected()
      return

   function GRID1_onMouseOver(flags, col, row)
      if form.radiobutton2.value =true
         class::setcontrolkey(1,0)   //hold down contol key
      endif  
      return

   function GRID1_onOpen
      class::deselectEntry()
      return

   function PUSHBUTTON1_onClick
      class::clear_selection()
      return
      
   function clear_selection  
      local aGrid
      aGrid = form.grid1.selected()
      for n = 1 to aGrid.size
         form.rowset.goto(aGrid[n])
         class::deselectEntry()
      next
      form.rowset.first()
      class::deselectEntry()
      return

   function form_onClose
      class::setcontrolkey(0,1)   //make quite sure control key is released
      return

   function form_onOpen
      clear
      #include winuser.h
      if type("SendMessage") # "FP"
          extern clong SendMessage(chandle,cuint,clong,clong) user32 ;
                from "SendMessageA"
      endif
      if type("GetKeyboardState") # "FP"
         extern CVOID GetKeyboardState(CPTR) User32
      endif
      if type("SetKeyboardState") # "FP"
         extern CVOID SetKeyboardState(CPTR) User32
      endif
      return

   function setcontrolkey(onoff,nstate)
      local keybuffer,state
      keybuffer = Space(256)
      GetKeyboardState(keybuffer)    
      state=keybuffer.getbyte(vk_control)
      If onoff # 0              
         nstate=bitor(128,state)
      endif
      keybuffer.setbyte(vk_control,nstate)
      SetKeyboardState(keybuffer)  
      return state

   function PUSHBUTTON2_onClick()
      class::process_selection()
      return
      
   function process_selection  
      clear
      if type('form.grid_selected') = 'U' or form.grid_selected.size = 0
        ? 'No records selected'
        return
      endif  
      if form.radiobutton4.value = true
         form.childtest1.rowset.notifycontrols = false
      endif  
      for n = 1 to form.grid_selected.size
          form.childtest1.rowset.goto(form.grid_selected[n])
          // This is where code to process the record needs to be placed
          ? 'Processed record '+form.childtest1.rowset.fields['id'].value
      next
      if form.radiobutton4.value = true  
         form.childtest1.rowset.notifycontrols = true
      else
         class::clear_selection()
      endif  
      return

   function deselectEntry
      local point
      class::setcontrolkey(1,0)    
      sendmessage(form.grid1.hwnd,wm_lbuttondown,9,0x220018)
      sendmessage(form.grid1.hwnd,wm_lbuttonup,9,0x220018)
      class::setcontrolkey(0,1)
      return

endclass