Identify only application windows from EnumDesktopWindows - c++

This is my very first C++ application. I have absolutely no experience in C++ or Windows application programming so any feedback/help is appreciated. Please let me know if I am making any mistakes or not following best practices in my code.
I am trying to write a C++ program that replicates the behaviour of the WIN + D
keyboard shortcut, but only affects the windows on the monitor with the mouse.
Inspite of checking IsWindowVisible() and IsIconic() there are some system windows that get minimized and maximized, resulting in weird glitches like:
All icons from the desktop get minimized, and a gray bar appears
A blank instance of Microsoft Edge opens
The Windows Settings app appears out of nowhere
The code to minimize the windows:
static std::stack<HWND> minimizedWindowPointers;
Monitors monitors;
RECT activeMonitorRect;
static BOOL CALLBACK windowEnumerator(HWND w, LPARAM l){
if(!IsWindowVisible(w) || IsIconic(w) || getWindowTitle(w).size() == 0) return true;
RECT r;
GetWindowRect(w, &r);
if(doRectsIntersect(r, activeMonitorRect)){
SendMessage(w, WM_SYSCOMMAND, SC_MINIMIZE, 0);
minimizedWindowPointers.push(w);
}
return true;
}
void minimizeWindowsOnActiveMoniter(){
if(monitors.getRectOfMonitorWithPointer(&activeMonitorRect)) return;
EnumDesktopWindows(NULL, windowEnumerator, NULL);
areWindowsMinimized = true;
}
void maximizeWindowsOnActiveMoniter(){
HWND w;
for(int i = minimizedWindowPointers.size(); i > 0; i--){
w = minimizedWindowPointers.top();
minimizedWindowPointers.pop();
if(IsIconic(w)){
SendMessage(w, WM_SYSCOMMAND, SC_RESTORE, 0);
std::wcout << "MAXIMIZING: " << getWindowTitle(w) << std::endl;
}
}
areWindowsMinimized = false;
}
I am running Windows 10 Pro, with Visual Studio 19 Preview.

GetWindowLong can get the window flags with GWL_STYLE. Check for WS_CAPTION and WS_MINIMIZEBOX. I would also check for WS_VISIBLE again for good measure.

Related

C++ bring console window to the front

I've made a little timer program in c++ and once the timer has run out I want the console window to pop up to the foreground in Windows to display the "finished" message. I read about using "SetForegroundWindow(hwnd)" which does exactly what I want when I run the code from visual studio, but when I build a release and run the exe from outside of VS, the console window doesn't pop up, instead it's icon in the system tray flashes. Any ideas why this might be? I've tested it on 64 bit Windows 7 and 10 and both did the same thing.
In most cases you can use SetForegroundWindow as long as the window is properly restored. Sometimes the system may refuse the request (see documentation) There is usually a good reason for it and you should not try to override the system. If SetForegroundWindow failed then you still have the backup option where you get that blinking button in the task bar to alert the user.
void show(HWND hwnd)
{
WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) };
GetWindowPlacement(hwnd, &place);
switch(place.showCmd)
{
case SW_SHOWMAXIMIZED:
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
break;
case SW_SHOWMINIMIZED:
ShowWindow(hwnd, SW_RESTORE);
break;
default:
ShowWindow(hwnd, SW_NORMAL);
break;
}
SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(hwnd);
}
int main()
{
HWND hwnd = GetConsoleWindow();
ShowWindow(hwnd, SW_SHOWMINIMIZED);
//Test: manually click another window, to bring that other window on top
Sleep(5000);
//this window should restore itself
show(hwnd);
system("pause");
return 0;
}

Function to check if a window is visible on screen does not work on Windows 7

