{"id":2369,"date":"2016-08-22T16:03:50","date_gmt":"2016-08-23T00:03:50","guid":{"rendered":"http:\/\/pididu.com\/wordpress\/?p=2369"},"modified":"2016-10-24T08:35:56","modified_gmt":"2016-10-24T16:35:56","slug":"winapi-example-common-control-toolbar-in-a-pager","status":"publish","type":"post","link":"http:\/\/pididu.com\/wordpress\/blog\/winapi-example-common-control-toolbar-in-a-pager\/","title":{"rendered":"WINAPI Example: Common Control Toolbar in a Pager"},"content":{"rendered":"<p><a href=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/example.gif\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-2377 alignleft\" alt=\"example\" src=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/example.gif\" width=\"261\" height=\"198\" \/><\/a><br \/>\nA toolbar is that strip of &#8220;buttons&#8221; that appears in many Windows applications, such as the one outlined in red to the left.<\/p>\n<p>I had a lot of problems with programming my first toolbar. It would not appear, or not appear where I wanted it, or the buttons would behave in a strange way, or the customize dialog didn&#8217;t work right.<\/p>\n<p>Following is a minimal Windows app in plain c to create a toolbar. It was compiled under Visual Studio Express 2010.<\/p>\n<pre>\/\/ toolbartest.cpp : minimal app to make a toolbar\r\n\r\n#pragma comment(lib, \"comctl32.lib\")\r\n\r\n#include \"stdafx.h\"\r\n\r\n#include &lt;commctrl.h&gt;\r\n\r\n\/\/ Globals\r\nHINSTANCE hInst;\r\nHWND hWndMain, hWndToolbar;\r\n\r\nLRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);\r\n\r\nint WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,\r\n            LPSTR lpCmdLine, int nCmdShow )\r\n{\r\n  MSG  msg ;    \r\n  WNDCLASS wc = {0};\r\n\r\n  hInst = hInstance;\r\n\r\n  wc.lpszClassName = TEXT(\"MainClass\") ;\r\n  wc.hInstance     = hInst ;\r\n  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);\r\n  wc.lpfnWndProc   = WndProc ;\r\n  wc.hCursor       = LoadCursor(0, IDC_ARROW);\r\n\r\n  RegisterClass(&amp;wc);\r\n\r\n  hWndMain = CreateWindow(wc.lpszClassName, TEXT(\"ToolbarTest\"),\r\n                WS_OVERLAPPEDWINDOW | WS_VISIBLE,\r\n                100, 100, 400, 300, 0, 0, hInst, 0);  \r\n\r\n  DWORD status;\r\n  INITCOMMONCONTROLSEX ic;\r\n\r\n  ic.dwSize = sizeof(INITCOMMONCONTROLSEX);\r\n  ic.dwICC = ICC_BAR_CLASSES;\r\n  InitCommonControlsEx(&amp;ic);\r\n\r\n   \/\/ Create Toolbar.  Arbitrary ID of 231.\r\n   hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME,\r\n                    TEXT(\"Toolbar Title\"),\r\n                    WS_VISIBLE | WS_CHILD | CCS_NORESIZE\r\n                    | CCS_ADJUSTABLE,\r\n                    50, 50, 200, 50, hWndMain, (HMENU) 231, hInst, 0);\r\n\r\n\twhile( GetMessage(&amp;msg, NULL, 0, 0)) {\r\n\t\tTranslateMessage(&amp;msg);\r\n\t\tDispatchMessage(&amp;msg);\r\n  }\r\n  return (int) msg.wParam;\r\n}\r\n\r\nLRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )\r\n{\r\n  switch(msg)  \r\n  {\r\n    case WM_DESTROY:\r\n        PostQuitMessage(0);\r\n        break;\r\n    default:\r\n        return DefWindowProc(hwnd, msg, wParam, lParam);\r\n  }\r\n  return 0;\r\n}<\/pre>\n<p>A toolbar is one of the Windows Common Controls, so we need to include <strong>comctrl.h<\/strong>, and at some point, link the object with <strong>comctl32.lib<\/strong> . In this case, the toolbar is the only control that we wish to use, so we can set <strong>ICC_BAR_CLASSES <\/strong>at the appropriate place in a structure, and call <strong>InitCommonControlsEx()<\/strong>. And here is what shows up when the program is run:<\/p>\n<figure id=\"attachment_2378\" aria-describedby=\"caption-attachment-2378\" style=\"width: 400px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb1.gif\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-2378 \" alt=\"It's invisible\" src=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb1.gif\" width=\"400\" height=\"300\" \/><\/a><figcaption id=\"caption-attachment-2378\" class=\"wp-caption-text\">Where&#8217;s the toolbar?<\/figcaption><\/figure>\n<p>The thing is, just because we create a toolbar with the <strong>WS_VISIBLE<\/strong> style doesn&#8217;t mean that we&#8217;ll be able to see it. The toolbar is the same color as the default window background, making it invisible. In fact, the toolbar may even be overlaid over another control, effectively disabling the control under it, all while appearing invisible.<\/p>\n<p>Let&#8217;s add a button to the toolbar, so that we can see where it is. The following code is added just after creating the toolbar:<\/p>\n<pre>status = SendMessage(hWndToolbar, TB_SETBITMAPSIZE,\r\n            (WPARAM)0, (LPARAM)MAKELONG(24,24));\r\nstatus = SendMessage(hWndToolbar, TB_LOADIMAGES,\r\n            (WPARAM)IDB_HIST_LARGE_COLOR, (LPARAM)HINST_COMMCTRL);\r\nstatus = SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE,\r\n            sizeof(TBBUTTON), 0);\r\nstatus = SendMessage(hWndToolbar, TB_ADDBUTTONS,\r\n            1, (LPARAM)tbButtonsAdd);\r\nstatus = SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);<\/pre>\n<p>The first call with <strong>TB_SETBITMAPSIZE<\/strong> sets the size of the images on the buttons. If this is not done, we get 16&#215;16 pixels as the default.<\/p>\n<p>The next call with <strong>TB_LOADIMAGES<\/strong> loads a set of images into the toolbar to be available for use on buttons. <strong>IDB_HIST_LARGE_COLOR<\/strong> is an identifier for a standard set of bitmap images. Usually, we will want to make up our own image list, or add images individually with <strong>TB_ADDBITMAP<\/strong>, but this will do for a quick demo.<\/p>\n<p><strong>TB_BUTTONSTRUCTSIZE<\/strong> must be sent to the toolbar before adding any buttons. This is because different versions of common controls may have different structure sizes.<\/p>\n<p><strong>TB_ADDBUTTONS<\/strong> adds buttons (just 1 in this case), from a list of buttons pointed to by <strong>tbButtonsAdd<\/strong> (more on this below).<\/p>\n<p>Finally, any time buttons are added, <strong>TB_AUTOSIZE<\/strong> must be sent, so that the toolbar can update its dimensions.<\/p>\n<p><strong>tbButtonsAdd<\/strong> is an array of buttons, and is set up as follows:<\/p>\n<pre>\/\/ Button list for toolbar\r\n\/\/ Note that wide strings explicitly used - TEXT(\"label\") messes up dialog box, even\r\n\/\/ if compiled as non-unicode\r\n\/\/ Arbitrary command 100-104 assigned to buttons, will never be processed\r\nTBBUTTON tbButtonsAdd[] = {\r\n\t{MAKELONG(HIST_BACK,0), 100, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"one\"},\r\n\t{MAKELONG(HIST_FORWARD,0), 101, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"two\"},\r\n\t{MAKELONG(HIST_VIEWTREE,0), 102, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"three\"},\r\n\t{MAKELONG(HIST_ADDTOFAVORITES,0), 103, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"four\"},\r\n\t{MAKELONG(HIST_FAVORITES,0), 104, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"five\"}\r\n}; \r\nconst int numButtons = sizeof(tbButtonsAdd)\/sizeof(TBBUTTON);<\/pre>\n<p>The first element (for example, <strong>MAKELONG(HIST_BACK,0)<\/strong> ) in the structure for each button specifies the bitmap that will be used for the button. The second element is the command associated with the button being pushed. Looking again at the first button, if that is pushed, the main window will get a message of <strong>WM_COMMAND<\/strong>, with wParam set to the button ID of 100. Numbers have been arbitrarily chosen for the button IDs.<\/p>\n<p><strong><em>Each button must have a unique ID.<\/em><\/strong> It&#8217;s tempting to route multiple buttons to the same ID for prototyping purposes, but don&#8217;t do it. That will cause Windows to see the second button as a duplicate, and ignore it when the customize dialog (more on this below) is opened.<\/p>\n<p>With these changes to the code, the program&#8217;s window now looks like:<\/p>\n<figure id=\"attachment_2376\" aria-describedby=\"caption-attachment-2376\" style=\"width: 400px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb2.gif\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-2376 \" alt=\"toolbar has wrong place and size\" src=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb2.gif\" width=\"400\" height=\"300\" \/><\/a><figcaption id=\"caption-attachment-2376\" class=\"wp-caption-text\">At least something shows up now. But wait &#8211; didn&#8217;t we ask for the toolbar to be positioned elsewhere?<\/figcaption><\/figure>\n<p>Looking back at the <strong>CreateWindowEx()<\/strong> for the toolbar, we would expect the bar to be created at (50, 50) with a size of (200, 50). Yet, the toolbar is jammed up against the top of the window, and seems to have ignored our width and height specifications. In fact, even if we were to call <strong>SetWindowPos()<\/strong> on the toolbar, it would neither move nor size. Toolbars always seem to be placed at the top of the client area of their parent windows, and take up the entire width of the window. A little further down, we will move the toolbar to a non-default location.<\/p>\n<p>Toolbars have an ability to customize themselves. The user can shift-drag buttons to rearrange or delete them, or double-click on a non-button area of the toolbar to open a customization dialog like this:<\/p>\n<p><a href=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tbcustom.gif\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-2388\" alt=\"toolbar customize dialog\" src=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tbcustom.gif\" width=\"542\" height=\"235\" \/><\/a><\/p>\n<p>This is enabled by specifying the <strong>CCS_ADJUSTABLE<\/strong> style when creating the toolbar. Also, the following case needs to be added to the Windows Procedure for the main window:<\/p>\n<pre>case WM_NOTIFY:\r\n    switch( ((LPNMHDR)lParam )-&gt;code) {\r\n        case TBN_QUERYINSERT:\r\n        case TBN_QUERYDELETE:\r\n            \/\/ no need to check the source of the request, as\r\n            \/\/ there is only one toolbar in the program,\r\n            \/\/ and the answer is always yes\r\n            return true;\r\n            break;  \/\/ not really needed, but good discipline\r\n        case TBN_GETBUTTONINFO:  \r\n            LPTBNOTIFY lpTbNotify;\r\n            lpTbNotify = (LPTBNOTIFY)lParam;\r\n\r\n            \/\/ Pass the next button from the array. There is no need\r\n            \/\/ to filter out buttons that are already used \u2014 they will\r\n            \/\/ be ignored.\r\n            if (lpTbNotify-&gt;iItem &lt; numButtons) {\r\n                lpTbNotify-&gt;tbButton = tbButtonsAdd[lpTbNotify-&gt;iItem];\r\n                return TRUE;\r\n            } else {\r\n                return FALSE;  \/\/ No more buttons.\r\n            }\r\n            break;  \/\/ programming discipline\r\n        default:\r\n            break;\r\n    }\r\n    break;<\/pre>\n<p>It is important to return true in response to <strong>TBN_QUERYINSERT<\/strong> and <strong>TBN_QUERYDELETE<\/strong>. Without these affirmative responses, customizing the toolbar will not be possible.<\/p>\n<p>When <strong>TBN_GETBUTTONINFO<\/strong> is received, the lParam pointer, which pointed to a general <strong>NMHDR<\/strong> structure, is re-characterized to point at a <strong>TBNOTIFY<\/strong> structure. \u00a0Same address, just additional data at the end. \u00a0At this point, the code responds with info about the buttons that should be available for adding in the customize dialog.\u00a0Note that multiple\u00a0<strong>TBN_GETBUTTONINFO \u00a0<\/strong>messages will be received, until the code returns false, \u00a0indicating that there are no further buttons to make available.<\/p>\n<p>Now let&#8217;s move the toolbar to an arbitrary size and location. To do that, we will put the toolbar into another window, and move that window. The Pager common control is ideal for this. Here&#8217;s the updated window creation code:<\/p>\n<pre>ic.dwSize = sizeof(INITCOMMONCONTROLSEX);\r\nic.dwICC = ICC_BAR_CLASSES | ICC_PAGESCROLLER_CLASS;\r\nInitCommonControlsEx(&amp;ic);\r\n\r\n\/\/ Create Pager.  Arbitrary ID of 343.\r\n    hWndPager = CreateWindow(WC_PAGESCROLLER, NULL, WS_VISIBLE | WS_CHILD | PGS_DRAGNDROP | PGS_HORZ,\r\n    50, 100, 100, 50, hWndMain, (HMENU) 343, hInst, NULL);\r\n\r\n\/\/ Create Toolbar.  Arbitrary ID of 231.\r\n\/\/ The parent window is the Pager.\r\nhWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, TEXT(\"Toolbar in Pager Demo\"), WS_VISIBLE | WS_CHILD | CCS_NORESIZE | CCS_ADJUSTABLE,\r\n      0, 0, 200, 50, hWndPager, (HMENU) 231, hInst, NULL);\r\n\r\nstatus = SendMessage(hWndToolbar, TB_SETBITMAPSIZE ,\r\n            (WPARAM)0, (LPARAM)MAKELONG(24,24));\r\nstatus = SendMessage(hWndToolbar, TB_LOADIMAGES,\r\n            (WPARAM)IDB_HIST_LARGE_COLOR, (LPARAM)HINST_COMMCTRL);\r\nstatus = SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE,\r\n            sizeof(TBBUTTON), 0);\r\nstatus = SendMessage(hWndToolbar, TB_ADDBUTTONS,\r\n            5, (LPARAM)tbButtonsAdd);\r\n\r\nstatus = SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);\r\n\r\n\/\/ Notify the pager that it contains the toolbar\r\n\/\/ This is in addition to making the Pager Window\r\n\/\/ the parent of the Toolbar Window in CreateWindowEx()\r\nSendMessage(hWndPager, PGM_SETCHILD, 0, (LPARAM) hWndToolbar);<\/pre>\n<p>We add the <strong>ICC_PAGESCROLLER_CLASS<\/strong> to the set of common controls to initialize. \u00a0The parent of the Toolbar window is set to the Pager window. \u00a0Moreover, we send a <strong>PGM_SETCHILD<\/strong> message to set up the parent-child relationship.<\/p>\n<p>The result is this:<\/p>\n<figure id=\"attachment_2391\" aria-describedby=\"caption-attachment-2391\" style=\"width: 400px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb3.gif\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-2391\" alt=\"toolbar in a pager control\" src=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb3.gif\" width=\"400\" height=\"300\" \/><\/a><figcaption id=\"caption-attachment-2391\" class=\"wp-caption-text\">The toolbar is now contained in a pager, and the pager is located where we want on the screen. Only 3 of the 5 buttons we want to present to the user are available, though. One more change is needed.<\/figcaption><\/figure>\n<p>As the name implies, a Pager control will allow the user to page through its contents. In this case, we want to present 5 buttons, but the Pager is only big enough to show three. The following additional case needs to be added to the processing of <strong>WM_NOTIFY<\/strong>:<\/p>\n<pre>case PGN_CALCSIZE:\r\n    \/\/ If more than one pager in the program\r\n    \/\/ may need to check which one sent message\r\n    LPNMPGCALCSIZE pCS;\r\n    SIZE tbSize;\r\n    if (SendMessage(hWndToolbar, TB_GETIDEALSIZE, 0, (LPARAM) &amp;tbSize)) {\r\n        pCS = (LPNMPGCALCSIZE)lParam;\r\n        switch( pCS-&gt;dwFlag ){\r\n            case PGF_CALCHEIGHT:\r\n                pCS-&gt;iHeight = tbSize.cy;\r\n                break;\r\n            case PGF_CALCWIDTH:\r\n                pCS-&gt;iWidth = tbSize.cx;\r\n                break;\r\n            default:\r\n                break;\r\n        }\r\n}\r\nbreak;<\/pre>\n<p>The <strong>PGN_CALCSIZE<\/strong> notification is asking about the size of the contents of the pager. \u00a0For example, if <strong>pCS-&gt;iWidth<\/strong> is larger than the actual width of the pager, arrow(s) appear to page left and\/or right. \u00a0Think of iWidth as &#8220;ideal width&#8221;. \u00a0In this case, the contained control is the toolbar, so we obtain its ideal dimensions with the <strong>TB_GETIDEALSIZE<\/strong> message. With these changes, the window looks like this:<\/p>\n<figure id=\"attachment_2393\" aria-describedby=\"caption-attachment-2393\" style=\"width: 400px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb4.gif\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-2393\" alt=\"toolbar in pager now pageable\" src=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb4.gif\" width=\"400\" height=\"300\" \/><\/a><figcaption id=\"caption-attachment-2393\" class=\"wp-caption-text\">Here is the pager offering a page-right arrow, since the contained toolbar is too big to display all at once.<\/figcaption><\/figure>\n<figure id=\"attachment_2392\" aria-describedby=\"caption-attachment-2392\" style=\"width: 400px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb5.gif\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-2392\" alt=\"This is what it looks like after clicking the page-right arrow.\" src=\"http:\/\/pididu.com\/wordpress\/wp-content\/uploads\/2016\/08\/tb5.gif\" width=\"400\" height=\"300\" \/><\/a><figcaption id=\"caption-attachment-2392\" class=\"wp-caption-text\">This is what it looks like after clicking the page-right arrow.<\/figcaption><\/figure>\n<p>For good measure, the following is added, to insure that the pager&#8217;s scroll buttons appear or disappear properly any time buttons are added or deleted:<\/p>\n<pre>case TBN_TOOLBARCHANGE:\r\n    PostMessage(hWndPager, PGM_RECALCSIZE, 0, 0);\r\n    break;<\/pre>\n<p>Finally, here is the complete demo source:<\/p>\n<pre>\/\/ toolbartest.cpp : minimal app to demo issue\r\n\r\n#pragma comment(lib, \"comctl32.lib\")\r\n\r\n#include \"stdafx.h\"\r\n\r\n#include \r\n\r\n\/\/ Globals\r\nHINSTANCE hInst;\r\nHWND hWndMain, hWndPager, hWndToolbar;\r\n\/\/ Button list for toolbar\r\n\/\/ Note that wide strings explicitly used - TEXT(\"label\") messes up dialog box, even\r\n\/\/ if compiled as non-unicode\r\n\/\/ Arbitrary command 100-104 assigned to buttons, will never be processed\r\nTBBUTTON tbButtonsAdd[] = {\r\n\t{MAKELONG(HIST_BACK,0), 100, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"one\"},\r\n\t{MAKELONG(HIST_FORWARD,0), 101, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"two\"},\r\n\t{MAKELONG(HIST_VIEWTREE,0), 102, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"three\"},\r\n\t{MAKELONG(HIST_ADDTOFAVORITES,0), 103, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"four\"},\r\n\t{MAKELONG(HIST_FAVORITES,0), 104, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR) L\"five\"}\r\n}; \r\nconst int numButtons = sizeof(tbButtonsAdd)\/sizeof(TBBUTTON);\r\n\r\nLRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);\r\n\r\nint WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,\r\n            LPSTR lpCmdLine, int nCmdShow )\r\n{\r\n\tMSG  msg ;    \r\n\tWNDCLASS wc = {0};\r\n\r\n\thInst = hInstance;\r\n\r\n\twc.lpszClassName = TEXT(\"MainClass\") ;\r\n\twc.hInstance     = hInst ;\r\n\twc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);\r\n\twc.lpfnWndProc   = WndProc ;\r\n\twc.hCursor       = LoadCursor(0, IDC_ARROW);\r\n\r\n\tRegisterClass(&amp;wc);\r\n\r\n\thWndMain = CreateWindow(wc.lpszClassName, TEXT(\"ToolbarTest\"),\r\n                WS_OVERLAPPEDWINDOW | WS_VISIBLE,\r\n                100, 100, 400, 300, 0, 0, hInst, 0);  \r\n\r\n\tDWORD status;\r\n\tINITCOMMONCONTROLSEX ic;\r\n\r\n\tic.dwSize = sizeof(INITCOMMONCONTROLSEX);\r\n\tic.dwICC = ICC_BAR_CLASSES | ICC_PAGESCROLLER_CLASS;\r\n\tInitCommonControlsEx(&amp;ic);\r\n\r\n    \/\/ Create Pager.  Arbitrary ID of 343.\r\n\thWndPager = CreateWindow(WC_PAGESCROLLER, NULL, WS_VISIBLE | WS_CHILD | PGS_DRAGNDROP | PGS_HORZ,\r\n\t  50, 100, 100, 50, hWndMain, (HMENU) 343, hInst, NULL);\r\n\r\n    \/\/ Create Toolbar.  Arbitrary ID of 231.\r\n\t\/\/ The parent window is the Pager.\r\n\thWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, TEXT(\"Toolbar in Pager Demo\"), WS_VISIBLE | WS_CHILD | CCS_NORESIZE | CCS_ADJUSTABLE,\r\n      0, 0, 200, 50, hWndPager, (HMENU) 231, hInst, NULL);\r\n\r\n\tstatus = SendMessage(hWndToolbar, TB_SETBITMAPSIZE, (WPARAM)0, (LPARAM)MAKELONG(24,24));\r\n\tstatus = SendMessage(hWndToolbar, TB_LOADIMAGES, (WPARAM)IDB_HIST_LARGE_COLOR, (LPARAM)HINST_COMMCTRL);\r\n\tstatus = SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);\r\n\tstatus = SendMessage(hWndToolbar, TB_ADDBUTTONS, 5, (LPARAM)tbButtonsAdd);\r\n\r\n\tstatus = SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);\r\n\r\n\t\/\/ Notify the pager that it contains the toolbar\r\n\t\/\/ This is in addition to making the Pager Window the parent of the Toolbar Window\r\n\t\/\/ in CreateWindowEx()\r\n\tSendMessage(hWndPager, PGM_SETCHILD, 0, (LPARAM) hWndToolbar);\r\n\r\n\twhile( GetMessage(&amp;msg, NULL, 0, 0)) {\r\n\t\tTranslateMessage(&amp;msg);\r\n\t\tDispatchMessage(&amp;msg);\r\n    }\r\n\r\n\treturn (int) msg.wParam;\r\n}\r\n\r\nLRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )\r\n{\r\n  switch(msg)  \r\n  {\r\n \tcase WM_NOTIFY:\r\n\t\tswitch( ((LPNMHDR)lParam )-&gt;code) {\r\n\t\t\tcase PGN_CALCSIZE:\r\n\t\t\t\t\/\/ If more than one pager in the program\r\n\t\t\t\t\/\/ may need to check which one sent message\r\n\t\t\t\tLPNMPGCALCSIZE pCS;\r\n\t\t\t\tSIZE tbSize;\r\n\t\t\t\tif (SendMessage(hWndToolbar, TB_GETIDEALSIZE, 0, (LPARAM) &amp;tbSize)) {\r\n\t\t\t\t\tpCS = (LPNMPGCALCSIZE)lParam;\r\n\t\t\t\t\tswitch( pCS-&gt;dwFlag ){\r\n\t\t\t\t\t\tcase PGF_CALCHEIGHT:\r\n\t\t\t\t\t\t\tpCS-&gt;iHeight = tbSize.cy;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase PGF_CALCWIDTH:\r\n\t\t\t\t\t\t\tpCS-&gt;iWidth = tbSize.cx;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase TBN_TOOLBARCHANGE:\r\n\t\t\t\tPostMessage(hWndPager, PGM_RECALCSIZE, 0, 0);\r\n\t\t\t\tbreak;\r\n\t\t\tcase TBN_GETBUTTONINFO:  \r\n                LPTBNOTIFY lpTbNotify;\r\n\t\t\t\tlpTbNotify = (LPTBNOTIFY)lParam;\r\n\r\n                \/\/ Pass the next button from the array. There is no need to filter out buttons\r\n                \/\/ that are already used\u2014they will be ignored.\r\n                if (lpTbNotify-&gt;iItem &lt; numButtons) {                     lpTbNotify-&gt;tbButton = tbButtonsAdd[lpTbNotify-&gt;iItem];\r\n                    return TRUE;\r\n                } else {\r\n                    return FALSE;  \/\/ No more buttons.\r\n                }\r\n\t\t\t\tbreak;  \/\/ not really necessary, but keep programming discipline\r\n\t\t\tcase TBN_QUERYINSERT:\r\n\t\t\tcase TBN_QUERYDELETE:\r\n\t\t\t\t\/\/ no need to check the source of the request, as\r\n\t\t\t\t\/\/ there is only one toolbar in the program,\r\n\t\t\t\t\/\/ and the answer is always yes\r\n\t\t\t\treturn true;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tbreak;\r\n    case WM_DESTROY:\r\n        PostQuitMessage(0);\r\n        break;\r\n\tdefault:\r\n\t\treturn DefWindowProc(hwnd, msg, wParam, lParam);\r\n  }\r\n  return 0;\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>A toolbar is that strip of &#8220;buttons&#8221; that appears in many Windows applications, such as the one outlined in red to the left. I had a lot of problems with programming my first toolbar. It would not appear, or not appear where I wanted it, or the buttons would behave in a strange way, or &hellip; <a href=\"http:\/\/pididu.com\/wordpress\/blog\/winapi-example-common-control-toolbar-in-a-pager\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">WINAPI Example: Common Control Toolbar in a Pager<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[166],"tags":[211,168,210,206,209,208,207,205],"_links":{"self":[{"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/posts\/2369"}],"collection":[{"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/comments?post=2369"}],"version-history":[{"count":0,"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/posts\/2369\/revisions"}],"wp:attachment":[{"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/media?parent=2369"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/categories?post=2369"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/pididu.com\/wordpress\/wp-json\/wp\/v2\/tags?post=2369"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}