Page 1 of 2

Get Cut/Paste problem

Posted: Fri Aug 04, 2006 2:31 pm
by Randal
All,

I have a problem using right click to Cut/Paste from a get. When you cut from one field then paste into another then type in the pasted field the text you pasted is deleted.

Compile and try this simple sample. Right click and cut the contents of field one, then right-click and paste into field three. If you then type something the pasted text is deleted.

#include "fivewin.ch"

function main()

local oDlg, oGet2, cVar1:="AAAAAA", cVar2:="BBBBBB", cVar3:=" "

define dialog oDlg title "Test Get"
@ 1,1 get cVar1 of oDlg update
@ 2,1 get oGet2 var cVar2 of oDlg update
@ 3,1 get cVar3 of oDlg update
activate dialog oDlg centered

return nil

Using FWH April 2006 and xHarbour March 2006.

Thanks,
Randal Ferguson

Posted: Sat Aug 05, 2006 9:46 am
by Antonio Linares
Randal,

Please declare cVar3:=Space( 6 ).

Your test works fine, once the third GET looses its focus. You may consider that the GET assigns its contents only when it looses it focus, so it you type in before, after the paste, then the contents are lost.

Posted: Sun Aug 06, 2006 7:59 pm
by James Bott
Antonio,

>You may consider that the GET assigns its contents only when it looses it focus, so it you type in before, after the paste, then the contents are lost.

This does not seem to be normal Windows behavior. When I paste into other applications, you can then type without loosing the pasted text.

Perhaps TGET should update the buffer after a paste.

James

Posted: Sun Aug 06, 2006 9:49 pm
by Antonio Linares
James,

We are going to review it.

Posted: Mon Aug 07, 2006 2:58 am
by Randal
Antonio,

I agree with what James said. No other windows applications that I know of behaves this way. In all other apps I've tried, when you paste into a field the cursor is positioned at the end of the pasted text and you can start typing there without having the pasted text deleted. Also, you can move the cursor to the beginning of the pasted text and when you type the data is inserted in front of the text.

This has become a serious problem and I have a lot of customers complaining about the cut/paste behaviour in our FWH/xHarbour app. In FW 16-bit it works correctly.

Thanks,
Randal Ferguson

Posted: Thu Aug 10, 2006 4:45 pm
by Roger Seiler
Randall,

I found that the problem is with the default RbuttonDown() menu, which TGEt uses, and which TMultiget does not (Mget.prg). The default RbuttonDown() edit menu does not use the Tget:Paste() method, so the problem is not there.

I found that by coping TGet.prg from FWH\Source to my app directory, and then coping and adapting the RButtondown() method from Mget.prg into Tget.prg, and then by linking in the revised Tget.prg, I was able to solve the problem.

- Roger

Posted: Thu Aug 10, 2006 5:10 pm
by Antonio Linares
Roger,

Thanks for the tip :-)

Anyhow, the difference between them is that Class TGet invokes the Windows standard popup menu, meanwhile Class TMultiGet creates it.

Our guess is that we have to properly manage WM_PASTE. We need to do some tests.

Posted: Thu Aug 10, 2006 5:12 pm
by James Bott
>I found that the problem is with the default RbuttonDown() menu, which TGEt uses.

I was confused when I read Roger's message, but the "default RButtonDown menu" he refers to is apparently a Windows common control. Since TGet is not a standard windows edit control, but rather a Harbour Get contained in a FW TGet class it makes some sense that the standard Windows cut/copy/paste control would not be able to update the FW get control.

I'm guessing that this very issue is why the MGet menu was written in the first place. The Windows cut/copy/paste menu didn't work there either.

So Roger's idea to use the MGet RButtonDown method in TGet does seem like a good solution.

Comments Antonio?

James

Posted: Thu Aug 10, 2006 5:26 pm
by Antonio Linares
James,

I modified my previous msg. Please review it.

Posted: Thu Aug 10, 2006 5:30 pm
by James Bott
Antonio,

It seems we were both writing responses at the same time, so I didn't see your message before writing mine. Thanks.

James

Posted: Thu Aug 10, 2006 5:39 pm
by Antonio Linares
This looks as a possible valid fix. We appreciate your feedback:

Code: Select all

