DAY 004: _WINDOWHASFOCUS
#1
A keyword which simply tells you if your program is topmost and has focus in your OS.  For those who don't understand what I'm talking about with topmost, let me give you a simple example:

1) Open your file explorer and click the qb64pe icon and start up a fresh instance of the IDE.  It'll pop up on your screen on top of any other windows which you may have open -- your browser, the file explorer, and whatever else was open on your desktop.  At this point, it's the *topmost* program on your screen, and it has focus.  When you hit keys on the keyboard, you'll be typing into the IDE and not your web browser.

2) Now, click on your file explorer once more and open notepad.  Start typing with the keyboard and watch as the letters appear in the notepad text area, rather than in QB64's IDE.  Notepad is now the topmost program and has focus, so QB64 has lost it.

Now let's say you have a program that you might want to respond differently, regarding whether it has focus or not.  How do you detect whether your program is the focus of the user, or not?

With _WINDOWHASFOCUS.  (Well, at least for Windows and Linux users.  The keyword is not yet supported on MAC, according to our wiki currently.)

Example from the wiki:
 
DO
    IF _WINDOWHASFOCUS THEN
        COLOR 15, 6
        CLS
        PRINT "*** Hi there! ***"
    ELSE
        COLOR 0, 7
        CLS
        PRINT "(ain't nobody looking...)"
    END IF
    _DISPLAY
    _LIMIT 30
LOOP


A simple example, where the program will PRINT "*** Hi there! ***" on the screen if the window has focus, and will print "(ain't nobody looking...)" when it doesn't.

QB64 Wiki Entry: _WINDOWHASFOCUS - QB64 Phoenix Edition Wiki
Reply
#2
Might this one encounter a racing problem?

Sometimes I do a compile and Run and new .exe Window has focus for moment and then blinks back to IDE. Seems rare and random.
b = b + ...
Reply
#3
(11-09-2022, 04:42 PM)bplus Wrote: Might this one encounter a racing problem?

Sometimes I do a compile and Run and new .exe Window has focus for moment and then blinks back to IDE. Seems rare and random.

Maybe right at start up.  QB64 is rather odd in how it starts.  If you notice, we first pop up a console window for just a few moments -- at that point, we have a window handle which is a console handle.  Then we close that initial console and we still have the old handle, with no screen whatsoever.  Then we swap to the screen the user specifies at start up (usually with a SCREEN _NEWIMAGE() statement), and it takes just a moment for windows to register and return this new window handle to us...

So *anything* to do with window handles can get themselves lost in just about any of those moments at start up.  

Do we have a window handle?  Sure do!  We have one from the moment the first console window is created.

Is it a *VALID* handle?  Maybe.  Are we still at the stage where that console window is up and viable?  Has it closed already?  If it's closed, and we haven't gotten back the new handle from the OS for the new window yet, then we've got a dead handle now that basically goes nowhere.  Trying to get _WINDOWHASFOCUS on that dead handle is either going to return a zero -- "Nope, can't have focus on a closed window!" -- or else it's going to give some false result.  "Sure, this console is still in focus!  We haven't registered it closing yet!"

What I've found to be good advice:  When starting your program for the first time, place a small _DELAY once in your program before the *FIRST* command which may rely upon any form of a window handle.  Give the OS time to make that console, close it, and then create and register the window we're actually going to be working with.  You don't need a long delay -- usually _DELAY 0.2 is more than enough for the programs which I've written in the past.
Reply
#4
Ah, focus problems, something the laptop musician must deal with regularly!

Then again, people complain about any modal dialogs. In a few programs I used way back on WindowsXP the "open" file dialog wasn't modal and sometimes it could hide behind the "parent" program which could cause a nasty crash. It always surprised me when I discovered an "orphan window" asking me to pick a filename. :/

The focus thing came up as recently as last month when I wanted to install Fedora and needed to use a Spanish keyboard to place an accented vowel somewhere in "real user's name" field. The "Anaconda" installer does provide a way to switch keyboards in this need, but I felt better opening "gucharmap" and copying the vowel from there and then pasting. The "Calamares" and the Ubuntu installer a lot like it aren't modal neither but might like less being focused away.

