Friday, January 11, 2008

Don't Save if Minimized

We've had a few people report an unusual problem: when they launch Stonefield Query, rather than displaying a login dialog, it looks like it's hung, but pressing Esc makes it close. It turns out that under some circumstances, the login dialog appears behind the application but has focus. As a result, it waits for the user to login and since it's a modal dialog, it looks like the application has hung. Pressing Esc cancels the dialog and closes the app. If you type the user name and password (blindly, of course, since you can't see the dialog) and press Enter, it succeeds.

We couldn't reproduce this ourselves and setting the login form's AlwaysOnTop to .T. didn't help for those people who did encounter it.

Then someone today reported the following situation: they minimize Stonefield Query then log off from Windows. (Minimizing, right-clicking on its Task Bar item, and choosing Close also caused the problem.) The next time they launch Stonefield Query, it starts minimized. They restore it and boom, the application is "hung" but pressing Esc closes it. Bingo -- we have a reproducible scenario.

In digging into this, I found the following code executes when the application shuts down:
with This.oRegistry
.SetKey(lcKey, 'WindowState', _screen.WindowState)
.SetKey(lcKey, 'Height', _screen.Height)
.SetKey(lcKey, 'Left', _screen.Left)
.SetKey(lcKey, 'Top', _screen.Top)
.SetKey(lcKey, 'Width', _screen.Width)
endwith
This code stores the current size, position, and window state of _SCREEN so the next time they launch Stonefield Query, it can restore those settings. And that's the start of the problem: when the application is minimized, _SCREEN.Top and Left are set to -32000. The login dialog then opens and since it has Desktop set to .T. so it looks nice in Windows Vista, it doesn't live inside _SCREEN but centers itself inside the current location of _SCREEN. That makes it really far offscreen. Then the user restores the application, which puts _SCREEN back where it was, but since the login dialog doesn't live in _SCREEN, it doesn't move. So, while it has focus and the user can type in it, they can't see the dialog.

The solution was easy: don't call the above code if _SCREEN.WindowState is 1-Minimized. That way, _SCREEN will be restored to the size and position it was the last time it was closed while actually visible.

1 comment:

Anonymous said...

Yeah, that's a good one. I remember doing this in the ReportPreview.App code.