Managing window size with respect to the taskbar - winapi

How can I resize my application's window when the taskbar's size has changed?
For example, when the taskbar has been reduced in size my window should increase in size to fill up the hole that was created. My window should never overlap the taskbar.
I was able to create the window in the correct place by calling CreateWindowEx with a position derived from calling SystemParametersInfo(SPI_GETWORKAREA, 0, &rectWorkArea, 0);
Now, when I increase the taskbar's size my window's size decreases automatically
without any code. But when I "go back", my window remains in its current position. How can I fix this?

Not judging if it is good or wrong idea (as standard applications just don't do it), I think it can be tracked by handling WM_SETTINGCHANGE in any top-level window.

Related

How to stop OpenGL from pausing when the window is out of focus or resizing?

I'm trying to prevent my rendering from stopping when my window is out of focus or resizing. In addition to the resizing, if I resize my window smaller, then bigger again anything that wasn't visible when it was smaller is now black. Is there any way to fix this?
There are really two distinct things going on here. The moving/resizing problem is caused by the windows DefWindowProc function which applications use to handle messages that aren't explicitly handled by the application itself. In the case of moving or resizing, it blocks, creating a new message queue to handle most messages, but there are a few that it will still dispatch to the application's main event queue, like WM_TIMER. You can find lots more information in this answer.
The second issue is that your program only "owns" the pixels inside your window, and only those that are not covered up by other windows. When you make the window smaller, the pixels at the edge need to be overwritten to show the window border or whatever's behind the window. When the window is made bigger, some drivers automatically set the newly acquired pixels to black, while others leave them at whatever they were before (usually part of the window border). The OS doesn't remember if those pixels had some specific color the last time the window was that size, because most of the time the program doesn't care. Instead, windows sends a WM_PAINT message to indicate that the application should redraw the window. Your program should either directly handle this, or use a library like GLFW that abstracts it. In addition, you need to handle resize events by calling glViewport with the new size of the window.

Bind Window to Another Window and always on Top

I need to create a Small Window that is bound to the Big Window.
Big window is a window of another process.
When Big window moves the Small window moves too.
When Big window comes to top then Small window comes too.
Small window should be always on top relatively to Big window.
What is the proper way to do that?
The best way is to inject a DLL into that process, subclass and handle the WM_MOVING windows message. It can stay on top using a normal SetWindowPos() call.

Getting the size of a minimized window

I never knew this, but apparently:
By default, the system reduces a
minimized window to the size of its
taskbar button and moves the minimized
window to the taskbar. A restored
window is a window that has been
returned to its previous size and
position, that is, the size it was
before it was minimized or maximized.
In an application, we want to save the position/size of various windows at exit. This leads to a problem for minimized windows. Our solution is to restore all windows before running the save-state logic, but that just seems hacky. Is there a better way?
How about using GetWindowPlacement?
That returns a WINDOWPLACEMENT structure that contains information about the window's coordinates in the restored position.
Remember that (as Leo Davidson points out in the comments) that you must respect the difference between workspace and screen coordinates. As the WINDOWPLACEMENT documentation explains:
The coordinates used in a
WINDOWPLACEMENT structure should be
used only by the GetWindowPlacement
and SetWindowPlacement functions.
Passing workspace coordinates to
functions which expect screen
coordinates (such as SetWindowPos)
will result in the window appearing in
the wrong location. For example, if
the taskbar is at the top of the
screen, saving window coordinates
using GetWindowPlacement and restoring
them using SetWindowPos causes the
window to appear to "creep" up the
screen.
Or, the simpler solution that I've no doubt used before is just to check if the window is minimized before saving the state, and if it is, skip saving any state information.
As far as explaining why a window changes its size when it gets minimized, Raymond Chen's blog entry (and the linked entry as well) on the subject is mandatory reading. They don't really change to their taskbar button's size, but rather to a pre-defined size of 160x31. He explains that you can see this by minimizing a MDI child window into its parent—that's really its size.
Handle WM_SIZE message. If wParam is not SIZE_MAXIMIZED or SIZE_MINIMIZED, keep window size and position in some varibles. Use these variables when window is closed.

WM_GETMINMAXINFO, the ptMaxSize not having any effect

In handling a WM_GETMINMAXINFO message, I attempt to alter the parameter MINMAXINFO structure by changing the ptMaxSize. It doesn't seem to have any effect. When I receive the WM_SIZE message, I always get the same value, no matter whether I increase or decrease the ptMaxSize in the WM_GETMINMAXINFO.
Are you sure your window is maximized? As per http://msdn.microsoft.com/en-us/library/ms632605(VS.85).aspx, MINMAXINFO::ptMaxSize controls the maximum size of the window wen maximized.
If you want to control the maximum tracking size of your window (the maximum size when the window is normal), you need to modify MINMAXINFO::ptMaxTrackSize.
Make sure you are handling the WM_GETMINMAXINFO message in the window procedure of the main application.
The message only makes sense when handled by the main frame window and will have no effect if the message is handled by one of the child window procedures.
A window must have the WS_THICKFRAME or WS_CAPTION style to receive WM_GETMINMAXINFO.
This is basically all you need to know.

Auto-Hide taskbar not appearing when my application is maximized

My application draws all its own window borders and decorations. It works fine with Windows taskbars that are set to auto-hide, except when my application window is maximized. The taskbar won't "roll up". It will behave normally if I have the application not maximized, even when sized all the way to the bottom of the screen. It even works normally if I just resize the window to take up the entire display (as though it was maximized).
I found the problem. My application was handling the WM_GETMINMAXINFO message, and was overriding the values in the parameter MINMAXINFO record. The values that were in the record were inflated by 7 (border width) the screen pixel resolution. That makes sense in that when maximized, it pushes the borders of the window beyond the visible part of the screen. It also set the ptMaxPosition (point that the window origin is set to when maximized) to -7, -7. My application was setting that to 0,0, and the max height and width to exactly the screen resolution size (not inflated). Not sure why this was done; it was written by a predecessor. If I comment out that code and don't modify the MINMAXINFO structure, the Auto-hide works.
As to why, I'm not entirely sure. It's possible that the detection for popping up an "autohidden" taskbar is hooked into the mechanism for handling WM_MOUSEMOVE messages, and not for WM_NCMOUSEMOVE. With my application causing the maximize to park my border right on the bottom of the screen, I would have been generating WM_NCMOUSEMOVE events; with the MINMAXINFO left alone, I would have been generating WM_MOUSEMOVE.
This is dependant on whether 'Keep the taskbar on top of other windows' is checked on the taskbar properties. If it's checked then the taskbar will appear.
But don't be tempted to programmatically alter this setting on an end users machine just to suit your needs, it's considered rude and bad practice. Your app should fit whatever environment it gets deployed to.

Resources