Change the icon on windows 7 taskbar for a pinned application - c++

My software Pomodoro Timer is going to display a dynamic icon on Windows 7 taskbar. You may wonder why the application icon need to be dynamic. It's actually a counting down timer for me to help me focus on current task, so called the pomodoro technique:
My way to change the icon is to simply change the Window icon. It works fine when I start the application, but after I pinned it to taskbar, it will display the default icon for the application. The dynamic counter down number will disappear. More worse, after I unpinned it from taskbar, the default behavior will never be recovered, that is, the dynamic icon will not able to be updated correctly. When I start the application again, it will display the default icon, unless I pinned it and unpinned it again, the counting down icon displays again.
I've searched this forum, and Change pinned taskbar icon (windows 7), and tried to change the overlay icon. It works, but not fulfill my requirement, the overlay icon can only display 16x16, and no enough room to display 4 digits.
I also read the MSDN article Application User Model IDs, but i am still not clear whether it can make it or not.
Anyone can help on this? Thanks a lot!

Windows 7 supports having a green progress bar be shown over an icon, and pinning doesnt effect the progress bar. So, instead of changing the icon every second, why not change it every few seconds, but have the progress bar count down from 100% of the original set counter value?

The pinned items in the Taskbar are stored as a shortcut at:
%appdata%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar
You can try changing the icon of the Shortcut of your program.

My final solution is:
on Windows: use icon overlay. You can get more screen shots here.
on Mac: use different icon. You can get more screen shots here.
I use different solution for Windows and Mac.

Generally an application would make use of the System Tray to show interactive state such as this to the user. There is a whole API set for interacting with it, setting icons, menus, providing text feedback (balloons), and so on.
The following is a good article on how such functionality can be achieved:
http://www.codeproject.com/Articles/74/Adding-Icons-to-the-System-Tray

Related

Colorizing the titlebar in macOS with multiple colors

I have a Qt app that runs on macOS. I found a way to change the color of the titlebar here, however I want to take it a step further. I want to mimic the titlebar that the Slack and Discord apps use. For example:
As you can see, the color of the controls in the window extend to the very top of the app's window. I figure there are two ways to accomplish what I want:
I can build on the code pasted above. Looking through some of the Apple developer documentation, I think I can create a couple NsWindows on top of the titlebar with whatever width I want and attach the titlebar as a parent for those windows. Once I do that I should be able to make the same backgroundColor() color call for each one. Of course, this will require me to keep track of when the controls or window are resized and adjust the NsWindows of the titlebar, and I am not sure what (if any) issues that could cause.
Maybe there is a way to essentially set the height of the titlebar to 0? I wonder if that's what the Discord app is doing because:
if you look closely, the edit box that says "Find or start a conversation" is vertically lined with the close, minimize and maximize buttons, as is the "Activity" label. But if the controls do extend to the top of the app's window then how are the standard app buttons getting painted?
I'd be curious to know how Slack and Discord accomplish this even though I know they're not using Qt.
I realize there is not a Qt solution since Qt does not paint the titlebar. I know this will be OS-specific, but since I do not have any real experience with Objective-C++ or working with Cocoa (all of my programming experience on macOS has been standard C++ with non-UI or Qt-based code) I'd appreciate any suggestions or guidance!
Natively this is done with fullSizeContentView and titlebarAppearsTransparent properties of NSWindow. Once you set them to true, you can draw or place controls beneath the title bar.

MFC picture control changes size when DPI awareness disabled or running on Win7

I made an MFC app for my friend using VS2015 in Win10. It looks like this, which is exactly the same as in resource editor.
.
But when he ran the app on his computer in Win7, the Bitmap image in Picture Control enlarges and covers up some text boxes below, which looks like this.
.
After I searched and realized it may be related with DPI awareness. I disabled DPI-Awareness in property page of Manifest Tool and rebuilt. The same thing happened even when it runs in Win10.
Could someone help me explain the cause of this and find a solution to fix the size of the image control? Thanks.
The main problem is that a dialog from a resource is always measured in DLUs.
And DLUs are calculated from the size of the font, that is used for the dialog.
See this article how dialog base units are calculated.
Now you have a static picture control that is sized in DLUs. The bitmap is just scaled in pixels and is never resized, when you assign it to a static dialog control. And because the real size of the static control depends on the used font, you get different layouts for your dialog and your bitmap.
And because just the font changes when you choose no DPI awareness and because the font changes from windows version to windows version your dialog always look different.
Advice: Paint you picture your own and stretch it accordingly.
Also this stackoverflow question is nice documents and shows the effect of DLUs.
And here some code for auto sizeing picture controls.
An auto-sizing bitmap picture control
A simple image preview class using GDI+
CxImage
Normally, I prefer to keep control in my hand by using SetWindowPos() to set the size of image I want in different situations. You can use below two lines to control/set position and size of your image.
Assume ID of the Picture Control is IDC_STATIC2 then you can use like:
CStatic * pStatic = (CStatic *) GetDlgItem(IDC_STATIC2);
pStatic->SetWindowPos(NULL,20,20,50,50,0);

How do you scale the title bar on a DPI aware win application?

