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

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.

Related

Minimize to tray on MacOSX

Good morning, in my application on MacOSX I want to give the user the option "minimize to tray". I use Qt5 and I rewrote the
changeEvent(QEvent *event)
function. There I do something like
switch( event->type() )
{
case QEvent::WindowStateChange:
{
if ( this->windowState() & Qt::WindowMinimized ) {
if( *option minimize to tray enable* ) {
event->ignore();
QTimer::singleShot(0, this, SLOT(hide()));
}
}
break;
}
default:
break;
}
Well, it works on Linux and Windows but the problem is that in MacOSX this code does not work properly and creates a bug. Indeed the window is still minimized in the taskbar (apart from the dock) and furthermore, if the window is resized from the taskbar instead of the tray icon, the GUI is blocked and does not change. The GUI can still send signals but it can not change. I have to reshow the window from the tray icon to unblock the GUI.
Then the question: How can I avoid to minimize the Window in the TaskBar on MacOSX?
Another related question: I have read some forum where some user speaks about a "standard behaviour" in MacOSX, as for example not to close the application when the "x" button is clicked, or not to use tray icon ecc. ecc.... Someone can post a official link how an application should behaves in MacOSX?
Thanks very much to everyone
Well, I don't know Qt, but I know Cocoa quite well. Speaking in terms of the Objective-C API, your hide() call is probably doing the equivalent of -orderOut:. Unfortunately, -orderOut: doesn't work properly for minimized windows. It leaves a "ghost" window in the Dock, which can be unminimized to an actual ghost window. That is, it's just an image of the window, it's not the actual live window.
It does work to call -close. I don't know what the Qt equivalent would be. You have to be careful to avoid some of the secondary consequences that -close has beyond those of -orderOut:, though. For example, some windows are set to release themselves on close, which you'd want to disable. Also, the window delegate's -windowWillClose: method will be called and it should do nothing for a not-really-closing call.
Don't worry that "closing" is more severe or permanent than "hiding" or "ordering out". It's really much the same thing, other than the above-mentioned additional consequences. For example, it is still possible to re-show a window that's been closed, etc.
The question is, does Qt give you the flexibility to do it. Alternatively, this can be considered a bug in Qt, that its hide() implementation uses -orderOut: rather than -close on minimized windows.
Finally, I'll ask if you really want to implement this feature. It's going to confuse users. When you minimize a window, it animates the minimization to the Dock. That gives the user a strong impression of where to find the window. If the window is not subsequently found where it went, the user is not going to know to look elsewhere. Likewise, Exposé/Mission Control shows users the minimized windows of an app in addition to the normal windows. Your supposedly minimized-to-tray windows won't show up there because they're no longer really minimized.
Perhaps just disable minimization. Have the user simply close the window when they're done with it and re-open it from your status item menu.

Why does my Windows app get focus when by rules it should not?

By now everyone writing for Windows probably knows that applications cannot (officially) steal focus from foreground processes, and why. But I have just managed to steal focus, inadvertently, and don't understand how this is even possible.
I have a Delphi app that user brings up with a hotkey (or by a mouse click, or by Alt+Tab), selects a piece of text and hits Enter. My app then minimizes (hides to the tray, even), and pastes the text user just selected into the active window. Nothing new here, plenty of similar projects out there - clipboard extenders, glossaries, macro programs, etc.
What is puzzling to me is that after doing all the above and then sleeping for 1500 ms, I restore my main form and it gets the focus back! It becomes the foreground window, even though it wasn't 1500 ms ago (tested; Windows 7 32-bit.).
In fact, I don't want this at all, so before restoring my main form I record which window has foreground and I give it back to that window after it's been given to me. I'm just curious why my app gets to be in the foreground when by rules it should not. Maybe I don't understand the rules as fully as I thought I did?
If you look at the documentation for SetForegroundWindow you see a list of conditions for the call to succeed, one of them is "The process received the last input event." So if the user does not do anything after pressing enter in your app you still have the right to steal focus. I don't know if Delphi calls SetForegroundWindow for you when the window is restored but it might be something to look into.
I don't know how you restore your window but using SW_SHOWNOACTIVATE with ShowWindow might help...

Win32API How can my window follow to existing window

To all Win32 professionals. Let's say we have completed existing application with window. The task is to write another application with (my) window. My window must always align its left edge to existing window right edge while user moves existing window across the screen (my window not allowed to move by user).
Precondition: a) Existing window can not be subclassed b) Windows hooks are not a case.
Yes, looks right. I'd not asked this question if it not become a problem. Forgot to say that OS is Vista 2, application is IE. I try to make an application that follows IE main window, align it edge. Subclassing of IE not allowed, and SetWindowsHook not works correctly under regular user (when user have admin privileges application works normally). Such way as all of you talking about works under Windows prior to Vista.
And looks like there is no trivial way to solve this task. Thank you all.
I think you can't without a hook. SetWindowLong allows you to set a WndProc, but this won't work if the window belongs to a different application.
If you dont want/cant subclass or set global hooks, you can look into the following:
Implement your code in a DLL
Call CreateRemoteThread on LoadLibrary's address and your DLL's name to inject your DLL into the target process
In the DLL's DllMain, you can SetWindowHook just on the thread that owns the window. This is a local hook and doesn't require special privileges and is very nice to the system.
In your hook function, process WM_WINDOWPOSCHANGED on the main window's HWND and adjust your window accordingly.

