Page 1 of 2

bDropOver - nRow, nCol

Posted: Mon Feb 11, 2008 8:30 am
by nageswaragunupudi
Mr Antonio

I am trying to use the nRow, nCol parameters of bDropOver block when drop occurs on a window.

Naturally I expected that the nRow,nCol refer to the destination window. It is not the case. I found that they are not even Screen Coordinates. On studying the Control.Prg, I observed that the nRow, nCol refer to the position with respect to originating control ( i.e, the Control where the drag began ).

The relevant code from Control.Prg is extracted below:

Code: Select all

METHOD LButtonUp( nRow, nCol, nKeyFlags ) CLASS TControl

   local aPoint := { nRow, nCol }

   ::lMouseDown = .f.

   if lDragging
      lDragging = .f.
      ReleaseCapture()

      aPoint = ClientToScreen( ::hWnd, aPoint )
      if aPoint[ 1 ] > 32768
         aPoint[ 1 ] -= 65535
      endif
      if aPoint[ 2 ] > 32768
         aPoint[ 2 ] -= 65535
      endif
      SendMessage( WindowFromPoint( aPoint[ 2 ], aPoint[ 1 ] ),;
                   FM_DROPOVER, nKeyFlags, nMakeLong( nRow, nCol ) )

      return nil
   endif
The destination (dropped) window can not use these nRow,nCol coordinates directly. We have to know the originating window ( the bdropdown does not contain the information, unless we stuff it in the udropinfo). So we have to ascertain the originating window, conver the coordinates to screen from orginating window and then convert again from screen to the destination window.

Kindly confirm if my understanding is correct.

I checked the drag drop programs in the samples folder. They do not contain any sample using the nRow,nCol coordnates in the bDropOver block.

I suggest it would be convenient for us, if the bDropOver is called with nRow,nCol relative to the destination window ( or at least the screen coordinates).

I suggest the following modified code.

Code: Select all

METHOD LButtonUp( nRow, nCol, nKeyFlags ) CLASS TControl

   local aPoint := { nRow, nCol }
   local hDropWnd

   ::lMouseDown = .f.

   if lDragging
      lDragging = .f.
      ReleaseCapture()

      aPoint = ClientToScreen( ::hWnd, aPoint )
      if aPoint[ 1 ] > 32768
         aPoint[ 1 ] -= 65535
      endif
      if aPoint[ 2 ] > 32768
         aPoint[ 2 ] -= 65535
      endif

      hDropWnd  = WindowFromPoint( aPoint[ 2 ], aPoint[ 1 ] )
      aPoint    = ScreenToClient( hDropWnd, aPoint )

      // do we need to make again any correction for 65535 here also ?

      SendMessage( hDropWnd, FM_DROPOVER, nKeyFlags, nMakeLong( aPoint[ 1 ], aPoint[ 2 ] ) )

      return nil
   endif
With this correction I expect when the drop occurs, the nRow, nCol parameters that the window receives on evaluation of bDropOver block are relative to itself and can straight away use the coordinates.

Is my understanding right ?

With this modification, dropover function can be written something like this

Code: Select all

oWnd:bDropOver := { |u,r,c,f| mousedropover( u,r,c,f ) }
//---
func mousedropover( u, nRow, nCol, nFlags )

   oWnd:Say ( nRow, nCol, 'Dropped here' )

 /*
   INSTEAD OF :

   LOCAL aPoint
   aPoint := ClientToScreen( OrginatingWnd:hWnd, { nRow, nCol } )
   // apply 65535 correction
   aPoint := ScreenToClient( oThisWnd:hWnd, aPoint )
   // i don't know if we again have to apply 65535 correction and if so what it is
   nRow := aPoint[ 1 ]
   nCol  := aPoint[ 2 ]
  // now use nRow,nCol
*/

Do other programmers agree with the suggestion?

Request Mr Antonio and other colleagues to advise.

Posted: Mon Feb 11, 2008 9:29 am
by Antonio Linares
Nageswararao,

> Is my understanding right ?

Yes. Actually the coordinates are absolute and are not relative to the destination window.

We should use ScreenToClient() as you describe to turn them local to the window where the drop is done

Posted: Mon Feb 11, 2008 9:32 am
by nageswaragunupudi
Mr Antonio

I do not think they are even absolute. I think they are relative to the control originating the drag. Can you kindly verify again please?

Posted: Mon Feb 11, 2008 9:35 am
by nageswaragunupudi
If the coordinates have to be absolute, the control.prg should have been like this :

Code: Select all

/*
    INSTEAD OF 

     SendMessage( WindowFromPoint( aPoint[ 2 ], aPoint[ 1 ] ),;
                   FM_DROPOVER, nKeyFlags, nMakeLong( nRow, nCol ) )
*/
      SendMessage( WindowFromPoint( aPoint[ 2 ], aPoint[ 1 ] ),;
                   FM_DROPOVER, nKeyFlags, ;
                   nMakeLong( aPoint[ 1 ], aPoint[ 2 ] ) )

Can you please confirm ?

Posted: Mon Feb 11, 2008 10:48 am
by Antonio Linares
Yes, you are right

Thanks,

Posted: Mon Feb 11, 2008 10:56 am
by nageswaragunupudi
Mr Antonio

1) Do you think we should modify ? So that the dropped window need now know the originating window. If you agree, I shall do it in my copy.

--- I still prefer if the coordinates provided are relative the dropped window avoiding the programmer to do the complex calculations.

2) Please advise me if we need to apply the 65535 correction after ScreenToClient also? If so what is that correction?

Posted: Mon Feb 11, 2008 11:30 am
by Antonio Linares
Nageswararao,

>
1) Do you think we should modify ? So that the dropped window need now know the originating window. If you agree, I shall do it in my copy.
>

Yes, I guess the best choice is to use local window coordinates

>
2) Please advise me if we need to apply the 65535 correction after ScreenToClient also? If so what is that correction?
>

We have to check it in case that we get negative values

Posted: Mon Feb 11, 2008 12:43 pm
by nageswaragunupudi
Mr Antonio

In that case, can you please comment on this code, if it looks okay?

Code: Select all

METHOD LButtonUp( nRow, nCol, nKeyFlags ) CLASS TControl

   local aPoint := { nRow, nCol }
   local hDropWnd

   ::lMouseDown = .f.

   if lDragging
      lDragging = .f.
      ReleaseCapture()

      aPoint = ClientToScreen( ::hWnd, aPoint )
      if aPoint[ 1 ] > 32768
         aPoint[ 1 ] -= 65535
      endif
      if aPoint[ 2 ] > 32768
         aPoint[ 2 ] -= 65535
      endif

      hDropWnd  = WindowFromPoint( aPoint[ 2 ], aPoint[ 1 ] )
      aPoint    = ScreenToClient( hDropWnd, aPoint )

      if aPoint[ 1 ] < 0
         aPoint[ 1 ] += 65535
      endif
      if aPoint[ 2 ] < 0
         aPoint[ 2 ] += 65535
      endif

      SendMessage( hDropWnd, FM_DROPOVER, nKeyFlags, nMakeLong( aPoint[ 1 ], aPoint[ 2 ] ) )

      return nil
   endif 
If this code looks to be logically correct, I shall incorporate in my copy and test it. If I encounter any problems, I shall seek your guidance again.

Another point:

Why can't the 65535 issue be handled in the ScreenToClient and ClientToScreen functions and return the fully rectified values? Why should the programmer apply the correction everytime in his code? In normal course I would never know that these two functions would need a correction like this. New programmers who use these functions may not know till they face problems and approach the forum.

Posted: Mon Feb 11, 2008 12:47 pm
by Antonio Linares
Nageswararao,

Your changes look fine, though I am not totally sure about this:

Code: Select all

      if aPoint[ 1 ] < 0 
         aPoint[ 1 ] += 65535 
      endif 
      if aPoint[ 2 ] < 0 
         aPoint[ 2 ] += 65535 
      endif 
Those changes are due to a sign problem that it is not properly managed

Posted: Mon Feb 11, 2008 12:50 pm
by nageswaragunupudi
>
Your changes look fine, though I am not totally sure about this:
>
This is my doubt too about the post-screentoclient call.

Posted: Tue Feb 12, 2008 12:11 pm
by nageswaragunupudi
Mr Antonio

Sorry to bother you again. I read the source code of the library functions again and again. I do not see any logical reason why we do not get the correct coordinates from the windows api. If this is a problem with windows api, even programmers working in other development platforms should have complained about it.

Has any FWH developer faced the problem of inaccuracy without applying the correction? Or are we carrying the correction from an old legacy which may not be required now. In any case how can the screen coordinates be negative?

In any case, I do not think we should correct if coordinates returned by ScreenToClient are negative, because they can be negative if the point is ouside the client.

Posted: Tue Feb 12, 2008 1:34 pm
by James Bott
>In any case how can the screen coordinates be negative?

If you draw or move items off the visible screen screen coordinates can be negative.

James

Posted: Tue Feb 12, 2008 1:39 pm
by nageswaragunupudi
>
f you draw or move items off the visible screen screen coordinates can be negative.
>
Yes

Posted: Tue Feb 12, 2008 1:44 pm
by James Bott
NageswaraRao,

I am not sure if you were confirming that you read my statement, or if you thought my statement was a question, and you were answering it?

James

Posted: Tue Feb 12, 2008 1:46 pm
by nageswaragunupudi
I accepted and confirmed your statement Mr James. How could Mr James be wrong ? :)