{"id":293,"date":"2012-02-12T13:24:30","date_gmt":"2012-02-12T02:24:30","guid":{"rendered":"http:\/\/blog.quppa.net\/?p=293"},"modified":"2012-02-12T13:24:30","modified_gmt":"2012-02-12T02:24:30","slug":"drawing-non-themed-push-buttons-in-windows","status":"publish","type":"post","link":"https:\/\/www.quppa.net\/blog\/2012\/02\/12\/drawing-non-themed-push-buttons-in-windows\/","title":{"rendered":"Drawing non-themed push buttons in Windows"},"content":{"rendered":"<p>When <a title=\"MSDN: Visual Styles\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/bb773187.aspx\">visual styles<\/a> are enabled in Windows, one may use the <a title=\"MSDN: DrawThemeBackground function\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/bb773289.aspx\">DrawThemeBackground function<\/a> to draw themed push buttons. However, users of Windows XP, Windows Vista and Windows 7 can disable visual styles by selecting the Windows Classic theme or one of the High Contrast themes (and in Windows 2000 and earlier, visual styles weren\u2019t available at all). The classic theming mode has been removed in Windows 8 (I have <a title=\"Quppa&#39;s Blog: Theming &amp; Visual Styles in Windows 8\" href=\"https:\/\/www.quppa.net\/blog\/2011\/10\/24\/theming-visual-styles-in-windows-8\/\">written about this previously<\/a>), so in that OS the visual styles APIs should always be available. I suspect it will be a long time before NT6.1 and earlier versions of Windows constitute an insignificant share of the market, though, so this post should be useful until then.<img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; margin: 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px\" title=\"Non-Themed Buttons\" border=\"0\" alt=\"Screenshot of Non-Themed Buttons\" align=\"right\" src=\"https:\/\/www.quppa.net\/blog\/wp-content\/uploads\/Non-Themed-Buttons.png\" width=\"250\" height=\"101\" \/><\/p>\n<p>There are four states that a non-themed button can be in: <strong>normal<\/strong>, <strong>pressed<\/strong>, <strong>defaulted<\/strong> or <strong>inactive<\/strong>. How can we draw these states?<\/p>\n<p>The rough non-themed equivalent of the DrawThemeBackground function is the <a title=\"MSDN: DrawFrameControl function\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd162480.aspx\">DrawFrameControl function<\/a>. It has a parameter <em>uType<\/em> that specifies the type of the frame control to draw \u2013 in our case, this should be <strong>DFC_BUTTON<\/strong> (= 4). The next parameter is <em>uState<\/em>. We should set this to <strong>DFCS_BUTTONPUSH<\/strong> (=0x0010). For the <strong>normal<\/strong> state, this is all that needs to be done. For the <strong>inactive<\/strong> state, we should set <em>uType<\/em> to <strong>DFCS_INACTIVE<\/strong> (=0x0100) | DFCS_BUTTONPUSH (in fact, this doesn\u2019t seem to change the appearance of the button frame; the button content\/text should be rendered as gray, but that&#8217;s out of the scope of this article).<\/p>\n<p>When a non-themed button is pressed or defaulted, it has a single pixel border drawn around it, and the frame control\u2019s bounding rectangle is contracted by 1 pixel on each side. The border\u2019s colour is that of the window frame (<strong>COLOR_WINDOWFRAME<\/strong> = 6) \u2013 you can use the <a title=\"MSDN: GetSysColorBrush function\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/dd144927.aspx\">GetSysColorBrush function<\/a> to get the appropriate brush. For the <strong>defaulted<\/strong> state, just call DrawFrameControl with <em>uType<\/em> set to DFCS_BUTTONPUSH (with the deflated rectangle). For the <strong>pressed<\/strong> state, it might seem like DFCS_PUSHED should be used for <em>uType<\/em>, but this creates an appearance different to that of standard push buttons. This style is used elsewhere, like on the Windows taskbar, for scrollbar buttons and window caption buttons, etc. Internet Explorer\u2019s owner\/custom-drawn buttons also use this style, and I\u2019m sure many other programs do, too. It should be avoided, however, if you\u2019re seeking the native appearance. To properly imitate a pressed push button, avoid using the DrawFrameControl function and use the <a title=\"MSDN: FrameRect function\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd144838.aspx\">FrameRect function<\/a> to draw an inner border with the button shadow colour (<strong>COLOR_BTNSHADOW<\/strong> = 16). It\u2019s important to then use the <a title=\"MSDN: FillRect function\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd162719.aspx\">FillRect function<\/a> to draw the background with the button face colour (<strong>COLOR_BTNFACE<\/strong> = 15).<\/p>\n<p>Here\u2019s some pseudocode to illustrate the whole process:<\/p>\n<pre class=\"lang:c decode:true \">\/* state = the button state\n   rect  = the bounding rectangle *\/\nuType = DFCS_BUTTONPUSH;\nif (state == DISABLED)\n  uType |= DFCS_INACTIVE;\nif (state == DEFAULTED || state == PRESSED) {\n  \/\/ draw the border if the push button is defaulted or pressed\n  brush = GetSysColorBrush(COLOR_WINDOWFRAME);\n  FrameRect(dc, &amp;rect, brush);\n  \/\/ deflate the rect to exclude the border just drawn\n  DeflateRect(&amp;rect, 1, 1);\n}\nif (state != PRESSED) {\n  \/\/ if the button\u2019s not pressed, we can use DrawFrameControl\n  DrawFrameControl(dc, &amp;rect, DFC_BUTTON, uType);\n} else {\n  \/\/ draw the inner shadow\n  brush = GetSysColorBrush(COLOR_BTNSHADOW);\n  FrameRect(dc, &amp;rect, brush);\n  \/\/ deflate the rect to exclude the inner border just drawn\n  DeflateRect(&amp;rect, 1, 1);\n  \/\/ draw the button face colour\n  brush = GetSysColorBrush(COLOR_BTNFACE);\n  FillRect(dc, &amp;rect, brush);\n}<\/pre>\n<p>In addition to drawing the background, note that for all states but <strong>pressed<\/strong>, the content (text) should be shifted one pixel left and one pixel up. When the button is pressed, it should move one pixel right and one pixel down, so it is centred in the button. Some owner\/custom-draw implementations neglect this detail.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When visual styles are enabled in Windows, one may use the DrawThemeBackground function to draw themed push buttons. However, users of Windows XP, Windows Vista and Windows 7 can disable visual styles by selecting the Windows Classic theme or one of the High Contrast themes (and in Windows 2000 and earlier, visual styles weren\u2019t available &hellip; <a href=\"https:\/\/www.quppa.net\/blog\/2012\/02\/12\/drawing-non-themed-push-buttons-in-windows\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Drawing non-themed push buttons in Windows&#8221;<\/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":[6],"tags":[148,159,160,170],"class_list":["post-293","post","type-post","status-publish","format-standard","hentry","category-programming","tag-themes","tag-user32","tag-uxtheme","tag-win32"],"_links":{"self":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts\/293","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/comments?post=293"}],"version-history":[{"count":0,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts\/293\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/media?parent=293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/categories?post=293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/tags?post=293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}