I got an application, which has a main window, and then it open new forms. Whole application is like a document reader with many types of sub-forms.
For example, I have Main window opened, 3 documet detail forms and 4 editors of other content.
Now. As all sub-forms are childrens of the main form, they are all grouped under one icon on taskbar, which can make a mess when you try to search for some window in list shown onhover.
Is it possible to tell the system, that all instances of specific form have to be grouped together in separate icon?
Like this
I got through some guides, but unfortunately, this specific problem I haven’t found beeing solved anywhere yet.
And althrough I am looking for C# implementation here for my app design and plain preview of solution, the real application will be probably implemented in Delphi, so the true and the main question is about if the operation systems even support this behavior, because of this is a huge override of normal behavior – is it even possible to do it that way in Windows? And it is also possible to do it on Linux (gnome, kde, xfce, unity) and MacOS? For theese questions, I don’t need to know HOW-TO, just if anyone hit the problem already and can point me to some solutions of articles mentioning this problem.
Thanks in advance.
Advertisement
Answer
I can’t help you with the other platforms such as Linux, but this is the Windows solution:
You can use the Windows taskbar API. For C#, .NET makes it available in a neat way. You have to reference the assemblies System.Xaml
and Microsoft.WindowsAPICodePack.Shell
, then you can use this code:
using Microsoft.WindowsAPICodePack.Taskbar; /* ... */ // Put this code in myForm.OnLoad or so TaskbarManager.Instance.SetApplicationIdForSpecificWindow(myForm.Handle, "MyInternalGroupID");
This will assign an “App Model ID” to your window. Windows will group all windows with the same app model ID together. So you have to use different names instead of MyInternalGroupID
for the different group.
Note that this will also work across multiple instances, so the windows belonging to the same group will appear together even when they come from multiple processes. If you don’t want that, you would have to include the current process ID in the group name.
Further reading: Taskbar API overview, The Old New Thing article (with C++ example)
For Delphi, I found a solution here, credits to Björn Ole:
unit uAppID; interface uses Windows, ActiveX, PropSys, PropKey; function GetAppID(AHandle: THandle): string; function SetAppID(AHandle: THandle; const AAppID: string): boolean; implementation function SHGetPropertyStoreForWindow(hwnd: hwnd; const riid: TGUID; out ppv: IPropertyStore) : HRESULT; stdcall; external 'shell32.dll'; function GetAppID(AHandle: THandle): string; var hr: HRESULT; pps: IPropertyStore; v: TPropVariant; begin hr := SHGetPropertyStoreForWindow(AHandle, IID_IPropertyStore, pps); if Succeeded(hr) then begin pps.GetValue(PKEY_AppUserModel_ID, v); result := v.bstrVal; end else result := ''; end; function SetAppID(AHandle: THandle; const AAppID: string): boolean; var hr: HRESULT; pps: IPropertyStore; v: TPropVariant; begin hr := SHGetPropertyStoreForWindow(AHandle, IID_IPropertyStore, pps); if Succeeded(hr) then begin v.vt := VT_BSTR; v.bstrVal := SysAllocString(PChar(AAppID)); result := pps.SetValue(PKEY_AppUserModel_ID, v) = S_OK; end else result := false; end; end.
You would need to call SetAppID
the way you call TaskbarManager.Instance.SetApplicationIdForSpecificWindow
in C#, basically.