My program needs to arbitrarily maximize any window on the current desktop. I achieve this by calling ShowWindow(hWnd, SW_MAXIMIZE), where hWnd is the HWND of the window I want to maximize. When that line of code executes, the window in question (here, Notepad) looks like this:
Everything seems fine, except for the fact that the window has not been positioned correctly, i.e. the window seems to be a few pixels to low, and the title bar does not look "squashed" like it should. Compared to how it should look when the maximize button is clicked, the problem is clearly visible:
Does anyone know why this behaviour occurs, and what I can do to fix it?
Telling the window to maximize itself might bypass some internal adjustments that the program makes when it maximizes via a system menu command. To emulate clicking on the maximize button, send it a SC_MAXIMIZE command:
SendMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
Antoher way to use SetWindowPos(); For example you got HWND handleWnd;
RECT rcWnd;
GetWindowRect(handleWnd,&rcWnd);
SetWindowPos(handleWnd,WHND_TOP,rcWnd.left,rcWnd.top,(rcWnd.right-rcWnd.left),(rcWnd.bottom-rcWnd.top),SWP_SHOWWINDOW);
So you got your previous position, place window on top of Z and show
Related
I have seen several tools adding a custom button and/or drawing on the title bar of all windows of all applications in Windows. How is that done?
Extra points for an example in Delphi.
EDIT:
I found something for dotNET that does this:
http://www.thecodeking.co.uk/2007/09/adding-caption-buttons-to-non-client.html#.VdmioEDenqQ
How I see this job:
First of all we should be able to paint this button on the our own window caption. This procedure will be used later
This part of the program enumerates the active and visible windows
This part of the program using injection attach our dll to enumerated windows
From injected dll we can draw the button on the window caption
Inside this dll we should process the click on the button
We should have mechanism to send result to our main program
I haven't done this, so the following is what I would investigate if I were to try:
For each application / each top-level window:
Create a floating window and position it over the title bar wherever you want it to sit. Set up the parent / child relationship, but this window is part of your own process. (There are occasionally problems parenting a window from one process to one from another process, but try. I'd avoid injecting into other processes if possible.)
You can investigate the window flags to see if the window has a title bar (ie if you should add a button) via GetWindowLong with GWL_STYLE looking for WS_CAPTION. The same call will also let you see the type of caption / frame, which you can combine with GetSystemMetrics with, eg, SM_CYDLGFRAME to figure out the right size for your button on this specific window's title bar.
This window is now your button: paint, handle clicks etc as appropriate.
Make it a non-focusable window so that clicks to it don't take focus away from the window is is on the title bar of. You don't want clicking it to make the title bar change colour, for example. Do this by setting the WS_EX_NOACTIVATE window flag, something like: SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) orWS_EX_NOACTIVATE).
The main problem is to keep it positioned correctly when the window moves, is resized, etc. To do this, install a hook for the system move events. You can also hook minimize and restore via EVENT_SYSTEM_MINIMIZESTART and EVENT_SYSTEM_MINIMIZEEND. This will allow you to keep track of all windows moving around onscreen, such that you can adjust the button-window position if necessary.
That gives you a window which you can paint as a button (and respond to clicks etc), that visually is "attached" to other windows so it stays in the same place as the user drags the title bar, minimizes or maximises the app, etc, and that is in your own process without cross-process problems.
I have a window which should pop up on top of any other windows (including the taskbar), stay on top while in focus, and become hidden completely when focus is lost.
To achieve this, I'm handling WM_ACTIVATEAPP with wParam being equal to FALSE. Nevertheless, sometimes the window falls in behind the taskbar, and since it's small, it's wholly overlapped by it. So, no way to reactivate it and take focus back to hide.
So, I'm looking for a way to handle that event, when the window Z-order changed relative to the taskbar one.
Regards,
UPDATE
I'm pointing to the fact, that this is not that type of questions, you know, how to stay on top forever. In fact, otherwise. It's about how to hide the window as soon as possible.
UPDATE 2
I have tried WM_WINDOWPOSCHANGING, but it never received, when I click on the taskbar and overlap my window.
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.
I am facing a little annoying design problem. Not easy to give a title of my question.
I must display two windows, one over another one. The first one is a Cocoa window, the second is made with Qt. In the second window, an action is performed, but the user can choose to close this window. He must fall back on the first window.
To display my first window, which is actually a SFAuthorizationPluginView, I do:
[myview displayView];
then, to display the window made with Qt on top of first window:
QWidget* w = openMyScreen();
NSView* v = (NSView*)w->winId();
[[v window] setLevel:2003];
This works well, however there is a small delay before the second window is displayed. We can thus see for a very short time the first window.
I need that the second window stays on top of the first window, because the user can close the second window and must have access to the first window.
Any ideas on a trick how to hide the first window, just the time, the second window appears?
Thanks in advance
NSDisableScreenUpdates and NSEnableScreenUpdates (link) might be useful in this situation. The documentation says:
You typically call this function so that operations on multiple windows appear atomic to the user.
which seems to describe your situation.
A word of unrelated advice though: Don't go setting window levels willy-nilly. A window level of 2003 will likely cause the window to appear over things like the dock or even the menu bar, which would definitely be strange. You should stick to the standard levels declared in NSWindow.h unless you have good reason. NSFloatingWindowLevel might be appropriate (although I'm not sure what level the SFAuthorizationPluginView window is displayed at).
Starting with MacOS 10.4, you can use :
[NSWindow disableScreenUpdatesUntilFlush];
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.