How to remove TOPMOST attribute from a window - c++

I have a Windows C++ app that creates two separate windows
I need to be able to make one window topmost temporarily, and then later remove that attribute so that other windows can then overlay it.
I've tried this code:
void setWindowAlwaysOnTop(const std::string& windowTitle, bool onTop) {
HWND hwnd = FindWindowA(NULL, windowTitle.c_str());
HWND insertAfter;
if (onTop) insertAfter = HWND_TOPMOST; //set the window always-on-top
else insertAfter = HWND_BOTTOM;
SetWindowPos(hwnd, insertAfter, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
}
But if I have previously called this code with onTop true it doesn't re-allow other windows to overlay the target window after I call it with onTop false.
I've also tried calling the function from the target window itself rather that from a separate window but it still doesn't work.
As far as I can see at https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setwindowpos it should work?
Is that correct, or is there another way of achieving this?

The documentation link that you provide in the question indicates that you should pass HWND_NOTOPMOST to hWndInsertAfter. Of this flag it says:
Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.

Use SetWindowLongPtr.
This function will discard your window styles, but u can restore them, like the example
below:
SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); //Discard WS_EX_TOPMOST
IMPORTANT NOTE:
To write code that is compatible with both 32-bit and 64-bit versions of Windows, use SetWindowLongPtr. When compiling for 32-bit Windows, SetWindowLongPtr is defined as a call to the SetWindowLong function.
Hope this works.

Related

Programmatically hide an application on windows

Is there a way to programmatically hide an application on windows? I want to achieve the same thing as the windows+D shortcut, but for a single application. I want to do this from within that application (application consists of several windows, one of those can't be moved, resized, closed or minimized by the user). Application is written in c++ and uses Qt for the UI.
to do so it's so easy:
1- retrieve the handle to that window:
HWND hChild = GetDlgItem(hWnd, ID_MYCHILD);
2- send to it SW_SHOW either using ShowWindow or via SendMessage:
ShowWindow(hChild, SW_HIDE); // hide
ShowWindow(hChild, SW_SHOW); // show
SendMessage(hChild, SW_HIDE, 0, 0); // hide
SendMessage(hChild, SW_SHOW, 0, 0); // show
if the window doesn't belong to your application then:
1 - retrieve the main window with:
HWND hWnd = GetForegroundWindow(void);
2- use the above to hide/show it
ShowWindow(HwndWindow, SW_MINIMIZE);
Here's the MSDN ShowWindow documentation.
In addition you may find EnumChildWindows useful for finding all these windows if their handles aren't readily available to you.

How do I get a handle to the Start button in Windows 7?

I use:
Hwnd hStart = ::FindWindow ("Shell_TrayWnd",NULL); // get HWND of taskbar first
hStart = ::FindWindowEx (hStart, NULL,"BUTTON", NULL); // get HWND of start button
to get start button's handle. It's running properly on Windows XP,
but in Windows 7, ::FindWindowEx (hStart, NULL,"BUTTON", NULL) always returns 0, and GetLastError() returns 0, too.
Why is that?
In Windows 7 the start button, which has class name "Button", is a child of the desktop window. Your code assumes that the start button is a child of the window named "Shell_TrayWnd" which does indeed appear to be the way the taskbar and start menu were implemented on XP.
For Windows 7 you want to use something like this:
hStart = ::FindWindowEx(GetDesktopWindow(), NULL, "Button", NULL);
Although I think it would be better search for it by name to be sure that you get the right button.
hStart = ::FindWindowEx(GetDesktopWindow(), NULL, "Button", "Start");
I'm not sure how Vista implements its taskbar and start menu, but you can use Spy++ to find out.
Having said all of this, it would be much better if you can find a way to achieve your goals without poking around in such implementation specific details.
::FindWindow (L"Shell_TrayWnd",NULL);
this code is for complete taskbar

What's wrong with this CreateWindowEx function?

Okay, so first a little overview of what I am tryna do..
I am trying to create 3 child window in a main parent window, and use EnumChildWindow and EnumChildProc to enumerate them, I want to create 3 child windows of same height as of parent but 1/3rd width, and align them one after the other..
So, I captured the WM_CREATE msg to create those child window, and WM_SIZE to move and align them using MoveWindow, everything is fine except for the fact that no child window is created. When I debugged it, I found that (in the Autos Window in Visual Studio 2008, while debugging) my CreateWindowEx statement is not getting executed (the autos window said "Expression cannot be evaluated."
Here's the statement:
CreateWindowEx(0, (LPCWSTR)("childClass"), (LPCWSTR)NULL, WS_CHILD | WS_BORDER, 0, 0, 0, 0, hWnd, (HMENU) (int) (ID_FIRSTCHILD + 1), hInst, NULL);
of course I was using it in a for loop to create 3 windows, but that's the other thing...
So, can anyone please help/guide/advice me what is going on in here? Or what am I doing wrong?
ps: I am reading this ebook from where I got this code and all, so please don't ask me to adopt another approach or something, say put the Child creation code somewhere else or so... because I am not making any program, but just following a book's example... :)
My psychic powers suggest you need to pass in the WS_VISIBLE style to the CreateWindow call above for your child windows - so you can seem them. :)
My development experience suggests the following:
What is the return value of CreateWindowEx? Did you assign the return value to a variable. And if so, did you set a breakpoint on that line in the debugger? And if the return value from CreateWindow is NULL, then what is GetLastError (which you can evaluate in the debugger as "#err").
After your main window pops up (with the children invisible), did you run Spy++ to see if the child windows exist? What is their state?
Otherwise, did you validate that the WM_CREATE callback of the WndProc of your child window class is getting called?

