Skip to content
Advertisement

Child forms groups on taskbar

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

Taskbar - grouped child forms

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.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement