OE 11.51: ABL Form: Identify on which widget the mouse is cu

Posted by Stefan Marquardt on 05-Oct-2015 09:56

I like to use an on anywhere (keyboard) event to identify the widget (get widget handle) even it's not enabled/sensitive.
Is this possible with (old) ABL forms (it's possible with .Net)

Posted by nborshukov on 09-Oct-2015 10:49

Use ClientToScreen.

The coordinates of a widget are relative to frame upper left corner. So, start "scanning" frame widgets you must ClientToScreen frame upper left corner, passing frame hwnd and loading in point structure 0 for x and y. Then ClientToScreen function returns frame 0,0 in screen coordinates. After that screen coordinates of a widget are:

Top left: frame-x-screen + widget:x, frame-y-screen + widget:y;

Bottom right: top-left-x + widget:width-pixels;  top-left-y + widget:height-pixels

All Replies

Posted by Matt Gilarde on 05-Oct-2015 10:14

I'm not sure what you mean. If a widget is insensitive it can't take focus and can't get keyboard events. Can you give a simple .NET example to demonstrate what you're asking for?

Posted by Matt Gilarde on 05-Oct-2015 10:17

Now I see that the question is about the mouse, not the keyboard. I still would like more clarification about what you need to do. Do you want an event to fire when the mouse is over a widget or do you want to determine which widget is under the mouse? Or something else? Again, a .NET example that shows how it works there will be helpful to clarify the question.

Posted by Mike Fechner on 05-Oct-2015 10:19

Those samples would be fairly easy translatable into ABL:

stackoverflow.com/.../is-there-a-quick-way-to-get-the-control-thats-under-the-mouse

Posted by Stefan Marquardt on 06-Oct-2015 02:03

But how to get that running for old pure ABL forms (no .net controls)?

What is the ABL function to get the mouse position and find out whether it's in the bounds of a "inner" ABL widget (not the frame)

Posted by Stefan Marquardt on 06-Oct-2015 02:06

Matt,

"do you want to determine which widget is under the mouse?

Yes - that's what I like to know when I press like a F-key with an registered anywhere event.

Posted by Matt Gilarde on 06-Oct-2015 04:57

I'll try to create an example of how to do this today. I have to warn you that it might not be perfect. The Windows functions that tell you which window is under a certain point don't always return what you'd expect.

Posted by Stefan Marquardt on 06-Oct-2015 07:41

That would be very nice, in the moment I only need a routine to iterate through all widget of the current window.

I found an example in KB but there it looks like I get all widgets in all windows and not only the current window.

How to prevent to iterate through every widget in the abl session?

hObject = current-window no-error.

RUN WalkChildTree (hObject).

PROCEDURE WalkChildTree:

   DEFINE INPUT PARAMETER phObject AS HANDLE NO-UNDO.

   DEFINE VARIABLE hNextObject AS HANDLE NO-UNDO.

   /* Drill down child object chain first */

   hNextObject = phObject:FIRST-CHILD NO-ERROR.

   IF VALID-HANDLE (hNextObject)

   THEN RUN WalkChildTree (hNextObject).

/* Check for siblings and their children.

       */

   hNextObject = phObject:NEXT-SIBLING NO-ERROR.

   IF VALID-HANDLE (hNextObject) THEN

       RUN WalkChildTree (hNextObject).

   /* This object does not have any children or siblings, or the children or

       siblings have already been processed in the recursive call. Process

       object information now.

       */

       MESSAGE phObject:name phObject:screen-value

         VIEW-AS ALERT-BOX INFO BUTTONS OK.*/

   end.

Posted by Matt Gilarde on 06-Oct-2015 07:57

That code walks through every widget in the widget tree. If you only want to walk through the children of the current window, pass CURRENT-WINDOW:FIRST-CHILD to procedure WalkChildTree:

RUN WalkChildTree(CURRENT-WINDOW:FIRST-CHILD).

Posted by Stefan Marquardt on 06-Oct-2015 08:25

Thanks, I think I need a course about widgets list childs/sibling.

With GetCursorPos and ScreenToClient I got the first positive result-

Posted by Matt Gilarde on 06-Oct-2015 08:33

It sounds like you're moving ahead pretty well with this. I don't think you need an example if you've got GetCursorPos and ScreenToClient working. You may also want to look at ChildWindowFromPoint.

Posted by Stefan Marquardt on 06-Oct-2015 08:40

Yes, looks good for the first try, I have to check now dual screens and the functions are not safe for right to left configurations. (but I think we don't use this)

I hit a bug during my tests, the (external) debugger didn't starts/visible at the first call of these statements:

debugger:initiate().

debugger:set-break().

Posted by Stefan Marquardt on 09-Oct-2015 08:57

Hi Matt,

in general it's working.

With WalkingChild I get now every widget from the active-window.

This works with the most windows but not with all.

In some windows the coordinates are different than fetched with  GetCursorPos and recalculated with ScreenToClient.

The pointer is on 228 where the upper left corner of the widget is, but the widget has 174 as Y value.

So I get the values being ~ 50 pixels above the visible widget.

The windows has many frames (visible and not visible)

The first frame at the top is o.k. and the one at the bottom.

The second with the offset, below the first once seems to have as offset the height of the first one above.

Other windows has many frames too but not this effect.

What can be the cause of the offset between the calculated mouse position and the widget position?

Posted by Matt Gilarde on 09-Oct-2015 09:36

ScreenToClient converts screen coordinates to client coordinates relative to a the window you pass as the first parameter. A widget's X and Y attributes are always relative to the frame which contains the widget. Are you calling ScreenToClient for each frame as you walk through the widgets?

Posted by nborshukov on 09-Oct-2015 10:49

Use ClientToScreen.

The coordinates of a widget are relative to frame upper left corner. So, start "scanning" frame widgets you must ClientToScreen frame upper left corner, passing frame hwnd and loading in point structure 0 for x and y. Then ClientToScreen function returns frame 0,0 in screen coordinates. After that screen coordinates of a widget are:

Top left: frame-x-screen + widget:x, frame-y-screen + widget:y;

Bottom right: top-left-x + widget:width-pixels;  top-left-y + widget:height-pixels

Posted by Stefan Marquardt on 12-Oct-2015 07:48

The next step would be to get the value from a cell of a browse widget ...

This thread is closed