Faceți căutări pe acest blog

miercuri, 8 noiembrie 2017

"Typing" characters programatically (2)

It is well known that  the KEYBOARD command place characters in the keyboard buffer.

Also it is known that calling the keypress() event have no visible effect upon the textbox. The following example illustrates that.

You'll notice that typing in the textbox, first is called keypress() and after interactivechange().
PUBLIC ofrm
CLEAR
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt as MyText
ENDDEFINE
*********************
* Text box class
*********************
DEFINE CLASS MyText as TextBox
    PROCEDURE keypress
         LPARAMETERS nKey,nShift
         ACTIVATE SCREEN
         ?"Keypress Text1",nKey,nShift,"text=",[']+This.text+['],"value=",[']+This.value+[']
    ENDPROC
    PROCEDURE interactivechange
      ACTIVATE SCREEN
      ?"Interactive Text1","text=",[']+This.text+['],"value=",[']+This.value+[']
    ENDPROC
ENDDEFINE

Let's add a command button, on whose click() event call the textbox's keypress() event, by trying to type an "A" (ASCII 65) and to "press" Enter (ASCII 13).
You'll notice that clicking the button, nothing happens to the textbox, only the keypress() is executed (obviously). But no chars appears and interactivechange() isn't triggered.


PUBLIC ofrm
CLEAR
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt as MyText
      ADD OBJECT cmd as CommandButton WITH left=250,Caption='click',Autosize=.T.
      PROCEDURE cmd.click
            ThisForm.txt.Keypress(65,0) && A
            ThisForm.txt.Keypress(13,0) && Enter
      ENDPROC
ENDDEFINE
*********************
* Text box class
*********************
DEFINE CLASS MyText as TextBox
    PROCEDURE keypress
         LPARAMETERS nKey,nShift
         ACTIVATE SCREEN
         ?"Keypress Text1",nKey,nShift,"text=",[']+This.text+['],"value=",[']+This.value+[']
    ENDPROC
    PROCEDURE interactivechange
      ACTIVATE SCREEN
      ?"Interactive Text1","text=",[']+This.text+['],"value=",[']+This.value+[']
    ENDPROC
ENDDEFINE

In one of my previous posts [1], I proposed an alternative way to "type" in a textbox, without altering the keyboard buffer.
The main idea is to add a third parameter, lraised. Keypress() is called programmatically with three parameters. When lraised is true (.T.), two additionally commands are executed.
First, a DODEFAULT() is called, whose purpose is to place the character in the textbox, then an assignment having textbox's Value property on the right side, with the purpose to store (maintain) the char in it's Value property.
Let's add to our example a second textbox, with the keypress() altered accordingly.
If you click the command button, you'll notice that the second textbox has the value and the text property properly changed. When the second textbox receive the focus, it's value remain, this is the main reason for "=This.value" placed inside keypress().
PUBLIC ofrm

CLEAR
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt as MyText
      ADD OBJECT txt2 as MyText2 WITH left = 125
      ADD OBJECT cmd as CommandButton WITH left=250,Caption='click',Autosize=.T.
      PROCEDURE cmd.click
            ThisForm.txt.Keypress(65,0) && A
            ThisForm.txt.Keypress(13,0) && Enter
            ThisForm.txt2.Keypress(65,0,.T.) && A
            ThisForm.txt2.Keypress(13,0,.T.) && Enter
      ENDPROC
ENDDEFINE
*********************
* Text box class
*********************
DEFINE CLASS MyText as TextBox
    PROCEDURE keypress
         LPARAMETERS nKey,nShift
         ACTIVATE SCREEN
         ?"Keypress Text1",nKey,nShift,"text=",[']+This.text+['],"value=",[']+This.value+[']
    ENDPROC
    PROCEDURE interactivechange
      ACTIVATE SCREEN
      ?"Interactive Text1","text=",[']+This.text+['],"value=",[']+This.value+[']
    ENDPROC
ENDDEFINE
*********************
* Text box class 2
*********************
DEFINE CLASS MyText2 as TextBox
    PROCEDURE keypress
         LPARAMETERS nKey,nShift,lraised
         IF lraised
              DODEFAULT(nKey,nShift)
              =This.value
         ENDIF
         ACTIVATE SCREEN
         ?"Keypress Text2",nKey,nShift
    ENDPROC
    PROCEDURE interactivechange
      ACTIVATE SCREEN
      ?"Interactive Text2",[text=']+This.text+['],[value=']+This.value+[']
    ENDPROC
ENDDEFINE

Also notice that interactivechange() event is fired, but with a major difference. When you fill the textbox using the keyboard, the order is keypress() followed by interactivechange(). When you click the command button, first is called interactivechange() and only the keypress().
This is bad, because when the textbox has a controlsource, the variable from the controlsource is not updated.
In the next example, click the commandbutton, and then click the second texbox. You'll notice that now the value disappears, simply because the controlsource isn't updated.
PUBLIC ofrm,lcVar
CLEAR
lcVar = ""
ofrm=CREATEOBJECT("MyForm")
ofrm.show()
DEFINE CLASS MyForm as Form
      autocenter = .T.
      ADD OBJECT txt as MyText WITH ControlSource = "lcVar"
      ADD OBJECT txt2 as MyText2 WITH left = 125, ControlSource = "lcVar"
      ADD OBJECT cmd as CommandButton WITH left=250,Caption='click',Autosize=.T.
      PROCEDURE cmd.click
            ThisForm.txt.Keypress(65,0) && A
            ThisForm.txt.Keypress(13,0) && Enter
            ThisForm.txt2.Keypress(65,0,.T.) && A
            ThisForm.txt2.Keypress(13,0,.T.) && Enter
            ?"Var='"+m.lcVar+"'"
      ENDPROC
ENDDEFINE
*********************
* Text box class
*********************
DEFINE CLASS MyText as TextBox
    PROCEDURE keypress
         LPARAMETERS nKey,nShift
         ACTIVATE SCREEN
         ?"Keypress Text1",nKey,nShift,"text=",[']+This.text+['],"value=",[']+This.value+['],[var=']+m.lcVar+[']
    ENDPROC
    PROCEDURE interactivechange
      ACTIVATE SCREEN
      ?"Interactive Text1","text=",[']+This.text+['],"value=",[']+This.value+['],[var=']+m.lcVar+[']
    ENDPROC
ENDDEFINE
*********************
* Text box class 2
*********************
DEFINE CLASS MyText2 as TextBox
    PROCEDURE keypress
         LPARAMETERS nKey,nShift,lraised
         IF lraised
              DODEFAULT(nKey,nShift)
              =This.value
         ENDIF
         ACTIVATE SCREEN
         ?"Keypress Text2",nKey,nShift,[']+m.lcVar+[']
    ENDPROC
    PROCEDURE interactivechange
      ACTIVATE SCREEN
      ?"Interactive Text2",[text=']+This.text+['],[value=']+This.value+['],[var=']+m.lcVar+[']
    ENDPROC
ENDDEFINE

See also

Niciun comentariu:

Trimiteți un comentariu