For my program, I need to know if at least a pixel of a window is visible on screen.
I'm currently using this code:
BOOL isWindowVisible(HWND hwnd) {
RECT r1;
GetWindowRect(hwnd, &r1);
HRGN x = CreateRectRgnIndirect(&r1);
HWND s = GetTopWindow(0);
do {
if (IsWindowVisible(s)) {
RECT r2;
GetWindowRect(s, &r2);
HRGN y = CreateRectRgnIndirect(&r2);
int res = CombineRgn(x, x, y, RGN_DIFF);
DeleteObject(y);
if (res == NULLREGION) {
DeleteObject(x);
return FALSE;
}
}
} while ((s = GetNextWindow(s, GW_HWNDNEXT)) && s != hwnd);
DeleteObject(x);
return TRUE;
}
This does work on Windows 8.1 and Windows 10, but not on Windows 7. On Windows 7, it returns FALSE every time.
I thought it is because of Aero effects, but even when I disable it, it still happens. I got this method here on StackOverflow and adapted it to C++.
Does someone know why this is happening?
OK, I figured it out by myself. It does not check if the window on top of the z-order is the same window like the one to check. If the window is still on top, the function subtracts itself and then returns FALSE. I don't know why this error only happens on Windows 7, but at least it is fixed now.

Get details about all running applications C++ [duplicate]

In VC++, I use EnumWindows(...), GetWindow(...), and GetWindowLong(), to get the list of windows and check whether the window is top window (no other window as owner), and whether the window is visible (WS_VISIBLE). However, although my desktop is showing only 5 windows, this EnumWindows is giving me 50 windows, how funny! Any Windows geek here please help me clarify...
The way to list out only windows in taskbar (or similarly in Alt-Tab box) is described by Raymond in this article on MSDN blog:
Which windows appear in the Alt+Tab list?
And this is the super function to check whether a window is shown in alt-tab:
BOOL IsAltTabWindow(HWND hwnd)
{
TITLEBARINFO ti;
HWND hwndTry, hwndWalk = NULL;
if(!IsWindowVisible(hwnd))
return FALSE;
hwndTry = GetAncestor(hwnd, GA_ROOTOWNER);
while(hwndTry != hwndWalk)
{
hwndWalk = hwndTry;
hwndTry = GetLastActivePopup(hwndWalk);
if(IsWindowVisible(hwndTry))
break;
}
if(hwndWalk != hwnd)
return FALSE;
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
// Tool windows should not be displayed either, these do not appear in the
// task bar.
if(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
return FALSE;
return TRUE;
}
Credited to the source code here:
http://www.dfcd.net/projects/switcher/switcher.c
The windows that you are talking about, with an X button and a title bar, etc. are not the only kind of windows. Buttons, dropdown menus, labels, icons, text boxes, the task bar, and just about everything else is a window too1. So EnumWindows is doing exactly what it's supposed to do: enumerate all the top level windows.
1 Even though this is true, EnumWindows only enumerates the top level windows. That means it won't enumerate any child windows:
The EnumWindows function does not enumerate child windows, with the exception of a few top-level windows owned by the system that have the WS_CHILD style.
However, many things on your desktop are windows as well, not just the "windows" you're thinking about.
The answer provided by #jondinham does work perfectly for me. So I work out my own solution.
1.Problems I met with previous solution
Running on Windows 10 home edition 1909., I get two extra unexpected Windows "Calculator" and "Setting".
In addition, windows of Tencent QQ can not be detected, because the following fails:
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
However, I think the bug may be resulted by the particularity of Tencent QQ, I can not even make its' window TOPMOST with DeferWindowPos.
Perhaps someone can help me figure out why this happened and help improving the previous solution by #jondinham.
2.My Solution
I tried to examing the icons of the windows, and filter out windows that does not have its own icon or uses the icon same as the system default. I use code snippets from answer and answer and do some modification. This solution works very well for me.
HICON get_windows_HICON_critical(HWND hwnd)
{
// Get the window icon
HICON icon = reinterpret_cast<HICON>(::SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0));
if (icon == 0) {
// Alternative method. Get from the window class
icon = reinterpret_cast<HICON>(::GetClassLongPtrW(hwnd, GCLP_HICONSM));
}
// Alternative method: get the first icon from the main module (executable image of the process)
if (icon == 0) {
icon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
}
// // Alternative method. Use OS default icon
// if (icon == 0) {
// icon = ::LoadIcon(0, IDI_APPLICATION);
// }
if(icon == ::LoadIcon(0, IDI_APPLICATION)){
// Filter out those with default icons
icon = 0;
}
return icon;
}
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
HICON icon = get_windows_HICON_critical(hWnd);
if(icon!=0){
std::cout << hWnd << ": " << windowTitle << std::endl;
}
}
return TRUE;
}
3.Problems with my solution
My solution can not deal with Windows Store APP, according to this question.
For all people looking to find a way to remove Invisible windows like Settings or Microsoft Store from the list:
These windows are cloaked, meaning they still have the dwStyle WS_VISIBLE, but the user can't see them.
You can detect this using the function DwmGetWindowAttribute. The dwAttribute you want to get is DWMWA_CLOAKED (enum constant 14). Only if the value in pvAttribute after the method call is 0, the window is not cloacked.

