PageRenderTime 4314ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/MahApps.Metro/Controls/MetroWindow.cs

https://github.com/jcadiba/MahApps.Metro
C# | 964 lines | 691 code | 134 blank | 139 comment | 139 complexity | e2dab68233977f2b3366c4422a313885 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Linq;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Input;
  6. using System.Windows.Interop;
  7. using System.Windows.Media;
  8. using System.Windows.Media.Animation;
  9. using MahApps.Metro.Controls.Dialogs;
  10. using MahApps.Metro.Native;
  11. using System.Windows.Shapes;
  12. using System.Collections.Generic;
  13. namespace MahApps.Metro.Controls
  14. {
  15. /// <summary>
  16. /// An extended, metrofied Window class.
  17. /// </summary>
  18. [TemplatePart(Name = PART_Icon, Type = typeof(UIElement))]
  19. [TemplatePart(Name = PART_TitleBar, Type = typeof(UIElement))]
  20. [TemplatePart(Name = PART_WindowTitleBackground, Type = typeof(UIElement))]
  21. [TemplatePart(Name = PART_LeftWindowCommands, Type = typeof(WindowCommands))]
  22. [TemplatePart(Name = PART_RightWindowCommands, Type = typeof(WindowCommands))]
  23. [TemplatePart(Name = PART_WindowButtonCommands, Type = typeof(WindowButtonCommands))]
  24. [TemplatePart(Name = PART_OverlayBox, Type = typeof(Grid))]
  25. [TemplatePart(Name = PART_MetroDialogContainer, Type = typeof(Grid))]
  26. [TemplatePart(Name = PART_FlyoutModal, Type = typeof(Rectangle))]
  27. public class MetroWindow : Window
  28. {
  29. private const string PART_Icon = "PART_Icon";
  30. private const string PART_TitleBar = "PART_TitleBar";
  31. private const string PART_WindowTitleBackground = "PART_WindowTitleBackground";
  32. private const string PART_LeftWindowCommands = "PART_LeftWindowCommands";
  33. private const string PART_RightWindowCommands = "PART_RightWindowCommands";
  34. private const string PART_WindowButtonCommands = "PART_WindowButtonCommands";
  35. private const string PART_OverlayBox = "PART_OverlayBox";
  36. private const string PART_MetroDialogContainer = "PART_MetroDialogContainer";
  37. private const string PART_FlyoutModal = "PART_FlyoutModal";
  38. public static readonly DependencyProperty ShowIconOnTitleBarProperty = DependencyProperty.Register("ShowIconOnTitleBar", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  39. public static readonly DependencyProperty IconEdgeModeProperty = DependencyProperty.Register("IconEdgeMode", typeof(EdgeMode), typeof(MetroWindow), new PropertyMetadata(EdgeMode.Aliased));
  40. public static readonly DependencyProperty IconBitmapScalingModeProperty = DependencyProperty.Register("IconBitmapScalingMode", typeof(BitmapScalingMode), typeof(MetroWindow), new PropertyMetadata(BitmapScalingMode.HighQuality));
  41. public static readonly DependencyProperty ShowTitleBarProperty = DependencyProperty.Register("ShowTitleBar", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true, OnShowTitleBarPropertyChangedCallback, OnShowTitleBarCoerceValueCallback));
  42. public static readonly DependencyProperty ShowMinButtonProperty = DependencyProperty.Register("ShowMinButton", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  43. public static readonly DependencyProperty ShowMaxRestoreButtonProperty = DependencyProperty.Register("ShowMaxRestoreButton", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  44. public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register("ShowCloseButton", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  45. public static readonly DependencyProperty ShowWindowButtonCommandsOnHiddenTitleBarProperty = DependencyProperty.Register("ShowWindowButtonCommandsOnHiddenTitleBar", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  46. public static readonly DependencyProperty ShowSystemMenuOnRightClickProperty = DependencyProperty.Register("ShowSystemMenuOnRightClick", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  47. public static readonly DependencyProperty TitlebarHeightProperty = DependencyProperty.Register("TitlebarHeight", typeof(int), typeof(MetroWindow), new PropertyMetadata(30, TitlebarHeightPropertyChangedCallback));
  48. public static readonly DependencyProperty TitleCapsProperty = DependencyProperty.Register("TitleCaps", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  49. public static readonly DependencyProperty SaveWindowPositionProperty = DependencyProperty.Register("SaveWindowPosition", typeof(bool), typeof(MetroWindow), new PropertyMetadata(false));
  50. public static readonly DependencyProperty WindowPlacementSettingsProperty = DependencyProperty.Register("WindowPlacementSettings", typeof(IWindowPlacementSettings), typeof(MetroWindow), new PropertyMetadata(null));
  51. public static readonly DependencyProperty TitleForegroundProperty = DependencyProperty.Register("TitleForeground", typeof(Brush), typeof(MetroWindow));
  52. public static readonly DependencyProperty IgnoreTaskbarOnMaximizeProperty = DependencyProperty.Register("IgnoreTaskbarOnMaximize", typeof(bool), typeof(MetroWindow), new PropertyMetadata(false));
  53. public static readonly DependencyProperty FlyoutsProperty = DependencyProperty.Register("Flyouts", typeof(FlyoutsControl), typeof(MetroWindow), new PropertyMetadata(null));
  54. public static readonly DependencyProperty WindowTransitionsEnabledProperty = DependencyProperty.Register("WindowTransitionsEnabled", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  55. public static readonly DependencyProperty MetroDialogOptionsProperty = DependencyProperty.Register("MetroDialogOptions", typeof(MetroDialogSettings), typeof(MetroWindow), new PropertyMetadata(new MetroDialogSettings()));
  56. public static readonly DependencyProperty WindowTitleBrushProperty = DependencyProperty.Register("WindowTitleBrush", typeof(Brush), typeof(MetroWindow), new PropertyMetadata(Brushes.Transparent));
  57. public static readonly DependencyProperty GlowBrushProperty = DependencyProperty.Register("GlowBrush", typeof(SolidColorBrush), typeof(MetroWindow), new PropertyMetadata(null));
  58. public static readonly DependencyProperty NonActiveGlowBrushProperty = DependencyProperty.Register("NonActiveGlowBrush", typeof(SolidColorBrush), typeof(MetroWindow), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(153, 153, 153)))); // #999999
  59. public static readonly DependencyProperty NonActiveBorderBrushProperty = DependencyProperty.Register("NonActiveBorderBrush", typeof(Brush), typeof(MetroWindow), new PropertyMetadata(Brushes.Gray));
  60. public static readonly DependencyProperty NonActiveWindowTitleBrushProperty = DependencyProperty.Register("NonActiveWindowTitleBrush", typeof(Brush), typeof(MetroWindow), new PropertyMetadata(Brushes.Gray));
  61. public static readonly DependencyProperty IconTemplateProperty = DependencyProperty.Register("IconTemplate", typeof(DataTemplate), typeof(MetroWindow), new PropertyMetadata(null));
  62. public static readonly DependencyProperty TitleTemplateProperty = DependencyProperty.Register("TitleTemplate", typeof(DataTemplate), typeof(MetroWindow), new PropertyMetadata(null));
  63. public static readonly DependencyProperty LeftWindowCommandsProperty = DependencyProperty.Register("LeftWindowCommands", typeof(WindowCommands), typeof(MetroWindow), new PropertyMetadata(null));
  64. public static readonly DependencyProperty RightWindowCommandsProperty = DependencyProperty.Register("RightWindowCommands", typeof(WindowCommands), typeof(MetroWindow), new PropertyMetadata(null));
  65. [Obsolete("This property is obsolete and will be delete in next release, use RightWindowCommands instead.")]
  66. public static readonly DependencyProperty WindowCommandsProperty = DependencyProperty.Register("WindowCommands", typeof(WindowCommands), typeof(MetroWindow), new PropertyMetadata(null, WindowCommandsPropertyChangedCallback));
  67. public static readonly DependencyProperty ShowWindowCommandsOnTopProperty = DependencyProperty.Register("ShowWindowCommandsOnTop", typeof(bool), typeof(MetroWindow), new PropertyMetadata(true));
  68. public static readonly DependencyProperty WindowMinButtonStyleProperty = DependencyProperty.Register("WindowMinButtonStyle", typeof(Style), typeof(MetroWindow), new PropertyMetadata(null));
  69. public static readonly DependencyProperty WindowMaxButtonStyleProperty = DependencyProperty.Register("WindowMaxButtonStyle", typeof(Style), typeof(MetroWindow), new PropertyMetadata(null));
  70. public static readonly DependencyProperty WindowCloseButtonStyleProperty = DependencyProperty.Register("WindowCloseButtonStyle", typeof(Style), typeof(MetroWindow), new PropertyMetadata(null));
  71. [Obsolete("This propery isn't needed anymore, it will be deleted in next release...")]
  72. public static readonly DependencyProperty TextBlockStyleProperty = DependencyProperty.Register("TextBlockStyle", typeof(Style), typeof(MetroWindow), new PropertyMetadata(default(Style)));
  73. public static readonly DependencyProperty UseNoneWindowStyleProperty = DependencyProperty.Register("UseNoneWindowStyle", typeof(bool), typeof(MetroWindow), new PropertyMetadata(false, OnUseNoneWindowStylePropertyChangedCallback));
  74. public static readonly DependencyProperty OverrideDefaultWindowCommandsBrushProperty = DependencyProperty.Register("OverrideDefaultWindowCommandsBrush", typeof(SolidColorBrush), typeof(MetroWindow));
  75. public static readonly DependencyProperty EnableDWMDropShadowProperty = DependencyProperty.Register("EnableDWMDropShadow", typeof(bool), typeof(MetroWindow), new PropertyMetadata(false));
  76. UIElement icon;
  77. UIElement titleBar;
  78. UIElement titleBarBackground;
  79. internal ContentPresenter LeftWindowCommandsPresenter;
  80. internal ContentPresenter RightWindowCommandsPresenter;
  81. internal WindowButtonCommands WindowButtonCommands;
  82. internal Grid overlayBox;
  83. internal Grid metroDialogContainer;
  84. private Storyboard overlayStoryboard;
  85. Rectangle flyoutModal;
  86. public static readonly RoutedEvent FlyoutsStatusChangedEvent = EventManager.RegisterRoutedEvent(
  87. "FlyoutsStatusChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MetroWindow));
  88. // Provide CLR accessors for the event
  89. public event RoutedEventHandler FlyoutsStatusChanged
  90. {
  91. add { AddHandler(FlyoutsStatusChangedEvent, value); }
  92. remove { RemoveHandler(FlyoutsStatusChangedEvent, value); }
  93. }
  94. /// <summary>
  95. /// CleanWindow sets this so it has the correct default window commands brush
  96. /// </summary>
  97. public SolidColorBrush OverrideDefaultWindowCommandsBrush
  98. {
  99. get { return (SolidColorBrush)this.GetValue(OverrideDefaultWindowCommandsBrushProperty); }
  100. set { this.SetValue(OverrideDefaultWindowCommandsBrushProperty, value); }
  101. }
  102. public MetroDialogSettings MetroDialogOptions
  103. {
  104. get { return (MetroDialogSettings)GetValue(MetroDialogOptionsProperty); }
  105. set { SetValue(MetroDialogOptionsProperty, value); }
  106. }
  107. [Obsolete("This propery isn't needed anymore, it will be deleted in next release...")]
  108. public Style TextBlockStyle
  109. {
  110. get { return (Style)this.GetValue(TextBlockStyleProperty); }
  111. set { SetValue(TextBlockStyleProperty, value); }
  112. }
  113. public bool EnableDWMDropShadow
  114. {
  115. get { return (bool)GetValue(EnableDWMDropShadowProperty); }
  116. set { SetValue(EnableDWMDropShadowProperty, value); }
  117. }
  118. /// <summary>
  119. /// Gets/sets whether the Window Commands will show on top of a Flyout with it's position set to Top or Right.
  120. /// </summary>
  121. public bool ShowWindowCommandsOnTop
  122. {
  123. get { return (bool)this.GetValue(ShowWindowCommandsOnTopProperty); }
  124. set { SetValue(ShowWindowCommandsOnTopProperty, value); }
  125. }
  126. /// <summary>
  127. /// Gets/sets the style for the MIN button style.
  128. /// </summary>
  129. public Style WindowMinButtonStyle
  130. {
  131. get { return (Style)this.GetValue(WindowMinButtonStyleProperty); }
  132. set { SetValue(WindowMinButtonStyleProperty, value); }
  133. }
  134. /// <summary>
  135. /// Gets/sets the style for the MAX button style.
  136. /// </summary>
  137. public Style WindowMaxButtonStyle
  138. {
  139. get { return (Style)this.GetValue(WindowMaxButtonStyleProperty); }
  140. set { SetValue(WindowMaxButtonStyleProperty, value); }
  141. }
  142. /// <summary>
  143. /// Gets/sets the style for the CLOSE button style.
  144. /// </summary>
  145. public Style WindowCloseButtonStyle
  146. {
  147. get { return (Style)this.GetValue(WindowCloseButtonStyleProperty); }
  148. set { SetValue(WindowCloseButtonStyleProperty, value); }
  149. }
  150. /// <summary>
  151. /// Gets/sets whether the window's entrance transition animation is enabled.
  152. /// </summary>
  153. public bool WindowTransitionsEnabled
  154. {
  155. get { return (bool)this.GetValue(WindowTransitionsEnabledProperty); }
  156. set { SetValue(WindowTransitionsEnabledProperty, value); }
  157. }
  158. /// <summary>
  159. /// Gets/sets the FlyoutsControl that hosts the window's flyouts.
  160. /// </summary>
  161. public FlyoutsControl Flyouts
  162. {
  163. get { return (FlyoutsControl)GetValue(FlyoutsProperty); }
  164. set { SetValue(FlyoutsProperty, value); }
  165. }
  166. /// <summary>
  167. /// Gets/sets the icon content template to show a custom icon.
  168. /// </summary>
  169. public DataTemplate IconTemplate
  170. {
  171. get { return (DataTemplate)GetValue(IconTemplateProperty); }
  172. set { SetValue(IconTemplateProperty, value); }
  173. }
  174. /// <summary>
  175. /// Gets/sets the title content template to show a custom title.
  176. /// </summary>
  177. public DataTemplate TitleTemplate
  178. {
  179. get { return (DataTemplate)GetValue(TitleTemplateProperty); }
  180. set { SetValue(TitleTemplateProperty, value); }
  181. }
  182. /// <summary>
  183. /// Gets/sets the left window commands that hosts the user commands.
  184. /// </summary>
  185. public WindowCommands LeftWindowCommands
  186. {
  187. get { return (WindowCommands)GetValue(LeftWindowCommandsProperty); }
  188. set { SetValue(LeftWindowCommandsProperty, value); }
  189. }
  190. /// <summary>
  191. /// Gets/sets the right window commands that hosts the user commands.
  192. /// </summary>
  193. public WindowCommands RightWindowCommands
  194. {
  195. get { return (WindowCommands)GetValue(RightWindowCommandsProperty); }
  196. set { SetValue(RightWindowCommandsProperty, value); }
  197. }
  198. /// <summary>
  199. /// Gets/sets the right window commands that hosts the user commands.
  200. /// </summary>
  201. [Obsolete("This property is obsolete and will be delete in next release, use RightWindowCommands instead.")]
  202. public WindowCommands WindowCommands
  203. {
  204. get { return (WindowCommands)GetValue(WindowCommandsProperty); }
  205. set { SetValue(WindowCommandsProperty, value); }
  206. }
  207. private static void WindowCommandsPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
  208. {
  209. if (e.NewValue != e.OldValue && e.NewValue != null)
  210. {
  211. ((MetroWindow)dependencyObject).RightWindowCommands = (WindowCommands)e.NewValue;
  212. }
  213. }
  214. /// <summary>
  215. /// Gets/sets whether the window will ignore (and overlap) the taskbar when maximized.
  216. /// </summary>
  217. public bool IgnoreTaskbarOnMaximize
  218. {
  219. get { return (bool)this.GetValue(IgnoreTaskbarOnMaximizeProperty); }
  220. set { SetValue(IgnoreTaskbarOnMaximizeProperty, value); }
  221. }
  222. /// <summary>
  223. /// Gets/sets the brush used for the titlebar's foreground.
  224. /// </summary>
  225. public Brush TitleForeground
  226. {
  227. get { return (Brush)GetValue(TitleForegroundProperty); }
  228. set { SetValue(TitleForegroundProperty, value); }
  229. }
  230. /// <summary>
  231. /// Gets/sets whether the window will save it's position between loads.
  232. /// </summary>
  233. public bool SaveWindowPosition
  234. {
  235. get { return (bool)GetValue(SaveWindowPositionProperty); }
  236. set { SetValue(SaveWindowPositionProperty, value); }
  237. }
  238. public IWindowPlacementSettings WindowPlacementSettings
  239. {
  240. get { return (IWindowPlacementSettings)GetValue(WindowPlacementSettingsProperty); }
  241. set { SetValue(WindowPlacementSettingsProperty, value); }
  242. }
  243. /// <summary>
  244. /// Get/sets whether the titlebar icon is visible or not.
  245. /// </summary>
  246. public bool ShowIconOnTitleBar
  247. {
  248. get { return (bool)GetValue(ShowIconOnTitleBarProperty); }
  249. set { SetValue(ShowIconOnTitleBarProperty, value); }
  250. }
  251. /// <summary>
  252. /// Gets/sets edge mode of the titlebar icon.
  253. /// </summary>
  254. public EdgeMode IconEdgeMode
  255. {
  256. get { return (EdgeMode)this.GetValue(IconEdgeModeProperty); }
  257. set { SetValue(IconEdgeModeProperty, value); }
  258. }
  259. /// <summary>
  260. /// Gets/sets bitmap scaling mode of the titlebar icon.
  261. /// </summary>
  262. public BitmapScalingMode IconBitmapScalingMode
  263. {
  264. get { return (BitmapScalingMode)this.GetValue(IconBitmapScalingModeProperty); }
  265. set { SetValue(IconBitmapScalingModeProperty, value); }
  266. }
  267. /// <summary>
  268. /// Gets/sets whether the TitleBar is visible or not.
  269. /// </summary>
  270. public bool ShowTitleBar
  271. {
  272. get { return (bool)GetValue(ShowTitleBarProperty); }
  273. set { SetValue(ShowTitleBarProperty, value); }
  274. }
  275. private static void OnShowTitleBarPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  276. {
  277. var window = (MetroWindow)d;
  278. if (e.NewValue != e.OldValue)
  279. {
  280. window.ToggleVisibiltyForAllTitleElements((bool)e.NewValue);
  281. }
  282. }
  283. private static object OnShowTitleBarCoerceValueCallback(DependencyObject d, object value)
  284. {
  285. // if UseNoneWindowStyle = true no title bar should be shown
  286. if (((MetroWindow)d).UseNoneWindowStyle)
  287. {
  288. return false;
  289. }
  290. return value;
  291. }
  292. /// <summary>
  293. /// Gets/sets whether the WindowStyle is None or not.
  294. /// </summary>
  295. public bool UseNoneWindowStyle
  296. {
  297. get { return (bool)GetValue(UseNoneWindowStyleProperty); }
  298. set { SetValue(UseNoneWindowStyleProperty, value); }
  299. }
  300. private static void OnUseNoneWindowStylePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  301. {
  302. if (e.NewValue != e.OldValue)
  303. {
  304. // if UseNoneWindowStyle = true no title bar should be shown
  305. if ((bool)e.NewValue)
  306. {
  307. ((MetroWindow)d).ShowTitleBar = false;
  308. }
  309. }
  310. }
  311. /// <summary>
  312. /// Gets/sets if the minimize button is visible.
  313. /// </summary>
  314. public bool ShowMinButton
  315. {
  316. get { return (bool)GetValue(ShowMinButtonProperty); }
  317. set { SetValue(ShowMinButtonProperty, value); }
  318. }
  319. /// <summary>
  320. /// Gets/sets if the Maximize/Restore button is visible.
  321. /// </summary>
  322. public bool ShowMaxRestoreButton
  323. {
  324. get { return (bool)GetValue(ShowMaxRestoreButtonProperty); }
  325. set { SetValue(ShowMaxRestoreButtonProperty, value); }
  326. }
  327. /// <summary>
  328. /// Gets/sets if the close button is visible.
  329. /// </summary>
  330. public bool ShowCloseButton
  331. {
  332. get { return (bool)GetValue(ShowCloseButtonProperty); }
  333. set { SetValue(ShowCloseButtonProperty, value); }
  334. }
  335. /// <summary>
  336. /// Gets/sets whether the Window Button Commands will show if the TitleBar is hidden.
  337. /// </summary>
  338. public bool ShowWindowButtonCommandsOnHiddenTitleBar
  339. {
  340. get { return (bool)GetValue(ShowWindowButtonCommandsOnHiddenTitleBarProperty); }
  341. set { SetValue(ShowWindowButtonCommandsOnHiddenTitleBarProperty, value); }
  342. }
  343. /// <summary>
  344. /// Gets/sets if the the system menu should popup on right click.
  345. /// </summary>
  346. public bool ShowSystemMenuOnRightClick
  347. {
  348. get { return (bool)GetValue(ShowSystemMenuOnRightClickProperty); }
  349. set { SetValue(ShowSystemMenuOnRightClickProperty, value); }
  350. }
  351. /// <summary>
  352. /// Gets/sets the TitleBar's height.
  353. /// </summary>
  354. public int TitlebarHeight
  355. {
  356. get { return (int)GetValue(TitlebarHeightProperty); }
  357. set { SetValue(TitlebarHeightProperty, value); }
  358. }
  359. private static void TitlebarHeightPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
  360. {
  361. var window = (MetroWindow)dependencyObject;
  362. if (e.NewValue != e.OldValue)
  363. {
  364. window.ToggleVisibiltyForAllTitleElements((int)e.NewValue > 0);
  365. }
  366. }
  367. private void ToggleVisibiltyForAllTitleElements(bool visible)
  368. {
  369. var newVisibility = visible && this.ShowTitleBar ? Visibility.Visible : Visibility.Collapsed;
  370. if (this.icon != null)
  371. {
  372. var iconVisibility = visible && this.ShowTitleBar && this.ShowIconOnTitleBar ? Visibility.Visible : Visibility.Collapsed;
  373. this.icon.Visibility = iconVisibility;
  374. }
  375. if (this.titleBar != null)
  376. {
  377. this.titleBar.Visibility = newVisibility;
  378. }
  379. if (this.titleBarBackground != null)
  380. {
  381. this.titleBarBackground.Visibility = newVisibility;
  382. }
  383. if (this.LeftWindowCommandsPresenter != null)
  384. {
  385. this.LeftWindowCommandsPresenter.Visibility = newVisibility;
  386. }
  387. if (this.RightWindowCommandsPresenter != null)
  388. {
  389. this.RightWindowCommandsPresenter.Visibility = newVisibility;
  390. }
  391. if (this.WindowButtonCommands != null)
  392. {
  393. var windowCommandsVisibility = ShowWindowButtonCommandsOnHiddenTitleBar ? Visibility.Visible : newVisibility;
  394. this.WindowButtonCommands.Visibility = windowCommandsVisibility;
  395. }
  396. SetWindowEvents();
  397. }
  398. /// <summary>
  399. /// Gets/sets if the TitleBar's text is automatically capitalized.
  400. /// </summary>
  401. public bool TitleCaps
  402. {
  403. get { return (bool)GetValue(TitleCapsProperty); }
  404. set { SetValue(TitleCapsProperty, value); }
  405. }
  406. /// <summary>
  407. /// Gets/sets the brush used for the Window's title bar.
  408. /// </summary>
  409. public Brush WindowTitleBrush
  410. {
  411. get { return (Brush)GetValue(WindowTitleBrushProperty); }
  412. set { SetValue(WindowTitleBrushProperty, value); }
  413. }
  414. /// <summary>
  415. /// Gets/sets the brush used for the Window's glow.
  416. /// </summary>
  417. public SolidColorBrush GlowBrush
  418. {
  419. get { return (SolidColorBrush)GetValue(GlowBrushProperty); }
  420. set { SetValue(GlowBrushProperty, value); }
  421. }
  422. /// <summary>
  423. /// Gets/sets the brush used for the Window's non-active glow.
  424. /// </summary>
  425. public SolidColorBrush NonActiveGlowBrush
  426. {
  427. get { return (SolidColorBrush)GetValue(NonActiveGlowBrushProperty); }
  428. set { SetValue(NonActiveGlowBrushProperty, value); }
  429. }
  430. /// <summary>
  431. /// Gets/sets the brush used for the Window's non-active border.
  432. /// </summary>
  433. public Brush NonActiveBorderBrush
  434. {
  435. get { return (Brush)GetValue(NonActiveBorderBrushProperty); }
  436. set { SetValue(NonActiveBorderBrushProperty, value); }
  437. }
  438. /// <summary>
  439. /// Gets/sets the brush used for the Window's non-active title bar.
  440. /// </summary>
  441. public Brush NonActiveWindowTitleBrush
  442. {
  443. get { return (Brush)GetValue(NonActiveWindowTitleBrushProperty); }
  444. set { SetValue(NonActiveWindowTitleBrushProperty, value); }
  445. }
  446. /// <summary>
  447. /// Gets/sets the TitleBar/Window's Text.
  448. /// </summary>
  449. public string WindowTitle
  450. {
  451. get { return TitleCaps ? Title.ToUpper() : Title; }
  452. }
  453. /// <summary>
  454. /// Begins to show the MetroWindow's overlay effect.
  455. /// </summary>
  456. /// <returns>A task representing the process.</returns>
  457. public System.Threading.Tasks.Task ShowOverlayAsync()
  458. {
  459. if (IsOverlayVisible() && overlayStoryboard == null)
  460. return new System.Threading.Tasks.Task(() => { }); //No Task.FromResult in .NET 4.
  461. Dispatcher.VerifyAccess();
  462. overlayBox.Visibility = Visibility.Visible;
  463. var tcs = new System.Threading.Tasks.TaskCompletionSource<object>();
  464. var sb = (Storyboard) this.Template.Resources["OverlayFastSemiFadeIn"];
  465. sb = sb.Clone();
  466. EventHandler completionHandler = null;
  467. completionHandler = (sender, args) =>
  468. {
  469. sb.Completed -= completionHandler;
  470. if (overlayStoryboard == sb)
  471. {
  472. overlayStoryboard = null;
  473. }
  474. tcs.TrySetResult(null);
  475. };
  476. sb.Completed += completionHandler;
  477. overlayBox.BeginStoryboard(sb);
  478. overlayStoryboard = sb;
  479. return tcs.Task;
  480. }
  481. /// <summary>
  482. /// Begins to hide the MetroWindow's overlay effect.
  483. /// </summary>
  484. /// <returns>A task representing the process.</returns>
  485. public System.Threading.Tasks.Task HideOverlayAsync()
  486. {
  487. if (overlayBox.Visibility == Visibility.Visible && overlayBox.Opacity == 0.0)
  488. return new System.Threading.Tasks.Task(() => { }); //No Task.FromResult in .NET 4.
  489. Dispatcher.VerifyAccess();
  490. var tcs = new System.Threading.Tasks.TaskCompletionSource<object>();
  491. var sb = (Storyboard) this.Template.Resources["OverlayFastSemiFadeOut"];
  492. sb = sb.Clone();
  493. EventHandler completionHandler = null;
  494. completionHandler = (sender, args) =>
  495. {
  496. sb.Completed -= completionHandler;
  497. if (overlayStoryboard == sb)
  498. {
  499. overlayBox.Visibility = Visibility.Hidden;
  500. overlayStoryboard = null;
  501. }
  502. tcs.TrySetResult(null);
  503. };
  504. sb.Completed += completionHandler;
  505. overlayBox.BeginStoryboard(sb);
  506. overlayStoryboard = sb;
  507. return tcs.Task;
  508. }
  509. public bool IsOverlayVisible()
  510. {
  511. return overlayBox.Visibility == Visibility.Visible && overlayBox.Opacity >= 0.7;
  512. }
  513. public void ShowOverlay()
  514. {
  515. overlayBox.Visibility = Visibility.Visible;
  516. //overlayBox.Opacity = 0.7;
  517. overlayBox.SetCurrentValue(Grid.OpacityProperty, 0.7);
  518. }
  519. public void HideOverlay()
  520. {
  521. //overlayBox.Opacity = 0.0;
  522. overlayBox.SetCurrentValue(Grid.OpacityProperty, 0.0);
  523. overlayBox.Visibility = System.Windows.Visibility.Hidden;
  524. }
  525. /// <summary>
  526. /// Initializes a new instance of the MahApps.Metro.Controls.MetroWindow class.
  527. /// </summary>
  528. public MetroWindow()
  529. {
  530. Loaded += this.MetroWindow_Loaded;
  531. }
  532. private void MetroWindow_Loaded(object sender, RoutedEventArgs e)
  533. {
  534. if (this.WindowTransitionsEnabled)
  535. {
  536. VisualStateManager.GoToState(this, "AfterLoaded", true);
  537. }
  538. // if UseNoneWindowStyle = true no title bar, window commands or min, max, close buttons should be shown
  539. if (UseNoneWindowStyle)
  540. {
  541. if (LeftWindowCommandsPresenter != null)
  542. {
  543. LeftWindowCommandsPresenter.Visibility = Visibility.Collapsed;
  544. }
  545. if (RightWindowCommandsPresenter != null)
  546. {
  547. RightWindowCommandsPresenter.Visibility = Visibility.Collapsed;
  548. }
  549. ShowMinButton = false;
  550. ShowMaxRestoreButton = false;
  551. ShowCloseButton = false;
  552. }
  553. if (this.Flyouts == null)
  554. {
  555. this.Flyouts = new FlyoutsControl();
  556. }
  557. this.ResetAllWindowCommandsBrush();
  558. ThemeManager.IsThemeChanged += ThemeManagerOnIsThemeChanged;
  559. this.Unloaded += (o, args) => ThemeManager.IsThemeChanged -= ThemeManagerOnIsThemeChanged;
  560. }
  561. private void MetroWindow_SizeChanged(object sender, RoutedEventArgs e)
  562. {
  563. // this all works only for CleanWindow style
  564. var titleBarGrid = titleBar as Grid;
  565. var titleBarLabel = titleBarGrid.Children[0] as Label;
  566. var titleControl = titleBarLabel.Content as ContentControl;
  567. var iconContentControl = icon as ContentControl;
  568. // Half of this MetroWindow
  569. var halfDistance = this.Width / 2;
  570. // Distance between center and left/right
  571. var distanceToCenter = titleControl.ActualWidth / 2;
  572. // Distance between right edge from LeftWindowCommands to left window side
  573. var distanceFromLeft = iconContentControl.ActualWidth + LeftWindowCommands.ActualWidth;
  574. // Distance between left edge from RightWindowCommands to right window side
  575. var distanceFromRight = WindowButtonCommands.ActualWidth + RightWindowCommands.ActualWidth;
  576. // Margin
  577. const double horizontalMargin = 5.0;
  578. if ((distanceFromLeft + distanceToCenter + horizontalMargin < halfDistance) && (distanceFromRight + distanceToCenter + horizontalMargin < halfDistance))
  579. {
  580. Grid.SetColumn(titleBarGrid, 0);
  581. Grid.SetColumnSpan(titleBarGrid, 5);
  582. }
  583. else
  584. {
  585. Grid.SetColumn(titleBarGrid, 2);
  586. Grid.SetColumnSpan(titleBarGrid, 1);
  587. }
  588. }
  589. private void ThemeManagerOnIsThemeChanged(object sender, OnThemeChangedEventArgs e)
  590. {
  591. if (e.Accent != null)
  592. {
  593. var flyouts = this.Flyouts.GetFlyouts().ToList();
  594. // since we disabled the ThemeManager OnThemeChanged part, we must change all children flyouts too
  595. // e.g if the FlyoutsControl is hosted in a UserControl
  596. var allChildFlyouts = (this.Content as DependencyObject).FindChildren<FlyoutsControl>(true).ToList();
  597. if (allChildFlyouts.Any())
  598. {
  599. flyouts.AddRange(allChildFlyouts.SelectMany(flyoutsControl => flyoutsControl.GetFlyouts()));
  600. }
  601. if (!flyouts.Any())
  602. {
  603. // we must update the window command brushes!!!
  604. this.ResetAllWindowCommandsBrush();
  605. return;
  606. }
  607. foreach (var flyout in flyouts)
  608. {
  609. flyout.ChangeFlyoutTheme(e.Accent, e.AppTheme);
  610. }
  611. this.HandleWindowCommandsForFlyouts(flyouts);
  612. }
  613. }
  614. private void FlyoutsPreviewMouseDown(object sender, MouseButtonEventArgs e)
  615. {
  616. FrameworkElement element = (e.OriginalSource as FrameworkElement);
  617. if (element != null && element.TryFindParent<Flyout>() != null)
  618. {
  619. return;
  620. }
  621. if (Flyouts.OverrideExternalCloseButton == null)
  622. {
  623. foreach (Flyout flyout in Flyouts.GetFlyouts().Where(x => x.IsOpen && x.ExternalCloseButton == e.ChangedButton && (!x.IsPinned || Flyouts.OverrideIsPinned)))
  624. {
  625. flyout.IsOpen = false;
  626. e.Handled = true;
  627. }
  628. }
  629. else if (Flyouts.OverrideExternalCloseButton == e.ChangedButton)
  630. {
  631. foreach (Flyout flyout in Flyouts.GetFlyouts().Where(x => x.IsOpen && (!x.IsPinned || Flyouts.OverrideIsPinned)))
  632. {
  633. flyout.IsOpen = false;
  634. e.Handled = true;
  635. }
  636. }
  637. }
  638. static MetroWindow()
  639. {
  640. DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroWindow), new FrameworkPropertyMetadata(typeof(MetroWindow)));
  641. }
  642. public override void OnApplyTemplate()
  643. {
  644. base.OnApplyTemplate();
  645. if (LeftWindowCommands == null)
  646. LeftWindowCommands = new WindowCommands();
  647. if (RightWindowCommands == null)
  648. RightWindowCommands = new WindowCommands();
  649. LeftWindowCommandsPresenter = GetTemplateChild(PART_LeftWindowCommands) as ContentPresenter;
  650. RightWindowCommandsPresenter = GetTemplateChild(PART_RightWindowCommands) as ContentPresenter;
  651. WindowButtonCommands = GetTemplateChild(PART_WindowButtonCommands) as WindowButtonCommands;
  652. overlayBox = GetTemplateChild(PART_OverlayBox) as Grid;
  653. metroDialogContainer = GetTemplateChild(PART_MetroDialogContainer) as Grid;
  654. flyoutModal = GetTemplateChild(PART_FlyoutModal) as Rectangle;
  655. flyoutModal.PreviewMouseDown += FlyoutsPreviewMouseDown;
  656. this.PreviewMouseDown += FlyoutsPreviewMouseDown;
  657. icon = GetTemplateChild(PART_Icon) as UIElement;
  658. titleBar = GetTemplateChild(PART_TitleBar) as UIElement;
  659. titleBarBackground = GetTemplateChild(PART_WindowTitleBackground) as UIElement;
  660. this.ToggleVisibiltyForAllTitleElements(this.TitlebarHeight > 0);
  661. }
  662. private void ClearWindowEvents()
  663. {
  664. // clear all event handlers first:
  665. if (titleBarBackground != null)
  666. {
  667. titleBarBackground.MouseDown -= TitleBarMouseDown;
  668. titleBarBackground.MouseUp -= TitleBarMouseUp;
  669. }
  670. if (titleBar != null)
  671. {
  672. titleBar.MouseDown -= TitleBarMouseDown;
  673. titleBar.MouseUp -= TitleBarMouseUp;
  674. }
  675. if (icon != null)
  676. {
  677. icon.MouseDown -= IconMouseDown;
  678. }
  679. MouseDown -= TitleBarMouseDown;
  680. MouseUp -= TitleBarMouseUp;
  681. SizeChanged -= MetroWindow_SizeChanged;
  682. }
  683. private void SetWindowEvents()
  684. {
  685. // clear all event handlers first
  686. this.ClearWindowEvents();
  687. // set mouse down/up for icon
  688. if (icon != null && icon.Visibility == Visibility.Visible)
  689. {
  690. icon.MouseDown += IconMouseDown;
  691. }
  692. // handle mouse events for PART_WindowTitleBackground -> MetroWindow
  693. if (titleBarBackground != null && titleBarBackground.Visibility == Visibility.Visible)
  694. {
  695. titleBarBackground.MouseDown += TitleBarMouseDown;
  696. titleBarBackground.MouseUp += TitleBarMouseUp;
  697. }
  698. // handle mouse events for PART_TitleBar -> MetroWindow and CleanWindow
  699. if (titleBar != null && titleBar.Visibility == Visibility.Visible)
  700. {
  701. titleBar.MouseDown += TitleBarMouseDown;
  702. titleBar.MouseUp += TitleBarMouseUp;
  703. // special title resizing for CleanWindow title
  704. if (titleBar.GetType() == typeof(Grid))
  705. {
  706. SizeChanged += MetroWindow_SizeChanged;
  707. }
  708. }
  709. else
  710. {
  711. // handle mouse events for windows without PART_WindowTitleBackground or PART_TitleBar
  712. MouseDown += TitleBarMouseDown;
  713. MouseUp += TitleBarMouseUp;
  714. }
  715. }
  716. protected override void OnStateChanged(EventArgs e)
  717. {
  718. if (WindowButtonCommands != null && !this.UseNoneWindowStyle)
  719. {
  720. WindowButtonCommands.RefreshMaximiseIconState();
  721. }
  722. base.OnStateChanged(e);
  723. }
  724. private void IconMouseDown(object sender, MouseButtonEventArgs e)
  725. {
  726. if (e.ChangedButton == MouseButton.Left)
  727. {
  728. if (e.ClickCount == 2)
  729. {
  730. Close();
  731. }
  732. else
  733. {
  734. ShowSystemMenuPhysicalCoordinates(this, PointToScreen(new Point(0, TitlebarHeight)));
  735. }
  736. }
  737. }
  738. protected void TitleBarMouseDown(object sender, MouseButtonEventArgs e)
  739. {
  740. if (e.ChangedButton == MouseButton.Left && !this.UseNoneWindowStyle)
  741. {
  742. // if UseNoneWindowStyle = true no movement, no maximize please
  743. IntPtr windowHandle = new WindowInteropHelper(this).Handle;
  744. UnsafeNativeMethods.ReleaseCapture();
  745. var mPoint = Mouse.GetPosition(this);
  746. var wpfPoint = this.PointToScreen(mPoint);
  747. var x = Convert.ToInt16(wpfPoint.X);
  748. var y = Convert.ToInt16(wpfPoint.Y);
  749. var lParam = x | (y << 16);
  750. UnsafeNativeMethods.SendMessage(windowHandle, Constants.WM_NCLBUTTONDOWN, Constants.HT_CAPTION, lParam);
  751. if (e.ClickCount == 2 && (this.ResizeMode == ResizeMode.CanResizeWithGrip || this.ResizeMode == ResizeMode.CanResize) && mPoint.Y <= this.TitlebarHeight && this.TitlebarHeight > 0)
  752. {
  753. if (this.WindowState == WindowState.Maximized)
  754. {
  755. Microsoft.Windows.Shell.SystemCommands.RestoreWindow(this);
  756. }
  757. else
  758. {
  759. Microsoft.Windows.Shell.SystemCommands.MaximizeWindow(this);
  760. }
  761. }
  762. }
  763. }
  764. protected void TitleBarMouseUp(object sender, MouseButtonEventArgs e)
  765. {
  766. if (ShowSystemMenuOnRightClick)
  767. {
  768. var mousePosition = e.GetPosition(this);
  769. if (e.ChangedButton == MouseButton.Right && (UseNoneWindowStyle || mousePosition.Y <= TitlebarHeight))
  770. {
  771. ShowSystemMenuPhysicalCoordinates(this, PointToScreen(mousePosition));
  772. }
  773. }
  774. }
  775. internal T GetPart<T>(string name) where T : DependencyObject
  776. {
  777. return GetTemplateChild(name) as T;
  778. }
  779. private static void ShowSystemMenuPhysicalCoordinates(Window window, Point physicalScreenLocation)
  780. {
  781. if (window == null) return;
  782. var hwnd = new WindowInteropHelper(window).Handle;
  783. if (hwnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(hwnd))
  784. return;
  785. var hmenu = UnsafeNativeMethods.GetSystemMenu(hwnd, false);
  786. var cmd = UnsafeNativeMethods.TrackPopupMenuEx(hmenu, Constants.TPM_LEFTBUTTON | Constants.TPM_RETURNCMD,
  787. (int)physicalScreenLocation.X, (int)physicalScreenLocation.Y, hwnd, IntPtr.Zero);
  788. if (0 != cmd)
  789. UnsafeNativeMethods.PostMessage(hwnd, Constants.SYSCOMMAND, new IntPtr(cmd), IntPtr.Zero);
  790. }
  791. internal void HandleFlyoutStatusChange(Flyout flyout, IEnumerable<Flyout> visibleFlyouts)
  792. {
  793. //checks a recently opened flyout's position.
  794. if (flyout.Position == Position.Left || flyout.Position == Position.Right || flyout.Position == Position.Top)
  795. {
  796. //get it's zindex
  797. var zIndex = flyout.IsOpen ? Panel.GetZIndex(flyout) + 3 : visibleFlyouts.Count() + 2;
  798. //if ShowWindowCommandsOnTop is true, set the window commands' and icon zindex to a number that is higher than the flyout's.
  799. if (icon != null)
  800. {
  801. icon.SetValue(Panel.ZIndexProperty, this.ShowWindowCommandsOnTop ? zIndex : 1);
  802. }
  803. if (LeftWindowCommandsPresenter != null)
  804. {
  805. LeftWindowCommandsPresenter.SetValue(Panel.ZIndexProperty, this.ShowWindowCommandsOnTop ? zIndex : 1);
  806. }
  807. if (RightWindowCommandsPresenter != null)
  808. {
  809. RightWindowCommandsPresenter.SetValue(Panel.ZIndexProperty, this.ShowWindowCommandsOnTop ? zIndex : 1);
  810. }
  811. if (WindowButtonCommands != null)
  812. {
  813. WindowButtonCommands.SetValue(Panel.ZIndexProperty, this.ShowWindowCommandsOnTop ? zIndex : 1);
  814. }
  815. this.HandleWindowCommandsForFlyouts(visibleFlyouts);
  816. }
  817. flyoutModal.Visibility = visibleFlyouts.Any(x => x.IsModal) ? Visibility.Visible : Visibility.Hidden;
  818. RaiseEvent(new FlyoutStatusChangedRoutedEventArgs(FlyoutsStatusChangedEvent, this)
  819. {
  820. ChangedFlyout = flyout
  821. });
  822. }
  823. public class FlyoutStatusChangedRoutedEventArgs : RoutedEventArgs
  824. {
  825. internal FlyoutStatusChangedRoutedEventArgs(RoutedEvent rEvent, object source): base(rEvent, source)
  826. { }
  827. public Flyout ChangedFlyout { get; internal set; }
  828. }
  829. }
  830. }