How can I skip hidden windows when using FindWindow()? - c++

I create a window without showing it:
int main()
{
CreateWindow("SysListView32","Geek",0, 0, 0, 0, 0,NULL, NULL, (HINSTANCE)GetCurrentProcess(), NULL);
getch();
}
...and in another process use FindWindow() to find its handle:
int main()
{
HWND H = FindWindow("SysListView32", "Geek");
std::cout<< "The handle of created window is : " <<H;
getch();
}
How is FindWindow finding its handle? I assumed it would not find it, because process1 is not showing the window.
How can I find only visible windows?

Even if a window is not visible, it is of course in the list of all existing windows that FindWindow enumerates (you can display this list using Spy++ for example). If you do not want to search for hidden windows, you have to check their flags:
HWND H = FindWindow("SysListView32", "Geek");
if (H) {
LONG style = GetWindowLong(H, GWL_STYLE);
if (style & WS_VISIBLE)
std::cout << "The handle of created visible window is : " << H << std::endl;
else
std::cout << "The handle of created hidden window is : " << H << std::endl;
} else {
std::cout << "No such window found" << std::endl;
}

FindWindow finds top-level windows.
While your CreateWindow call is creating a top-level window (i.e. one with no parent) I'm not convinced it will actually work.
It's certainly very unusual (if not wrong) to create a top-level SysListView32. ListView controls should be the children of top-level windows, not top-level windows in their own right.

Related

Stuck in a do while loop

