{"id":21613,"date":"2008-07-15T10:00:00","date_gmt":"2008-07-15T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2008\/07\/15\/the-evolution-of-menu-templates-16-bit-extended-menus\/"},"modified":"2008-07-15T10:00:00","modified_gmt":"2008-07-15T10:00:00","slug":"the-evolution-of-menu-templates-16-bit-extended-menus","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20080715-00\/?p=21613","title":{"rendered":"The evolution of menu templates: 16-bit extended menus"},"content":{"rendered":"<p><P>\nWindows&nbsp;95 introduced a new menu format,\nknown as &#8220;extended menus&#8221;.\nYou declare these in a resource file with the <CODE>MENUEX<\/CODE> keyword.\nThe 16-bit extended menu is really just a temporary stopping point\non the way to the 32-bit extended menu,\nsince the 16-bit form is\nsupported only by the Windows&nbsp;95 family of operating\nsystems.\nIt&#8217;s sort of the missing link of menu templates.\n<\/P>\n<P>\nThings start off the same as\n<A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/07\/09\/8711897.aspx\">\nthe 16-bit classic menu<\/A>,\nwith a structure I&#8217;ve been calling <CODE>MENUHEADER16<\/CODE>:\n<\/P>\n<PRE>\nstruct MENUHEADER16 {\n WORD wVersion;\n WORD cbHeaderSize;\n BYTE rgbExtra[cbHeaderSize-4];\n};\n<\/PRE>\n<P>\nThe version number for extended menus is one instead of zero,\nand the <CODE>cbHeaderSize<\/CODE> now includes the size of the\n<CODE>wVersion<\/CODE> and <CODE>cbHeaderSize<\/CODE> fields in\nthe header size count; therefore, the number of interstitial bytes\nfour less than the value specified by the <CODE>cbHeaderSize<\/CODE> member.\n<\/P>\n<P>\nDue to a bug in Windows&nbsp;95 (and its descendants),\nthe <CODE>cbHeaderSize<\/CODE> is ignored, and its value is assumed\nto be four.\nFortunately, every version of the 16-bit resource compiler that\nsupports 16-bit extended menu templates sets the <CODE>cbHeaderSize<\/CODE>\nto four.\nConsequently, nothing goes wrong in practice.\nAnd I suspect nobody has noticed this bug in the over fifteen years\n(not twenty-five\n<A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/07\/15\/8732375.aspx#8733629\">\nas I had originally written<\/A>)\nthe code has been in existence.\n<\/P>\n<P>\nUnlike the classic menu, there is a prefix structure that\ncomes before the list of menu items.\n<\/P>\n<PRE>\nstruct MENUPREFIX16 {\n DWORD dwContextHelpID;\n};\n<\/PRE>\n<P>\nNew to extended menus is the addition of context help&nbsp;IDs.\nThese values can be set and retrieved\nprogrammatically with the\n<CODE>GetMenuContextHelpId<\/CODE> and\n<CODE>SetMenuContextHelpId<\/CODE> functions.\n<\/P>\n<P>\nThe template then continues with a packed array of structures\nI will call <CODE>MENUITEMEX16<\/CODE>:\n<\/P>\n<PRE>\nstruct MENUITEMEX16 {\n DWORD dwType;\n DWORD dwState;\n WORD  wID;\n BYTE  bFlags;\n CHAR  szText[]; \/\/ null terminated ANSI string\n};\n<\/PRE>\n<P>\nWhereas the members of the classic <CODE>MENUITEM16<\/CODE>\nwere designed to be passed to the function\n<CODE>InsertMenu<\/CODE>,\nthe members of the extended <CODE>MENUITEMEX16<\/CODE> were\ndesigned to be passed to the function\n<CODE>InsertMenuItem<\/CODE>.\nThe <CODE>dwType<\/CODE>, <CODE>dwState<\/CODE>, and\n<CODE>wID<\/CODE> members correspond to\nthe <CODE>fType<\/CODE>, <CODE>fState<\/CODE>, and\n<CODE>wID<\/CODE>\nmembers of the 16-bit <CODE>MENUITEMINFO<\/CODE> structure.\nSimilarly, the <CODE>szText<\/CODE> goes into the\n<CODE>dwItemData<\/CODE> if the item requires a string.\n(If the item doesn&#8217;t require a string, then the\n<CODE>szText<\/CODE> should be an empty string; i.e.,\nshould consist solely of the null terminator.)\n<\/P>\n<P>\nNotice that a new feature of extended menus is that pop-up menus\ncan have IDs as well as normal menu items.\n<\/P>\n<P>\nThe <CODE>bFlags<\/CODE> describes other information about the\nmenu item,\ninformation that in the classic menu was hidden in spare bits\nin the <CODE>wFlags<\/CODE>.\nBut here, the <CODE>bFlags<\/CODE> is where this information is kept.\nThe following flags are currently defined:\n<\/P>\n<TABLE BORDER=\"0\">\n<TR><TD><CODE>0x01<\/CODE><\/TD><TD>This item is a pop-up submenu<\/TD><\/TR>\n<TR><TD><CODE>0x80<\/CODE><\/TD><TD>This item is the last item in the menu<\/TD><\/TR>\n<\/TABLE>\n<P>\nIf indeed the bottom bit is set, then after the <CODE>MENUITEMEX16<\/CODE>\ncomes a description of the submenu, recursively.\n(Note that the submenu does not have\na <CODE>MENUHEADER16<\/CODE>.)\n<\/P>\n<P>\nAs before, we&#8217;ll illustrate this format with an example.\n<\/P>\n<PRE>\n1 MENUEX 1000\nBEGIN\n  POPUP &#8220;&amp;File&#8221;, 200,,, 1001\n  BEGIN\n    MENUITEM &#8220;&amp;Open\\tCtrl+O&#8221;, 100\n    MENUITEM &#8220;&#8221;, -1, MFT_SEPARATOR\n    MENUITEM &#8220;&amp;Exit\\tAlt+X&#8221;,  101\n  END\n  POPUP &#8220;&amp;View&#8221;, 201,,, 1002\n  BEGIN\n    MENUITEM &#8220;&amp;Status Bar&#8221;, 102,, MFS_CHECKED\n  END\nEND\n<\/PRE>\n<P>\nThe resulting 16-bit extended menu template begins with the header:\n<\/P>\n<PRE>\n0000  01 00          \/\/ wVersion = 1\n0002  04 00          \/\/ cbHeaderSize = 4\n<\/PRE>\n<P>\nSince this is the start of a menu, we get a context help ID:\n<\/P>\n<PRE>\n0004  E8 03 00 00    \/\/ dwContextHelpID = 1000\n<\/PRE>\n<P>\nAfter the context help ID come the menu items.\nOur first is a pop-up submenu,\nso the <CODE>bFlags<\/CODE> indicates that a submenu is coming:\n<\/P>\n<PRE>\n0008  00 00 00 00    \/\/ dwType = MFT_STRING\n000C  00 00 00 00    \/\/ dwState = 0\n0010  C8 00          \/\/ wID = 200\n0012  01             \/\/ bFlags = &#8220;pop-up submenu&#8221;\n0013  26 46 69 6C 65 00 \/\/ &#8220;&amp;File&#8221; + null terminator\n<\/PRE>\n<P>\nSince we have a pop-up submenu, we recursively include\na template for that submenu directly after the menu item template.\nConsequently, we begin with the context help&nbsp;ID:\n<\/P>\n<PRE>\n0019  E9 03 00 00    \/\/ dwContextHelpID = 1001\n<\/PRE>\n<P>\nAnd then the contents of the submenu:\n<\/P>\n<PRE>\n001D  00 00 00 00    \/\/ dwType = MFT_STRING\n0021  00 00 00 00    \/\/ dwState = 0\n0025  64 00          \/\/ wID = 100\n0027  00             \/\/ bFlags = 0\n0028  26 4F 70 65 6E 09 43 74 72 6C 2B 4F 00\n                     \/\/ &#8220;&amp;Open\\tCtrl+O&#8221; + null terminator<\/p>\n<p>0035  00 08 00 00     \/\/ dwType = MFT_SEPARATOR\n0039  00 00 00 00     \/\/ dwState = 0\n003D  FF FF           \/\/ wID = -1\n003F  00              \/\/ bFlags = 0\n0040  00              \/\/ &#8220;&#8221;<\/p>\n<p>0041  00 00 00 00     \/\/ dwType = MFT_STRING\n0045  00 00 00 00     \/\/ dwState = 0\n0049  65 00           \/\/ wID = 101\n004B  80              \/\/ bFlags = &#8220;this is the last menu item&#8221;\n004C  26 45 78 69 74 09 41 6C 74 2B 58 00\n                     \/\/ &#8220;&amp;Exit\\tAlt+X&#8221; + null terminator\n<\/PRE>\n<P>\nWhen we reach the end of the pop-up submenu, we \npop up a level.\nTherefore, the next entries describe more top-level menu items.\n<\/P>\n<PRE>\n0058  00 00 00 00     \/\/ dwType = MFT_STRING\n005C  00 00 00 00     \/\/ dwState = 0\n0060  C9 00           \/\/ wID = 201\n0062  81              \/\/ bFlags = &#8220;pop-up submenu&#8221; |\n                      \/\/          &#8220;this is the last menu item&#8221;\n0063  26 56 69 65 77 00 \/\/ &#8220;&amp;View&#8221; + null terminator\n<\/PRE>\n<P>\nAh, no sooner do we pop up than we push back down with\nanother submenu.\nAnd the &#8220;last menu item&#8221; flag is set,\nwhich means that once the submenu is finished,\nwe are done with the extended menu template.\n<\/P>\n<PRE>\n0069  EA 03 00 00    \/\/ dwContextHelpID = 1002<\/p>\n<p>006D  00 00 00 00    \/\/ dwType = MFT_STRING\n0071  08 00 00 00    \/\/ dwState = MFS_CHECKED\n0075  66 00          \/\/ wID = 102\n0077  80             \/\/ bFlags = &#8220;this is the last menu item&#8221;\n0078  26 53 74 61 74 75 73 20 42 61 72 00\n                     \/\/ &#8220;&amp;Status Bar&#8221; + null terminator\n<\/PRE>\n<P>\nAfter the context help ID, we have the sole menu item for\nthis pop-up submenu, so the first item is also the last item.\n<\/P>\n<P>\nNext time, we&#8217;ll wrap up by looking at the final menu template format,\nthe 32-bit extended menu.\nI bet you all can&#8217;t wait.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Windows&nbsp;95 introduced a new menu format, known as &#8220;extended menus&#8221;. You declare these in a resource file with the MENUEX keyword. The 16-bit extended menu is really just a temporary stopping point on the way to the 32-bit extended menu, since the 16-bit form is supported only by the Windows&nbsp;95 family of operating systems. It&#8217;s [&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":[2],"class_list":["post-21613","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Windows&nbsp;95 introduced a new menu format, known as &#8220;extended menus&#8221;. You declare these in a resource file with the MENUEX keyword. The 16-bit extended menu is really just a temporary stopping point on the way to the 32-bit extended menu, since the 16-bit form is supported only by the Windows&nbsp;95 family of operating systems. It&#8217;s [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/21613","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=21613"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/21613\/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=21613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=21613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=21613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}