I should use this function to rewrite an utility very much like Pete's which gets text data from the clipboard and pastes it into a different application. "You have five seconds to switch windows!" message on QB64 user program screenie otherwise. LOL I've relied a bit too much on that user program out of QB64 v0.98 32-bit.
Reply
#5
The real need here is to get something Windows is very poor at doing, forcing a window to be active. Spriggsy and I both found slightly different methods with a common requirement. You have to write code to minimize the window and restore it. Doing that forces it active. The downside is the slight loss of window effect or the effect of seeing the window go to the task bar and back. I mention the two visuals because you could hide the window before minimizing it, which gets rid of the task bar trip effect. Anyway, this was the way I got the TCP/IP messenger app user friendly.

Pete
Reply
#6
(11-10-2022, 12:00 AM)Pete Wrote: The real need here is to get something Windows is very poor at doing, forcing a window to be active. Spriggsy and I both found slightly different methods with a common requirement. You have to write code to minimize the window and restore it. Doing that forces it active. The downside is the slight loss of window effect or the effect of seeing the window go to the task bar and back. I mention the two visuals because you could hide the window before minimizing it, which gets rid of the task bar trip effect. Anyway, this was the way I got the TCP/IP messenger app user friendly.

Pete

https://staging.qb64phoenix.com/showthre...44#pid8744 -- Was this not what you were looking for?
Reply
#7
I'm totally enjoying this keyword of the day series.  Keep 'em coming !
Reply
#8
(11-10-2022, 12:35 AM)SMcNeill Wrote:
(11-10-2022, 12:00 AM)Pete Wrote: The real need here is to get something Windows is very poor at doing, forcing a window to be active. Spriggsy and I both found slightly different methods with a common requirement. You have to write code to minimize the window and restore it. Doing that forces it active. The downside is the slight loss of window effect or the effect of seeing the window go to the task bar and back. I mention the two visuals because you could hide the window before minimizing it, which gets rid of the task bar trip effect. Anyway, this was the way I got the TCP/IP messenger app user friendly.

Pete

https://staging.qb64phoenix.com/showthre...44#pid8744 -- Was this not what you were looking for?

No unfortunately, it doesn't . That's a persistency routine. I already have a couple of methods I've coded in the past to keep a window persistent (on top) which is what your snippet does. It's a whole different shooting match forcing it to be "active." Try your routine, and click an open window running on your desktop. Your window is coded to stay on top but the focus will be on the other window you clicked. With the min/restore trick, you can keep your app in focus. Windows devs should have created a simple way to achieve that effect, without minimizing and restoring. SetActiveWindow just doesn't cut it as far as my research discovered. I get it, they probably feel the user should determine the active window, not a process.

Thanks for taking a shot at it though though,

Pete
Reply
#9
(11-10-2022, 01:20 AM)Pete Wrote:
(11-10-2022, 12:35 AM)SMcNeill Wrote:
(11-10-2022, 12:00 AM)Pete Wrote: The real need here is to get something Windows is very poor at doing, forcing a window to be active. Spriggsy and I both found slightly different methods with a common requirement. You have to write code to minimize the window and restore it. Doing that forces it active. The downside is the slight loss of window effect or the effect of seeing the window go to the task bar and back. I mention the two visuals because you could hide the window before minimizing it, which gets rid of the task bar trip effect. Anyway, this was the way I got the TCP/IP messenger app user friendly.

Pete

https://staging.qb64phoenix.com/showthre...44#pid8744 -- Was this not what you were looking for?

No unfortunately, it doesn't . That's a persistency routine. I already have a couple of methods I've coded in the past to keep a window persistent (on top) which is what your snippet does. It's a whole different shooting match forcing it to be "active." Try your routine, and click an open window running on your desktop. Your window is coded to stay on top but the focus will be on the other window you clicked. With the min/restore trick, you can keep your app in focus. Windows devs should have created a simple way to achieve that effect, without minimizing and restoring. SetActiveWindow just doesn't cut it as far as my research discovered. I get it, they probably feel the user should determine the active window, not a process.

Thanks for taking a shot at it though though,

Pete

Took a second shot at what you were looking for....  Too bad it appears I've only got it configured for my old shotgun and not your six-shooters!!  For Pete -- Keeping a window topmost and active (qb64phoenix.com)
Reply
#10
Been there tried a bunch of stuff like that, works once or inconsistently. Researched it a bit, too, but nothing consistent other than the min/restore hack I mentioned.

Pete
Reply




Users browsing this thread: 3 Guest(s)