Mac style menus on Windows, system wide

I'm a Mac user and a Windows user (and once upon a time I used to be an Amiga user). I much prefer the menu-bar-at-the-top-of-the-screen approach that Mac (and Amiga) take (/took), and I'd like to write something for Windows that can provide this functionality (and work with existing applications).
I know this is a little ambitious, especially as it's just an itch-to-scratch type of a project and, thanks to a growing family, I have virtually zero free time. I looked in to this a few years a go and concluded that it was very difficult, but that was before StackOverflow ;)
I presume that I would need to do something like this to achieve the desired outcome:
Create application that will be the custom menu bar that sits on top of all other windows. The custom menus would have to provide all functionality to replace the standard Win32 in-window menus. That's OK, it's just an application that behaves like a menu bar.
It would continuously enumerate windows to find windows that are being created/destroyed. It would enumerate the child windows collection to find the menu bar.
It would build a menu that represents the menu options in the window.
It would hide the menu bar in the window and move all direct child windows up by a corresponding pixel amount. It would shorten the window height too.
It would capture all messages that an application sends to its menu, to adjust the custom menu accordingly.
It would constantly poll for the currently active window, so it can switch menus when necessary.
When a menu hit occurs, it would post a message to the window using the hwnd of the real menu child control.
That's it! Easy, eh? No, probably not.
I would really appreciate any advice from Win32 gurus about where to start, ideas, pitfalls, thoughts on if it's even possible. I'm not a Win32 C++ programmer by day, but I've done a bit in my time and I don't mind digging my way through the MSDN platform SDK docs...
(I also have another idea, to create a taskbar for each screen in a multi-monitor setup and show the active windows for the desktop -- but I think I can do that in managed code and save myself a lot of work).
The real difference between the Mac menu accross the top, and the Windows approach, is not just in the menu :- Its how the menu is used to crack open MDI apps.
In windows, MDI applications - like dev studio and office - have all their document windows hosted inside an application frame window. On the Mac, there are no per-application frame windows, all document windows share the desktop with all other document windows from other applications.
Lacking the ability to do a deep rework of traditional MDI apps to get their document windows out and onto the desktop, an attempt, however noble, to get a desktop menu, seems doomed to be a novelty with no real use or utility.
I am, all things considered, rather depressed by the current state of window managers on both Mac and Windows (and Linux): Things like tabbed paged in browsers are really acts of desperation by application developers who have not been given such things as part of the standard window manager - which is where I believe tabs really belong. Why should notepad++ have a set of tabs, and chrome, and firefox, and internet explorer (yes, I have been known to run all 4), along with dev studios docking view, various paint programs.
Its just a mess of different interpretations of what a modern multi document interface should look like.
The menu bar on a typical window is part of the non-client area of the window. It's drawn when the WndProc gets a WM_NCPAINT message and passes it on to DefWindowProc, which is part of User32.dll - the core window manager code.
Other things that are drawn in the same message? The caption, the window borders, the min/max/close boxes. These are all drawn while processing a single message. So in order to hide the menu for an application, you will have to take over handling of this message, which means changing the behavior of user32.dll. Hiding the menu is going to mean that you become responsible for drawing all of the non-client area.
And the appearance of all of these elements - The caption, the borders, etc. changes with every major version of Windows. So you have to chase that as well.
That's just one of about a dozen insurmountable problems with this idea. Even Microsoft probably couldn't pull this off and they have access to the source code of user32.dll!
It would be a far less difficult job to echo the menu for each application at the top of the screen, and even that is a nearly impossible job. When the menu pops there is lots of interaction with the application during which the menu can be (and often is) changed. It is very common for applications to change the state of menu items just before they are drawn. So you will have to replicate not only the appearance of the menus, but their entire message flow interaction with the application.
What you are trying to do is about a dozen impossible jobs all at once, If you try it, you will probably learn a lot, but you will never get it to work.

How may a Window be "pinned" to the desktop surface?

This question is more academic than practical and doesn't involve any one specific language. For the sake of discussion, we'll use Win32 API.
What is the most appropriate way to create a window with the following behavior goals:
Z-Order is lower than every other window except the desktop surface.
Cannot be made to appear on a higher z-order than other windows through mouse or keyboard clicks.
Assumption may be made that the window is borderless.
There are two basic approaches here :-
make your window the 'child' of the desktop.
make your window simply refuse to accept focus or activation :-
The wonder of the windows window manager is that there isn't one. Rather, there is an appearance of a window manager as a result of the emergent behavior of all the windows in the system - namely how they react to messages - which in 99% of cases is handeld by DefWindowProc.
Which means that you can subvert a lot of normal window manager type behaviour by handling messages before DefWindowProc. If you create a window, and position it using the relevent flags at the bottom of the z-order with SetWindowPos, and then handle messages like WM_WINDOWPOSCHANGING, you can ensure that your window never receives activation or focus and always - even when other apps call SetWindowPos - always has the z-bottom flag set.
both approaches are problematic as its very difficult to find out what the desktop window is. GetDesktopWindow returns a handle to a window that is only ever visible if explorer crashes. The rest of the time, the visible desktop is a window created by explorer - ultimately a syslistview control. Spy++ + Findwindow will get you a handle to the window you want to be above.

Resources