We have an application that uses various system tray icons to communicate with users. Different icons indicate different internal states of the (otherwise windowless) application. We implemented our system tray stuff using code from this Code Guru project (the MFC version; this is not a new application by any means), and until recently, it has worked fine. However, recently we have tried to add another icon and have run into trouble.
Here's how it's supposed to work:
We have one main icon (call it 'A') that indicates that the application is running.
If a particular event occurs, we display icon 'B', over which the user can hover their mouse to get a tooltip with status regarding that event.
If a (recently added, internal, threaded) procedure starts, we display icon 'C', and again, the user can hover over that to see a tooltip that indicates the progress of that activity.
What's actually happening: if icon 'B' is visible when we (try to) display icon 'C', then icon 'B' either disappears entirely, never to return, or it stays there and icon 'C' never shows up, but the tooltip for icon 'B' is changed to what icon 'C' should have.
I've simplified the scenario a bit; we actually have a few other icons, but they're rarely used. However, we have never had any trouble displaying multiple icons until we added icon 'C' in the last couple of weeks.
Any ideas? Happy to clarify anything I haven't explained well.
You need to use a different uID for each icon. The documentation says:
The application-defined identifier of the taskbar icon. The Shell uses either (hWnd plus uID) or guidItem to identify which icon to operate on when Shell_NotifyIcon is invoked. You can have multiple icons associated with a single hWnd by assigning each a different uID. If guidItem is specified, uID is ignored.
In other words you need to pick a value for uID. This is how the shell knows which icon you are referring to each time you call Shell_NotifyIcon(). Clearly you must use a different value for each icon. So, use 0 for icon A, 1 for icon B etc.
Related
I have a bug that I am having a hard time solving. I have two windows.
Window A is the main window that contains a text box (in this simplified version). The user is able to edit the contents of this text box by clicking on it where Window B appears as a keypad. Besides the buttons for the numbers, there are 2 additional buttons, Enter and Done. If the user changes the value and presses Enter, then the value in the text box is immediately updated. Pressing Done will then exit the window.
However, if the user presses done without having first pressing enter, then a modal dialog will appear asking the user if they would like to save the value. Once a selection has been made, the model dialog and Window B will exit.
The bug occurs when the user enters a value and presses the Done button. When the modal dialog appears, Window B moves behind Window A. What should happen is that Window B stays ontop of Window A. Interestingly enough, when I step through the code, this bug never happens which is making it tricky to pinpoint.
Has anyone every ran into this issue before?
I am currently running Qt 5.9 on the latest version of Linux Mint (as of this writing)
Also, I have prepared a sample project that demonstrates this bug. Due to the larger complexity of it, I was unable to fit it into 1 file. If needed, I might be able to find some time this week to move everything in one file. However, I can post the Dropbox link if permitted.
Maybe the problem stems from a wrong setting of the parent child relationship of the [QDialog][1] classes.
The following passage might be crucial for your application, but it is hard to say, if you don't show a minimal-reproducible-example.
Note: The parent relationship of the dialog does not imply that the
dialog will always be stacked on top of the parent window. To ensure
that the dialog is always on top, make the dialog modal. This also
applies for child windows of the dialog itself. To ensure that child
windows of the dialog stay on top of the dialog, make the child
windows modal as well.
Are notification/alert windows (that appear above the Windows System Tray) like the examples below just a standard window, owner drawn HMENU's or are they implemented using NOTIFYICONDATA? Note: I know that the actual system tray icon is implemented using NOTIFYICONDATA, but are the notification windows also implemented using this structure?
In my WinAPI C++ application I want to show a similar notification where it will appear above the system tray icon, have buttons, horizontal scroll bars and etc. I know I can just create a new HWND, position it above the system tray and show that but if there is a specific WinAPI 'System Tray Notification' class/function I would prefer to use that, thus my question.
Are notification/alert windows (that appear above the Windows System Tray) like the examples below just a standard window, owner drawn HMENU's or are they implemented using NOTIFYICONDATA?
These are custom dialogs displayed when needed. They are not implemented using NOTIFYICONDATA. You can use Shell_NotifyIconGetRect() to get the current location of your tray icon when needed.
Tray notifications are all about notifying the process that owns the icon that a click event has occurred so it can then do its thing, whatever that may be.
There is no specialised mechanism or framework for anything GUI related in this case.
Best Practices: When a user right-clicks the icon, it should
bring up a normal shortcut menu. However, the result of a single
click with the left mouse button will vary with the function of the
icon. It should display what the user would expect to see in the form
best suited to that content—a popup window, a dialog box or the program
window itself. For instance, it could show status text for a status icon,
or a slider for the volume control.
Is it possible to add custom controls to a console window? You can use GetConsoleWindow() to get the window's handle, and then add your own menu items or consume all its events. I can't find any examples of people adding extra controls though.
I am developing a small, high performance serial terminal app. It is a console application - RichTextBox is too slow and has issues that make it unsuitable for VT100 terminal emulation.
I want to add some little graphics to show the state of the serial control lines (RTS/CTS/DTR/RI etc.) and perhaps a capture on/off toggle button. Ideally I'd like to add them to the window title bar. Bitmaps are all that are required.
After lots of research I found that it isn't easy, or even possible really.
You can add controls to the window with CreateWindow(), but of course only in the client area which is taken up entirely by the console text box. However, you can at least create floating controls that way, which hover over the text to provide status info etc.
You can put controls in the window borders but only with some hacking on XP or a new API that was introduced with Vista. The problem with this API is that it requires you to draw your own program icon and title text, and the console window doesn't seem to cope with it very well.
You can't add your own menu items because the console window doesn't pass the messages.
In the end I used the function keys for everything and gave a status indication by changing the console window icon.
In C++, is there anyway to let the user chose the icon of the app? For example, Winamp lets you select which icon you wish to use from a list of icons in it's preferences. How is it done?
There is the icon that you see in explorer. This is a resource in your executable. You could change that, but I wouldn't advise you too. Virus scanners can get nervous if executables are modified, and in Windows Vista you will not even be allowed to write in the Program Files folder.
But the icon that is displayed on the task bar or in the system tray can be changed. This is actually the icon of your application window and it can be set by sending a WM_SETICON message.
And there are shortcuts. They can be changed too, and in a shortcut you can specify which icon should be used.
I found a discussion on changing icons that has information about the first two options.
For Visual Studio 2010 in an MFC dialog based app
A. In the resource view, rightclick Icon folder and add icon. Give it an ID like IDI_MYICON. Leave it as is or draw something nice.
B. Go to OnInitDialog. Add the following two lines of code:
HICON hMyIcon = LoadIcon( AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_MYICON) );
SetIcon( hMyIcon, FALSE ); // FALSE == use as small icon
You can read about these functions in the help to understand what is happening.
This sets the icon as icon for the sysmenu (topleft) and in the taskbar. This is however not automatically reflected in all situations. E.g. for a systray icon you need to explicitly specify the icon again in the call to Shell_NotifyIcon().
I have a simple console application written in C++ that acts as a stub for launching another application through it's jumplist. Purpose is to add jumplist abilities to applications that do not support this. Call it stub.exe. When running stub.exe it creates a custom jumplist using these steps (taken right form the MS samples):
create an ICustomDestinationList
ICustomDestinationList::BeginList()
create an IObjectCollection
for_each item_to_add
create an IShellLink, set its path/arguments/title/icon
add IShellLink to the IObjectCollection
get the IObjectArray interface from the IObjectCollection
call ICustomDestinationList::AddUserTasks( IObjectArray interface )
ICustomDestinationList::CommitList()
When pinning stub.exe to the taskbar and right-clicking it, the jumpilst appears and it contains all IShellLinks added. When clicking an item, it will launch the corresponding process.
Now I'd like a process launched through this jumplist have it's window(s) grouped under stub.exe's taskbar icon, instead of having it's own group. They key to get this working seems to be the AppUsermodelID. This is what I tried so far:
just for testing, create a couple of shortcuts and set the id through IPropertyStore->SetValue( PKEY_AppUserModel_ID, "id" ). Indeed, when launching these shortcuts, they will all group under the same taskbar icon.
since the shortcuts do what I want, I tried adding shortcuts to stub.exe's jumplist: no effect. The shortcuts don't even show up in the jumplist (maybe one cannot have a shortcut to a shortcut?), yet all methods return S_OK
setting the PKEY_AppUserModel_ID on each of the IShellLinks that get added to the jumplist: no effect
calling ICustomDestinationList->SetAppID(): no effect
instead of using SubTasks, tried with SHAddToRecentDocs: no effect. The recent doc list does not show up. But now things get messy. After setting the AppUserModelID on the shortcut that is responsible for the pinned taskbar item (the one in %APPDATA%/Roaming/Microsoft/Internet Explorer/Quick Launch/User Pinned/TaskBar), the jumplist changed: it does not show the 'Tasks' item anymore, but does show 'Recent' and the items I added using SHAddToRecentDocs. Now when clicking them I get a dialog box with a title that starts with 'd:\desktop' followed by Chinese characters. Hovering the items in the jumplist also shows Chinese characters instead of the descirption I set.
Questions:
What's with the Chinese characters in the jumplist?
How come setting the app id on the taskbar shortcut toggles between 'Tasks' and 'Recent' sections, why are they not both there?
What would be the way, if even possible, to achive what I actually want: a custom jump list of which the items launched will group under it's taskbar icon? (note that the processes I plan to laucnh their do not have their app id set currently)
not much reactions here ;]
In the meantime I managed to solve the main problem myself; it's not quite a straightforward solution but it fullfills the requirements: a program runs in the backround and installs a CBT hook. Each time an application creates a window (HookProc code = HCBT_CREATEWND), the hook checks the application's path against a map containing paths and desired application ids. If a match is found, the application id of the HWND is set. Since this occurs before the window is actually shown and is combined with the custom task list, from a user's point of view the application behaves just like one that does support a recent/pinned document list.