1

When you use a CTaskDialog you can set the footer icon, which is 16 x 16. I would like to do something similar on my own dialog:

enter image description here

At the moment my own dialog has a static resource at the bottom.


I know that I can load the information icon like this:

HICON hInfo = LoadStandardIcon(IDI_INFORMATION);
  1. How do we load it as 16 x 16?
  2. How do we display it on the left on the dialog?
Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164

2 Answers2

2

If you (hopefully) don't need to support Windows XP, you can use LoadIconWithScaleDown

For example:

HICON hicon;
HRESULT hr = LoadIconWithScaleDown(NULL, (PCWSTR)IDI_INFORMATION,
             GetSystemMetrics(SM_CXICON) / 2, GetSystemMetrics(SM_CYICON) / 2,  &hicon);
...

This gives you the additional benefit of loading the modern version of the icons instead of the old ugly ones. See also this SO article.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • Awesome. And you would use that with a CStatic control dialog resource. Correct? – Andrew Truckle Jan 12 '22 at 07:24
  • 1
    @AndrewTruckle just use it the same way as if you'd use `LoadStandardIcon`. Simply `yourstaticcontrol.SetIcon(hicon)`. – Jabberwocky Jan 12 '22 at 07:26
  • Is it better to use GetSystemMetrics(SM_CXICON) etc instead of 16 to factor for DPI awareness? – Andrew Truckle Jan 12 '22 at 07:32
  • 1
    @AndrewTruckle Yes, actually `GetSystemMetrics(SM_CXICON) / 2` for the 16x16 icon. – Jabberwocky Jan 12 '22 at 07:39
  • 2
    `GetSystemMetrics` returns logical pixels. It is not DPI-aware, and indeed cannot be (which value should it return if you have two displays with different DPI settings?). If your application is marked as (per-monitor) DPI-aware you have to manually scale those sizes by a factor calculated from the result of calling e.g. [`GetDpiForWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow). – IInspectable Jan 12 '22 at 08:31
  • @IInspectable thank you for pointing that out. But for a system DPI aware program (not per monitor), it doesn't matter. Also `GetDpiForWindow` is only available on Windows 10, which leads to further complications if older Windows versions need to be supported (using `GetProcaddress` and fall back to `GetSystemMetrics` if appropriate). – Jabberwocky Jan 12 '22 at 08:36
  • I have used the picture control and mapped it to an icon. I added the code and it loads and displays. But its placement is somewhat ugley - upper left of the static control. Can we centralize it? – Andrew Truckle Jan 12 '22 at 08:40
  • 1
    @AndrewTruckle I think you should ask a new question with more details. – Jabberwocky Jan 12 '22 at 08:41
  • 1
    [`GetDpiForMonitor`](https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getdpiformonitor) is available on all supported versions of Windows. You can get the monitor with a call to [`MonitorFromWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow). As for *"system DPI aware"* I'm struggling to find an explanation why that isn't called *"DPI unaware"*. – IInspectable Jan 12 '22 at 08:51
  • 2
    @and [`SS_CENTERIMAGE`](https://learn.microsoft.com/en-us/windows/win32/controls/static-control-styles). – IInspectable Jan 12 '22 at 08:53
  • @IInspectable Great! - Now spotted that at the very bottom in the IDE. Sorted! – Andrew Truckle Jan 12 '22 at 08:54
2

You could do it by using Picture Control, and position it whenever you want. And as code you could do:

CStatic  myicon;
myicon.Attach(GetDlgItem(ID_STATIC_ICON));
myicon.SetIcon(static_cast<HICON>(::LoadImage(nullptr, MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0)));

I didn't test the code, but should work.

enter image description here

Flaviu_
  • 1,285
  • 17
  • 33