I am making my app dpi-aware per monitor by setting <dpiAware>True/PM</dpiAware> in the manifest file. I can verify with process explorer that this is indeed working or by calling GetProcessDpiAwareness.
This is all working fine and I can scale anything in the client area fine in my code. However, my only problem is that if I drag my app from a system-dpi monitor to a non-system dpi monitor, the title bar and any system menu would either become too big or too small. This isn't the case for most built-in apps (e.g. calc, edge browser, etc..) so there must be away to scale it properly. Does anyone how the devs at MS did this?
The screenshot below should explain my problem better. Also notice, that the padding between the close, min, and max button is different when it's scaled (96dpi).
Sample app I'm attaching a very simple app that is per-monitor dpi aware.
The Windows 10 Anniversary Update (v1607) has added a new API you must call to enable DPI scaling of the non-client areas: EnableNonClientDpiScaling. This function should be called, when WM_NCCREATE is received. The message is sent to the window's procedure callback during window creation.
Example:
case WM_NCCREATE:
{
if (!EnableNonClientDpiScaling(hWnd))
{
// Error handling
return FALSE;
}
return DefWindowProcW(...);
}
If the application's DPI-awareness context is DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, then calling EnableNonClientDpiScaling should be omitted, as it won't have any effect, although the function will still return successfully.
From the documentation:
Non-client scaling for top-level windows is not enabled by default. You must call this API to enable it for each individual top-level window for which you wish to have the non-client area scale automatically. Once you do, there is no way to disable it. Enabling non-client scaling means that all the areas drawn by the system for the window will automatically scale in response to DPI changes on the window. That includes areas like the caption bar, the scrollbars, and the menu bar. You want to call EnableNonClientDpiScaling when you want the operating system to be responsible for rendering these areas automatically at the correct size based on the API of the monitor.
See this blog post for additional information about DPI scaling changes in Windows 10 AU.
Does anyone how the devs at MS did this?
This has a pretty disappointing answer. Using Alin Constantin's WinCheat and inspecting the top-level window of Calculator, I see a window size of 320x576, and a client size that is also 320x576.
In other words, Microsoft entirely avoids the problem by suppressing the non-client area of the window, putting everything in the client area instead. Making this work well for you may involve custom drawing of the title bar.
Something worth noting is that Calculator and e.g. Windows Explorer don't use the same colour for the title bars. Calculator doing custom drawing of the title bar would explain that perfectly.
UPDATE:
It is enough to add new <dpiAwarness> declaration to manifest to solve all this mess. Example is here.
Remnants of former investigations (obsolete):
More investigations on the subject.
System setup: two monitors, one is 96 dpi another one is 267 dpi (Microsoft Surface 4).
Testing window is moved to secondary 96 dpi monitor:
Here is rendering (wrong, IMO) with <dpiAware>true/pm</dpiAware> in manifest:
Note huge size of caption bar and wrong sizes of window icons.
And here is correct rendering using <dpiAware>true</dpiAware>
And I suspect that MSDN documentation is plainly misleading about values of PROCESS_DPI_AWARENESS. I do not see any differences in messages and styles between <dpiAware>true</dpiAware> and <dpiAware>true/pm</dpiAware>. The later one just makes caption larger. In both case application receives WM_DPICHANGED message while moving between monitors with different DPI.
Sigh.
The documentation says:
Note that the non-client area of a per monitor–DPI aware application is not scaled by Windows, and will appear proportionately smaller on a high DPI display.
The Microsoft apps that you link to deal with this by removing the non-client area and making the client area cover the entire window.

How do I place my app window in a certain position in the desktop window hierarchy on Windows using win32 api?

I want my application window to be in a certain spot in the window hierarchy. That is, say I have 3 windows on my desktop. At the very bottom I have Word, the window on top of word is explorer, and the active foreground window is itunes. I want to place my application window on top of word but beneath explorer. How can I achieve this with win32?
You might be able to use SetWindowPos - look at the hWndInsertAfter parameter. I'm not sure if this will work across process boundaries, but it's worth a shot. Perform this after your window is created but before you make it visible.
This is most likely not possible, because you will get caught by the code that tries to prevent focus stealing - it might work if your app initially has focus and you try to give it away (i.e. you are on top, then you try to hide behind the Explorer window)
If you want to maintain this arrangement, the simplest way is to create your window specifying Words window as your parent
Otherwise SetwindowPos is the all purpose worker for controlling a windows position, visibility and depth. But any z-ordering performed here will obviously be lost as soon as the user actually starts switching tasks.
One thing to watch out for: windows always raises the active window to the top of the z-order, and likewise, activates any window that is moved to the top of the z-order. There are restrictions however :- to prevent all manner of irritating behaviour Windows prevents applications from stealing activation without a user interaction - which means that, if word is currently the active window, SetWindowPos to place yourself above Word will only succeed if your app is allowed to take activation at that time.

User-Interface: Best way to toggle MDI frame's on-top status?

I maintain an MFC (VC6) MDI application that uses Frame Windows as views for a document. There is only one document at a time but there are several MDI-Frames each with a different view of the document data.
Recently a request came up to be able to keep one of those frame windows on top of the others while being able to interact with the background windows.
One idea was to add a "pin-button" to the frame's title bar. During my research I found out that every implementation uses bitmaps instead of for example CButton objects. This starts to get ugly as soon as one uses window colors other than the default-grey let alone UI-Themes.
An option in the menu of the frame window (the thing that appears when left-clicking the window icon in the title bar) would be possible but I'm searching for something that is more obvious to the user.
What other possibilities to set this frame window's on-top state are there?
Update
I have decided to go for the solution suggested by Uli as that one works fine with the XP themes.
Unfortunately this directly lead me to my next question: How can I actually make the frame window stay on top?
Maybe this or this helps.
Uli