/FishComponents/FullScreenBehavior.cs

https://github.com/verbatium/KinectFish · C# · 338 lines · 171 code · 85 blank · 82 comment · 28 complexity · 893c380f4ae7ce727abb3207a36a7133 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Runtime.InteropServices;
  6. using System.Windows.Interactivity;
  7. using System.Windows;
  8. using System.Windows.Input;
  9. using System.Windows.Interop;
  10. namespace FishComponents
  11. {
  12. /// <summary>
  13. /// A behavior that adds full-screen functionality to a window when the window is maximized,
  14. /// double clicked, or the escape key is pressed.
  15. /// </summary>
  16. public sealed class FullScreenBehavior : Behavior<Window>
  17. {
  18. #region Fields
  19. private HwndSource hwndSource;
  20. #endregion
  21. #region Constructors
  22. /// <summary>
  23. /// Initializes a new instance of the <see cref="T:FullScreenBehavior"/> class.
  24. /// </summary>
  25. public FullScreenBehavior( )
  26. {
  27. }
  28. #endregion
  29. #region Properties
  30. #region FullScreenOnMaximize
  31. /// <summary>
  32. /// Dependency property for the <see cref="P:FullScreenOnMaximize"/> property.
  33. /// </summary>
  34. public static readonly DependencyProperty FullScreenOnMaximizeProperty = DependencyProperty.Register( "FullScreenOnMaximize", typeof( bool ), typeof( FullScreenBehavior ), new PropertyMetadata( default( bool ) ) );
  35. /// <summary>
  36. /// Whether or not user initiated maximizing should put the window into full-screen mode.
  37. /// </summary>
  38. public bool FullScreenOnMaximize
  39. {
  40. get
  41. {
  42. return (bool)GetValue( FullScreenOnMaximizeProperty );
  43. }
  44. set
  45. {
  46. SetValue( FullScreenOnMaximizeProperty, value );
  47. }
  48. }
  49. #endregion
  50. #region FullScreenOnDoubleClick
  51. /// <summary>
  52. /// Dependency property for the <see cref="P:FullScreenOnDoubleClick"/> property.
  53. /// </summary>
  54. public static readonly DependencyProperty FullScreenOnDoubleClickProperty = DependencyProperty.Register( "FullScreenOnDoubleClick", typeof( bool ), typeof( FullScreenBehavior ), new PropertyMetadata( default( bool ) ) );
  55. /// <summary>
  56. /// Whether or not double clicking the window's contents should put the window into full-screen mode.
  57. /// </summary>
  58. public bool FullScreenOnDoubleClick
  59. {
  60. get
  61. {
  62. return (bool)GetValue( FullScreenOnDoubleClickProperty );
  63. }
  64. set
  65. {
  66. SetValue( FullScreenOnDoubleClickProperty, value );
  67. }
  68. }
  69. #endregion
  70. #region RestoreOnEscape
  71. /// <summary>
  72. /// Dependency property for the <see cref="P:RestoreOnEscape"/> property.
  73. /// </summary>
  74. public static readonly DependencyProperty RestoreOnEscapeProperty = DependencyProperty.Register( "RestoreOnEscape", typeof( bool ), typeof( FullScreenBehavior ), new PropertyMetadata( default( bool ) ) );
  75. /// <summary>
  76. /// Whether or not pressing escape while in full screen mode returns to windowed mode.
  77. /// </summary>
  78. public bool RestoreOnEscape
  79. {
  80. get
  81. {
  82. return (bool)GetValue( RestoreOnEscapeProperty );
  83. }
  84. set
  85. {
  86. SetValue( RestoreOnEscapeProperty, value );
  87. }
  88. }
  89. #endregion
  90. #region IsFullScreen
  91. /// <summary>
  92. /// Dependency property for the <see cref="P:IsFullScreen"/> property.
  93. /// </summary>
  94. private static readonly DependencyProperty IsFullScreenProperty = DependencyProperty.RegisterAttached( "IsFullScreen", typeof( bool ), typeof( FullScreenBehavior ), new PropertyMetadata( default( bool ), OnIsFullScreenChanged ) );
  95. /// <summary>
  96. /// Gets a value indicating whether or not the specified window is currently in full-screen mode.
  97. /// </summary>
  98. public static bool GetIsFullScreen( Window window )
  99. {
  100. return (bool)window.GetValue( IsFullScreenProperty );
  101. }
  102. /// <summary>
  103. /// Sets a value indicating whether or not the specified window is currently in full-screen mode.
  104. /// </summary>
  105. /// <param name="window">The window.</param>
  106. /// <param name="value">The value.</param>
  107. public static void SetIsFullScreen( Window window, bool value )
  108. {
  109. window.SetValue( IsFullScreenProperty, value );
  110. }
  111. /// <summary>
  112. /// Called when the value of the IsFullScreenProperty dependency property changes.
  113. /// </summary>
  114. /// <param name="sender">The control instance.</param>
  115. /// <param name="e">The event arguments.</param>
  116. private static void OnIsFullScreenChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
  117. {
  118. var window = (Window)sender;
  119. var oldValue = (bool)e.OldValue;
  120. var newValue = (bool)e.NewValue;
  121. if ( newValue != oldValue && window != null ) {
  122. if ( newValue ) {
  123. window.WindowStyle = WindowStyle.None;
  124. window.Topmost = true;
  125. window.WindowState = WindowState.Maximized;
  126. } // if
  127. else {
  128. window.Topmost = false;
  129. window.WindowStyle = WindowStyle.SingleBorderWindow;
  130. window.WindowState = WindowState.Normal;
  131. } // else
  132. } // if
  133. }
  134. #endregion
  135. #endregion
  136. #region Methods
  137. /// <summary>
  138. /// Called after the behavior is attached to an AssociatedObject.
  139. /// </summary>
  140. /// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
  141. protected override void OnAttached( )
  142. {
  143. base.OnAttached( );
  144. AssociatedObject.SourceInitialized += Window_SourceInitialized;
  145. AssociatedObject.MouseDoubleClick += Window_MouseDoubleClick;
  146. AssociatedObject.KeyDown += Window_KeyDown;
  147. AttachHook( );
  148. }
  149. /// <summary>
  150. /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
  151. /// </summary>
  152. /// <remarks>Override this to unhook functionality from the AssociatedObject.</remarks>
  153. protected override void OnDetaching( )
  154. {
  155. DetachHook( );
  156. AssociatedObject.SourceInitialized -= Window_SourceInitialized;
  157. AssociatedObject.MouseDoubleClick -= Window_MouseDoubleClick;
  158. AssociatedObject.KeyDown -= Window_KeyDown;
  159. base.OnDetaching( );
  160. }
  161. /// <summary>
  162. /// Adds the hook procedure to the Window's HwndSource.
  163. /// </summary>
  164. private void AttachHook( )
  165. {
  166. if ( hwndSource == null ) {
  167. hwndSource = (HwndSource)HwndSource.FromVisual( AssociatedObject );
  168. if ( hwndSource != null ) {
  169. hwndSource.AddHook( WndProc );
  170. } // if
  171. } // if
  172. }
  173. /// <summary>
  174. /// Removes the hook procedure from the Window's HwndSource.
  175. /// </summary>
  176. private void DetachHook( )
  177. {
  178. if ( hwndSource != null ) {
  179. hwndSource.RemoveHook( WndProc );
  180. hwndSource = null;
  181. } // if
  182. }
  183. /// <summary>
  184. /// A hook procedure that intercepts messages sent to the attached window.
  185. /// </summary>
  186. /// <param name="hwnd">The window handle.</param>
  187. /// <param name="msg">The message.</param>
  188. /// <param name="wParam">The wParam which varies by message.</param>
  189. /// <param name="lParam">The lParam which varies by message.</param>
  190. /// <param name="handled">Set to true to suppress default process of this message.</param>
  191. /// <returns>The return value which depends upon the message.</returns>
  192. private IntPtr WndProc( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
  193. {
  194. if ( msg == WM_SYSCOMMAND ) {
  195. int wParam32 = wParam.ToInt32( ) & 0xFFF0;
  196. if ( wParam32 == SC_MAXIMIZE || wParam32 == SC_RESTORE ) {
  197. if ( FullScreenOnMaximize ) {
  198. // Cancel the default handling
  199. handled = true;
  200. // Go to full screen on maximize
  201. // Return from full screen on restore
  202. SetIsFullScreen( AssociatedObject, (wParam32 == SC_MAXIMIZE) );
  203. } // if
  204. } // if
  205. } // if
  206. return IntPtr.Zero;
  207. }
  208. #endregion
  209. #region Event Handlers
  210. /// <summary>
  211. /// Handles the SourceInitialized event of the Window.
  212. /// </summary>
  213. /// <param name="sender">The source of the event.</param>
  214. /// <param name="e">The <see cref="T:EventArgs"/> instance containing the event data.</param>
  215. private void Window_SourceInitialized( object sender, EventArgs e )
  216. {
  217. AttachHook( );
  218. }
  219. /// <summary>
  220. /// Handles the MouseDoubleClick event of the Window.
  221. /// </summary>
  222. /// <param name="sender">The source of the event.</param>
  223. /// <param name="e">The <see cref="T:MouseButtonEventArgs"/> instance containing the event data.</param>
  224. private void Window_MouseDoubleClick( object sender, MouseButtonEventArgs e )
  225. {
  226. if ( e.Handled == false ) {
  227. if ( FullScreenOnDoubleClick ) {
  228. bool current = GetIsFullScreen( AssociatedObject );
  229. SetIsFullScreen( AssociatedObject, !current );
  230. } // if
  231. } // if
  232. }
  233. /// <summary>
  234. /// Handles the KeyDown event of the Window.
  235. /// </summary>
  236. /// <param name="sender">The source of the event.</param>
  237. /// <param name="e">The <see cref="T:KeyEventArgs"/> instance containing the event data.</param>
  238. private void Window_KeyDown( object sender, KeyEventArgs e )
  239. {
  240. if ( e.Key == Key.Escape && e.Handled == false ) {
  241. if ( RestoreOnEscape ) {
  242. SetIsFullScreen( AssociatedObject, false );
  243. } // if
  244. } // if
  245. }
  246. #endregion
  247. #region Interop Stuff
  248. const int WM_SYSCOMMAND = 0x112;
  249. const int SC_RESTORE = 0xF120;
  250. const int SC_MAXIMIZE = 0xF030;
  251. #endregion
  252. } // class
  253. } // namespace