How can I check if a window has WS_VISIBLE to set? (or if is visible)

How can I do it? It's an external window, not from my program. Thanks
One nuance to be aware of. IsWindowVisible will return the true visibility state of the window, but that includes the visibility of all parent windows as well.
If you need to check the WS_VISIBLE flag for a specific window you can do GetWindowLong(hWnd, GWL_STYLE) and test for WS_VISIBLE.
... It sounds like you don't need to do this for your case, but adding this for future reference in case others run across this question.
Do you have an HWND to the window? If not, then you will need to obtain the window handle somehow, for example through FindWindow() (or FindWindowEx()).
Once you have the HWND to the window, call IsWindowVisible().

Do you have to register a Dialog Box?

So, I am a total beginner in any kind of Windows related programming. I have been playing around with the Windows API and came across a couple of examples on how to initialize create windows and such.
One example creates a regular window (I abbreviated some of the code):
int WINAPI WinMain( [...] )
{
[...]
// Windows Class setup
wndClass.cbSize = sizeof( wndClass );
wndClass.style = CS_HREDRAW | CS_VREDRAW;
[...]
// Register class
RegisterClassEx( &wndClass );
// Create window
hWnd = CreateWindow( szAppName, "Win32 App",
WS_OVERLAPPEDWINDOW,
0, 0, 512, 384,
NULL, NULL, hInstance, NULL );
[...]
}
The second example creates a dialog box (no abbreviations except the WinMain arguments):
int WINAPI WinMain( [...] )
{
// Create dialog box
DialogBox(hInstance,
MAKEINTRESOURCE(IDD_MAIN_DLG),
NULL,
(DLGPROC)DialogProc);
}
The second example does not contain any call to the register function. It just creates the DialogBox with its DialogProc process attached.
This works fine, but I am wondering if there is a benefit of registering the window class and then creating the dialog box (if this is at all possible).
You do not have to register a dialog box.
Dialog boxes are predefined so (as you noted) there is no reference to a window class when you create a dialog. If you want more control of a dialog (like you get when you create your own window class) you would subclass the dialog which is a method by which you replace the dialogs window procedure with your own. When your procedure is called you modify the behavior of the dialog window; you then might or might not call the original window procedure depending upon what you're trying to do.
It's been a while since I've done this, but IIRC, the first case is for creating a dialog dynamically, from an in-memory template. The second example is for the far more common case of creating a dialog using a resource. The dynamic dialog stuff in Win32 was fairly complex, but it allowed you to create a true data-driven interface, and avoid issues with bundling resources with DLLs.
As for why use Win32 - if you need a windows app and you don't want to depend on MFC or the .NET runtime, then that's what you use.