{"id":94745,"date":"2016-11-18T07:00:00","date_gmt":"2016-11-18T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=94745"},"modified":"2019-03-13T10:33:55","modified_gmt":"2019-03-13T17:33:55","slug":"20161118-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20161118-00\/?p=94745","title":{"rendered":"Why does calling SetForegroundWindow immediately followed by GetForegroundWindow not return the same window back?"},"content":{"rendered":"<p>A customer said that their program used <code>Find&shy;Window<\/code> to find a window in the system, then called <code>Set&shy;Foreground&shy;Window<\/code> to set that window to the foreground. The call succeeds, but if they enumerate the windows to check the z-order, the window that they set as foreground is not at the top of the z-order. And if they call <code>Get&shy;Foreground&shy;Window<\/code>, they don&#8217;t get that window back. <\/p>\n<p>So what does it mean when <code>Set&shy;Foreground&shy;Window<\/code> succeeds, but doesn&#8217;t actually set the foreground window? <\/p>\n<p>The <code>Set&shy;Foreground&shy;Window<\/code> function actually does two things, one immediately and one asynchronously. <\/p>\n<p>It immediately sets the input queue associated with the window as being the foreground input queue. Among other thing, it means that keyboard input will be directed to that input queue. It also means that threads belonging to that input queue now have permission to call <code>Set&shy;Foreground&shy;Window<\/code>, which is why many people affectionately call this <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20090220-00\/?p=19083\">having the foreground love<\/a>. <\/p>\n<p>The function also notifies the window, &#8220;Hey, you should make yourself the active window for your queue.&#8221; This notification is processed synchronously if the target window&#8217;s thread belongs to the same input queue as the thread that is calling <code>Set&shy;Foreground&shy;Window<\/code>, and it is processed asynchronously if the window belongs to a different thread group. This notification is done by roughly the same internal nudging mechanism that <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20130606-00\/?p=4153\">threads sharing an input queue use to coordinate access to input<\/a>. In particular, it means that the thread responsible for the target window needs to process messages in order to receive the nudge. <\/p>\n<p>The fact that the &#8220;Go make yourself the active window for your queue&#8221; portion is asynchronous (in the cross-thread-group case) means that at the moment that <code>Set&shy;Foreground&shy;Window<\/code> returns, the window is <i>becoming<\/i> the foreground window, but it is not necessarily the foreground window <i>yet<\/i>. If you check the z-order or call <code>Get&shy;Foreground&shy;Window<\/code>, you are likely to see that the target window hasn&#8217;t activated yet. <\/p>\n<p>Let&#8217;s assume that the customer&#8217;s program is doing this sort of <code>Find&shy;Window<\/code> trickery as part of test automation. And let&#8217;s suppose that they want the automation to wait until the target window has arrived to the foreground, so that it can continue the next step in the automation. <\/p>\n<p>A bad solution would be to use the <code>Attach&shy;Thread&shy;Input<\/code> function to connect the test automation tool&#8217;s input queue to the input queue of the target window. This is a bad solution because it means that if the target window has stopped responding, then the test automation will also stop responding. And it&#8217;s bad for a test to stop responding. The purpose of the test is to monitor the main application reliably, not to <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">get into the same jail<\/a>. (Or to use a different earlier analogy, to <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20130619-00\/?p=4043\">create a joint bank account with an unreliable chap<\/a>.) <\/p>\n<p>What the test could do is something like this: <\/p>\n<pre>\n    SetForegroundWindow(hwndTarget);\n\n    \/\/ Wait up to 5 seconds for the window to process the\n    \/\/ foreground notification.\n    DWORD_PTR result; \/\/ unused\n    if (!SendMessageTimeout(hwndTarget, WM_NULL,\n                            0, 0, 0, 5000, &amp;result)) {\n        \/\/ Window was unresponsive for 5 seconds, or the\n        \/\/ window was destroyed, or some other bad thing.\n        ReportFailedTest();\n    }\n\n    if (GetForegroundWindow() != hwndTarget) {\n        \/\/ The window did not become foreground for some reason.\n        \/\/ Maybe there was some interference from elsewhere in the\n        \/\/ system.\n        ReportFailedTest();\n    }\n<\/pre>\n<p>Here we take advantage of the <code>WM_NULL<\/code> message. This message does nothing, so sending it has no practical effect, but the fact that we sent a message means that our code waits for the window to finish processing the <i>previous<\/i> message, which was &#8220;Hey, you should make yourself the active window for your queue.&#8221; And that&#8217;s what we are <i>really<\/i> waiting for. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Because it&#8217;s not the foreground window&#8230; yet.<\/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-94745","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Because it&#8217;s not the foreground window&#8230; yet.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/94745","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=94745"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/94745\/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=94745"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=94745"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=94745"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}