{"id":4349,"date":"2015-05-04T16:01:10","date_gmt":"2015-05-04T14:01:10","guid":{"rendered":"https:\/\/www.kolja-engelmann.de\/blog\/?p=4349"},"modified":"2015-05-04T16:01:10","modified_gmt":"2015-05-04T14:01:10","slug":"wpf-fenster-im-windows-task-switcher-verstecken","status":"publish","type":"post","link":"https:\/\/www.kolja-engelmann.de\/blog\/2015\/05\/wpf-fenster-im-windows-task-switcher-verstecken\/","title":{"rendered":"WPF Fenster im Windows Task Switcher verstecken"},"content":{"rendered":"<p>Eine meiner Applikationen sollte neulich\u00a0parallel und ohne Benutzereingabe neben einigen\u00a0Standardapplikationen (Folien, Videos, Webbrowser usw.) ihren Dienst\u00a0verrichten,\u00a0um\u00a0vom Nutzer je nach Bedarf in den Vordergrund geholt werden zu k\u00f6nnen. Leider waren die Nutzer nicht in der Lage die <code>ALT-Tab<\/code>-Funktionalit\u00e4t von Windows korrekt zu nutzen und \u00e4rgerten sich lautstark\u00a0(\u00fcber mich), wann immer sie mit <code>ALT-Tab<\/code> auf meiner Applikation landeten anstatt auf den gew\u00fcnschten Powerpoint Folien. *schnauff* Ok, also musste meine Applikation aus dem Task Switcher verschwinden. Das erwies sich als gar nicht mal so einfach.<\/p>\n<p>Alle Fenster die das Flag &#8222;<code>WS_EX_TOOLWINDOW<\/code>&#8220; besitzen, also ein &#8222;Toolwindow&#8220; sind, werden nicht im Task-Switcher angezeigt. Allerdings besitzen sie eine \u00dcberschriftenleiste und ein &#8222;Schlie\u00dfen&#8220; Symbol, was ich normalerweise in XAML explizit durch\u00a0<code>WindowStyle=None<\/code> verhinderte.\u00a0Ich suchte also eine M\u00f6glichkeit ein Toolwindow ohne diese Fensterdekorationen zu erzeugen.\u00a0Zum Gl\u00fcck brachte ein Tipp aus dem\u00a0StackOverflow Forum die L\u00f6sung.<\/p>\n<p>Man ben\u00f6tigt zun\u00e4chst das\u00a0WindowHandle des eigenen Fensters und setzt die\u00a0n\u00f6tigen Flags einfach von Hand. Hierzu ist ein wenig <code>user32.dll<\/code> Magic n\u00f6tig, die man jedoch einfach in die eigene View-Klasse kopieren kann.<\/p>\n<pre class=\"lang:c# decode:true  \">#region Window styles\r\n[Flags]\r\npublic enum ExtendedWindowStyles\r\n{\r\n\t\/\/ ...\r\n\tWS_EX_TOOLWINDOW = 0x00000080,\r\n\t\/\/ ...\r\n}\r\n\r\npublic enum GetWindowLongFields\r\n{\r\n\t\/\/ ...\r\n\tGWL_EXSTYLE = (-20),\r\n\t\/\/ ...\r\n}\r\n\r\n[DllImport(\"user32.dll\")]\r\npublic static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);\r\n\r\npublic static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)\r\n{\r\n\tint error = 0;\r\n\tIntPtr result = IntPtr.Zero;\r\n\t\/\/ Win32 SetWindowLong doesn't clear error on success\r\n\tSetLastError(0);\r\n\r\n\tif (IntPtr.Size == 4)\r\n\t{\r\n\t\t\/\/ use SetWindowLong\r\n\t\tInt32 tempResult = IntSetWindowLong(hWnd, nIndex, IntPtrToInt32(dwNewLong));\r\n\t\terror = Marshal.GetLastWin32Error();\r\n\t\tresult = new IntPtr(tempResult);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t\/\/ use SetWindowLongPtr\r\n\t\tresult = IntSetWindowLongPtr(hWnd, nIndex, dwNewLong);\r\n\t\terror = Marshal.GetLastWin32Error();\r\n\t}\r\n\r\n\tif ((result == IntPtr.Zero) &amp;&amp; (error != 0))\r\n\t{\r\n\t\tthrow new System.ComponentModel.Win32Exception(error);\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\n[DllImport(\"user32.dll\", EntryPoint = \"SetWindowLongPtr\", SetLastError = true)]\r\nprivate static extern IntPtr IntSetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);\r\n\r\n[DllImport(\"user32.dll\", EntryPoint = \"SetWindowLong\", SetLastError = true)]\r\nprivate static extern Int32 IntSetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong);\r\n\r\nprivate static int IntPtrToInt32(IntPtr intPtr)\r\n{\r\n\treturn unchecked((int)intPtr.ToInt64());\r\n}\r\n\r\n[DllImport(\"kernel32.dll\", EntryPoint = \"SetLastError\")]\r\npublic static extern void SetLastError(int dwErrorCode);\r\n#endregion<\/pre>\n<p>Die Methoden werden im\u00a0<code>WindowLoaded-<\/code>Eventhandler angewandt, denn erst\u00a0dort existiert das ben\u00f6tigte Window Handle meiner WPF Applikation. \u00dcber\u00a0dieses Handle (Zeile 3) gelangen wir an den Window Style (Zeile 5) und setzen das Flag (Zeile 7) welches Windows mitteilt, dass es sich bei besagtem Fenster fortan um ein Tool Window handelt, das nicht im Task Switcher aufzutauchen braucht.<\/p>\n<pre class=\"lang:c# decode:true\">private void Window_Loaded(object sender, RoutedEventArgs e)\r\n{\r\n\tWindowInteropHelper wndHelper = new WindowInteropHelper(this);\r\n\r\n\tint exStyle = (int)GetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE);\r\n\r\n\texStyle |= (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW;\r\n\tSetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);\r\n}<\/pre>","protected":false},"excerpt":{"rendered":"<p>Eine meiner Applikationen sollte parallel zu einigen Standardapplikationen (Folien, Videos, Webbrowser usw.) ihren Dienst verrichten, um vom Nutzer je nach Bedarf in den Vordergrund geholt werden zu k\u00f6nnen. Leider waren die Nutzer nicht in der Lage die ALT-Tab-Funktionalit\u00e4t von Windows korrekt zu nutzen und \u00e4rgerten sich lautstark (\u00fcber mich), wann immer sie mit ALT-Tab auf meiner Applikation landeten anstatt auf den gew\u00fcnschten Powerpoint Folien. Also musste meine Applikation irgendwie aus dem Task Switcher verschwinden. Das erwies sich als gar nicht mal so einfach.<\/p>\n","protected":false},"author":1,"featured_media":4350,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[38],"tags":[39,40],"class_list":["post-4349","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codeschnippsel","tag-c","tag-wpf"],"jetpack_featured_media_url":"https:\/\/www.kolja-engelmann.de\/blog\/wp-content\/uploads\/2015\/05\/hide-wpf-taskswitcher-GetWindowLong.png","jetpack_sharing_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/posts\/4349","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/comments?post=4349"}],"version-history":[{"count":0,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/posts\/4349\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/media\/4350"}],"wp:attachment":[{"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/media?parent=4349"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/categories?post=4349"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/tags?post=4349"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}