{"id":2326,"date":"2022-05-17T03:17:09","date_gmt":"2022-05-17T03:17:09","guid":{"rendered":"https:\/\/cml-a.com\/content\/?p=2326"},"modified":"2022-05-17T03:17:09","modified_gmt":"2022-05-17T03:17:09","slug":"why-doesnt-btns_dropdown-work","status":"publish","type":"post","link":"https:\/\/cml-a.com\/content\/2022\/05\/17\/why-doesnt-btns_dropdown-work\/","title":{"rendered":"Why doesn't BTNS_DROPDOWN work?"},"content":{"rendered":"\n<p>Say you're writing a Win32 application. You add a toolbar. Simple enough.  Toolbar would look better with some things on it.  <\/p>\n\n\n\n<p>You want to, say, add a button to it. Like this<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/image-5.png\" alt=\"\" class=\"wp-image-2373\"\/><\/figure>\n\n\n\n<p>Flip through <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20120517-01\/?p=7593\">Petzold<\/a>. <\/p>\n\n\n\n<p>No chapters for toolbar dropdowns. <\/p>\n\n\n\n<p>No obvious samples to use. <\/p>\n\n\n\n<p>We're on our own, then.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Attempt 1: BTNS_DROPDOWN<\/h2>\n\n\n\n<p>You follow some of the sample code, and do the most natural thing. Use the toolbar button style 'BTNS_DROPDOWN'. (By the way, BTNS_DROPDOWN is the updated define for TBSTYLE_DROPDOWN. They mean the same thing.)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n    TBBUTTON tbButtons[] =\n    {\n        { STD_CUT, 0, TBSTATE_ENABLED, BTNS_DROPDOWN, {0}, 0, (INT_PTR)L\"Test\" },\n    };\n\n    m_hwnd = CreateToolbarEx(\n        parent,\n        WS_CHILD | WS_VISIBLE | CCS_ADJUSTABLE | TBSTYLE_TOOLTIPS,\n        0, \n        sizeof(tbButtons) \/ sizeof(TBBUTTON), \/\/nBitmaps\n        HINST_COMMCTRL,\n        0, \/\/ wBMID\n        tbButtons, \/\/lpButtons\n        sizeof(tbButtons) \/ sizeof(TBBUTTON), \/\/ iNumButtons\n        90, 90, 90, 90,\n        sizeof(TBBUTTON)); \/\/ uStructSize\n\n    SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this);\n    SendMessage(m_hwnd, TB_AUTOSIZE, 0, 0);\n    ShowWindow(m_hwnd, TRUE);\n <\/code><\/pre>\n\n\n\n<p>Compile and run. STD_CUT is your standard built-in Windows scissors 'cut' icon. Result looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/image.png\" alt=\"\" class=\"wp-image-2331\"\/><\/figure>\n\n\n\n<p>That visually looks fine. But wait. Let's try clicking on it.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/PointlessClick2.mp4\"><\/video><figcaption>Clicking on it doesn't do anything \ud83d\ude41<\/figcaption><\/figure>\n\n\n\n<p>It doesn't even show a 'button is pushed' animation. It should at least do that, right?<\/p>\n\n\n\n<p>What gives? It's not disabled. <\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Attempt 2: TBSTYLE_EX_DRAWDDARROWS<\/h2>\n\n\n\n<p>Okay, so maybe our initialization of the dropdown menu was incomplete. Dropdown menus usually have an arrow at the right. Perhaps we need to add the \"arrow at the right\" extended style? Let's try adding the code<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    SendMessage(m_hwnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS);<\/code><\/pre>\n\n\n\n<p>So that now, it looks like<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n    TBBUTTON tbButtons[] =\n    {\n        { STD_CUT, 0, TBSTATE_ENABLED, BTNS_DROPDOWN, {0}, 0, (INT_PTR)L\"Test\" },\n    };\n\n    m_hwnd = CreateToolbarEx(\n        parent,\n        WS_CHILD | WS_VISIBLE | CCS_ADJUSTABLE | TBSTYLE_TOOLTIPS,\n        0, \n        sizeof(tbButtons) \/ sizeof(TBBUTTON), \/\/nBitmaps\n        HINST_COMMCTRL,\n        0, \/\/ wBMID\n        tbButtons, \/\/lpButtons\n        sizeof(tbButtons) \/ sizeof(TBBUTTON), \/\/ iNumButtons\n        90, 90, 90, 90,\n        sizeof(TBBUTTON)); \/\/ uStructSize\n\n    SendMessage(m_hwnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS);\n\n    SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this);\n    SendMessage(m_hwnd, TB_AUTOSIZE, 0, 0);\n    ShowWindow(m_hwnd, TRUE);\n <\/code><\/pre>\n\n\n\n<p>Let's compile and run it and see what it looks like now.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/image-1.png\" alt=\"\" class=\"wp-image-2345\"\/><\/figure>\n\n\n\n<p>This looks better. There's an arrow on the right. That should mean something good. Let's try clicking on it.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/PointlessClick3.mp4\"><\/video><\/figure>\n\n\n\n<p>Clicking on the button itself works. <\/p>\n\n\n\n<p>Clicking on the arrow doesn't \ud83d\ude41 <\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Attempt 3: BTNS_WHOLEDROPDOWN<\/h2>\n\n\n\n<p>Maybe the ticket is WHOLEDROPDOWN. Looking it up in the header, BTNS_WHOLEDROPDOWN purports to<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/image-2.png\" alt=\"\" class=\"wp-image-2351\"\/><\/figure>\n\n\n\n<p>That sounds like it could make the whole button appear responsive, so why not let's try it.<\/p>\n\n\n\n<p>Result looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/image-3.png\" alt=\"\" class=\"wp-image-2352\"\/><figcaption>The arrow is all merged with the button.<\/figcaption><\/figure>\n\n\n\n<p>Okay. What if we try to click on it?<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/PointlessClick4.mp4\"><\/video><\/figure>\n\n\n\n<p>Nothing happens \ud83d\ude41<\/p>\n\n\n\n<p>What to do?<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The Answer<\/h2>\n\n\n\n<p><strong>The answer<\/strong>: toolbar dropdown menus, by default, <strong>don't have any animation for clicking on them<\/strong>. They're not like normal buttons. That's right, the button is still working, there's just no visual feedback unless you explicitly attach some yourself. <\/p>\n\n\n\n<p>To make the toolbar dropdown button do something, you have to just trust that it is set up ok, and attach some behavior to the dropdown notification.<\/p>\n\n\n\n<p> Fortunately you don't have to re-invent the wheel to do that. Here's an easy way to attach a simple pop-up menu to the dropdown.<\/p>\n\n\n\n<p>First, you need to have your <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/winuser\/nc-winuser-wndproc\">WndProc<\/a> pay attention to <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/controls\/wm-notify\">WM_NOTIFY<\/a>. The handler can be something like<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n    case WM_NOTIFY:\n    {\n        LPNMTOOLBAR lpnmtb = (LPNMTOOLBAR)lParam;\n\n        if (lpnmtb->hdr.code == TBN_DROPDOWN)\n        {\n            \/\/ Get the coordinates of the button.\n            RECT rc;\n            SendMessage(lpnmtb->hdr.hwndFrom, TB_GETRECT, (WPARAM)lpnmtb->iItem, (LPARAM)&amp;rc);\n\n            \/\/ Convert to screen coordinates.            \n            MapWindowPoints(lpnmtb->hdr.hwndFrom, HWND_DESKTOP, (LPPOINT)&amp;rc, 2);\n\n            HMENU hMenuLoaded = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU1));\n\n            \/\/ Get the submenu for the first menu item.\n            HMENU hPopupMenu = GetSubMenu(hMenuLoaded, 0);\n\n            TPMPARAMS tpm;\n            tpm.cbSize = sizeof(TPMPARAMS);\n            tpm.rcExclude = rc;\n\n            TrackPopupMenuEx(hPopupMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL, rc.left, rc.bottom, hWnd, &amp;tpm);\n\n            DestroyMenu(hMenuLoaded);\n        }\n        break;\n    }<\/code><\/pre>\n\n\n\n<p>As for the menu IDR_MENU1, you can point it to a menu you have defined. Or, if you want a placeholder thing, put something like this in your .rc file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>IDR_MENU1 MENU\nBEGIN\n    POPUP \"TEST\"\n    BEGIN\n        MENUITEM \"Option 1\",                        ID_TEST_OPTION1\n        MENUITEM \"Option 2\",                        ID_TEST_OPTION2\n    END\nEND<\/code><\/pre>\n\n\n\n<p>That goes along with these defines in the Resources.h coupled to the .rc file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define IDR_MENU1                       132\n#define ID_TEST_OPTION1                 32777\n#define ID_TEST_OPTION2                 32778<\/code><\/pre>\n\n\n\n<p>Build, and you get this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/image-6.png\" alt=\"\" class=\"wp-image-2387\"\/><\/figure>\n\n\n\n<p>In animated form:<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/UsefulClick2.mp4\"><\/video><\/figure>\n\n\n\n<p>The dropdown works. Success!<\/p>\n\n\n\n<p>It so happens if you re-try Attempt 2, TBSTYLE_EX_DRAWDDARROWS <strong>with <\/strong>a pop up menu, then it'll provide visual arrow-is-pressed feedback where it didn't before. See:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2022\/05\/image-7.png\" alt=\"\" class=\"wp-image-2393\"\/><\/figure>\n\n\n\n<p>This is because BTNS_DROPDOWN, TBSTYLE_EX_DRAWDDARROWS, and BTNS_WHOLEDROPDOWN follow a common principle: anything that appeared unresponsive with no pop up menu attached is responsive once a menu is attached.<\/p>\n\n\n\n<p>This system was not super well explained elsewhere, so maybe this will help you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Say you&#8217;re writing a Win32 application. You add a toolbar. Simple enough. Toolbar would look better with some things on it. You want to, say, add a button to it. Like this Flip through Petzold. No chapters for toolbar dropdowns. No obvious samples to use. We&#8217;re on our own, then. Attempt 1: BTNS_DROPDOWN You follow [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[178,204,222],"class_list":["post-2326","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-software-development-project","tag-ui","tag-win32"],"_links":{"self":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts\/2326","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/comments?post=2326"}],"version-history":[{"count":0,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts\/2326\/revisions"}],"wp:attachment":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/media?parent=2326"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/categories?post=2326"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/tags?post=2326"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}