{"id":4343,"date":"2013-05-16T07:00:00","date_gmt":"2013-05-16T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/05\/16\/untangling-the-confusingly-named-wm_updateuistate-and-wm_changeuistate-messages\/"},"modified":"2013-05-16T07:00:00","modified_gmt":"2013-05-16T07:00:00","slug":"untangling-the-confusingly-named-wm_updateuistate-and-wm_changeuistate-messages","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130516-00\/?p=4343","title":{"rendered":"Untangling the confusingly-named WM_UPDATEUISTATE and WM_CHANGEUISTATE messages"},"content":{"rendered":"<p>I always get confused by the <code>WM_UPDATE&shy;UI&shy;STATE<\/code> and <code>WM_CHANGE&shy;UI&shy;STATE<\/code> messages, and I have to go figure them out each time I need to mess with them. So this time, I&#8217;m going to write it down so I don&#8217;t forget. Because the act of writing it down helps me to remember.<\/p>\n<p> It&#8217;s like in school, where the teacher says, &#8220;This is a closed-book, closed-notes exam, but you are allowed to bring one piece of standard 8&frac12;&Prime;&times;11&Prime; paper with you, on which you can write anything you like. No funny business.&#8221; You work really hard to create the ultimate sheet of paper to bring to the exam, and then it turns out that during the exam, you barely refer to it at all. Because the act of deciding what to put on the cheat sheet made you remember the material. <\/p>\n<p> Part of the problem with the messages <code>WM_UPDATE&shy;UI&shy;STATE<\/code> and <code>WM_CHANGE&shy;UI&shy;STATE<\/code> is their confusing names, because to most people <i>update<\/i> and <i>change<\/i> are basically the same concept. The difference is the direction the message travels. Before we look at that, let&#8217;s look at the mysterious <code>WPARAM<\/code>. <\/p>\n<p> The <code>WPARAM<\/code> specifies what action you want to perform (initialize, set, or clear) and the target of the action (focus, accelerators, or both). <\/p>\n<table border=\"1\" style=\"border-collapse: collapse\">\n<tr>\n<th>Action<\/th>\n<th>Meaning<\/th>\n<\/tr>\n<tr>\n<td><code>UIS_SET<\/code><\/td>\n<td>Set the flag (hide the indicator).<\/td>\n<\/tr>\n<tr>\n<td><code>UIS_CLEAR<\/code><\/td>\n<td>Clear the flag (show the indicator).<\/td>\n<\/tr>\n<tr>\n<td><code>UIS_INITIALIZE<\/code><\/td>\n<td>Set or clear the flag     based on whether the last input event was mouse (set)     or keyboard (clear).<\/td>\n<\/tr>\n<\/table>\n<p> Setting a flag hides the corresponding indicator. For example, if you have a <code>UIS_SET<\/code> for <code>UISF_HIDE&shy;FOCUS<\/code>, that means that you want to hide focus indicators. <\/p>\n<p> Clearing a flag shows the corresponding indicator. For example, if you have a <code>UIS_CLEAR<\/code> for <code>UISF_HIDE&shy;FOCUS<\/code>, that means that you want to show focus indicators. <\/p>\n<p> Yes, it&#8217;s a bit of a double-negative situation. <\/p>\n<p> Each window has its own internal state that remembers which indicators have been hidden for that window. You can query this state by sending the window a <code>WM_QUERY&shy;UI&shy;STATE<\/code> message. <\/p>\n<p> The <code>WM_UPDATE&shy;UI&shy;STATE<\/code> message travels down the tree: When a window receives the <code>WM_UPDATE&shy;UI&shy;STATE<\/code> message, it updates its state according to the <code>WPARAM<\/code> and then forwards the message to its children. Therefore, if you want to change the state for an entire window tree, you can send the <code>WM_UPDATE&shy;UI&shy;STATE<\/code> message to the top-level window, and the message will be delivered to that window and all its children. <\/p>\n<p> It&#8217;s called <i>update<\/i> because it says, &#8220;Okay, listen up everybody, this is what we&#8217;re going to do.&#8221; <\/p>\n<p> The <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message is more like a change <i>request<\/i>. It travels up the tree: When a window receives the message, it sees if the state being requested matches the window&#8217;s current state. If so, then processing stops since there is nothing to change. Otherwise, the window forwards the message to its parent. The idea here is to push the change request up the tree until it finds the top-level window. <\/p>\n<p> If a top-level window receives a <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message for a state change that actually changes something, it turns around and sends itself a <code>WM_UPDATE&shy;UI&shy;STATE<\/code> message, which as we saw before, tells the entire window tree to set its indicator state to the value specified. <\/p>\n<p> Okay, let&#8217;s draw a picture. Suppose we have a top-level window with two children, and suppose that everybody starts out with all indicators hidden. <\/p>\n<table>\n<tr>\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" summary=\"A top-level window named A, with children B and C. All of them are marked hideFocus=1 and hideAccel=1\">\n<tr>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\" style=\"width: 6em\">&nbsp;<\/td>\n<td colspan=\"2\" align=\"center\" style=\"border: solid black .75pt;height: 3em;width: 6em\">     <font size=\"+2\">A<\/font><br>hideFocus=1<br>hideAccel=1<\/td>\n<td colspan=\"2\" style=\"width: 6em\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td colspan=\"2\" style=\"width: 6em;border-bottom: solid black .75pt;border-right: solid black .75pt\">&nbsp;<\/td>\n<td colspan=\"2\" style=\"width: 6em;border-bottom: solid black .75pt\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td colspan=\"4\" style=\"width:12em;border-left: solid black .75pt;border-right: solid black .75pt\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\" align=\"center\" style=\"border: solid black .75pt;height: 3em;width: 6em\">     <font size=\"+2\">B<\/font><br>hideFocus=1<br>hideAccel=1<\/td>\n<td colspan=\"2\" style=\"width: 6em\">&nbsp;<\/td>\n<td colspan=\"2\" align=\"center\" style=\"border: solid black .75pt;height: 3em;width: 6em\">     <font size=\"+2\">C<\/font><br>hideFocus=1<br>hideAccel=1<\/td>\n<\/tr>\n<\/table>\n<p> Window&nbsp;B decides that it wants to show accelerators, say because the user tapped the <kbd>Alt<\/kbd> key. It sends itself a <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message with a <code>wParam<\/code> of <code>MAKEWPARAM(UIS_CLEAR, UISF_HIDE&shy;ACCEL)<\/code>. <\/p>\n<p> The <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message handler for Window&nbsp;B sees that the <code>UISF_HIDE&shy;ACCEL<\/code> flag is set, so the <i>clear<\/i> action is meaningful. It forwards the request to its parent, Window&nbsp;A. <\/p>\n<p> The <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message handler for Window&nbsp;A also sees that the <code>UISF_HIDE&shy;ACCEL<\/code> flag is set, so the <i>clear<\/i> action is meaningful. Since it has no parent, Window&nbsp;A converts the <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message to a <code>WM_UPDATE&shy;UI&shy;STATE<\/code> message and sends it to itself. <\/p>\n<p> The <code>WM_UPDATE&shy;UI&shy;STATE<\/code> message handler for Window&nbsp;A sees that it is being told to clear the <code>UISF_HIDE&shy;ACCEL<\/code> flag, so it clears the flag and then forwards the mesage to both its children. <\/p>\n<p> Each of the child windows B&nbsp;and&nbsp;C receive the <code>WM_UPDATE&shy;UI&shy;STATE<\/code> message and see that they are also being told to clear the <code>UISF_HIDE&shy;ACCEL<\/code> flag, so they do so. Those windows have no children of their own, so message processing stops. By this mechanism, Window&nbsp;B has managed to convince all the other windows in the hierarchy to clear the <code>UISF_HIDE&shy;ACCEL<\/code> flag. <\/p>\n<table>\n<tr>\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" summary=\"A top-level window named A, with children B and C. All of them are marked hideFocus=1 and hideAccel=0\">\n<tr>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\" style=\"width: 6em\">&nbsp;<\/td>\n<td colspan=\"2\" align=\"center\" style=\"border: solid black .75pt;height: 3em;width: 6em\">     <font size=\"+2\">A<\/font><br>hideFocus=1<br>hideAccel=0<\/td>\n<td colspan=\"2\" style=\"width: 6em\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td colspan=\"2\" style=\"width: 6em;border-bottom: solid black .75pt;border-right: solid black .75pt\">&nbsp;<\/td>\n<td colspan=\"2\" style=\"width: 6em;border-bottom: solid black .75pt\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<td colspan=\"4\" style=\"width:12em;border-left: solid black .75pt;border-right: solid black .75pt\">&nbsp;<\/td>\n<td style=\"width: 3em\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\" align=\"center\" style=\"border: solid black .75pt;height: 3em;width: 6em\">     <font size=\"+2\">B<\/font><br>hideFocus=1<br>hideAccel=0<\/td>\n<td colspan=\"2\" style=\"width: 6em\">&nbsp;<\/td>\n<td colspan=\"2\" align=\"center\" style=\"border: solid black .75pt;height: 3em;width: 6em\">     <font size=\"+2\">C<\/font><br>hideFocus=1<br>hideAccel=0<\/td>\n<\/tr>\n<\/table>\n<p> Now, suppose that Window&nbsp;C also decides to clear the accelerator indicator. It does the same thing as Window&nbsp;B and sends itself a <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message with a <code>wParam<\/code> of <code>MAKEWPARAM(UIS_CLEAR, UISF_HIDE&shy;ACCEL)<\/code>. This time, the <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message handler for Window&nbsp;C sees that the <code>UISF_HIDE&shy;ACCEL<\/code> flag is already clear, so the <i>clear<\/i> action is redundant. Message processing stops. <\/p>\n<p> These two examples show the flow of the UI state change messages. When somebody wants to suggest a change to the UI state, they send themselves a <code>WM_CHANGE&shy;UI&shy;STATE<\/code> message with a description of what they want to change. The above algorithm then kicks in to decide whether the change is meaningful, and if so, it notifies all the other windows in the hierarchy about the new state. <\/p>\n<p> <!-- forwardref: --> Next time, we&#8217;ll look at how this whole indicator state thing gets off the ground. <\/p>\n<\/tr>\n<\/table>\n<\/tr>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>I always get confused by the WM_UPDATE&shy;UI&shy;STATE and WM_CHANGE&shy;UI&shy;STATE messages, and I have to go figure them out each time I need to mess with them. So this time, I&#8217;m going to write it down so I don&#8217;t forget. Because the act of writing it down helps me to remember. It&#8217;s like in school, where [&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":[25],"class_list":["post-4343","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>I always get confused by the WM_UPDATE&shy;UI&shy;STATE and WM_CHANGE&shy;UI&shy;STATE messages, and I have to go figure them out each time I need to mess with them. So this time, I&#8217;m going to write it down so I don&#8217;t forget. Because the act of writing it down helps me to remember. It&#8217;s like in school, where [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/4343","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=4343"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/4343\/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=4343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=4343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=4343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}