{"id":93775,"date":"2016-06-29T07:00:00","date_gmt":"2016-06-29T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=93775"},"modified":"2019-03-13T11:51:31","modified_gmt":"2019-03-13T18:51:31","slug":"20160629-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20160629-00\/?p=93775","title":{"rendered":"How can I detect whether the Game Bar is covering my window?"},"content":{"rendered":"<p><a HREF=\"http:\/\/windows.microsoft.com\/en-us\/windows-10\/open-game-bar\">Pressing the <kbd>Win<\/kbd>+<kbd>G<\/kbd> hotkey opens the Game Bar<\/a>, which lets you record game clips and screenshots. Actually, I use it a lot even for programs that aren&#8217;t games: <!-- backref: I finally finished this awesome game called Photoshop, let me send you a video -->It&#8217;s great for taking video clips of a bug<\/a>. <\/p>\n<p>Anyway, maybe you have a program that wants to know when the Game Bar is on screen. For example, if you&#8217;re a game, you may want to pause the game automatically when the user is trying to configure their screen capture. <\/p>\n<p>If you are writing a Store app, you can register for Game Bar events. Here&#8217;s the short version for C# apps: <\/p>\n<pre>\nif (Windows.Gaming.UI.GameBar.Visible) {\n  the game bar is visible;\n}\n\nif (Windows.Gaming.UI.GameBar.IsInputRedirected) {\n  the game bar has input;\n}\n\nWindows.Gaming.UI.GameBar.VisibilityChanged +=\n    (s, e) =&gt; { the visibility changed };\nWindows.Gaming.UI.GameBar.IsInputRedirectedChanged +=\n    (s, e) =&gt; { the input state changed };\n<\/pre>\n<p>(Of course, you can avoid having to type <code>Windows.Gaming.UI<\/code> all the time by using the <code>using<\/code> statement, but I&#8217;m writing it out just to make it explicit what&#8217;s going on.) <\/p>\n<p>If you are a desktop app, you will have to talk to the ABI. It&#8217;s not too difficult, although it is a bit more tedious. <\/p>\n<p>Continuing our crash course in projection: <\/p>\n<table BORDER=\"1\" CELLPADDING=\"3\" style=\"border-collapse: collapse\">\n<tr>\n<th><\/th>\n<th>Call static method<\/th>\n<\/tr>\n<tr>\n<th>ABI<\/th>\n<td><code>IWidgetStatics* widgetStatics;<br>    GetActivationFactory(L\"Widget\", &amp;widgetStatics);<br>    widgetStatics-&gt;Foo();<\/code><\/td>\n<\/tr>\n<tr>\n<th>C++\/CX<\/th>\n<td><code>Widget::Foo();<\/code><\/td>\n<\/tr>\n<tr>\n<th>C#<\/th>\n<td><code>Widget.Foo();<\/code><\/td>\n<\/tr>\n<tr>\n<th>JavaScript<\/th>\n<td><code>Widget.foo();<\/code><\/td>\n<\/tr>\n<\/table>\n<p>At the ABI level, static members of a Windows Runtime class are represented as <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2012\/10\/19\/ccx-part-4-of-n-static-member-functions\/\">instance members of the class&#8217;s activation factory<\/a>. By convention, the interface name for static members is the runtime class name, followed by the word <code>Statics<\/code>. <\/p>\n<p>Okay, we now know just enough to be dangerous. Start with <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20030723-00\/?p=43073\">the scratch program<\/a> and make these changes. (Remember, Little Programs do little to no error checking.) <\/p>\n<pre>\n<font COLOR=\"blue\">#include &lt;wrl\/client.h&gt;\n#include &lt;wrl\/event.h&gt;\n#include &lt;wrl\/wrappers\/corewrappers.h&gt;\n#include &lt;windows.gaming.ui.h&gt;\n#include &lt;EventToken.h&gt;\n#include &lt;tchar.h&gt; \/\/ Huh? Why are you still using ANSI?\n\nnamespace WRL = Microsoft::WRL;\nnamespace awf = ABI::Windows::Foundation;\nnamespace gameui = ABI::Windows::Gaming::UI;\n\nWRL::ComPtr&lt;gameui::IGameBarStatics&gt; g_gameBarStatics;\nboolean g_isVisible;\nboolean g_isInputRedirected;\nEventRegistrationToken g_tokenVisibility;\nEventRegistrationToken g_tokenInput;<\/font>\n<\/pre>\n<p>After including a few header files and declaring some namespace aliases, we create a few global variables to keep track of our state. In a real program, these would probably be instance members of some C++ class, but I&#8217;m being lazy. <\/p>\n<pre>\n<font COLOR=\"blue\">void CheckGameBarVisibility(HWND hwnd)\n{\n    boolean isVisible;\n    g_gameBarStatics-&gt;get_Visible(&amp;isVisible);\n    if (g_isVisible != isVisible)\n    {\n        g_isVisible = isVisible;\n        InvalidateRect(hwnd, nullptr, TRUE);\n    }\n}\n\nvoid CheckGameBarInput(HWND hwnd)\n{\n    boolean isInputRedirected;\n    g_gameBarStatics-&gt;get_IsInputRedirected(&amp;isInputRedirected);\n    if (g_isInputRedirected != isInputRedirected)\n    {\n        g_isVisible = isVisible;\n        InvalidateRect(hwnd, nullptr, TRUE);\n    }\n}<\/font>\n<\/pre>\n<p>These two little functions read the current visibility and input redirection states of the game bar, and if they changed, we invalidate the window. <!-- backref: Using the Windows::Globalization::Calendar object from a Win32 app -->We learned about property access a little while ago<\/a>. In our case, the properties are static, so the property accessors live on the <code>Statics<\/code> interface. <\/p>\n<pre>\nBOOL\nOnCreate(HWND hwnd, LPCREATESTRUCT lpcs)\n{\n  <font COLOR=\"blue\">Windows::Foundation::GetActivationFactory(WRL::Wrappers::HStringReference(\n    RuntimeClass_Windows_Gaming_UI_GameBar).Get(), &amp;g_gameBarStatics);\n\n  auto visibilityHandler = WRL::Callback&lt;awf::IEventHandler&lt;IInspectable*&gt;&gt;(\n    [hwnd](IInspectable*, IInspectable*)\n    {\n      CheckGameBarVisibilty(hwnd);\n      return S_OK;\n    });\n  g_gamebarStatics-&gt;add_VisibilityChanged(visibilityHandler.Get(), &amp;g_tokenVisibility);\n\n  auto inputHandler = WRL::Callback&lt;awf::IEventHandler&lt;IInspectable*&gt;&gt;(\n    [hwnd](IInspectable*, IInspectable*)\n    {\n      CheckGameBarInput(hwnd);\n      return S_OK;\n    });\n  g_gamebarStatics-&gt;add_IsInputRedirectedChanged(inputHandler.Get(), &amp;g_tokenInput);\n\n  CheckGameBarVisibility(hwnd);\n  CheckGameBarInput(hwnd);<\/font>\n  return TRUE;\n}\n<\/pre>\n<p>We create the game bar statics by asking for the <code>IGameBarStatics<\/code> interface from the activation factory. From there, we register two event handlers, one to be called when the visibility changes, and another to be called when input redirection changes. In both cases, we respond to the event by checking the new visiblity or input redirection state. <\/p>\n<p>After registering the handlers, we manually check the visibility and input to get the initial values set up properly. <\/p>\n<pre>\nvoid\nOnDestroy(HWND hwnd)\n{\n  <font COLOR=\"blue\">g_gameBar-&gt;remove_VisibilityChanged(g_tokenVisibility);\n  g_gameBar-&gt;remove_IsInputRedirectedChanged(g_tokenInput);\n  g_gameBar.Reset();<\/font>\n  PostQuitMessage(0);\n}\n<\/pre>\n<p>Naturally, we need to clean up when we&#8217;re done. <\/p>\n<pre>\nvoid\nPaintContent(HWND hwnd, PAINTSTRUCT *pps)\n{\n  <font COLOR=\"blue\">PCTSTR visibleMessage =\n    g_isVisible ? TEXT(\"GameBar is visible\")\n                : TEXT(\"GameBar is not visible\");\n\n  TextOut(pps-&gt;hdc, 0, 0, visibleMessage, _tcslen(visibleMessage));\n\n  PCTSTR inputMessage =\n    g_isInputRedirected ? TEXT(\"GameBar has taken input\")\n                        : TEXT(\"GameBar does not have input\");\n\n  TextOut(pps-&gt;hdc, 0, 20, inputMessage, _tcslen(inputMessage));<\/font>\n}\n<\/pre>\n<p>Our <code>Paint&shy;Content<\/code> function prints the current state of the game bar: Is it visible? Does it have input? <\/p>\n<p>And that&#8217;s it. Run this program, press the <kbd>Win<\/kbd>+<kbd>G<\/kbd> hotkey to call up the game bar, and observe that the program updates its window to reflect the game bar state. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>A little interop.<\/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-93775","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A little interop.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/93775","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=93775"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/93775\/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=93775"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=93775"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=93775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}