TGet and bChange

TGet and bChange

Postby James Bott » Fri Mar 16, 2007 4:32 pm

I found that in the FWH 2.7 Aug 2006 build, the location of the eval of bChange in the TGet:keyChar() method was changed from a previous version (Feb 2006). It was moved below the code that rejects new keystrokes. Now if your bChange function returns .f. the keystroke still gets accepted--before it got rejected. You can test this with the code below. It should reject all keystrokes.

Has the location of the eval of bChange been returned to it's original location in newer versions of FWH? If not, why was it moved, and can we resolve both issues somehow? I really need to be able to reject keystrokes like when doing incremental searches.

James


Code: Select all  Expand view
#include "fivewin.ch"

function main()
   local oDlg, oGet, cVar:=space(10)

   define dialog oDlg title "Test bChange"

   @5,5 get oGet var cVar of oDlg update;
      on change test(nKey,nFlags,oGet) pixel

   activate dialog oDlg center

return nil


function test(nKey,nFlags,oGet)
return .f.


.
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: TGet and bChange

Postby Enrico Maria Giordano » Fri Mar 16, 2007 5:09 pm

I confirm the problem, although I never used that feature so far.

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8710
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Postby Antonio Linares » Sat Mar 17, 2007 10:36 am

James,

Do you mean this code (changed as you suggest):
Code: Select all  Expand view
      case nKey >= 32 .and. nKey < 256

           #ifdef __HARBOUR__
           // <lk> deadkey+tab [or enter] previously pressed will cause a r/t error
              if ::oGet:buffer == nil
                 return 0
              endif
           #endif

           ::GetSelPos( @nLo, @nHi )
           // Delete selection
           if nHi != nLo
              ::GetDelSel( nLo, nHi )
              ::EditUpdate()
           endif

           if ::bChange != nil
              lAccept = Eval( ::bChange, nKey, nFlags, Self )
              if ValType( lAccept ) == "L" .and. ! lAccept
                 return 0
              endif
           endif

           if ::oGet:Type == "N" .and. ;
              ( Chr( nKey ) == "." .or. Chr( nKey ) == "," )
              if ::oGet:Clear()
                 ::oGet:DelEnd()
              endif
              ::oGet:ToDecPos()
           else
              if Set( _SET_INSERT )             // many thanks to HMP
                 ::oGet:Insert( Chr( nKey ) )
              else
                 ::oGet:Overstrike( Chr( nKey ) )
              end
           endif
           if ::oGet:Rejected
              if Set( _SET_BELL )
                 MsgBeep()
              endif   
           endif
           ::EditUpdate()
           if ::oGet:TypeOut
              if ! Set( _SET_CONFIRM )
                 ::oWnd:nLastKey = VK_RETURN
                 ::oWnd:GoNextCtrl( ::hWnd )
              else
                 if Set( _SET_BELL )
                    MsgBeep()
                 endif   
              endif
           endif
           Eval( ::bPostKey, Self, ::oGet:Buffer )


Will that be ok ?
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42078
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby James Bott » Sat Mar 17, 2007 2:02 pm

Antonio,

> Will that be OK?

I'm not sure, I will have to do some testing. I think it will solve my problem, but I am also concerned as to the reason it was moved. Do you remember why? I don't want this change to undo whatever you were attempting to do by moving it in the first place.

In the Feb 2006 code, bChange was in a different place (see below). It was after numeric keys were processed. Is the new location going to create a problem with that--or maybe it solves a problem?

To be consistant, the msgBeep() should probably also be added before the RETURN 0 as it is when ::oGet:Rejected is true.

James


Code: Select all  Expand view
case nKey >= 32 .and. nKey < 256

           #ifdef __HARBOUR__
           // <lk> deadkey+tab [or enter] previously pressed will cause a r/t error
              if ::oGet:buffer == nil
                 return 0
              endif
           #endif

           ::GetSelPos( @nLo, @nHi )
           // Delete selection
           if nHi != nLo
              ::GetDelSel( nLo, nHi )
              ::EditUpdate()
           endif

           if ::bChange != nil
              lAccept = Eval( ::bChange, nKey, nFlags, Self )
              if ValType( lAccept ) == "L" .and. ! lAccept
                 return 0
              endif
           endif

           if ::oGet:Type == "N" .and. ;
              ( Chr( nKey ) == "." .or. Chr( nKey ) == "," )
              if ::oGet:Clear()
                 ::oGet:DelEnd()
              endif
              ::oGet:ToDecPos()
           else

