Faceți căutări pe acest blog

duminică, 26 noiembrie 2017

"Typing" characters programatically (4)

As a practical application, here is a simple way to extract the content of an editbox, row by row

In the next demo, type whatever you want in the edit box, and click the form to see the "extraction" process

PUBLIC ofrm
ofrm = CREATEOBJECT("myform")
ofrm.show()

DEFINE CLASS myform as Form
 autocenter = .T.
 ADD OBJECT edt as myeditbox && addlinefeeds = .F. && successfully tested
 PROCEDURE click
  LOCAL lnStart,lnLen
  * keep the potential selection 
  lnStart = This.edt.SelStart
  lnSen = This.edt.SelLength
  * Jump to the beginning of editbox
  This.edt.keypress(1,2,.T.) &&CTRL+HOME
  DO WHILE .T.
   * go to the beginning of the row
   This.edt.keypress(1,0,.T.) && HOME
   * select to the end of the row
   This.edt.keypress(49,1,.T.) &&SHIFT+END
   * type the row content
   ACTIVATE SCREEN 
   ?This.edt.seltext
   * test if the task was completed
   IF This.edt.Selstart + This.edt.Sellength = LEN(This.edt.value)
    EXIT
   ENDIF
   *adwance to the next row
   This.edt.keypress(24,0,.T.) && DOWN ARROW
  ENDDO 
  * restore the selection
  This.edt.SelStart = m.lnStart 
  This.edt.SelLength = m.lnSen 
 ENDPROC
ENDDEFINE

DEFINE CLASS myeditbox as EditBox
 PROCEDURE keypress
  LPARAMETERS nkey,nshift,lraise
  IF m.lraise
   DODEFAULT(m.nkey,m.nshift)
   =This.Value
  ENDIF
 ENDPROC
ENDDEFINE 
 
Related links
[1] "Typing" characters programatically 
[2] "Typing" characters programatically (2) 
[3] "Typing" characters programatically (3) 

miercuri, 8 noiembrie 2017

"Typing" characters programmatically (3)

