Closing window rather than withdraw TCL - window

I am using a graphic user interface builder for Tcl/Tk called "GUI Builder (Komodo Pro)". I have built three different windows that will each be opened after the respective button is clicked. I have managed to get the windows to open and "withdraw", but the process remains open in the background. If the user opens enough windows the program will crash due to the large number of windows.
My question is how can I get the window to fully close, instead of withdraw, thereby save some of the computers memory and process power?

When you click on the window manager close button for a window (which varies a bit in style, but is often a red “X”) Tk ends up receiving a WM_DELETE_WINDOW protocol event (non-X11 platforms are translated to this inside the lower levels of Tk). Tk then responds to this for that window in “the appropriate way”.
By default, windows are destroyed when a WM_DELETE_WINDOW is sent to them; this is the right thing to do in the simple case. You can also explicitly enable this by doing:
wm protocol $toplevel WM_DELETE_WINDOW [list destroy $toplevel]
You wouldn't normally bother with that; the default (which is what happens when you've got an empty handler) has the same effect.
Alternatively, you can make the window withdraw (wm withdraw $toplevel instead of destroy $toplevel) or iconify (wm iconify $toplevel) or even pop up a dialog to check whether the user is really sure about that.
Tk-enabled applications normally exit once they enter the main event loop with all toplevel windows are closed. In the simplest case (only one Tcl interpreter with Tk loaded) this is the same as saying that the application stops once the . window is destroyed. However, I'm not entirely sure if this is true if you run the Tk application in tclsh by doing package require Tk (there's magic in the code to integrate Tcl and Tk). The best way to find out whether things go away right is to test for yourself; it should only take a moment…

Related

Intercepting a window's attempt to steal global focus on Windows

I'm a developer and a long-time Windows user with an obsession about making my system as convenient to use as possible.
Yesterday I thought about something that has always annoyed me in Windows and that I've taken for granted, and I realized that I have a better idea for how it could work, and I'm now wondering whether it's possible to tweak Windows to work like that.
The thing that annoys me is when windows steal focus. For example, I could be running an installer for some program. While it's working, I'll switch to my browser and browse, maybe entering some text into an email in my browser. Then suddenly the installer finishes and its window steals the focus. Now I'm in the middle of writing an email, so I might press a key that happens to be bound to a button on that installer, and then that button gets invoked, doing some action that I never intended to happen!
This is doubly annoying to me because I'm using a multiple-desktop program called DexPot, and when a window steals focus, it also brings itself to the desktop I'm currently on, which can be really annoying, because then I have to put it back into its original desktop.
How my ideal solution to this problem would work: Every time a window tries to steal focus, we intercept that, and don't let it. We show something like a toaster message saying "Foobar installer wants focus, press Win-Whatever to switch to it". If and when you press the key combo, it switches to the window.
The question is: Is there an easy way to tweak Windows to make this happen? I know very little about Windows programming. I do know AHK and if it's possible with that, that'd be great.
No, there isn't an easy way to add this behavior, but Windows tries to do this automatically.
In theory apps shouldn't be able to steal the foreground while you're actively using another app. Unfortunatly there are some scenarios where Windows can't tell the difference between legitimate user actions that should change the foreground and unwanted foreground-theft. The window manager generally tightens up the holes a bit with each new version of Windows, but also needs to make sure that apps can come to the foreground when the user wants them to, even if that desire is expressed indirectly.
For example, a process launched by the current foreground process can put a window into the foreground. This is necessary so that when a user launches a window from Explorer the newly launched process can open its main window. This permission only lasts until the next user input, so if an application is slow to launch and you start working on an email the app may lose its foreground permissions before it can use them.
See the SetForegroundWindow function documentation for a list of requirements for a process to be able to set a window into the foreground.
There are also apps which specifically make use of these requirements to steal the permission (by joining the foreground queue or synthsising user input to themselves), but I suspect in your installer scenario it is accidental.
I'm not sure what exactly is going on, but I suspect that the problem comes from the installer running as a service and accidentally stealing the foreground permission when it tries to launch the app on your current desktop.
It would be theoretically possible for an external process to hook into the foreground system to override this and show your confirmation toast, but it would be tricky to get right and would require significant low level code (I'd probably start with a CbtHook). It would not be possible in a scripting package like AHK (assuming you mean AutoHotKey) but would need to be native C/C++ code injected into every running process.

How to write a program that runs another GUI program inside it

I am not sure how to ask the question so here is a picture of some idea that came to mind
So for example, when you run my "custom launcher" it displays a window with a couple buttons on the side which you can assign values to. When you click on a button, the appropriate program will run in the big panel on the right (in window mode).
This is all from the user's perspective of course. They will just see that the program they want to run appears in that panel. The actual implementation may have nothing to do with "one program running inside another program"
My own use case is limited to windows desktop platforms only, but if it is possible to generalize it that would be nice as well.
Is this actually possible? Can I write such a program that will run another program inside a panel? The program that's launched may be someone else's, such as MS paint or calculator.
Just to expand on my comment above, here is an approach that may work for you: Fake it :)
When you launch the program, intercept all windows messages to the program that control it's position on screen. That way it 'appears' to be fixed in place, but in reality it's still attached to the normal Windows desktop.
Here's some light reading for you:
Windows Event Hooks
A hook is a mechanism by which an application can intercept events,
such as messages, mouse actions, and keystrokes. A function that
intercepts a particular type of event is known as a hook procedure. A
hook procedure can act on each event it receives, and then modify or
discard the event.
I would recommend against it in a commercial application because you are modifying the behavior of software you don't own - that software may make assumptions about what its parent window is, but for experimentation there's the SetParent Win32 function.

Win32 C++ - Do something when window is restored, which message?

