views:

460

answers:

7

I am trying to debug a strange issue with users that have LogMeIn installed. After a few days, some of my dialogs that my app opens can end up offscreen. If I could reliable detect that, I could programmatically move the dialogs back where they are visible again.

Note: this has to work for multiple monitors and use the win32 API. However, if you know how to do it from .NET I can probably extrapolate from there...

Update: For the curious, the bug mentioned above has to do with wxWidgets. If you run a wxWidgets application, then walk away and let your screen saver go, then log in remotely with LogMeIn, then try to open a dialog from your app, you will have trouble if you use wxDisplay::GetFromPoint(pos) or wxWindowBase::Center() to position the dialog.

A: 

Hmm. This might not help, but when I did VB, you could do screen.width and screen.height, and then window.x and window.y...

Of course, I don't know how that works with multiple monitors.

mattl
A: 

In .NET, you use the Screen.PrimaryScreen.WorkingArea structure to get the bounds of the primary screen (Screen.Screens[x].WorkingArea for other monitors, I think), and then use the Left and Top properties of the window to find out where the window is (if it's off the screen, Top and Left will be bigger than [Screen].Width and .Height.

DannySmurf
A: 

In .NET, I would iterate on each Screen in Screen.AllScreen, then either call screen.Bounds.Contains() passing your form's rectangle if you want to make sure all of your window is within bounds(*), or call screen.Bounds.IntersectsWith() if you only want to make sure at least a portion of your form is visible.

(*) Not being fully within one screen bounds does not mean it's not within the total screens' bounds. You could also call Rectangle.Union on each screen bounds to create a single rectangle to test your form's rectangle against, but then you must watch out if screen bounds are not of the same size, since the englobing rectangle is not fully visible either.

That was the longer answer. The shorter one is: There is no easy way I know of.

Martin Plante
A: 

It looks like GetMonitorInfo() is the Win32 equivalent of Danny's suggestion. I'm not sure how you'd go about getting an HMONITOR for all of the monitors on the system, but it looks like the example linked from the documentation has some ways of doing it.

Andy
+1  A: 

All the basics on multiple monitor support from June 1997 Microsoft Systems Journal:

Positioning Objects on a Multiple Display Setup:

Michael Burr
+6  A: 

Simply use MonitorFromWindow with the MONITOR_DEFAULTTONULL flag. If the return value is null, your window is not visible. You can subsequently pass MONITOR_DEFAULTTONEAREST to be able to reposition your window on the nearest monitor.

Frederik Slijkerman
Removing my answer - the MONITOR_DEFAULTTONULL flag seems perfect...
Aardvark
I ended up using MonitorFromPoint, which works similarly to MonitorFromWindow.
Kurt
+1  A: 

Whatever you do, please account for multiple monitors which may have coordinates thousands of pixels away from (0,0) in any direction. I hate it when an app forces itself back into another screen, frequently messing up any full-screen games I may be in at the time.

tsilb