PlanetSquires Forums

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Can't see the forest for the trees  (Read 696 times)

Paul Squires

  • Administrator
  • Guru Member
  • *****
  • Posts: 9287
  • Windows 10
    • PlanetSquires Software
Can't see the forest for the trees
« on: March 05, 2020, 09:23:11 PM »

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.

Code: [Select]
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  :-)

Logged
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Josť Roca

  • Guru Member
  • *****
  • Posts: 3271
Re: Can't see the forest for the trees
« Reply #1 on: March 06, 2020, 01:27:18 AM »

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

That's not fair :)

Johan Klassen

  • Junior Member
  • **
  • Posts: 90
  • FF3 User
Re: Can't see the forest for the trees
« Reply #2 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
Logged

Josť Roca

  • Guru Member
  • *****
  • Posts: 3271
Re: Can't see the forest for the trees
« Reply #3 on: March 06, 2020, 09:04:06 AM »

Ice cold.

Paul Squires

  • Administrator
  • Guru Member
  • *****
  • Posts: 9287
  • Windows 10
    • PlanetSquires Software
Re: Can't see the forest for the trees
« Reply #4 on: March 06, 2020, 12:18:43 PM »

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.
Logged
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Johan Klassen

  • Junior Member
  • **
  • Posts: 90
  • FF3 User
Re: Can't see the forest for the trees
« Reply #5 on: March 06, 2020, 01:04:47 PM »

I will make my ignorance shine even more, (it's OK if you laugh) my next guess is that this function
Code: [Select]
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
Code: [Select]
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
Logged

Josť Roca

  • Guru Member
  • *****
  • Posts: 3271
Re: Can't see the forest for the trees
« Reply #6 on: March 06, 2020, 01:26:51 PM »

Chilly :)

Josť Roca

  • Guru Member
  • *****
  • Posts: 3271
Re: Can't see the forest for the trees
« Reply #7 on: March 06, 2020, 01:37:37 PM »

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

  • Junior Member
  • **
  • Posts: 102
Re: Can't see the forest for the trees
« Reply #8 on: March 13, 2020, 05:42:11 PM »

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

Your turn Johan...  :-)
Logged

Paul Squires

  • Administrator
  • Guru Member
  • *****
  • Posts: 9287
  • Windows 10
    • PlanetSquires Software
Re: Can't see the forest for the trees
« Reply #9 on: March 14, 2020, 12:44:46 PM »

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.
« Last Edit: March 14, 2020, 12:54:18 PM by Paul Squires »
Logged
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer