• Welcome to PlanetSquires Forums.
 

Can't see the forest for the trees

Started by Paul Squires, March 05, 2020, 09:23:11 PM

Previous topic - Next topic

Paul Squires

Here is one that was driving me nuts for over a day.....

I made some additions to the wfxPoint class so that it could automatically convert the point from one window coordinate to another (the most common being from screen coordinates to control client coordinates). Easiest way to do that is with MapWindowPoints. So I built that into the class. Thinking everything was okay, I moved on. A few days later I was working on the TreeView.GetNodeAt function and then used wfxPoint during the TreeView's OnMouseDown event handler to do a test. Everything crashed. Immediate GPF when I clicke don a treeview node (granted, it happened more quickly on 32-bit than it did on 64-bit compiled exe's). Where in the world did I go wrong? I thought that maybe it was related to code that I had written to handle SelectedNode for the TreeView but eventually I was able to track it down to the wfxPoint class and specifically the call to wfxPoint.Convert. I thought that my conversion was somehow screwing up the incoming e.pt (from EventArgs) that was assigned to the wfxPoint class and then when OnMouseDown exited it was causing a crash because the point was corrupted in memory. Well, that was somewhat correct.

Here is the code. Can you immediately spot the problem? I must have stared at it for hours thinking that the point address was the problem.


function wfxPoint.Convert( byval hWndFrom as HWND, byval hWndTo as HWND ) as Long
   MapWindowPoints( hWndFrom, hWndTo, cast(point ptr, @_pt), 2)
   function = 0
end function

function wfxPoint.Convert( byval hWndTo as HWND ) as Long
   this.Convert( HWND_DESKTOP, hWndTo )
   function = 0
end function


See it? Well, when I eventually did realize my mistake I think I actually cursed out loud and scolded myself for being so stupid. Funny though how something so simple crashed my whole program so easily.

(Jose, I forbid you from answering this question first!) LOL  :-)

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

> (Jose, I forbid you from answering this question first!) LOL  :-)

That's not fair :)

Johan Klassen

the only thing I see is that the function wfxPoint.Convert is defined twice with different arguments

José Roca


Paul Squires

Quote from: Johan Klassen on March 06, 2020, 08:33:54 AM
the only thing I see is that the function wfxPoint.Convert is defined twice with different arguments

One of the great things about FreeBasic is that you can overload functions by defining different parameters for each.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Johan Klassen

I will make my ignorance shine even more, (it's OK if you laugh) my next guess is that this function

function wfxPoint.Convert( byval hWndFrom as HWND, byval hWndTo as HWND ) as Long
   MapWindowPoints( hWndFrom, hWndTo, cast(point ptr, @_pt), 2)
   function = 0
end function

should be

function wfxPoint.Convert( byval hWndFrom as HWND, byval hWndTo as HWND ) as Long
   this.Convert( hWndFrom, hWndTo, cast(point ptr, @_pt), 2)
   function = 0
end function


José Roca

Hint: Read carefully the documentation for MapWindowPoints, specially the lpPoints and cPoints parameters.

MapWindowPoint function: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapwindowpoints

Pierre Bellisle

Yep, I see it... It's to long to explain... You where asking for too much...

Your turn Johan...  :-)

Paul Squires

#9
Pierre messaged me privately and of course knew the correct answer. :-)

This is a good example of reading and understanding a Windows API function call. Jose's hint for understanding the MapWindowPoints function parameters is the starting point.

If you can't understand why the problem is the MapWindowPoints function, then hopefully you've at least been able to learn what the MapWindowPoints function does because it is an important concept in Windows programming. Being able to convert POINT and/or RECT structures to and from one coordinate system relative to another happens frequently in Windows programming.

For example, when we retrieve the mouse cursor position using the api GetCursorPos, it returns a POINT structure based on the entire screen coordinates. Now let's say you have a ListBox and you want to do hit testing that the mouse is over a particular row in the ListBox. Such hit testing would entail converting the screen cursor POINT to a value that is relative to the client area of the ListBox. You can then test the POINT to see if it is over the particular ListBox row in question (PtInRect api function).

Once you understand that the MapWindowPoints function converts both use cases of converting POINT and RECT structures then you should be able to figure out why my particular use of the function failed and resulted in a random crash.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer