LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

mouse state with menu items overlapping control

Solved!
Go to solution

Hi,

 

I have an issue with retrieving the mouse location using GetGraphCoordsFromPoint...

 

I am using the return status of GetGraphCoordsFromPoint to determine if the mouse cursor is above the plot area of my graph control (1) or not (0) in order to switch between the mouse styles (VAL_DEFAULT_CURSOR versus VAL_CROSS_HAIR_CURSOR).

 

It works in most cases...

 

On top of the panel there is a menu bar, located below is the xy graph. Now, if the mouse opens a menu and is over the menu (and also over the graph) the mouse style depends on mouse history:

 

If the mouse has always been located over the menu, it is not recognized by GetGraphCoordsFromPoint to be loacted over the graph - which is what I would like to see, in this case the cursor style still is the default style.

 

Now, if the mouse leaves the menu for a short distance, the menu does not disappear (only if the mouse is at a larger distance) and acccordingly GetGraphCoordsFromPoint realizes that the mouse is over the graph. This is correct and as expected, too.(the mouse style is changed to a cross hair then)

 

Now, if I move the mouse back over the menu, this is not recognized by GetGraphCoordsFromPoint, unfortunately, and the mouse style is not switched back to default.

 

Am I missing something, or is there a way to correct this behavior? Having different mouse styles over a menu is confusing for the user and I'd like to avoid that, of course Smiley Happy

 

Thanks....

0 Kudos
Message 1 of 11
(5,116 Views)

Hi Wolfgang,

 

I would like to assist you, but therefore I do need some more information. What CVI version are you using ? And could you please attach to your next post

a short example file, the smallest bit of code that shows that behavior?

 

Regards

 

Thomas

0 Kudos
Message 2 of 11
(5,080 Views)

Hi Thomas,

 

thanks for feedback!

 

1) CVI 2009SP1 (9.1.1 450)

2) short demo example is attached 

 

To reproduce the issue

- move the mouse over the graph, it will be a cross hair (I tried to prepare screen shots, but the mouse cursor doesn't show up there...): this is the desired behavior Smiley Happy

- move the mouse somewhere else, not over the graph: the mouse cursor changes back to default: this still is the desired behavior Smiley Happy

- now, open a menu, i.e.choose menu 2, item 7, subitem 11: if you are skilful, the mouse will remain in the default style, however, if you are clumsy and happen to move your mouse slight beyond the menu over the graph, the mouse will change to a crosshair and will remain a crosshair even if you move back over the menu Smiley Surprised

 

I understand why this happens - but I need a possibility to fix it... Unfortunately, I did not find a suitable event to check for.

 

Wolfgang

0 Kudos
Message 3 of 11
(5,058 Views)

Hi Thomas,

 

there is actually no workaround I could figure out. I do think this behavior may be related to the menu layers, but I am not sure.

I could see the mouse gets back to default when moving over menu2, but I do not know if this is helpful for you.

 

Regards

 

 

Thomas

0 Kudos
Message 4 of 11
(5,030 Views)

Thanks Thomas,

 

may be someone else can assist?

0 Kudos
Message 5 of 11
(5,006 Views)
Solution
Accepted by topic author Wolfgang

Hi Wolfgang,

 

There isn't a very good way to get around this problem. As you've found, panel move events are sent to the panel's callback even while a menu is being tracked, and when you change the mouse cursor this this also impacts any menu that might be active at the time.

 

If you don't mind the cursor not changing at all while the menu is active, even if the user moves over the graph, then there is a possible strategy you can pursue to remedy the situation. It consists of trying to detect when a menu is active so that you don't try to change the cursor while the menu is active. Unfortunately, this is easier said than done. Although it's straightforward to be notified whenever a new menu becomes active (via a menu dimmer callback) there is no good way to be notified when the menu goes away. And there are multiple ways in which it can go away. So it it not possible for you to set an internal flag that tracks when the menu is active.

 

However, it is possible to find out whether the menu is active at the time that you receive the panel move event (or in the timer tick event, although I'm not completely sure why you are also using a timer). You can't do it with the CVI UI library, but you can, using the Windows SDK, in a somewhat round-about way.

 

The idea is to find out which window is the topmost window. And if it is not the panel window, then you should be able to assume that a menu is active and thus refrain from changing the cursor. Note that you also have to make sure that the active window belongs to your process, since there could be any number of other windows that could be the "topmost" window at any one time. But if it belongs to your process and it is not your panel, then we can assume that it's the menu.

 

I did a quick test with the following code and it seems to work, although you might want to test it more thoroughly than I did:


topHwnd = GetTopWindow (NULL);
GetWindowModuleFileName (topHwnd, topHwndModule, MAX_PATHNAME_LEN);


GetPanelAttribute (panel, ATTR_SYSTEM_WINDOW_HANDLE, (intptr_t *)&panelHwnd);
GetWindowModuleFileName (panelHwnd, panelHwndModule, MAX_PATHNAME_LEN);


if (!strcmp (topHwndModule, panelHwndModule) && panelHwnd != topHwnd)
    return 0; // don't change the cursor unless the panel really is on top

 

Good luck,

Luis


Message 6 of 11
(4,937 Views)

Thanks Luis!

 

I was quite pessimistic about a way out, the more I am happy about your suggested solution Smiley Happy I will give it a try!

 

Anyway, for us as users it would be much more convenient not having to involve Windows SDK, and hence I have suggested an improvement for the GetGraphCoordsFromPoint function here

 

Thanks again,

Wolfgang

0 Kudos
Message 7 of 11
(4,928 Views)

Luis,

 

I am trying to understand your approach and am stuck:

 

I seem to understand the idea of obtaining the two file names of the current CVI process and of the Windows process with the top most panel and see if they are identical or not. If they are identical, the CVI application is supposed to have the focus and one needs to check if the current CVI panel has the same panel handle as the topmost Windows panel. If not, "something else" is on top of the CVI panel.

 

As I understand you, "something else" would mean a menu...

  1. What about a ring control that is opened? A CVI ring control, if open, can be quite large and easily cover (partially) a nearby plot area, resulting in the same problem with the mouse cursor. Still I would expect that this ring belongs to the very same panel as the graph...?
  2. And (tyically I am not using Windows SDK) do I understand it correctly that for Windows a menu is considered a different panel with its own panel handle? 

 

Thanks!

0 Kudos
Message 8 of 11
(4,912 Views)

1. If you have a ring control with a drop-down menu that overlaps the plot area, the end result should be pretty much the same as with a menubar menu. In other words, the same mechanism I suggested would take care of both situations.

 

2. A panel is a CVI concept, not a Windows concept. But yes, there is a Windows window associated with every top-level panel in CVI. And each menu and sub-menu (including ring menus) also has a window associated with it. The windows associated with those menus also belong to your program, as reported by GetWindowModuleFileName, and so you can apply the logic that if the topmost window belongs to your program and it is not your panel's window, then it's probably a menu.

 

If your program creates any other panels, then those panels could also be on top, of course. And they would also belong to your program. But in that scenario you won't be receiving panel move events for the main panel, so I don't think you need to worry about that case.

 

Luis

0 Kudos
Message 9 of 11
(4,902 Views)

Hi Luis,

 

I've implemented your solution --- partially --- and skipped the comparison panelHwnd != topHwnd because I have not managed to ever get the condition panelHwnd == topHwnd fulfilled... When is it supposed to happen? Is it supposed to happen also in debug mode?

 

Concerning your earlier question why I am also using a timer: this is to catch the possibility that the mouse cursor leaves the graph too fast, i.e. without generating a panel event: In this case the timer will reset the mouse cursor style to its default value.

 

Wolfgang

0 Kudos
Message 10 of 11
(4,865 Views)