Get all windows from Alt + Tab excluding Metro windows - Windows 8/8.1

Is it possible to get all windows hwnd from a Alt + Tab window - excluding Metro? Maybe there is some alternative for Windows 8?
I was trying to get all windows using EnumWindows function and paste hwnd's to the GetAltTabInfo function and it is not working for me. I get error message: "Invalid window handle" from GetLastError, because this function (GetAltTabInfo) is no longer usable when you've got Aero enabled. This conclusion is from here: GetAltTabInfo usage?.
Using "Which windows appear in the Alt+Tab list?" article by Raymond Chen, I have been able to reproduce the window list.
// See http://blogs.msdn.com/b/oldnewthing/archive/2007/10/08/5351207.aspx
BOOL IsAltTabWindow(HWND hwnd)
{
// Start at the root owner
HWND hwndWalk = GetAncestor(hwnd, GA_ROOTOWNER);
// See if we are the last active visible popup
HWND hwndTry;
while ((hwndTry = GetLastActivePopup(hwndWalk)) != hwndTry) {
if (IsWindowVisible(hwndTry)) break;
hwndWalk = hwndTry;
}
return hwndWalk == hwnd;
}
BOOL CALLBACK CbEnumAltTab(HWND hwnd, LPARAM lParam)
{
// Do not show invisible windows
if (!IsWindowVisible(hwnd))
return TRUE;
// Alt-tab test as described by Raymond Chen
if (!IsAltTabWindow(hwnd))
return TRUE;
const size_t MAX_WINDOW_NAME = 256;
TCHAR windowName[MAX_WINDOW_NAME];
if (hwnd == GetShellWindow())
_tcscpy_s(windowName, MAX_WINDOW_NAME, _T("Desktop")); // Beware of localization
else
GetWindowText(hwnd, windowName, MAX_WINDOW_NAME);
// Do not show windows that has no caption
if (0 == windowName[0])
return TRUE;
// Print found window to debugger's output
const size_t MAX_MESSAGE_NAME = 64 + MAX_WINDOW_NAME;
TCHAR message[MAX_MESSAGE_NAME];
_stprintf_s(message, MAX_MESSAGE_NAME, _T("AltTab: %08X %s\n"), hwnd, windowName);
OutputDebugString(message);
return TRUE;
}
void ListAltTabWindows()
{
EnumWindows(CbEnumAltTab, 0);
}
Notes:
metro seems to be excluded already
Didn't check WS_EX_TOOLWINDOW
Didn't check WS_EX_APPWINDOW.
Didn't test extensively

Why does EnumWindows return more windows than I expected?