#define WM_PASTE           770
...
METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TGet

   do case
      case nMsg == WM_CUT
           CallWindowProc( ::nOldProc, ::hWnd, WM_CUT, 0, 0 )
           ::oGet:buffer = Pad( GetWindowText( ::hWnd ), Len( ::oGet:buffer ) )
           ::oGet:Pos = 1
           ::oGet:Assign()
           return 0
           
      case nMsg == WM_PASTE
           CallWindowProc( ::nOldProc, ::hWnd, WM_PASTE, 0, 0 )
           ::oGet:buffer = Pad( GetWindowText( ::hWnd ), Len( ::oGet:buffer ) )
           ::oGet:Assign()
           return 0
   endcase
   
return Super:HandleEvent( nMsg, nWParam, nLParam )           
Method RButtonDown() remains unchanged.

Posted: Thu Aug 10, 2006 6:48 pm
by James Bott
Antonio,

Well, there is progress, but there are still problems with the location of the cursor. When you paste text the cursor is (properly) at the end of the pasted text, but then when you then type a character, the cursor jumps to the beginning of the pasted text then overwrites the character.

Starting field contains:

123456789

I paste ABCD in right after the 5. The cursor appears where the bracket is:

12345ABCD[6789

Then I type z and it appears where the A was:

12345z[BCD6789

If I do the same thing in a field in Outlook Express I get this:

12345ABCDz[6789

Note that the FW app defaults to overwrite mode the the OE defaults to insert mode.

If I use Ctrl-V, instead of Paste in the menu, the cursor jumps to the first postion:

[12345ABCD6789

This is incorrect also. Of course, both Paste and Ctrl-V should do exactly the same thing.

James

Posted: Thu Aug 10, 2006 7:16 pm
by Antonio Linares
James,

It looks as we have to modify ::oGet:Pos, but what value should we assign to it ?

Posted: Thu Aug 10, 2006 7:23 pm
by Antonio Linares
James,

This looks to works fine with your explained sample:

Code: Select all

METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TGet

   local oClp

   do case
      case nMsg == WM_CUT
           CallWindowProc( ::nOldProc, ::hWnd, WM_CUT, 0, 0 )
           ::oGet:buffer = Pad( GetWindowText( ::hWnd ), Len( ::oGet:buffer ) )
           ::oGet:Pos = 1
           ::oGet:Assign()
           return 0
           
      case nMsg == WM_PASTE
           CallWindowProc( ::nOldProc, ::hWnd, WM_PASTE, 0, 0 )
           ::oGet:buffer = Pad( GetWindowText( ::hWnd ), Len( ::oGet:buffer ) )
           DEFINE CLIPBOARD oClp OF Self FORMAT TEXT
           ::oGet:Pos += Len( oClp:GetText() )
           oClp:End()
           ::oGet:Assign()
           return 0
   endcase
   
return Super:HandleEvent( nMsg, nWParam, nLParam )           

Posted: Thu Aug 10, 2006 7:55 pm
by James Bott
Antonio,

Yes it works--I was just about to post a similar fix I did myself.

The Cut routine also needs a similar fix. This seems to be working:

Code: Select all

METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TGet

   local oClp

   do case
      case nMsg == WM_CUT
           CallWindowProc( ::nOldProc, ::hWnd, WM_CUT, 0, 0 )
           ::oGet:buffer = Pad( GetWindowText( ::hWnd ), Len( ::oGet:buffer ) )
           DEFINE CLIPBOARD oClp OF Self FORMAT TEXT
           ::oGet:Pos -= Len( oClp:GetText() )
           oClp:End()
           ::oGet:Assign()
           return 0

      case nMsg == WM_PASTE
           CallWindowProc( ::nOldProc, ::hWnd, WM_PASTE, 0, 0 )
           ::oGet:buffer = Pad( GetWindowText( ::hWnd ), Len( ::oGet:buffer ) )
           DEFINE CLIPBOARD oClp OF Self FORMAT TEXT
           ::oGet:Pos += Len( oClp:GetText() )
           oClp:End()
           ::oGet:Assign()
           return 0
   endcase

return Super:HandleEvent( nMsg, nWParam, nLParam ) 
Now Ctrl-X and Ctrl-V need fixing.

James