Hello guys so here is my problem since i was stuck in this block of code for more then 2 day
i want to make my programe monitor a specifique application and wait for it to be lunch i tried the "Do and While loop" but its not working i have checked and rechecked and i couldnt find a solution for this problem
HWND hwnd = FindWindow(0,("my programme window name"));
do {
if(hwnd == nullptr ) { /* if the window has not beign found */
cout << "window not found!" << endl;
Sleep(1000);
system("cls");
}
}while(hwnd == nullptr);
/*******************************************************************/
starting the next code once the window of the programe has been found
so my problem is i keep getting ""window not found!" when i launch my own program first and then lunch the program wish i try to monitor , but when i start the program i wish to monitor then i launch my own program everything work fine
tnks for your help--- edit Problem sloved
You're not changing hwnd inside the loop. You need to call FindWindow() in the loop. You can use a regular while loop instead of do-while, so you don't need to do the call twice.
while ((hwnd = FindWindow(0, "my programme window name")) == nullptr) {
cout << "window not found!" << endl;
Sleep(1000);
system("cls");
}
First things first: Polling is wrong.
If you need to be informed that a certain window is created, use the tool that's specifically tailored for this. Set up a WinEvents hook (calling SetWinEventHook) that listens for EVENT_OBJECT_CREATE events. In your WinEventProc callback you can filter out the your window of interest, by inspecting it's window title, window class, certain styles (and combinations thereof).
This doesn't waste resources like your attempt to poll every second, and doesn't exhibit the race conditions either (e.g. missing a window because it was created and destroyed in between sampling points).
Assuming that the value of hwnd was nullptr when it entered the loop; you are not changing its value in the loop. Since the condition hwnd == nullptr is always true, you get an infinite loop.
In order to overcome this issue, you need to change the value of hwnd inside your loop.
Nothing in your loop changes hwnd, so it is impossible to get out of the loop (as you've seen).
You need to make something inside the loop change hwnd so that it is possible that (eventually) hwnd won't == nullptr. e.g. hwnd = FindWindow(0,("my programme window name"));
I'd refactor to:
HWND hwnd = FindWindow(0,("my programme window name"));
while(hwnd == nullptr)
{
cout << "window not found!" << endl;
Sleep(1000);
system("cls");
hwnd = FindWindow(0,("my programme window name"));
}
I think the problem is "FindWindow(0,("my programme window name"))" can't return an available hwnd so the loop is stuck.
Maybe you can try 10 times, if hwnd was still null, break the loop or exit the program.
#define MAX_COUNT 10
HWND hwnd = FindWindow(0,("my programme window name"));
int count = 0;
while(hwnd == nullptr && count < MAX_COUNT) {
count++;
cout << "window not found!" << endl;
Sleep(1000);
system("cls");
hwnd = FindWindow(0,("my programme window name"));
}

Simply update label in Qt

I have created a label with Qt Creator using a unique name, 'statusLabel'.
I then made a function to update this status label like so:
//Function to set the text in the status bar.
void AutoFish::updatelabel(QString str)
{
ui->statusLabel->setText(str);
}
This does not work and gives the following error:
C:\Qt\Tools\QtCreator\bin\AutoFish\autofish.cpp:24: error: C2227: left of '->statusLabel' must point to class/struct/union/generic type
I'm not sure what I'm doing wrong, I'm just trying to update the label text using that function. Should I be using something other than a label? I've been looking into slots to create an event to update the label, but most slot examples I find involve a pushButton as an event start, and that is not what I need.
Thank you.
EDIT: As per request, here is all of my source code(it's not very big): http://pastebin.com/CfQXdzBK
Because your method is declared as static, you can't acces non-static member ui directly.
Change
static void AutoFish::updatelabel(QString str);
to
void updatelabel(QString str);
in your header file.
There is no need for static keyword, because you want to set label for the specific instance of the window. Also, there is no need for AutoFish:: as you are declaring a method inside class declaration (however, you do need it in your cpp file).
As per the second error - inside your getWindow function, you need to have a instance of the AutoFish object in order to call updateLabel. So, either change your getWindow definition to:
HWND getWindow(AutoFish *af, LPCSTR processName)
{
HWND hwnd = FindWindowA(0, processName);
if(!hwnd) {
std::cout << "Error: Cannot find window!" << std::endl;
af->updatelabel("Error: Cannot find window.");
}
else {
std::cout << "Seccess! Window found!" << std::endl;
af->updatelabel("Seccess! Window Found!");
}
return hwnd;
}
and call it like this:
HWND window = getWindow(this, "FFXIVLauncher");
or make getWindow member of AutoFish class:
class AutoFish : public QMainWindow
{
// ...
HWND getWindow(LPCSTR processName);
// ...
};
HWND AutoFish::getWindow(LPCSTR processName) {
HWND hwnd = FindWindowA(0, processName);
if(!hwnd) {
std::cout << "Error: Cannot find window!" << std::endl;
updatelabel("Error: Cannot find window.");
}
else {
std::cout << "Seccess! Window found!" << std::endl;
updatelabel("Seccess! Window Found!");
}
return hwnd;
}
and this pointer will be implicitely passed to the getWindow.

How to find jump lists window?

How to get Windows 7 jump list window via ::FindWindow or ::EnumWindows?
What's it's class or parent?
I can't Spy++ it because it disappears if loses focus.
Thank you.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa511446.aspx
Here's a way, similar to the Spy++ technique, to find it through code as soon as it's shown using an event hook:
void CALLBACK WinEventProc(HWINEVENTHOOK, DWORD, HWND hwnd, LONG, LONG, DWORD, DWORD) {
std::wstring className(256, L'\0');
std::wstring windowText;
windowText.resize(GetWindowTextLengthW(hwnd) + 1);
GetWindowTextW(hwnd, &windowText[0], windowText.size());
windowText = windowText.c_str();
GetClassNameW(hwnd, &className[0], className.size());
className = className.c_str();
std::wcout << "Class: \"" << className << "\"\n";
std::wcout << "Window: \"" << windowText << "\"\n";
}
int main() {
HWINEVENTHOOK hWinEventHook = SetWinEventHook(
EVENT_OBJECT_SHOW, EVENT_OBJECT_SHOW,
nullptr, WinEventProc,
0, 0,
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS
);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (hWinEventHook) {
UnhookWinEvent(hWinEventHook);
}
}
As each window is shown, it appears in the console (or whatever stdout is at the time) output as a class name of DV2ControlHost and text of Jump List. If you want to interact with it, however, I believe there's a much more structured API, though I might be mistaken.
Open spy++, open jump list, click the refresh button on spy++.

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.

Drawing on the Desktop Background (WIN32)

Is there any way to draw on the desktop background in WIN32 and also receive notifications when the desktop background is repainted?
I tried this:
desk = GetDesktopWindow();
dc = GetDC(desk);
MoveToEx(dc,0,0,NULL);
LineTo(dc,1680,1050);
ReleaseDC(desk,dc);
But it draws on the whole screen, even over windows that are on the screen.
You can use Spy++ to find which window is the desktop background window.
On my system I see the following hierarchy:
Window 000100098 "Program Manager" Progman
Window 0001009E "" SHELLDLL_DefView
Window 00100A0 "FolderView" SysListView32
I guess you are referring to the SysListView32 - the window with all the icons. You can use FindWindowEx to find this window.
Edit
You should use a combination of FindWindowEx and EnumerateChildWindows. The code presented below can be compiled in a command line box like this: cl /EHsc finddesktop.cpp /DUNICODE /link user32.lib
#include <windows.h>
#include <iostream>
#include <string>
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
std::wstring windowClass;
windowClass.resize(255);
unsigned int chars = ::RealGetWindowClass(hwnd, &*windowClass.begin(), windowClass.size());
windowClass.resize(chars);
if (windowClass == L"SysListView32")
{
HWND* folderView = reinterpret_cast<HWND*>(lParam);
*folderView = hwnd;
return FALSE;
}
return TRUE;
}
int wmain()
{
HWND parentFolderView = ::FindWindowEx(0, 0, L"Progman", L"Program Manager");
if (parentFolderView == 0)
{
std::wcout << L"Couldn't find Progman window, error: 0x" << std::hex << GetLastError() << std::endl;
}
HWND folderView = 0;
::EnumChildWindows(parentFolderView, EnumChildProc, reinterpret_cast<LPARAM>(&folderView));
if (folderView == 0)
{
std::wcout << L"Couldn't find FolderView window, error: 0x" << std::hex << GetLastError() << std::endl;
}
HWND desktopWindow = ::GetDesktopWindow();
std::wcout << L"Folder View: " << folderView << std::endl;
std::wcout << L"Desktop Window: " << desktopWindow << std::endl;
return 0;
}
Here are the results after running finddesktop.exe
Folder View: 000100A0
Desktop Window: 00010014
As you can see the window handles are quite different.
Just quoting MSDN:
The GetDesktopWindow function returns
a handle to the desktop window. The
desktop window covers the entire
screen. The desktop window is the area
on top of which other windows are
painted.
So you are getting a Window with nested windows on them.
I'm not quite a WIN32 user, but I think the approach here is get to the lower level, take control of the graphic object that is painting the background picture, and draw there.