So, I have a dialog based application using pure WinAPI. There is a main dialog, and then multiple other dialogs that are toolwindows. These toolwindows are meant to free-float around, the user can drag them, hide them, and show them, but they have no taskbar entry. This is what I intended, but the problem is, when I switch from the main window to a different application, then click on the taskbar entry for the main window, the main window will show up, but the toolwindows will not. They stay hidden behind the main window and sometimes windows of other applications, and you cannot use them until you move all of the top-most windows and hunt down the toolwindow.
So, what I'm trying to do to work around this is, when the user restores the window from being minimized, I want to enumerate through all of the tool windows and bring them to the front, maybe by calling SetActiveWindow().
But what message gets sent when the window is restored? I was thinking WM_SHOW, or WM_RESTORE, but they don't exist.
Another question, and if you answer this the first question is irrelevant because I will no longer need to use that workaround: Is there a better method of bringing all tool-windows to the front?
Give the tool windows the WS_POPUP style (and not WS_OVERLAPPED), and make the main window their parent (strictly it is their owner window). That way the tool windows will remain on top of the main window. This may (or may not) be what you want.
The naive answer to the question is to listen to WM_SIZE and respond to a wParam value of SIZE_RESTORED.
The other obvious possibility is to make all the tool windows be owned by the main window. So long as you are happy for the tool windows always to be on top of the main window, this will solve your problem. The owned windows will be hidden when the owner is minimized, and re-shown when the owner is restored.
Learn more about ownership in the MSDN topic on Window Features.

Window hooks and applications

Related to my question here, is it possible to create a window hook that will monitor if an application has been opened or not?
Most that I have found about hooks seem to focus on user input (keyboard press, mouse events), but I could not confirm if it is possible to know that the "double click" the user made is to open an application, or just to highlight a word.
Thank you.
Indeed, window hooks would not be sufficient. In fact for the task you are asking about you could use various strategies, such as:
enumerating the processes to find the one you're looking for (Tool Help API or PSAPI)
enumerating the top-level windows on the desktop (but you're limited to your desktop then)
check for a global or local event, mutex (or other kernel object) to deduce from that that some instance of the application is running
... or even from kernel PsSetCreateProcessNotifyRoutine
probably there are variations on the above plus some more.
In essence the question is whether you want to check for the process or for some other indicator that signifies whether the program you want to check for has been started.

OS X design decisions. Terminate the app on last window close?

Unlike Windows, GNOME and most other GUI's, OS X application programs do not all terminate if the main window (or all the windows) of that application are closed.
For example, fire up Firefox, Safari, Word, or most document based apps. Either click the red dot in the corner or type cmdW to close the window. You can see that the menu of that program is still active, and the program is still running. With OS X newbies, sometimes you will see dozens of these windowless zombies running and they wonder why their computer is getting slower.
With some document based programs, there is some sense to not terminating the application if it has no windows. For example, with Safari or Word, you can still type CmdN and get a new document window for whatever that application was designed to do: browse the web (Safari) or type a new document (Word).
Apple is mixed with their design philosophy on this. Some close on the last window closed and some do not. Third party apps are even more mixed.
There are other apps that do close when their red close button is clicked. System Preferences, Dictionary, the Mac App Store, iPhoto and Calculator do terminate when the sole or last window is closed. iCal, Address Book, iTunes, DVD Player do not terminate.
What I find particularly annoying is the applications that do not have a logical "New Document" or "Open" function yet they do not terminate when the document window is closed. Example: fire up iTunes or Address Book and terminate the main window. There sits a zombie with no window and no function other than manually selecting "Quit".
It is easy to close the application after the last window closes. Cocoa even gives you notification of that event. Just add this to your application delegate:
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
return YES;
}
My question is this: Is there any reason I should NOT terminate my application after the last window closes? Why is this so variable on OS X software? Unless the app has a "new" or "open" or some other clearly understood reason to not terminate with no window open, the failure to terminate seems like a bug to me.
Per Apple's Human Interface Guidelines (a guide for Mac developers):
In most cases, applications that are
not document-based should quit when
the main window is closed. For
Example, System Preferences quits if
the user closes the window. If an
application continues to perform some
function when the main window is
closed, however, it may be appropriate
to leave it running when the main
window is closed. For example, iTunes
continues to play when the user closes
the main window.
In general, never close a document based application when the last window closes. The user will expect to be able to open a new document without relaunching the application, and it will confuse them if they can't.
For non-document based applications, you need to consider a few things:
How long does it take for my application to open? If it takes more than a second, you should probably not quit.
Does my application need a window to be useful? If your application can do work without windows, you should not quit.
iTunes doesn't quit because, as Anne mentioned, you don't need a window to play music (question 2). It is also not based on Cocoa, so it is much more difficult to close after the last window, especially since it allows you to open windows for specific playlists so there are an indefinite number of possible windows to be open.
In my opinion, Address Book does not need to stay open. This could be a left-over design decision from older versions of OS X, or it could be that someone at Apple just thought it was better to leave it open (maybe so you can add a contact?). Both iTunes and Address Book provide access to their main interfaces through the Window menu, as well as a keyboard shortcut (Option+Command+1 for iTunes, Command+0 for Address Book).
The main iTunes window can be reopened from the 'Window' menu. Mail.app has similar behavior. I can't think of any applications that close when the last window is closed, and as such I don't think there's a good reason that your app should behave that way (in fact, i'm surprised its not in Apple's user experience guidelines, it would really bother me!).
One reason why you'd want to close e.g. the iTunes main window but keep the app open is to be able to use the app as sort of a server for third party scripts/applications. I rarely use the main iTunes interface, but instead control my music with a third party app. I also write AppleScripts for other apps that I launch instead of interacting with that app's interface.

Resources