C++ system tray only program - c++

After checking Microsoft's documentation on system tray icons (that I could find):
Shell_NotifyIconA function
NOTIFYICONDATAA structure
I've noticed that a window handle (HWND) is REQUIRED. This is very bad for what I'm trying to accomplish, as I'm looking to create a program that only reacts to the system tray: it doesn't "minimize" the window to the tray, it just uses notifications (clicking/right clicking on the icon) to interact.
How would I go about doing this?

The Windows 7 SDK contains an example called NotificationIcon. This example contains a line
ShowWindow(hwnd, nCmdShow);
in its wWinMain function. The effect of this call is that you see a program window.
Just change this line to
ShowWindow(hwnd, SW_HIDE);
to hide the program window and only display the icon in the system tray. As others have pointed out the program needs a program window, even if it is not visible.

Related

Hiding the new Windows Terminal

I used to hide my background app's console window until I needed it with
ShowWindow(console_hwnd,SW_HIDE);
My Windows got an update and switched to "Windows Terminal" as the default console app.
That line of code doesn't work anymore it just minimizes the console to taskbar. What is the proper way to fully hide Windows Terminal?
EDIT:
Please read the question carefully. It says HIDE the console window. NOT remove the console completely. I need to be able to show it again later. Thats the purpose of SW_HIDE and SW_SHOW that are no longer working with the new Windows Terminal.
If you want to show the console at any time, you could hide and show the console by changing the coordinates of the console.
int main() {
HWND consoleWindow = GetConsoleWindow();
SetWindowPos(consoleWindow, 0, -600, -600, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
return 0;
}
EDIT:
According to this document, the second parameter to ShowWindow() might get ignored the first time it is called. Try calling it twice.
ShowWindow(hWnd, SW_HIDE);
ShowWindow(hWnd, SW_HIDE);
In addition, did you run this program as administrator? If so, I suggest you cancel it, since the window is in a higher privileged process, so your call will be ignored.
Hope it helps.

Hide windows console if minimized

I have a Qt based console application, that has to be located on the Windows System Tray (aka Notification Area).
The question: how can I hide the console window instead of minimizing it if the user clicks on "minimize" icon? I know the ShowWindow method, but as I guess, I have to call it asynchronously.
You need to obtain the HWND window handle of the Console window, then you can use ShowWindow to show or hide it in the usual way.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683175(v=vs.85).aspx
The question is when do you do this? You need to know when the window is minimised in order to know whether to hide it.
You could check this periodically, but you should be careful to ensure you are not preventing laptops etc. from sleeping by doing so.
Alternatively you could install a message hook, or subclass the window, to recieve immediate notifications.
Subclassing the window is probably the best method.

IsIconic() always return false and OpenIcon() never open the window

Platform: Windows 7 64bit.
First of, the Windows API IsIconic() always return false. Doesn't matter if the window is maximized, normal or minimized (where IsIconic() should return true).
The window belongs to another process and has been retrieved with enumWindows()
Here is a small excerpt from my test code.
TCHAR WndCaption[100];
TCHAR NewCaption[] = TEXT("My Window handle is valid");
BOOL res;
GetWindowText(MyHWND,WndCaption,100);
SetWindowText(MyHWND,NewCaption);
// This always return 0, no matter what state the window is in.
res = IsIconic(MyHWND);
if(res) {
...
}
I know the window handle is valid because I can get and set the window's caption text. The Is Iconic() function however always return 0 (false) even when the window has been minimized.
But if we change the IsIconic() to IsWindowVisible() it reports correctly false when the window is minimized and true when it is maximized or normal.
TCHAR WndCaption[100];
TCHAR NewCaption[] = TEXT("My Window handle is valid");
BOOL res;
GetWindowText(MyHWND,WndCaption,100);
SetWindowText(MyHWND,NewCaption);
// This works correctly.
res = IsWindowVisible(MyHWND);
if(!res) {
// This always fail
OpenIcon(MyHWND);
}
So now when I can detect the window being minimized I want to restore it. IsIconic's counterpart OpenIcon() does nothing. It returns true, telling that the operation was successful, but the window is still minimized. In fact, it always return true no matter what state the window is in.
So lets try the old fashion way.
TCHAR WndCaption[100];
TCHAR NewCaption[] = TEXT("My Window handle is valid");
BOOL res;
GetWindowText(MyHWND,WndCaption,100);
SetWindowText(MyHWND,NewCaption);
// Only works if the window wasn't minimized by clicking the minimize button
res = ShowWindow(MyHWND,SW_MINIMIZE);
res = ShowWindow(MyHWND,SW_NORMAL);
res = ShowWindow(MyHWND,SW_MAXIMIZE);
If the window is in the normal or maximized state it will first minimize it, restores it back again and then maximize it. But if I run the program when the window has been minimized by clicking the minimize button, nothing happens. It doesn't restore it or maximize it.
It feels like the window becomes unresponsive if I minimize it by clicking the minimize button.
After hours of searching I have only found posts with similar problems but no solutions.
Can some one please help me to figure out how to restore a window (owned by another process) after it has been minimized by the minimize button.
Without knowing anything about the external app in question, my guess is that the window you are manipulating is not the actual window being minimized to the Taskbar, which would account for why IsIconic() is always false but IsWindowVisible() varies.
It is not uncommon, especially in legacy apps written before Vista, or apps using older versions of frameworks like Borland's VCL before they were updated to support Vista, to have a top-level hidden window that owns other windows in the same app, especially the main window. One reason (amongst others) is to group multiple windows on the same Taskbar button, before Microsoft created APIs to control that.
In such an app, when the "main" window is "minimized", the app would intercept that action, hide the "main" window, and minimize the owner window instead. When the "main" window is "restored", the app would restore the owner window and then show the "main" window.
Try checking if GetWindow(MyHWND, GW_OWNER) returns an HWND and if so then check what IsIconic() says about it.
Vista made some dramatic changes to how apps interact with the Taskbar and Alt+Tab dialog. Some coding techniques and assumptions that had been true and working fine since Win95 no longer worked correctly in Vista onwards. Some apps and frameworks adapted to the changes, some did not.
Had similar issue in Windows 7 Pro. 32-bit.
IsIconic() function is from user32.dll.
IsIconic function correctly working once copied below files to current folder.
user32.dll, advapi32.dll, gdi32.dll, kernel32.dll, ntdll.dll
Note:
These dependencies can be find usnig DEPENDS.EXE in VC 6.0 ++. Also these files copied from Windows 7 64-bit pc (IsIconic is working fine in this pc).
May be windows update is not installed on Windows 7 32-bit pc.

Debugging "crashed" top most window

I have application that must run in Top most window. It works great till it crashes. When it crashes window becomes whiteis and windows crash window shows asking if you want to debug it.
In that moment I would like to use that option to debug that application. But I can't see anything because of that crashed topmost window.
I can't run application without topmost window. I can't attach debugger to application while it is running. My only possibility is to attach debugger after crash. But then I can't see anything.
Is there any way to "hide" crashed topmost window?
UPDATE:
I'm using WinApi.
You can hide a window using ShowWindow(HWND,int):
If you have the handle of the window:
ShowWindow(hwnd, SW_HIDE);
If you only know the title:
HWND hwnd = FindWindowA(NULL,"Title");
ShowWindow(hwnd, SW_HIDE);
So when you want to do something but the crashed window is in the way, run these commands to hide it.

Show System Menu From Another Window

The project I'm working on right now is essentially an open source version of Ultramon (the multiple taskbar program). Thus think of the application to be just like the windows taskbar. Buttons for each window, etc. This is coded in C/C++ using WinAPI
I've just started doing it, and have some of the functionality down. However, I'm getting stuck at getting the system menus (eg the menus that you get when you rightclick on a taskbar 'button') showing when and where I want them to.
I'm trying to use:
HMENU menu = GetSystemMenu(item, false);
SetForegroundWindow(hWnd);
TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, 0, 0, 0, hWnd, NULL);
PostMessage(hWnd, WM_NULL, 0, 0);
item is the HWND I want the menu for, hWnd is the HWND for the button/item I want the menu to show up on. (its showing at 0, 0 for now, the top left corner of my main monitor).
This code works perfectly every time for a system menu which is customized. Eg: its NOT the standard menu of just "Restore", "Maximize" etc etc, it has some added in menu items. Those menus will always display where I want.
However, the default basic system menus (eg the ones with only Maximize, restore, close etc), will ONLY display for the FIRST time I use them. After that they refuse to show up. Unless I restart the computer, run it again, at which point they work perfectly.
Note: SetForegroundWindow(hWnd); and PostMessage(hWnd, WM_NULL, 0, 0); are in there because I read somewhere that the system menu would only work the first time unless I did that trick of bringing it to the foreground, but it still doesn't work correctly.
So does anyone have any idea how to get this working correctly? Or why it works only the first time after I restart the computer?
Just tested something, it will also show the system menu again for a window if I close the window (eg exiting the program) and re-opening it. But once again, it will only show it once then it stops working.
It might be hacky, but have you tried setting the window focus and then issuing an Alt+Space through something like SendInput?