In VC++, I use EnumWindows(...), GetWindow(...), and GetWindowLong(), to get the list of windows and check whether the window is top window (no other window as owner), and whether the window is visible (WS_VISIBLE). However, although my desktop is showing only 5 windows, this EnumWindows is giving me 50 windows, how funny! Any Windows geek here please help me clarify...
The way to list out only windows in taskbar (or similarly in Alt-Tab box) is described by Raymond in this article on MSDN blog:
Which windows appear in the Alt+Tab list?
And this is the super function to check whether a window is shown in alt-tab:
BOOL IsAltTabWindow(HWND hwnd)
{
TITLEBARINFO ti;
HWND hwndTry, hwndWalk = NULL;
if(!IsWindowVisible(hwnd))
return FALSE;
hwndTry = GetAncestor(hwnd, GA_ROOTOWNER);
while(hwndTry != hwndWalk)
{
hwndWalk = hwndTry;
hwndTry = GetLastActivePopup(hwndWalk);
if(IsWindowVisible(hwndTry))
break;
}
if(hwndWalk != hwnd)
return FALSE;
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
// Tool windows should not be displayed either, these do not appear in the
// task bar.
if(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
return FALSE;
return TRUE;
}
Credited to the source code here:
http://www.dfcd.net/projects/switcher/switcher.c
The windows that you are talking about, with an X button and a title bar, etc. are not the only kind of windows. Buttons, dropdown menus, labels, icons, text boxes, the task bar, and just about everything else is a window too1. So EnumWindows is doing exactly what it's supposed to do: enumerate all the top level windows.
1 Even though this is true, EnumWindows only enumerates the top level windows. That means it won't enumerate any child windows:
The EnumWindows function does not enumerate child windows, with the exception of a few top-level windows owned by the system that have the WS_CHILD style.
However, many things on your desktop are windows as well, not just the "windows" you're thinking about.
The answer provided by #jondinham does work perfectly for me. So I work out my own solution.
1.Problems I met with previous solution
Running on Windows 10 home edition 1909., I get two extra unexpected Windows "Calculator" and "Setting".
In addition, windows of Tencent QQ can not be detected, because the following fails:
// the following removes some task tray programs and "Program Manager"
ti.cbSize = sizeof(ti);
GetTitleBarInfo(hwnd, &ti);
if(ti.rgstate[0] & STATE_SYSTEM_INVISIBLE)
return FALSE;
However, I think the bug may be resulted by the particularity of Tencent QQ, I can not even make its' window TOPMOST with DeferWindowPos.
Perhaps someone can help me figure out why this happened and help improving the previous solution by #jondinham.
2.My Solution
I tried to examing the icons of the windows, and filter out windows that does not have its own icon or uses the icon same as the system default. I use code snippets from answer and answer and do some modification. This solution works very well for me.
HICON get_windows_HICON_critical(HWND hwnd)
{
// Get the window icon
HICON icon = reinterpret_cast<HICON>(::SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0));
if (icon == 0) {
// Alternative method. Get from the window class
icon = reinterpret_cast<HICON>(::GetClassLongPtrW(hwnd, GCLP_HICONSM));
}
// Alternative method: get the first icon from the main module (executable image of the process)
if (icon == 0) {
icon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
}
// // Alternative method. Use OS default icon
// if (icon == 0) {
// icon = ::LoadIcon(0, IDI_APPLICATION);
// }
if(icon == ::LoadIcon(0, IDI_APPLICATION)){
// Filter out those with default icons
icon = 0;
}
return icon;
}
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
HICON icon = get_windows_HICON_critical(hWnd);
if(icon!=0){
std::cout << hWnd << ": " << windowTitle << std::endl;
}
}
return TRUE;
}
3.Problems with my solution
My solution can not deal with Windows Store APP, according to this question.
For all people looking to find a way to remove Invisible windows like Settings or Microsoft Store from the list:
These windows are cloaked, meaning they still have the dwStyle WS_VISIBLE, but the user can't see them.
You can detect this using the function DwmGetWindowAttribute. The dwAttribute you want to get is DWMWA_CLOAKED (enum constant 14). Only if the value in pvAttribute after the method call is 0, the window is not cloacked.