//--- bChange was here in Feb 2006 version

              if Set( _SET_INSERT )             // many thanks to HMP
                 ::oGet:Insert( Chr( nKey ) )
              else
                 ::oGet:Overstrike( Chr( nKey ) )
              end
           endif
           if ::oGet:Rejected
              if Set( _SET_BELL )
                 MsgBeep()
              endif   
           endif
           ::EditUpdate()
           if ::oGet:TypeOut
              if ! Set( _SET_CONFIRM )
                 ::oWnd:nLastKey = VK_RETURN
                 ::oWnd:GoNextCtrl( ::hWnd )
              else
                 if Set( _SET_BELL )
                    MsgBeep()
                 endif   
              endif
           endif
           Eval( ::bPostKey, Self, ::oGet:Buffer )
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Maurilio Viana » Mon Mar 19, 2007 5:26 pm

In older FW versions bChange was evaluated in wrong place. Then if you ask to show the variable buffer the last key pressed wasn't considered.
I think Antonio fixed it months ago...
If I'm not wrong it was corrected 2006/march.

Regards,
Maurilio
User avatar
Maurilio Viana
 
Posts: 252
Joined: Tue Oct 25, 2005 2:48 pm
Location: Garça/Garza/Heron City - Brazil

Postby James Bott » Mon Mar 19, 2007 6:14 pm

Maurilio,

Thanks for your response.

>In older FW versions bChange was evaluated in wrong place. Then if you ask to show the variable buffer the last key pressed wasn't considered. I think Antonio fixed it months ago...

Well, that explains it, but there is a problem. Before the "fix," you could reject any keystroke by returning .f. from the bChange codeblock. This was really useful as you could have complete control over what was entered. The downside is that if you need everything that has been input you have to use oGet:varGet() + chr( nKey ). Note that nKey is automatically passed by the eval so this can be done.

Code: Select all  Expand view
Eval( ::bChange, nKey, nFlags, Self )


The "fix" you mentioned makes it much more difficult to reject keystrokes. You might think that you could just chop off the last character, but it is not so simple. First, the user will have already seen the character in the GET (not so with the previous method). Second, the user could be inserting or overstriking a character in the middle of the existing data in the GET. So, you have to write a rather complex processing routine and you still can't overcome the issue of the last character already having been displayed to the user.

I notice in TGet:keyChar() there is also another codeblock that could be used the way you want. Near the end of the method you will see this:

Code: Select all  Expand view
Eval( ::bPostKey, Self, ::oGet:Buffer )


At the time of this eval, ::bPostKey will contain the entire buffer including the last key typed (unless the last key was rejected either by other code or by bChange).

So, the last "fix" broke existing code. Any change now will likely break other code so there is no perfect solution, but I think you can easily change your code to use bPostkey instead of bChange. If that works, then we can move bChange back to its original location and we will have access to both features. Having both features would also allow you to easily both reject keystrokes before they reached the buffer AND to evaluate the buffer with each new keystroke by using both bChange and bPostKey.

Will you test changing your existing code to use bPostKey instead of bChange to see if that works for you? Then let us know what you find and we can either look for a different solution or we can make a recommendation to Antonio.

Anyone else have any comments or suggestions?

Regards,
James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Maurilio Viana » Mon Mar 19, 2007 7:21 pm

James, I understood the problem.
I'll try bPostKey instead bChange in all code I have and I'll post here my results.

Regards,
Maurilio
User avatar
Maurilio Viana
 
Posts: 252
Joined: Tue Oct 25, 2005 2:48 pm
Location: Garça/Garza/Heron City - Brazil

Postby Maurilio Viana » Wed Mar 21, 2007 6:46 pm

I changed all code were I used bChange to bPostKey and worked fine.
In all cases were I used bChange worked fine replacing to bPostKey.

Best regards
Maurilio
User avatar
Maurilio Viana
 
Posts: 252
Joined: Tue Oct 25, 2005 2:48 pm
Location: Garça/Garza/Heron City - Brazil

Postby James Bott » Thu Mar 22, 2007 5:20 am

Maurilio,

Thanks for testing that and reporting your results.

So, Antonio, I recommend putting bChange back were it was initially (see my message above for the specific location). Also, I recommend putting in the msgbeep() if SET BELL is on. If you like I can write something up explaining all this that you can put into the What's New.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Julio Cepeda and 65 guests