{"id":2543,"date":"2012-03-13T16:47:15","date_gmt":"2012-03-13T16:47:15","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2012\/03\/13\/setting-winver-for-mfc-applications\/"},"modified":"2021-10-04T11:08:46","modified_gmt":"2021-10-04T11:08:46","slug":"setting-winver-for-mfc-applications","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/setting-winver-for-mfc-applications\/","title":{"rendered":"Setting WINVER for MFC Applications"},"content":{"rendered":"<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2012\/06\/6837.image_thumb_3440E26C.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2012\/06\/6837.image_thumb_3440E26C.png\" alt=\"Pat Brenner\" width=\"78\" height=\"104\" class=\"alignleft size-full wp-image-29012\" \/><\/a><\/p>\n<p>Hello, I\u2019m Pat Brenner, a developer on the Visual C++ Libraries team, and I am the primary developer working on MFC.<\/p>\n<p>I\u2019ve realized over the course of the past several years that a number of developers (especially those using ATL and\/or MFC) can be confused about the proper usage and setting of the <font face=\"Courier New\">WINVER #define<\/font> (and\/or the corresponding <font face=\"Courier New\">_WINNT_WIN32<\/font> and <font face=\"Courier New\">NTDDI_VERSION #defines<\/font>). This setting is especially important when building an application that supports multiple Windows platforms, as MFC itself does. So I would like to suggest a best practice for how these <font face=\"Courier New\">#defines<\/font> should be set when building an MFC application for multiple platforms.<\/p>\n<h2>Build time settings<\/h2>\n<p>At build time, you <b>should not<\/b><font face=\"Courier New\"> #define WINVER<\/font> (or <font face=\"Courier New\">_WINNT_WIN32<\/font> or <font face=\"Courier New\">NTDDI_VERSION<\/font>) to the lowest platform you want to support. This will keep you from using the latest APIs and structures available to you, and keep you from handling the latest Windows messages. Instead, you should <font face=\"Courier New\">#define WINVER<\/font> (or <font face=\"Courier New\">_WINNT_WIN32<\/font> or <font face=\"Courier New\">NTDDI_VERSION<\/font>) to the highest platform that you want to support. This will ensure that you have available the latest APIs, messages, and structures, so that your application can make use of all of the capabilities that the newest platforms have to offer. This is the way that MFC itself is built\u2014this way we can add handlers for the latest Windows messages and use the latest Windows APIs. For example, MFC 10.0 (which shipped with Visual Studio 2010) supported Windows XP as the lowest platform, but also supported features only available in Windows 7, like live taskbar display of multiple MDI window contents.<\/p>\n<h2>Run time behavior and checking<\/h2>\n<p>At run-time, however, you need to ensure that your application will run on your lowest supported platform. This means that you cannot call an API available only on newer platforms directly, because calling the API directly will result in an \u201cimport not found\u201d message on the older platform and your application will simply not start. Instead, you must dynamically load (via <font face=\"Courier New\">LoadLibrary<\/font>\/<font face=\"Courier New\">GetProcAddress<\/font>) any API that is supported only on newer platforms. For example, MFC does this when using the D2D APIs. Here\u2019s an example from the current version of MFC\u2014see the InitD2D method of the <font face=\"Courier New\">_AFX_D2D_STATE<\/font> class in module AFXRENDERTARGET.CPP provided with Visual Studio 11 Beta:<\/p>\n<p>&#160;<\/p>\n<pre class=\"code\"><span style=\"background: white;color: black\">m_hinstDWriteDLL = AtlLoadSystemLibraryUsingFullPath(L<\/span><span style=\"background: white;color: maroon\">&quot;DWrite.dll&quot;<\/span><span style=\"background: white;color: black\">);\r\n<\/span><span style=\"background: white;color: blue\">if <\/span><span style=\"background: white;color: black\">(m_hinstDWriteDLL != NULL)\r\n{\r\n    <\/span><span style=\"background: white;color: blue\">auto <\/span><span style=\"background: white;color: black\">pfD2D1CreateFactory = AtlGetProcAddressFn(m_hinstDWriteDLL, DWriteCreateFactory);\r\n    <\/span><span style=\"background: white;color: blue\">if <\/span><span style=\"background: white;color: black\">(pfD2D1CreateFactory)\r\n    {\r\n        hr = (*pfD2D1CreateFactory)(writeFactoryType, <\/span><span style=\"background: white;color: blue\">__uuidof<\/span><span style=\"background: white;color: black\">(IDWriteFactory), (IUnknown**)&amp;m_pWriteFactory);\r\n    }\r\n}\r\n<\/span><\/pre>\n<p>&#160;<\/p>\n<p>Note the use of the <font face=\"Courier New\">AtlLoadSystemLibraryUsingFullPath<\/font> helper (whose implementation is in ATLCORE.H), which will ensure that the \u201csystem\u201d DLL is loaded only from the correct Windows library folder. Also note the use of the <font face=\"Courier New\">AtlGetProcAddressFn<\/font> macro (whose definition is in ATLDEF.H), which will call <font face=\"Courier New\">GetProcAddress<\/font> using the correct function prototype.<\/p>\n<p>You also must ensure that you are not calling any Windows API with a structure that is larger than it expects, because it may simply fail. Make sure that you understand the structure size that the API is expecting on that platform and use that size. For example, MFC does this when sending tool-tip messages. Here\u2019s a (slightly modified) example from the current version of MFC\u2014see the <font face=\"Courier New\">HitTest<\/font> method of the <font face=\"Courier New\">CToolTipCtrl<\/font> class in module TOOLTIP.CPP, and the definition of the <font face=\"Courier New\">AFX_OLDTOOLTIPINFO<\/font> structure in AFXIMPL.H, provided with Visual Studio 11 Beta:<\/p>\n<p>&#160;<\/p>\n<pre class=\"code\"><span style=\"background: white;color: black\">TTHITTESTINFO hti = {};\r\nhti.ti.cbSize = <\/span><span style=\"background: white;color: blue\">sizeof<\/span><span style=\"background: white;color: black\">(AFX_OLDTOOLINFO);\r\nhti.hwnd = pWnd-&gt;GetSafeHwnd();\r\nhti.pt = pt;\r\n<\/span><span style=\"background: white;color: blue\">if <\/span><span style=\"background: white;color: black\">(::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)&amp;hti))\r\n{\r\n    Checked::memcpy_s(lpToolInfo, <\/span><span style=\"background: white;color: blue\">sizeof<\/span><span style=\"background: white;color: black\">(*lpToolInfo), &amp;hti.ti, <\/span><span style=\"background: white;color: blue\">sizeof<\/span><span style=\"background: white;color: black\">(AFX_OLDTOOLINFO));\r\n    <\/span><span style=\"background: white;color: blue\">return <\/span><span style=\"background: white;color: black\">TRUE;\r\n}\r\n<\/span><\/pre>\n<h2>Cautions <\/h2>\n<p>Please note that you do have to be careful when using this approach. It is very easy to end up using an API that is only available on a later platform, only to find that when your customers try to run your application on an older platform, it won\u2019t even run. When your application tries to load a non-existent API from a system DLL at startup (when the import table is being initialized), it will fail, and an error message to the effect of \u201cimport not found\u201d will be issued. So make sure to test your application on all supported platforms to make sure that it is compatible.<\/p>\n<p>It is only necessary to follow this recommended practice when building an application that is expected to support multiple Windows platforms. If your application only needs to support a single platform, you can set WINVER (or the corresponding other <font face=\"Courier New\">#defines<\/font>) to the value that matches that platform. This way you are sure to use only the APIs and other features that are available on that platform.<\/p>\n<p>I hope you find this information helpful. Please feel free to respond with any questions you may have.<\/p>\n<p>&#160;<\/p>\n<p>Pat Brenner\n  <br \/>Visual C++ Libraries Development<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello, I\u2019m Pat Brenner, a developer on the Visual C++ Libraries team, and I am the primary developer working on MFC. I\u2019ve realized over the course of the past several years that a number of developers (especially those using ATL and\/or MFC) can be confused about the proper usage and setting of the WINVER #define [&hellip;]<\/p>\n","protected":false},"author":289,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2543","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>Hello, I\u2019m Pat Brenner, a developer on the Visual C++ Libraries team, and I am the primary developer working on MFC. I\u2019ve realized over the course of the past several years that a number of developers (especially those using ATL and\/or MFC) can be confused about the proper usage and setting of the WINVER #define [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/2543","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/289"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=2543"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/2543\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=2543"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=2543"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=2543"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}