In my previous post [2] I show how to add characters in a textbox, without using the keyboard or using the KWYBOARD command, but altering the keyboard() event.
The major drawback of the solution, was that if the textbox has a controlsource, the variable from the controlsource isn't updated and the value property isn't preserved.
Also, the reason for that behavior is the switch of the order of the interactivechange(0 and keypress().

As a solution, I propose to simply update the controlsource in the interactivechange.
The next example shows this, having as controlsource a memory variable in txt2 and a cursor field in txt3. Next to this example follows several others, showing the same trick applied to editbox, combobox, grid, and with other data type, like number and date.


PUBLIC ofrm,lcVar
CLEAR
lcVar = ""
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt2 as MyText2 WITH width = 225, ControlSource = "lcVar"
      ADD OBJECT txt3 as MyText2 WITH top=50, width = 225, ControlSource = "cCur.cVar"
      ADD OBJECT cmd as CommandButton WITH left=250,Caption='click',Autosize=.T.
      PROCEDURE load
            CREATE CURSOR cCur (cVar C(120))
            APPEND BLANK
      ENDPROC
      PROCEDURE cmd.click
            FOR lni = 97 TO 106
                  ThisForm.txt2.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.txt2.Keypress(13,0,.T.) && Enter
            FOR lni = 65 TO 86
                  ThisForm.txt3.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.txt3.Keypress(13,0,.T.) && Enter
      ENDPROC
      PROCEDURE click
            ACTIVATE SCREEN
            ?'lcVar = ['+m.lcVar+']','cCur=['+cCur.cVar+']'
ENDDEFINE
*********************
* Text box class 2
*********************
DEFINE CLASS MyText2 as TextBox
      PROCEDURE keypress
            LPARAMETERS nKey,nShift,lraised
            IF lraised
                  DODEFAULT(nKey,nShift)
                  =This.value
            ENDIF
      ENDPROC
      PROCEDURE interactivechange
            IF !EMPTY(This.ControlSource)
                  TRY
                        replace (This.ControlSource) WITH (This.Value)
                  CATCH
                        STORE (This.Value) TO (This.ControlSource)
                  ENDTRY
            ENDIF
      ENDPROC
ENDDEFINE

The next example illustrate the same approach applied to editboxes (I changed only the baseclass type)

PUBLIC ofrm,lcVar
CLEAR
lcVar = ""
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt2 as MyText2 WITH width = 225, ControlSource = "lcVar"
      ADD OBJECT txt3 as MyText2 WITH top=100, width = 225, ControlSource = "cCur.cVar"
      ADD OBJECT cmd as CommandButton WITH left=250,Caption='click',Autosize=.T.
      PROCEDURE load
            CREATE CURSOR cCur (cVar C(120))
            APPEND BLANK
      ENDPROC
      PROCEDURE cmd.click
            FOR lni = 97 TO 105
                  ThisForm.txt2.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.txt2.Keypress(13,0,.T.) && Enter
            FOR lni = 66 TO 86
                  ThisForm.txt3.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.txt3.Keypress(13,0,.T.) && Enter
      ENDPROC
      PROCEDURE click
            ACTIVATE SCREEN
            ?'lcVar = ['+m.lcVar+']','cCur=['+cCur.cVar+']'
ENDDEFINE
*********************
* Text box class 2
*********************
DEFINE CLASS MyText2 as EditBox
      PROCEDURE keypress
            LPARAMETERS nKey,nShift,lraised
            IF lraised
                  DODEFAULT(nKey,nShift)
                  =This.value
            ENDIF
      ENDPROC
      PROCEDURE interactivechange
            IF !EMPTY(This.ControlSource)
                  TRY
                        replace (This.ControlSource) WITH (This.Value)
                  CATCH
                        STORE (This.Value) TO (This.ControlSource)
                  ENDTRY
            ENDIF
      ENDPROC
ENDDEFINE
  

And the same approach applied to comboboxes (I changed only the baseclass type)
PUBLIC ofrm,lcVar
CLEAR
lcVar = ""
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt2 as MyText2 WITH width = 225, ControlSource = "lcVar"
      ADD OBJECT txt3 as MyText2 WITH top=50, width = 225, ControlSource = "cCur.cVar"
      ADD OBJECT cmd as CommandButton WITH left=250,Caption='click',Autosize=.T.
      PROCEDURE load
            CREATE CURSOR cCur (cVar C(120))
            APPEND BLANK
      ENDPROC
      PROCEDURE cmd.click
            FOR lni = 97 TO 105
                  ThisForm.txt2.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.txt2.Keypress(13,0,.T.) && Enter
            FOR lni = 66 TO 86
                  ThisForm.txt3.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.txt3.Keypress(13,0,.T.) && Enter
      ENDPROC
      PROCEDURE click
            ACTIVATE SCREEN
            ?'lcVar = ['+m.lcVar+']','cCur=['+cCur.cVar+']'
ENDDEFINE
*********************
* Text box class 2
*********************
DEFINE CLASS MyText2 as ComboBox
      PROCEDURE keypress
            LPARAMETERS nKey,nShift,lraised
            IF lraised
                  DODEFAULT(nKey,nShift)
                  =This.value
            ENDIF
      ENDPROC
      PROCEDURE interactivechange
            IF !EMPTY(This.ControlSource)
                  TRY
                        replace (This.ControlSource) WITH (This.Value)
                  CATCH
                        STORE (This.Value) TO (This.ControlSource)
                  ENDTRY
            ENDIF
      ENDPROC
ENDDEFINE

Now let's try with a grid

PUBLIC ofrm,lcVar
CLEAR
lcVar = ""
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT grd as grid WITH Recordsource = "cCur",allowaddnew = .T.
      ADD OBJECT cmd as CommandButton WITH left=325,Caption='click',Autosize=.T.
      PROCEDURE load
            CREATE CURSOR cCur (cVar C(120))
            APPEND BLANK
            APPEND BLANK
            APPEND BLANK
            GO TOP
      ENDPROC
      PROCEDURE Init
            This.grd.Column1.RemoveObject("Text1")
            This.grd.Column1.AddObject("Text1","MyText2")
            This.grd.Column1.Text1.Visible = .T.
      PROCEDURE cmd.click
            FOR lni = 97 TO 105
                  ThisForm.grd.Column1.Text1.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.grd.Column1.Text1.Keypress(13,0,.T.) && Enter
      ENDPROC
      PROCEDURE click
            ACTIVATE SCREEN
            ?'lcVar = ['+m.lcVar+']','cCur=['+cCur.cVar+']'
ENDDEFINE
*********************
* Text box class 2
*********************
DEFINE CLASS MyText2 as TextBox
      margin = 0
      borderstyle = 0
      PROCEDURE keypress
            LPARAMETERS nKey,nShift,lraised
            IF lraised
                  DODEFAULT(nKey,nShift)
                  =This.value
            ENDIF
      ENDPROC
      PROCEDURE interactivechange
            IF !EMPTY(This.ControlSource)
                  TRY
                        replace (This.ControlSource) WITH (This.Value)
                  CATCH
                        STORE (This.Value) TO (This.ControlSource)
                  ENDTRY
            ENDIF
      ENDPROC
ENDDEFINE
 
Now having numeric variable and field
PUBLIC ofrm,lcVar
CLEAR
lcVar = 0
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt2 as MyText2 WITH width = 225, ControlSource = "lcVar"
      ADD OBJECT txt3 as MyText2 WITH top=50, width = 225, ControlSource = "cCur.cVar"
      ADD OBJECT cmd as CommandButton WITH left=250,Caption='click',Autosize=.T.
      PROCEDURE load
            CREATE CURSOR cCur (cVar N(20))
            APPEND BLANK
      ENDPROC
      PROCEDURE cmd.click
            FOR lni = 53 TO 55
                  ThisForm.txt2.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.txt2.Keypress(13,0,.T.) && Enter
            FOR lni = 48 TO 52
                  ThisForm.txt3.Keypress(m.lni,0,.T.) && A
            NEXT
            ThisForm.txt3.Keypress(13,0,.T.) && Enter
      ENDPROC
      PROCEDURE click
            ACTIVATE SCREEN
            ?'lcVar = ',m.lcVar,'cCur=',cCur.cVar
ENDDEFINE
*********************
* Text box class 2
*********************
DEFINE CLASS MyText2 as TextBox
      PROCEDURE keypress
            LPARAMETERS nKey,nShift,lraised
            IF lraised
                  DODEFAULT(nKey,nShift)
                  =This.value
            ENDIF
      ENDPROC
      PROCEDURE interactivechange
            IF !EMPTY(This.ControlSource)
                  TRY
                        replace (This.ControlSource) WITH (This.Value)
                  CATCH
                        STORE (This.Value) TO (This.ControlSource)
                  ENDTRY
            ENDIF
      ENDPROC
ENDDEFINE

Finally, having date variable and field

PUBLIC ofrm,lcVar
CLEAR
lcVar = {}
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt2 as MyText2 WITH width = 225, ControlSource = "lcVar"
      ADD OBJECT txt3 as MyText2 WITH top=50, width = 225, ControlSource = "cCur.cVar"
      ADD OBJECT cmd as CommandButton WITH left=250,Caption='click',Autosize=.T.
      PROCEDURE load
            CREATE CURSOR cCur (cVar D)
            APPEND BLANK
      ENDPROC
      PROCEDURE cmd.click
            FOR lni = 1 TO 6
                  ThisForm.txt2.Keypress(49,0,.T.) && A
            NEXT
            ThisForm.txt2.Keypress(13,0,.T.) && Enter
            FOR lni = 1 TO 6
                  ThisForm.txt3.Keypress(49,0,.T.) && A
            NEXT
            ThisForm.txt3.Keypress(13,0,.T.) && Enter
      ENDPROC
      PROCEDURE click
            ACTIVATE SCREEN
            ?'lcVar = ',m.lcVar,'cCur=',cCur.cVar
ENDDEFINE
*********************
* Text box class 2
*********************
DEFINE CLASS MyText2 as TextBox
      PROCEDURE keypress
            LPARAMETERS nKey,nShift,lraised
            IF lraised
                  DODEFAULT(nKey,nShift)
                  =This.value
            ENDIF
      ENDPROC
      PROCEDURE interactivechange
            IF !EMPTY(This.ControlSource)
                  TRY
                        replace (This.ControlSource) WITH (This.Value)
                  CATCH
                        STORE (This.Value) TO (This.ControlSource)
                  ENDTRY
            ENDIF
      ENDPROC
ENDDEFINE

 See also