WindowChromeWorker.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.CodeAnalysis;
  4. using System.Runtime.InteropServices;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Interop;
  8. using System.Windows.Media;
  9. using System.Windows.Threading;
  10. using Standard;
  11. namespace Microsoft.Windows.Shell;
  12. internal class WindowChromeWorker : DependencyObject
  13. {
  14. public WindowChromeWorker()
  15. {
  16. this._messageTable = new List<KeyValuePair<WM, MessageHandler>>
  17. {
  18. new KeyValuePair<WM, MessageHandler>(WM.SETTEXT, new MessageHandler(this._HandleSetTextOrIcon)),
  19. new KeyValuePair<WM, MessageHandler>(WM.SETICON, new MessageHandler(this._HandleSetTextOrIcon)),
  20. new KeyValuePair<WM, MessageHandler>(WM.NCACTIVATE, new MessageHandler(this._HandleNCActivate)),
  21. new KeyValuePair<WM, MessageHandler>(WM.NCCALCSIZE, new MessageHandler(this._HandleNCCalcSize)),
  22. new KeyValuePair<WM, MessageHandler>(WM.NCHITTEST, new MessageHandler(this._HandleNCHitTest)),
  23. new KeyValuePair<WM, MessageHandler>(WM.NCRBUTTONUP, new MessageHandler(this._HandleNCRButtonUp)),
  24. new KeyValuePair<WM, MessageHandler>(WM.SIZE, new MessageHandler(this._HandleSize)),
  25. new KeyValuePair<WM, MessageHandler>(WM.WINDOWPOSCHANGED, new MessageHandler(this._HandleWindowPosChanged)),
  26. new KeyValuePair<WM, MessageHandler>(WM.DWMCOMPOSITIONCHANGED, new MessageHandler(this._HandleDwmCompositionChanged))
  27. };
  28. if (Utility.IsPresentationFrameworkVersionLessThan4)
  29. {
  30. this._messageTable.AddRange(new KeyValuePair<WM, MessageHandler>[]
  31. {
  32. new KeyValuePair<WM, MessageHandler>(WM.WININICHANGE, new MessageHandler(this._HandleSettingChange)),
  33. new KeyValuePair<WM, MessageHandler>(WM.ENTERSIZEMOVE, new MessageHandler(this._HandleEnterSizeMove)),
  34. new KeyValuePair<WM, MessageHandler>(WM.EXITSIZEMOVE, new MessageHandler(this._HandleExitSizeMove)),
  35. new KeyValuePair<WM, MessageHandler>(WM.MOVE, new MessageHandler(this._HandleMove))
  36. });
  37. }
  38. }
  39. public void SetWindowChrome(WindowChrome newChrome)
  40. {
  41. base.VerifyAccess();
  42. if (newChrome == this._chromeInfo)
  43. {
  44. return;
  45. }
  46. if (this._chromeInfo != null)
  47. {
  48. this._chromeInfo.PropertyChangedThatRequiresRepaint -= this._OnChromePropertyChangedThatRequiresRepaint;
  49. }
  50. this._chromeInfo = newChrome;
  51. if (this._chromeInfo != null)
  52. {
  53. this._chromeInfo.PropertyChangedThatRequiresRepaint += this._OnChromePropertyChangedThatRequiresRepaint;
  54. }
  55. this._ApplyNewCustomChrome();
  56. }
  57. private void _OnChromePropertyChangedThatRequiresRepaint(object sender, EventArgs e)
  58. {
  59. this._UpdateFrameState(true);
  60. }
  61. private static void _OnChromeWorkerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  62. {
  63. Window window = (Window) d;
  64. WindowChromeWorker windowChromeWorker = (WindowChromeWorker) e.NewValue;
  65. windowChromeWorker._SetWindow(window);
  66. }
  67. private void _SetWindow(Window window)
  68. {
  69. this._window = window;
  70. this._hwnd = new WindowInteropHelper(this._window).Handle;
  71. if (Utility.IsPresentationFrameworkVersionLessThan4)
  72. {
  73. Utility.AddDependencyPropertyChangeListener(this._window, Control.TemplateProperty, new EventHandler(this._OnWindowPropertyChangedThatRequiresTemplateFixup));
  74. Utility.AddDependencyPropertyChangeListener(this._window, FrameworkElement.FlowDirectionProperty, new EventHandler(this._OnWindowPropertyChangedThatRequiresTemplateFixup));
  75. }
  76. this._window.Closed += this._UnsetWindow;
  77. if (IntPtr.Zero != this._hwnd)
  78. {
  79. this._hwndSource = HwndSource.FromHwnd(this._hwnd);
  80. this._window.ApplyTemplate();
  81. if (this._chromeInfo != null)
  82. {
  83. this._ApplyNewCustomChrome();
  84. return;
  85. }
  86. }
  87. else
  88. {
  89. this._window.SourceInitialized += delegate (object sender, EventArgs e)
  90. {
  91. this._hwnd = new WindowInteropHelper(this._window).Handle;
  92. this._hwndSource = HwndSource.FromHwnd(this._hwnd);
  93. if (this._chromeInfo != null)
  94. {
  95. this._ApplyNewCustomChrome();
  96. }
  97. };
  98. }
  99. }
  100. private void _UnsetWindow(object sender, EventArgs e)
  101. {
  102. if (Utility.IsPresentationFrameworkVersionLessThan4)
  103. {
  104. Utility.RemoveDependencyPropertyChangeListener(this._window, Control.TemplateProperty, new EventHandler(this._OnWindowPropertyChangedThatRequiresTemplateFixup));
  105. Utility.RemoveDependencyPropertyChangeListener(this._window, FrameworkElement.FlowDirectionProperty, new EventHandler(this._OnWindowPropertyChangedThatRequiresTemplateFixup));
  106. }
  107. if (this._chromeInfo != null)
  108. {
  109. this._chromeInfo.PropertyChangedThatRequiresRepaint -= this._OnChromePropertyChangedThatRequiresRepaint;
  110. }
  111. this._RestoreStandardChromeState(true);
  112. }
  113. [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
  114. public static WindowChromeWorker GetWindowChromeWorker(Window window)
  115. {
  116. Verify.IsNotNull<Window>(window, "window");
  117. return (WindowChromeWorker) window.GetValue(WindowChromeWorker.WindowChromeWorkerProperty);
  118. }
  119. [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
  120. public static void SetWindowChromeWorker(Window window, WindowChromeWorker chrome)
  121. {
  122. Verify.IsNotNull<Window>(window, "window");
  123. window.SetValue(WindowChromeWorker.WindowChromeWorkerProperty, chrome);
  124. }
  125. private void _OnWindowPropertyChangedThatRequiresTemplateFixup(object sender, EventArgs e)
  126. {
  127. if (this._chromeInfo != null && this._hwnd != IntPtr.Zero)
  128. {
  129. this._window.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new WindowChromeWorker._Action(this._FixupFrameworkIssues));
  130. }
  131. }
  132. private void _ApplyNewCustomChrome()
  133. {
  134. if (this._hwnd == IntPtr.Zero)
  135. {
  136. return;
  137. }
  138. if (this._chromeInfo == null)
  139. {
  140. this._RestoreStandardChromeState(false);
  141. return;
  142. }
  143. if (!this._isHooked)
  144. {
  145. this._hwndSource.AddHook(new HwndSourceHook(this._WndProc));
  146. this._isHooked = true;
  147. }
  148. this._FixupFrameworkIssues();
  149. this._UpdateSystemMenu(new WindowState?(this._window.WindowState));
  150. this._UpdateFrameState(true);
  151. NativeMethods.SetWindowPos(this._hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP.DRAWFRAME | SWP.NOACTIVATE | SWP.NOMOVE | SWP.NOOWNERZORDER | SWP.NOSIZE | SWP.NOZORDER);
  152. }
  153. private void _FixupFrameworkIssues()
  154. {
  155. if (!Utility.IsPresentationFrameworkVersionLessThan4)
  156. {
  157. return;
  158. }
  159. if (this._window.Template == null)
  160. {
  161. return;
  162. }
  163. if (VisualTreeHelper.GetChildrenCount(this._window) == 0)
  164. {
  165. this._window.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new WindowChromeWorker._Action(this._FixupFrameworkIssues));
  166. return;
  167. }
  168. FrameworkElement frameworkElement = (FrameworkElement) VisualTreeHelper.GetChild(this._window, 0);
  169. RECT windowRect = NativeMethods.GetWindowRect(this._hwnd);
  170. RECT rect = this._GetAdjustedWindowRect(windowRect);
  171. Rect rect2 = DpiHelper.DeviceRectToLogical(new Rect((double) windowRect.Left, (double) windowRect.Top, (double) windowRect.Width, (double) windowRect.Height));
  172. Rect rect3 = DpiHelper.DeviceRectToLogical(new Rect((double) rect.Left, (double) rect.Top, (double) rect.Width, (double) rect.Height));
  173. Thickness thickness = new Thickness(rect2.Left - rect3.Left, rect2.Top - rect3.Top, rect3.Right - rect2.Right, rect3.Bottom - rect2.Bottom);
  174. frameworkElement.Margin = new Thickness(0.0, 0.0, -(thickness.Left + thickness.Right), -(thickness.Top + thickness.Bottom));
  175. if (this._window.FlowDirection == FlowDirection.RightToLeft)
  176. {
  177. frameworkElement.RenderTransform = new MatrixTransform(1.0, 0.0, 0.0, 1.0, -(thickness.Left + thickness.Right), 0.0);
  178. }
  179. else
  180. {
  181. frameworkElement.RenderTransform = null;
  182. }
  183. if (!this._isFixedUp)
  184. {
  185. this._hasUserMovedWindow = false;
  186. this._window.StateChanged += this._FixupRestoreBounds;
  187. this._isFixedUp = true;
  188. }
  189. }
  190. [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
  191. private void _FixupWindows7Issues()
  192. {
  193. if (this._blackGlassFixupAttemptCount > 5)
  194. {
  195. return;
  196. }
  197. if (Utility.IsOSWindows7OrNewer && NativeMethods.DwmIsCompositionEnabled())
  198. {
  199. this._blackGlassFixupAttemptCount++;
  200. bool flag = false;
  201. try
  202. {
  203. flag = (NativeMethods.DwmGetCompositionTimingInfo(this._hwnd) != null);
  204. }
  205. catch (Exception)
  206. {
  207. }
  208. if (!flag)
  209. {
  210. base.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new WindowChromeWorker._Action(this._FixupWindows7Issues));
  211. return;
  212. }
  213. this._blackGlassFixupAttemptCount = 0;
  214. }
  215. }
  216. private void _FixupRestoreBounds(object sender, EventArgs e)
  217. {
  218. if ((this._window.WindowState == WindowState.Maximized || this._window.WindowState == WindowState.Minimized) && this._hasUserMovedWindow)
  219. {
  220. this._hasUserMovedWindow = false;
  221. WINDOWPLACEMENT windowPlacement = NativeMethods.GetWindowPlacement(this._hwnd);
  222. RECT rect = this._GetAdjustedWindowRect(new RECT
  223. {
  224. Bottom = 100,
  225. Right = 100
  226. });
  227. Point point = DpiHelper.DevicePixelsToLogical(new Point((double) (windowPlacement.rcNormalPosition.Left - rect.Left), (double) (windowPlacement.rcNormalPosition.Top - rect.Top)));
  228. this._window.Top = point.Y;
  229. this._window.Left = point.X;
  230. }
  231. }
  232. private RECT _GetAdjustedWindowRect(RECT rcWindow)
  233. {
  234. WS dwStyle = (WS) ((int) NativeMethods.GetWindowLongPtr(this._hwnd, GWL.STYLE));
  235. WS_EX dwExStyle = (WS_EX) ((int) NativeMethods.GetWindowLongPtr(this._hwnd, GWL.EXSTYLE));
  236. return NativeMethods.AdjustWindowRectEx(rcWindow, dwStyle, false, dwExStyle);
  237. }
  238. private bool _IsWindowDocked
  239. {
  240. get
  241. {
  242. if (this._window.WindowState != WindowState.Normal)
  243. {
  244. return false;
  245. }
  246. RECT rect = this._GetAdjustedWindowRect(new RECT
  247. {
  248. Bottom = 100,
  249. Right = 100
  250. });
  251. Point point = new Point(this._window.Left, this._window.Top);
  252. point -= (Vector) DpiHelper.DevicePixelsToLogical(new Point((double) rect.Left, (double) rect.Top));
  253. return this._window.RestoreBounds.Location != point;
  254. }
  255. }
  256. private IntPtr _WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  257. {
  258. foreach (KeyValuePair<WM, MessageHandler> keyValuePair in this._messageTable)
  259. {
  260. if (keyValuePair.Key == (WM) msg)
  261. {
  262. return keyValuePair.Value((WM) msg, wParam, lParam, out handled);
  263. }
  264. }
  265. return IntPtr.Zero;
  266. }
  267. private IntPtr _HandleSetTextOrIcon(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  268. {
  269. bool flag = this._ModifyStyle(WS.VISIBLE, WS.OVERLAPPED);
  270. IntPtr result = NativeMethods.DefWindowProc(this._hwnd, uMsg, wParam, lParam);
  271. if (flag)
  272. {
  273. this._ModifyStyle(WS.OVERLAPPED, WS.VISIBLE);
  274. }
  275. handled = true;
  276. return result;
  277. }
  278. private IntPtr _HandleNCActivate(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  279. {
  280. IntPtr result = NativeMethods.DefWindowProc(this._hwnd, WM.NCACTIVATE, wParam, new IntPtr(-1));
  281. handled = true;
  282. return result;
  283. }
  284. private IntPtr _HandleNCCalcSize(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  285. {
  286. handled = true;
  287. return new IntPtr(768);
  288. }
  289. private IntPtr _HandleNCHitTest(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  290. {
  291. IntPtr intPtr = IntPtr.Zero;
  292. handled = false;
  293. if (Utility.IsOSVistaOrNewer && this._chromeInfo.GlassFrameThickness != default(Thickness) && this._isGlassEnabled)
  294. {
  295. handled = NativeMethods.DwmDefWindowProc(this._hwnd, uMsg, wParam, lParam, out intPtr);
  296. }
  297. if (IntPtr.Zero == intPtr)
  298. {
  299. Point point = new Point((double) Utility.GET_X_LPARAM(lParam), (double) Utility.GET_Y_LPARAM(lParam));
  300. Rect deviceRectangle = this._GetWindowRect();
  301. HT ht = this._HitTestNca(DpiHelper.DeviceRectToLogical(deviceRectangle), DpiHelper.DevicePixelsToLogical(point));
  302. if (ht != HT.CLIENT)
  303. {
  304. Point point2 = point;
  305. point2.Offset(-deviceRectangle.X, -deviceRectangle.Y);
  306. point2 = DpiHelper.DevicePixelsToLogical(point2);
  307. IInputElement inputElement = this._window.InputHitTest(point2);
  308. if (inputElement != null && WindowChrome.GetIsHitTestVisibleInChrome(inputElement))
  309. {
  310. ht = HT.CLIENT;
  311. }
  312. }
  313. handled = true;
  314. intPtr = new IntPtr((int) ht);
  315. }
  316. return intPtr;
  317. }
  318. private IntPtr _HandleNCRButtonUp(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  319. {
  320. if (2 == wParam.ToInt32())
  321. {
  322. SystemCommands.ShowSystemMenuPhysicalCoordinates(this._window, new Point((double) Utility.GET_X_LPARAM(lParam), (double) Utility.GET_Y_LPARAM(lParam)));
  323. }
  324. handled = false;
  325. return IntPtr.Zero;
  326. }
  327. private IntPtr _HandleSize(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  328. {
  329. WindowState? assumeState = null;
  330. if (wParam.ToInt32() == 2)
  331. {
  332. assumeState = new WindowState?(WindowState.Maximized);
  333. }
  334. this._UpdateSystemMenu(assumeState);
  335. handled = false;
  336. return IntPtr.Zero;
  337. }
  338. private IntPtr _HandleWindowPosChanged(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  339. {
  340. this._UpdateSystemMenu(null);
  341. if (!this._isGlassEnabled)
  342. {
  343. WINDOWPOS value = (WINDOWPOS) Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
  344. this._SetRoundingRegion(new WINDOWPOS?(value));
  345. }
  346. handled = false;
  347. return IntPtr.Zero;
  348. }
  349. private IntPtr _HandleDwmCompositionChanged(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  350. {
  351. this._UpdateFrameState(false);
  352. handled = false;
  353. return IntPtr.Zero;
  354. }
  355. private IntPtr _HandleSettingChange(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  356. {
  357. this._FixupFrameworkIssues();
  358. handled = false;
  359. return IntPtr.Zero;
  360. }
  361. private IntPtr _HandleEnterSizeMove(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  362. {
  363. this._isUserResizing = true;
  364. if (this._window.WindowState != WindowState.Maximized && !this._IsWindowDocked)
  365. {
  366. this._windowPosAtStartOfUserMove = new Point(this._window.Left, this._window.Top);
  367. }
  368. handled = false;
  369. return IntPtr.Zero;
  370. }
  371. private IntPtr _HandleExitSizeMove(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  372. {
  373. this._isUserResizing = false;
  374. if (this._window.WindowState == WindowState.Maximized)
  375. {
  376. this._window.Top = this._windowPosAtStartOfUserMove.Y;
  377. this._window.Left = this._windowPosAtStartOfUserMove.X;
  378. }
  379. handled = false;
  380. return IntPtr.Zero;
  381. }
  382. private IntPtr _HandleMove(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled)
  383. {
  384. if (this._isUserResizing)
  385. {
  386. this._hasUserMovedWindow = true;
  387. }
  388. handled = false;
  389. return IntPtr.Zero;
  390. }
  391. private bool _ModifyStyle(WS removeStyle, WS addStyle)
  392. {
  393. WS ws = (WS) NativeMethods.GetWindowLongPtr(this._hwnd, GWL.STYLE).ToInt32();
  394. WS ws2 = (ws & ~removeStyle) | addStyle;
  395. if (ws == ws2)
  396. {
  397. return false;
  398. }
  399. NativeMethods.SetWindowLongPtr(this._hwnd, GWL.STYLE, new IntPtr((int) ws2));
  400. return true;
  401. }
  402. private WindowState _GetHwndState()
  403. {
  404. WINDOWPLACEMENT windowPlacement = NativeMethods.GetWindowPlacement(this._hwnd);
  405. return windowPlacement.showCmd switch
  406. {
  407. SW.SHOWMINIMIZED => WindowState.Minimized,
  408. SW.SHOWMAXIMIZED => WindowState.Maximized,
  409. _ => WindowState.Normal
  410. };
  411. }
  412. private Rect _GetWindowRect()
  413. {
  414. RECT windowRect = NativeMethods.GetWindowRect(this._hwnd);
  415. return new Rect((double) windowRect.Left, (double) windowRect.Top, (double) windowRect.Width, (double) windowRect.Height);
  416. }
  417. private void _UpdateSystemMenu(WindowState? assumeState)
  418. {
  419. WindowState windowState = assumeState ?? this._GetHwndState();
  420. if (assumeState != null || this._lastMenuState != windowState)
  421. {
  422. this._lastMenuState = windowState;
  423. bool flag = this._ModifyStyle(WS.VISIBLE, WS.OVERLAPPED);
  424. IntPtr systemMenu = NativeMethods.GetSystemMenu(this._hwnd, false);
  425. if (IntPtr.Zero != systemMenu)
  426. {
  427. WS value = (WS) NativeMethods.GetWindowLongPtr(this._hwnd, GWL.STYLE).ToInt32();
  428. bool flag2 = Utility.IsFlagSet((int) value, 131072);
  429. bool flag3 = Utility.IsFlagSet((int) value, 65536);
  430. bool flag4 = Utility.IsFlagSet((int) value, 262144);
  431. switch (windowState)
  432. {
  433. case WindowState.Minimized:
  434. NativeMethods.EnableMenuItem(systemMenu, SC.RESTORE, MF.ENABLED);
  435. NativeMethods.EnableMenuItem(systemMenu, SC.MOVE, MF.GRAYED | MF.DISABLED);
  436. NativeMethods.EnableMenuItem(systemMenu, SC.SIZE, MF.GRAYED | MF.DISABLED);
  437. NativeMethods.EnableMenuItem(systemMenu, SC.MINIMIZE, MF.GRAYED | MF.DISABLED);
  438. NativeMethods.EnableMenuItem(systemMenu, SC.MAXIMIZE, flag3 ? MF.ENABLED : (MF.GRAYED | MF.DISABLED));
  439. break;
  440. case WindowState.Maximized:
  441. NativeMethods.EnableMenuItem(systemMenu, SC.RESTORE, MF.ENABLED);
  442. NativeMethods.EnableMenuItem(systemMenu, SC.MOVE, MF.GRAYED | MF.DISABLED);
  443. NativeMethods.EnableMenuItem(systemMenu, SC.SIZE, MF.GRAYED | MF.DISABLED);
  444. NativeMethods.EnableMenuItem(systemMenu, SC.MINIMIZE, flag2 ? MF.ENABLED : (MF.GRAYED | MF.DISABLED));
  445. NativeMethods.EnableMenuItem(systemMenu, SC.MAXIMIZE, MF.GRAYED | MF.DISABLED);
  446. break;
  447. default:
  448. NativeMethods.EnableMenuItem(systemMenu, SC.RESTORE, MF.GRAYED | MF.DISABLED);
  449. NativeMethods.EnableMenuItem(systemMenu, SC.MOVE, MF.ENABLED);
  450. NativeMethods.EnableMenuItem(systemMenu, SC.SIZE, flag4 ? MF.ENABLED : (MF.GRAYED | MF.DISABLED));
  451. NativeMethods.EnableMenuItem(systemMenu, SC.MINIMIZE, flag2 ? MF.ENABLED : (MF.GRAYED | MF.DISABLED));
  452. NativeMethods.EnableMenuItem(systemMenu, SC.MAXIMIZE, flag3 ? MF.ENABLED : (MF.GRAYED | MF.DISABLED));
  453. break;
  454. }
  455. }
  456. if (flag)
  457. {
  458. this._ModifyStyle(WS.OVERLAPPED, WS.VISIBLE);
  459. }
  460. }
  461. }
  462. private void _UpdateFrameState(bool force)
  463. {
  464. if (IntPtr.Zero == this._hwnd)
  465. {
  466. return;
  467. }
  468. bool flag = NativeMethods.DwmIsCompositionEnabled();
  469. if (force || flag != this._isGlassEnabled)
  470. {
  471. this._isGlassEnabled = (flag && this._chromeInfo.GlassFrameThickness != default(Thickness));
  472. if (!this._isGlassEnabled)
  473. {
  474. this._SetRoundingRegion(null);
  475. }
  476. else
  477. {
  478. this._ClearRoundingRegion();
  479. this._ExtendGlassFrame();
  480. this._FixupWindows7Issues();
  481. }
  482. NativeMethods.SetWindowPos(this._hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP.DRAWFRAME | SWP.NOACTIVATE | SWP.NOMOVE | SWP.NOOWNERZORDER | SWP.NOSIZE | SWP.NOZORDER);
  483. }
  484. }
  485. private void _ClearRoundingRegion()
  486. {
  487. NativeMethods.SetWindowRgn(this._hwnd, IntPtr.Zero, NativeMethods.IsWindowVisible(this._hwnd));
  488. }
  489. private void _SetRoundingRegion(WINDOWPOS? wp)
  490. {
  491. WINDOWPLACEMENT windowPlacement = NativeMethods.GetWindowPlacement(this._hwnd);
  492. if (windowPlacement.showCmd == SW.SHOWMAXIMIZED)
  493. {
  494. int num;
  495. int num2;
  496. if (wp != null)
  497. {
  498. num = wp.Value.x;
  499. num2 = wp.Value.y;
  500. }
  501. else
  502. {
  503. Rect rect = this._GetWindowRect();
  504. num = (int) rect.Left;
  505. num2 = (int) rect.Top;
  506. }
  507. IntPtr hMonitor = NativeMethods.MonitorFromWindow(this._hwnd, 2u);
  508. MONITORINFO monitorInfo = NativeMethods.GetMonitorInfo(hMonitor);
  509. RECT rcWork = monitorInfo.rcWork;
  510. rcWork.Offset(-num, -num2);
  511. IntPtr hRgn = IntPtr.Zero;
  512. try
  513. {
  514. hRgn = NativeMethods.CreateRectRgnIndirect(rcWork);
  515. NativeMethods.SetWindowRgn(this._hwnd, hRgn, NativeMethods.IsWindowVisible(this._hwnd));
  516. hRgn = IntPtr.Zero;
  517. return;
  518. }
  519. finally
  520. {
  521. Utility.SafeDeleteObject(ref hRgn);
  522. }
  523. }
  524. Size size;
  525. if (wp != null && !Utility.IsFlagSet(wp.Value.flags, 1))
  526. {
  527. size = new Size((double) wp.Value.cx, (double) wp.Value.cy);
  528. }
  529. else
  530. {
  531. if (wp != null && this._lastRoundingState == this._window.WindowState)
  532. {
  533. return;
  534. }
  535. size = this._GetWindowRect().Size;
  536. }
  537. this._lastRoundingState = this._window.WindowState;
  538. IntPtr intPtr = IntPtr.Zero;
  539. try
  540. {
  541. double num3 = Math.Min(size.Width, size.Height);
  542. double num4 = DpiHelper.LogicalPixelsToDevice(new Point(this._chromeInfo.CornerRadius.TopLeft, 0.0)).X;
  543. num4 = Math.Min(num4, num3 / 2.0);
  544. if (WindowChromeWorker._IsUniform(this._chromeInfo.CornerRadius))
  545. {
  546. intPtr = WindowChromeWorker._CreateRoundRectRgn(new Rect(size), num4);
  547. }
  548. else
  549. {
  550. intPtr = WindowChromeWorker._CreateRoundRectRgn(new Rect(0.0, 0.0, size.Width / 2.0 + num4, size.Height / 2.0 + num4), num4);
  551. double num5 = DpiHelper.LogicalPixelsToDevice(new Point(this._chromeInfo.CornerRadius.TopRight, 0.0)).X;
  552. num5 = Math.Min(num5, num3 / 2.0);
  553. Rect region = new Rect(0.0, 0.0, size.Width / 2.0 + num5, size.Height / 2.0 + num5);
  554. region.Offset(size.Width / 2.0 - num5, 0.0);
  555. WindowChromeWorker._CreateAndCombineRoundRectRgn(intPtr, region, num5);
  556. double num6 = DpiHelper.LogicalPixelsToDevice(new Point(this._chromeInfo.CornerRadius.BottomLeft, 0.0)).X;
  557. num6 = Math.Min(num6, num3 / 2.0);
  558. Rect region2 = new Rect(0.0, 0.0, size.Width / 2.0 + num6, size.Height / 2.0 + num6);
  559. region2.Offset(0.0, size.Height / 2.0 - num6);
  560. WindowChromeWorker._CreateAndCombineRoundRectRgn(intPtr, region2, num6);
  561. double num7 = DpiHelper.LogicalPixelsToDevice(new Point(this._chromeInfo.CornerRadius.BottomRight, 0.0)).X;
  562. num7 = Math.Min(num7, num3 / 2.0);
  563. Rect region3 = new Rect(0.0, 0.0, size.Width / 2.0 + num7, size.Height / 2.0 + num7);
  564. region3.Offset(size.Width / 2.0 - num7, size.Height / 2.0 - num7);
  565. WindowChromeWorker._CreateAndCombineRoundRectRgn(intPtr, region3, num7);
  566. }
  567. NativeMethods.SetWindowRgn(this._hwnd, intPtr, NativeMethods.IsWindowVisible(this._hwnd));
  568. intPtr = IntPtr.Zero;
  569. }
  570. finally
  571. {
  572. Utility.SafeDeleteObject(ref intPtr);
  573. }
  574. }
  575. private static IntPtr _CreateRoundRectRgn(Rect region, double radius)
  576. {
  577. if (DoubleUtilities.AreClose(0.0, radius))
  578. {
  579. return NativeMethods.CreateRectRgn((int) Math.Floor(region.Left), (int) Math.Floor(region.Top), (int) Math.Ceiling(region.Right), (int) Math.Ceiling(region.Bottom));
  580. }
  581. return NativeMethods.CreateRoundRectRgn((int) Math.Floor(region.Left), (int) Math.Floor(region.Top), (int) Math.Ceiling(region.Right) + 1, (int) Math.Ceiling(region.Bottom) + 1, (int) Math.Ceiling(radius), (int) Math.Ceiling(radius));
  582. }
  583. [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "HRGNs")]
  584. private static void _CreateAndCombineRoundRectRgn(IntPtr hrgnSource, Rect region, double radius)
  585. {
  586. IntPtr hrgnSrc = IntPtr.Zero;
  587. try
  588. {
  589. hrgnSrc = WindowChromeWorker._CreateRoundRectRgn(region, radius);
  590. if (NativeMethods.CombineRgn(hrgnSource, hrgnSource, hrgnSrc, RGN.OR) == CombineRgnResult.ERROR)
  591. {
  592. throw new InvalidOperationException("Unable to combine two HRGNs.");
  593. }
  594. }
  595. catch
  596. {
  597. Utility.SafeDeleteObject(ref hrgnSrc);
  598. throw;
  599. }
  600. }
  601. private static bool _IsUniform(CornerRadius cornerRadius)
  602. {
  603. return DoubleUtilities.AreClose(cornerRadius.BottomLeft, cornerRadius.BottomRight) && DoubleUtilities.AreClose(cornerRadius.TopLeft, cornerRadius.TopRight) && DoubleUtilities.AreClose(cornerRadius.BottomLeft, cornerRadius.TopRight);
  604. }
  605. private void _ExtendGlassFrame()
  606. {
  607. if (!Utility.IsOSVistaOrNewer)
  608. {
  609. return;
  610. }
  611. if (IntPtr.Zero == this._hwnd)
  612. {
  613. return;
  614. }
  615. if (!NativeMethods.DwmIsCompositionEnabled())
  616. {
  617. this._hwndSource.CompositionTarget.BackgroundColor = SystemColors.WindowColor;
  618. return;
  619. }
  620. this._hwndSource.CompositionTarget.BackgroundColor = Colors.Transparent;
  621. Point point = DpiHelper.LogicalPixelsToDevice(new Point(this._chromeInfo.GlassFrameThickness.Left, this._chromeInfo.GlassFrameThickness.Top));
  622. Point point2 = DpiHelper.LogicalPixelsToDevice(new Point(this._chromeInfo.GlassFrameThickness.Right, this._chromeInfo.GlassFrameThickness.Bottom));
  623. MARGINS margins = new MARGINS
  624. {
  625. cxLeftWidth = (int) Math.Ceiling(point.X),
  626. cxRightWidth = (int) Math.Ceiling(point2.X),
  627. cyTopHeight = (int) Math.Ceiling(point.Y),
  628. cyBottomHeight = (int) Math.Ceiling(point2.Y)
  629. };
  630. NativeMethods.DwmExtendFrameIntoClientArea(this._hwnd, ref margins);
  631. }
  632. private HT _HitTestNca(Rect windowPosition, Point mousePosition)
  633. {
  634. int num = 1;
  635. int num2 = 1;
  636. bool flag = false;
  637. if (mousePosition.Y >= windowPosition.Top && mousePosition.Y < windowPosition.Top + this._chromeInfo.ResizeBorderThickness.Top + this._chromeInfo.CaptionHeight)
  638. {
  639. flag = (mousePosition.Y < windowPosition.Top + this._chromeInfo.ResizeBorderThickness.Top);
  640. num = 0;
  641. }
  642. else if (mousePosition.Y < windowPosition.Bottom && mousePosition.Y >= windowPosition.Bottom - (double) ((int) this._chromeInfo.ResizeBorderThickness.Bottom))
  643. {
  644. num = 2;
  645. }
  646. if (mousePosition.X >= windowPosition.Left && mousePosition.X < windowPosition.Left + (double) ((int) this._chromeInfo.ResizeBorderThickness.Left))
  647. {
  648. num2 = 0;
  649. }
  650. else if (mousePosition.X < windowPosition.Right && mousePosition.X >= windowPosition.Right - this._chromeInfo.ResizeBorderThickness.Right)
  651. {
  652. num2 = 2;
  653. }
  654. if (num == 0 && num2 != 1 && !flag)
  655. {
  656. num = 1;
  657. }
  658. HT ht = WindowChromeWorker._HitTestBorders[num, num2];
  659. if (ht == HT.TOP && !flag)
  660. {
  661. ht = HT.CAPTION;
  662. }
  663. return ht;
  664. }
  665. private void _RestoreStandardChromeState(bool isClosing)
  666. {
  667. base.VerifyAccess();
  668. this._UnhookCustomChrome();
  669. if (!isClosing)
  670. {
  671. this._RestoreFrameworkIssueFixups();
  672. this._RestoreGlassFrame();
  673. this._RestoreHrgn();
  674. this._window.InvalidateMeasure();
  675. }
  676. }
  677. private void _UnhookCustomChrome()
  678. {
  679. if (this._isHooked)
  680. {
  681. this._hwndSource.RemoveHook(new HwndSourceHook(this._WndProc));
  682. this._isHooked = false;
  683. }
  684. }
  685. private void _RestoreFrameworkIssueFixups()
  686. {
  687. if (Utility.IsPresentationFrameworkVersionLessThan4)
  688. {
  689. FrameworkElement frameworkElement = (FrameworkElement) VisualTreeHelper.GetChild(this._window, 0);
  690. frameworkElement.Margin = default(Thickness);
  691. this._window.StateChanged -= this._FixupRestoreBounds;
  692. this._isFixedUp = false;
  693. }
  694. }
  695. private void _RestoreGlassFrame()
  696. {
  697. if (!Utility.IsOSVistaOrNewer || this._hwnd == IntPtr.Zero)
  698. {
  699. return;
  700. }
  701. this._hwndSource.CompositionTarget.BackgroundColor = SystemColors.WindowColor;
  702. if (NativeMethods.DwmIsCompositionEnabled())
  703. {
  704. MARGINS margins = default(MARGINS);
  705. NativeMethods.DwmExtendFrameIntoClientArea(this._hwnd, ref margins);
  706. }
  707. }
  708. private void _RestoreHrgn()
  709. {
  710. this._ClearRoundingRegion();
  711. NativeMethods.SetWindowPos(this._hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP.DRAWFRAME | SWP.NOACTIVATE | SWP.NOMOVE | SWP.NOOWNERZORDER | SWP.NOSIZE | SWP.NOZORDER);
  712. }
  713. // Note: this type is marked as 'beforefieldinit'.
  714. static WindowChromeWorker()
  715. {
  716. HT[,] array = new HT[3, 3];
  717. array[0, 0] = HT.TOPLEFT;
  718. array[0, 1] = HT.TOP;
  719. array[0, 2] = HT.TOPRIGHT;
  720. array[1, 0] = HT.LEFT;
  721. array[1, 1] = HT.CLIENT;
  722. array[1, 2] = HT.RIGHT;
  723. array[2, 0] = HT.BOTTOMLEFT;
  724. array[2, 1] = HT.BOTTOM;
  725. array[2, 2] = HT.BOTTOMRIGHT;
  726. WindowChromeWorker._HitTestBorders = array;
  727. }
  728. private const SWP _SwpFlags = SWP.DRAWFRAME | SWP.NOACTIVATE | SWP.NOMOVE | SWP.NOOWNERZORDER | SWP.NOSIZE | SWP.NOZORDER;
  729. private readonly List<KeyValuePair<WM, MessageHandler>> _messageTable;
  730. private Window _window;
  731. private IntPtr _hwnd;
  732. private HwndSource _hwndSource;
  733. private bool _isHooked;
  734. private bool _isFixedUp;
  735. private bool _isUserResizing;
  736. private bool _hasUserMovedWindow;
  737. private Point _windowPosAtStartOfUserMove = default(Point);
  738. private int _blackGlassFixupAttemptCount;
  739. private WindowChrome _chromeInfo;
  740. private WindowState _lastRoundingState;
  741. private WindowState _lastMenuState;
  742. private bool _isGlassEnabled;
  743. public static readonly DependencyProperty WindowChromeWorkerProperty = DependencyProperty.RegisterAttached("WindowChromeWorker", typeof(WindowChromeWorker), typeof(WindowChromeWorker), new PropertyMetadata(null, new PropertyChangedCallback(WindowChromeWorker._OnChromeWorkerChanged)));
  744. [SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional", MessageId = "Member")]
  745. private static readonly HT[,] _HitTestBorders;
  746. private delegate void _Action();
  747. }