{"id":993,"date":"2014-05-14T07:00:00","date_gmt":"2014-05-14T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/05\/14\/the-mystery-of-the-icon-that-never-appears\/"},"modified":"2014-05-14T07:00:00","modified_gmt":"2014-05-14T07:00:00","slug":"the-mystery-of-the-icon-that-never-appears","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20140514-00\/?p=993","title":{"rendered":"The mystery of the icon that never appears"},"content":{"rendered":"<p>\nA customer reported a problem showing an icon on their dialog box.\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nWe verified that this code does execute during\nthe handling of the <code>WM_INIT&shy;DIALOG<\/code> message.\nNo assertion fires, yet no icon appears either.\n<\/p>\n<pre>\nSHFILEINFO sfi = { 0 };\nDWORD_PTR dwResult = SHGetFileInfo(m_pszFile, &amp;sfi,\n                                   sizeof(sfi), SHGFI_ICON);\nassert(dwResult != 0);\nm_hico = sfi.hIcon;\nassert(m_hico != nullptr);\nassert(GetDlgItem(hdlg, IDI_CUSTOMICON) != nullptr);\nSendDlgItemMessage(hdlg, IDI_CUSTOMICON,\n                   WM_SETICON, ICON_BIG, (LPARAM)m_hico);\nassert(SendDlgItemMessage(hdlg, IDI_CUSTOMICON,\n                   WM_GETICON, ICON_BIG, 0) == (LPARAM)m_hico);\n<\/pre>\n<p>\nOur dialog template says\n<\/p>\n<pre>\n  ICON \"\", IDI_CUSTOMICON, 10, 10, 0, 0\n<\/pre>\n<\/blockquote>\n<p>\nThe customer did some helpful preliminary troubleshooting:\n<\/p>\n<ul>\n<li>Verify that the code does indeed execute.\n    It sounds obvious, but some people forget to check this.\n    They get distracted trying to figure out why a function isn&#8217;t\n    working, when in fact the root cause is that\n    <i>you forgot to call the function in the first place<\/i>.<\/p>\n<li>Verify that the <code>SHGet&shy;File&shy;Info<\/code>\n    call succeeded.\n    That rules out the case that the static control is\n    displaying nothing because you didn&#8217;t give it anything to display.<\/p>\n<li>Verify via <code>Get&shy;Dlg&shy;Item<\/code>\n    that the control you&#8217;re trying to talk to really does exist.\n    That rules out the case that you are talking to an empty room.\n    (For example, maybe you added the control to the wrong template.)<\/p>\n<li>Verify via <code>WM_GET&shy;ICON<\/code> that the attempt\n    to change the icon really worked.\n<\/ul>\n<p>\nThe problem is that the customer is using the wrong icon-setting message.\n<\/p>\n<p>\nThe <code>WM_SET&shy;ICON<\/code> message\nlets you customize the icon that is\ndisplayed in the window&#8217;s caption bar.\nFor this to have any effect, your window naturally needs to have the\n<code>WS_CAPTION<\/code> style.\nIf you don&#8217;t have a caption, then telling the window manager,\n&#8220;Please display this icon in my caption&#8221; is mostly a waste of time.\nIt&#8217;s like signing up for a lawn-mowing service when you don&#8217;t have\na lawn.\n<\/p>\n<p>\nThe message to change the icon displayed\n<i>inside<\/i> a static control is\n<code>STM_SET&shy;ICON<\/code>.\n<\/p>\n<pre>\nSendDlgItemMessage(hdlg, IDI_CUSTOMICON,\n                   STM_SETICON, (LPARAM)m_hico, 0);\n<\/pre>\n<p>\n<b>Red herring<\/b>:\nSome of you may have noticed that the customer set their\ncontrol size to 0&times;0.\n&#8220;You aren&#8217;t seeing an icon because you set the control to zero size!&#8221;\nBut since this control was not created with\n<code>SS_REAL&shy;SIZE&shy;CONTROL<\/code> or\n<code>SS_CENTER&shy;IMAGE<\/code>,\nthe control will resize itself to match the size of the icon.\n<\/p>\n<p>\nHere&#8217;s a sample program to show both types of icons set on the same\nwindow, so you can see the difference.\n<\/p>\n<pre>\n#include &lt;windows.h&gt;\n#include &lt;commctrl.h&gt;\nLRESULT CALLBACK SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,\n    LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)\n{\n switch (uMsg) {\n case WM_NCDESTROY:\n  RemoveWindowSubclass(hwnd, SubclassProc, 0);\n  PostQuitMessage(0);\n  break;\n }\n return DefSubclassProc(hwnd, uMsg, wParam, lParam);\n}\nint WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,\n                   PSTR lpCmdLine, int nShowCmd)\n{\n HWND hwnd = CreateWindow(\"static\", nullptr,\n               WS_OVERLAPPEDWINDOW | WS_VISIBLE |\n               SS_ICON | SS_CENTERIMAGE,\n               CW_USEDEFAULT, CW_USEDEFAULT,\n               CW_USEDEFAULT, CW_USEDEFAULT,\n               nullptr, nullptr, hinst, nullptr);\n SetWindowSubclass(hwnd, SubclassProc, 0, 0);\n HICON hicoCaption = LoadIcon(nullptr, IDI_EXCLAMATION)\n SendMessage(hwnd, WM_SETICON, ICON_BIG,\n             reinterpret_cast&lt;LPARAM&gt;(hicoCaption));\n HICON hicoClient = LoadIcon(nullptr, IDI_QUESTION);\n SendMessage(hwnd, STM_SETICON,\n             reinterpret_cast&lt;LPARAM&gt;(hicoClient), 0);\n MSG msg;\n while (GetMessage(&amp;msg, NULL, 0, 0)) {\n  TranslateMessage(&amp;msg);\n  DispatchMessage(&amp;msg);\n }\n DestroyIcon(hicoClient);\n DestroyIcon(hicoCaption);\n return 0;\n}\n<\/pre>\n<p>\nWe create a top-level static window, which is highly unusual,\nsince static controls are nearly always children of some other window.\nI&#8217;m doing this specifically to show the two different icons.\nYou don&#8217;t want to do this in a real program.\n<\/p>\n<p>\nThe static control has the <code>SS_ICON<\/code>\nstyle, because we want it to display an icon, and the\n<code>SS_CENTER&shy;IMAGE<\/code> style,\nbecause we just want it to center the icon in its client area\nwithout resizing.\n(We will control the size.)\n<\/p>\n<p>\nWe subclass the window so that we can post a quit message to exit the program\nwhen the window is destroyed,\nwhich the user can do by pressing <code>Alt<\/code>+<code>F4<\/code>.\n(Hey, this is just a demo program.\nCatching clicks on the &times; button is just extra code that will\ndistract from the purpose of the demonstration.\nHeck, this entire subclass thing is already distracting from the purpose\nof the demonstration!)\n<\/p>\n<p>\nWe load up two icons, an exclamation point, which we set as our caption icon,\nand a question mark, which we put in our client area.\n(We could have used the\n<code>Static_Set&shy;Icon<\/code> macro in\n<code>windowsx.h<\/code> to send the\n<code>STM_SET&shy;ICON<\/code> message,\nbut I did it manually just to make the message explicit.)\n<\/p>\n<p>\nRun the program, and there you can see the two different types of icons:\nThe exclamation point goes in the caption, and the question mark\ngoes in the client area.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer reported a problem showing an icon on their dialog box. We verified that this code does execute during the handling of the WM_INIT&shy;DIALOG message. No assertion fires, yet no icon appears either. SHFILEINFO sfi = { 0 }; DWORD_PTR dwResult = SHGetFileInfo(m_pszFile, &amp;sfi, sizeof(sfi), SHGFI_ICON); assert(dwResult != 0); m_hico = sfi.hIcon; assert(m_hico != [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-993","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer reported a problem showing an icon on their dialog box. We verified that this code does execute during the handling of the WM_INIT&shy;DIALOG message. No assertion fires, yet no icon appears either. SHFILEINFO sfi = { 0 }; DWORD_PTR dwResult = SHGetFileInfo(m_pszFile, &amp;sfi, sizeof(sfi), SHGFI_ICON); assert(dwResult != 0); m_hico = sfi.hIcon; assert(m_hico != [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/993","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=993"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/993\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=993"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=993"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=993"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}