LayoutAutoHideWindowControl.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*************************************************************************************
  2. Extended WPF Toolkit
  3. Copyright (C) 2007-2013 Xceed Software Inc.
  4. This program is provided to you under the terms of the Microsoft Public
  5. License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
  6. For more features, controls, and fast professional support,
  7. pick up the Plus Edition at http://xceed.com/wpf_toolkit
  8. Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
  9. ***********************************************************************************/
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Windows.Interop;
  15. using System.Windows.Controls;
  16. using System.Runtime.InteropServices;
  17. using System.Windows;
  18. using System.Windows.Input;
  19. using System.Windows.Data;
  20. using System.Windows.Media;
  21. using Xceed.Wpf.AvalonDock.Layout;
  22. using System.Diagnostics;
  23. using System.Windows.Threading;
  24. namespace Xceed.Wpf.AvalonDock.Controls
  25. {
  26. public class LayoutAutoHideWindowControl : HwndHost, ILayoutControl
  27. {
  28. static LayoutAutoHideWindowControl()
  29. {
  30. DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(typeof(LayoutAutoHideWindowControl)));
  31. UIElement.FocusableProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(true));
  32. Control.IsTabStopProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(true));
  33. VisibilityProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(Visibility.Hidden));
  34. }
  35. internal LayoutAutoHideWindowControl()
  36. {
  37. }
  38. internal void Show(LayoutAnchorControl anchor)
  39. {
  40. if (_model != null)
  41. throw new InvalidOperationException();
  42. _anchor = anchor;
  43. _model = anchor.Model as LayoutAnchorable;
  44. _side = (anchor.Model.Parent.Parent as LayoutAnchorSide).Side;
  45. _manager = _model.Root.Manager;
  46. CreateInternalGrid();
  47. _model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged);
  48. Visibility = System.Windows.Visibility.Visible;
  49. InvalidateMeasure();
  50. UpdateWindowPos();
  51. Trace.WriteLine("LayoutAutoHideWindowControl.Show()");
  52. }
  53. internal void Hide()
  54. {
  55. if (_model == null)
  56. return;
  57. _model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged);
  58. RemoveInternalGrid();
  59. _anchor = null;
  60. _model = null;
  61. _manager = null;
  62. Visibility = System.Windows.Visibility.Hidden;
  63. Trace.WriteLine("LayoutAutoHideWindowControl.Hide()");
  64. }
  65. LayoutAnchorControl _anchor;
  66. LayoutAnchorable _model;
  67. public ILayoutElement Model
  68. {
  69. get { return _model; }
  70. }
  71. HwndSource _internalHwndSource = null;
  72. IntPtr parentWindowHandle;
  73. protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent)
  74. {
  75. parentWindowHandle = hwndParent.Handle;
  76. _internalHwndSource = new HwndSource(new HwndSourceParameters()
  77. {
  78. ParentWindow = hwndParent.Handle,
  79. WindowStyle = Win32Helper.WS_CHILD | Win32Helper.WS_VISIBLE | Win32Helper.WS_CLIPSIBLINGS | Win32Helper.WS_CLIPCHILDREN,
  80. Width = 0,
  81. Height = 0,
  82. });
  83. _internalHost_ContentRendered = false;
  84. _internalHwndSource.ContentRendered += _internalHwndSource_ContentRendered;
  85. _internalHwndSource.RootVisual = _internalHostPresenter;
  86. AddLogicalChild(_internalHostPresenter);
  87. Win32Helper.BringWindowToTop(_internalHwndSource.Handle);
  88. return new HandleRef(this, _internalHwndSource.Handle);
  89. }
  90. private bool _internalHost_ContentRendered = false;
  91. void _internalHwndSource_ContentRendered(object sender, EventArgs e)
  92. {
  93. _internalHost_ContentRendered = true;
  94. }
  95. protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  96. {
  97. if (msg == Win32Helper.WM_WINDOWPOSCHANGING)
  98. {
  99. if (_internalHost_ContentRendered)
  100. Win32Helper.SetWindowPos(_internalHwndSource.Handle, Win32Helper.HWND_TOP, 0, 0, 0, 0, Win32Helper.SetWindowPosFlags.IgnoreMove | Win32Helper.SetWindowPosFlags.IgnoreResize);
  101. }
  102. return base.WndProc(hwnd, msg, wParam, lParam, ref handled);
  103. }
  104. protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd)
  105. {
  106. if (_internalHwndSource != null)
  107. {
  108. _internalHwndSource.ContentRendered -= _internalHwndSource_ContentRendered;
  109. _internalHwndSource.Dispose();
  110. _internalHwndSource = null;
  111. }
  112. }
  113. public override void OnApplyTemplate()
  114. {
  115. base.OnApplyTemplate();
  116. }
  117. ContentPresenter _internalHostPresenter = new ContentPresenter();
  118. Grid _internalGrid = null;
  119. LayoutAnchorableControl _internalHost = null;
  120. AnchorSide _side;
  121. LayoutGridResizerControl _resizer = null;
  122. DockingManager _manager;
  123. void _model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
  124. {
  125. if (e.PropertyName == "IsAutoHidden")
  126. {
  127. if (!_model.IsAutoHidden)
  128. {
  129. _manager.HideAutoHideWindow(_anchor);
  130. }
  131. }
  132. }
  133. void CreateInternalGrid()
  134. {
  135. _internalGrid = new Grid() { FlowDirection = System.Windows.FlowDirection.LeftToRight};
  136. _internalGrid.SetBinding(Grid.BackgroundProperty, new Binding("Background") { Source = this });
  137. _internalHost = new LayoutAnchorableControl() { Model = _model, Style = AnchorableStyle };
  138. _internalHost.SetBinding(FlowDirectionProperty, new Binding("Model.Root.Manager.FlowDirection") { Source = this });
  139. KeyboardNavigation.SetTabNavigation(_internalGrid, KeyboardNavigationMode.Cycle);
  140. _resizer = new LayoutGridResizerControl();
  141. _resizer.DragStarted += new System.Windows.Controls.Primitives.DragStartedEventHandler(OnResizerDragStarted);
  142. _resizer.DragDelta += new System.Windows.Controls.Primitives.DragDeltaEventHandler(OnResizerDragDelta);
  143. _resizer.DragCompleted += new System.Windows.Controls.Primitives.DragCompletedEventHandler(OnResizerDragCompleted);
  144. if (_side == AnchorSide.Right)
  145. {
  146. _internalGrid.ColumnDefinitions.Add(new ColumnDefinition(){ Width = new GridLength(_manager.GridSplitterWidth)});
  147. _internalGrid.ColumnDefinitions.Add(new ColumnDefinition(){
  148. Width = _model.AutoHideWidth == 0.0 ? new GridLength(_model.AutoHideMinWidth) : new GridLength(_model.AutoHideWidth, GridUnitType.Pixel)});
  149. Grid.SetColumn(_resizer, 0);
  150. Grid.SetColumn(_internalHost, 1);
  151. _resizer.Cursor = Cursors.SizeWE;
  152. HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
  153. VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
  154. }
  155. else if (_side == AnchorSide.Left)
  156. {
  157. _internalGrid.ColumnDefinitions.Add(new ColumnDefinition()
  158. {
  159. Width = _model.AutoHideWidth == 0.0 ? new GridLength(_model.AutoHideMinWidth) : new GridLength(_model.AutoHideWidth, GridUnitType.Pixel),
  160. });
  161. _internalGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(_manager.GridSplitterWidth) });
  162. Grid.SetColumn(_internalHost, 0);
  163. Grid.SetColumn(_resizer, 1);
  164. _resizer.Cursor = Cursors.SizeWE;
  165. HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
  166. VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
  167. }
  168. else if (_side == AnchorSide.Top)
  169. {
  170. _internalGrid.RowDefinitions.Add(new RowDefinition()
  171. {
  172. Height = _model.AutoHideHeight == 0.0 ? new GridLength(_model.AutoHideMinHeight) : new GridLength(_model.AutoHideHeight, GridUnitType.Pixel),
  173. });
  174. _internalGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(_manager.GridSplitterHeight) });
  175. Grid.SetRow(_internalHost, 0);
  176. Grid.SetRow(_resizer, 1);
  177. _resizer.Cursor = Cursors.SizeNS;
  178. VerticalAlignment = System.Windows.VerticalAlignment.Top;
  179. HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
  180. }
  181. else if (_side == AnchorSide.Bottom)
  182. {
  183. _internalGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(_manager.GridSplitterHeight) });
  184. _internalGrid.RowDefinitions.Add(new RowDefinition()
  185. {
  186. Height = _model.AutoHideHeight == 0.0 ? new GridLength(_model.AutoHideMinHeight) : new GridLength(_model.AutoHideHeight, GridUnitType.Pixel),
  187. });
  188. Grid.SetRow(_resizer, 0);
  189. Grid.SetRow(_internalHost, 1);
  190. _resizer.Cursor = Cursors.SizeNS;
  191. VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
  192. HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
  193. }
  194. _internalGrid.Children.Add(_resizer);
  195. _internalGrid.Children.Add(_internalHost);
  196. _internalHostPresenter.Content = _internalGrid;
  197. }
  198. void RemoveInternalGrid()
  199. {
  200. _resizer.DragStarted -= new System.Windows.Controls.Primitives.DragStartedEventHandler(OnResizerDragStarted);
  201. _resizer.DragDelta -= new System.Windows.Controls.Primitives.DragDeltaEventHandler(OnResizerDragDelta);
  202. _resizer.DragCompleted -= new System.Windows.Controls.Primitives.DragCompletedEventHandler(OnResizerDragCompleted);
  203. _internalHostPresenter.Content = null;
  204. }
  205. protected override bool HasFocusWithinCore()
  206. {
  207. return false;
  208. }
  209. #region Resizer
  210. Border _resizerGhost = null;
  211. Window _resizerWindowHost = null;
  212. Vector _initialStartPoint;
  213. void ShowResizerOverlayWindow(LayoutGridResizerControl splitter)
  214. {
  215. _resizerGhost = new Border()
  216. {
  217. Background = splitter.BackgroundWhileDragging,
  218. Opacity = splitter.OpacityWhileDragging
  219. };
  220. var areaElement = _manager.GetAutoHideAreaElement();
  221. var modelControlActualSize = this._internalHost.TransformActualSizeToAncestor();
  222. Point ptTopLeftScreen = areaElement.PointToScreenDPIWithoutFlowDirection(new Point());
  223. var managerSize = areaElement.TransformActualSizeToAncestor();
  224. Size windowSize;
  225. if (_side == AnchorSide.Right || _side == AnchorSide.Left)
  226. {
  227. windowSize = new Size(
  228. managerSize.Width - 25.0 + splitter.ActualWidth,
  229. managerSize.Height);
  230. _resizerGhost.Width = splitter.ActualWidth;
  231. _resizerGhost.Height = windowSize.Height;
  232. ptTopLeftScreen.Offset(25, 0.0);
  233. }
  234. else
  235. {
  236. windowSize = new Size(
  237. managerSize.Width,
  238. managerSize.Height - _model.AutoHideMinHeight - 25.0 + splitter.ActualHeight);
  239. _resizerGhost.Height = splitter.ActualHeight;
  240. _resizerGhost.Width = windowSize.Width;
  241. ptTopLeftScreen.Offset(0.0, 25.0);
  242. }
  243. _initialStartPoint = splitter.PointToScreenDPIWithoutFlowDirection(new Point()) - ptTopLeftScreen;
  244. if (_side == AnchorSide.Right || _side == AnchorSide.Left)
  245. {
  246. Canvas.SetLeft(_resizerGhost, _initialStartPoint.X);
  247. }
  248. else
  249. {
  250. Canvas.SetTop(_resizerGhost, _initialStartPoint.Y);
  251. }
  252. Canvas panelHostResizer = new Canvas()
  253. {
  254. HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
  255. VerticalAlignment = System.Windows.VerticalAlignment.Stretch
  256. };
  257. panelHostResizer.Children.Add(_resizerGhost);
  258. _resizerWindowHost = new Window()
  259. {
  260. ResizeMode = ResizeMode.NoResize,
  261. WindowStyle = System.Windows.WindowStyle.None,
  262. ShowInTaskbar = false,
  263. AllowsTransparency = true,
  264. Background = null,
  265. Width = windowSize.Width,
  266. Height = windowSize.Height,
  267. Left = ptTopLeftScreen.X,
  268. Top = ptTopLeftScreen.Y,
  269. ShowActivated = false,
  270. Owner = Window.GetWindow(this),
  271. Content = panelHostResizer
  272. };
  273. _resizerWindowHost.Show();
  274. }
  275. void HideResizerOverlayWindow()
  276. {
  277. if (_resizerWindowHost != null)
  278. {
  279. _resizerWindowHost.Close();
  280. _resizerWindowHost = null;
  281. }
  282. }
  283. internal bool IsResizing
  284. {
  285. get;
  286. private set;
  287. }
  288. void OnResizerDragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
  289. {
  290. LayoutGridResizerControl splitter = sender as LayoutGridResizerControl;
  291. var rootVisual = this.FindVisualTreeRoot() as Visual;
  292. var trToWnd = TransformToAncestor(rootVisual);
  293. Vector transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) -
  294. trToWnd.Transform(new Point());
  295. double delta;
  296. if (_side == AnchorSide.Right || _side == AnchorSide.Left)
  297. delta = Canvas.GetLeft(_resizerGhost) - _initialStartPoint.X;
  298. else
  299. delta = Canvas.GetTop(_resizerGhost) - _initialStartPoint.Y;
  300. if (_side == AnchorSide.Right)
  301. {
  302. if (_model.AutoHideWidth == 0.0)
  303. _model.AutoHideWidth = _internalHost.ActualWidth - delta;
  304. else
  305. _model.AutoHideWidth -= delta;
  306. _internalGrid.ColumnDefinitions[1].Width = new GridLength(_model.AutoHideWidth, GridUnitType.Pixel);
  307. }
  308. else if (_side == AnchorSide.Left)
  309. {
  310. if (_model.AutoHideWidth == 0.0)
  311. _model.AutoHideWidth = _internalHost.ActualWidth + delta;
  312. else
  313. _model.AutoHideWidth += delta;
  314. _internalGrid.ColumnDefinitions[0].Width = new GridLength(_model.AutoHideWidth, GridUnitType.Pixel);
  315. }
  316. else if (_side == AnchorSide.Top)
  317. {
  318. if (_model.AutoHideHeight == 0.0)
  319. _model.AutoHideHeight = _internalHost.ActualHeight + delta;
  320. else
  321. _model.AutoHideHeight += delta;
  322. _internalGrid.RowDefinitions[0].Height = new GridLength(_model.AutoHideHeight, GridUnitType.Pixel);
  323. }
  324. else if (_side == AnchorSide.Bottom)
  325. {
  326. if (_model.AutoHideHeight == 0.0)
  327. _model.AutoHideHeight = _internalHost.ActualHeight - delta;
  328. else
  329. _model.AutoHideHeight -= delta;
  330. _internalGrid.RowDefinitions[1].Height = new GridLength(_model.AutoHideHeight, GridUnitType.Pixel);
  331. }
  332. HideResizerOverlayWindow();
  333. IsResizing = false;
  334. InvalidateMeasure();
  335. }
  336. void OnResizerDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
  337. {
  338. LayoutGridResizerControl splitter = sender as LayoutGridResizerControl;
  339. var rootVisual = this.FindVisualTreeRoot() as Visual;
  340. var trToWnd = TransformToAncestor(rootVisual);
  341. Vector transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) -
  342. trToWnd.Transform(new Point());
  343. if (_side == AnchorSide.Right || _side == AnchorSide.Left)
  344. {
  345. if (FrameworkElement.GetFlowDirection(_internalHost) == System.Windows.FlowDirection.RightToLeft)
  346. transformedDelta.X = -transformedDelta.X;
  347. Canvas.SetLeft(_resizerGhost, MathHelper.MinMax(_initialStartPoint.X + transformedDelta.X, 0.0, _resizerWindowHost.Width - _resizerGhost.Width));
  348. }
  349. else
  350. {
  351. Canvas.SetTop(_resizerGhost, MathHelper.MinMax(_initialStartPoint.Y + transformedDelta.Y, 0.0, _resizerWindowHost.Height - _resizerGhost.Height));
  352. }
  353. }
  354. void OnResizerDragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
  355. {
  356. var resizer = sender as LayoutGridResizerControl;
  357. ShowResizerOverlayWindow(resizer);
  358. IsResizing = true;
  359. }
  360. #endregion
  361. protected override System.Collections.IEnumerator LogicalChildren
  362. {
  363. get
  364. {
  365. if (_internalHostPresenter == null)
  366. return new UIElement[] { }.GetEnumerator();
  367. return new UIElement[] { _internalHostPresenter }.GetEnumerator();
  368. }
  369. }
  370. protected override Size MeasureOverride(Size constraint)
  371. {
  372. if (_internalHostPresenter == null)
  373. return base.MeasureOverride(constraint);
  374. _internalHostPresenter.Measure(constraint);
  375. //return base.MeasureOverride(constraint);
  376. return _internalHostPresenter.DesiredSize;
  377. }
  378. protected override Size ArrangeOverride(Size finalSize)
  379. {
  380. if (_internalHostPresenter == null)
  381. return base.ArrangeOverride(finalSize);
  382. _internalHostPresenter.Arrange(new Rect(finalSize));
  383. return base.ArrangeOverride(finalSize);// new Size(_internalHostPresenter.ActualWidth, _internalHostPresenter.ActualHeight);
  384. }
  385. #region Background
  386. /// <summary>
  387. /// Background Dependency Property
  388. /// </summary>
  389. public static readonly DependencyProperty BackgroundProperty =
  390. DependencyProperty.Register("Background", typeof(Brush), typeof(LayoutAutoHideWindowControl),
  391. new FrameworkPropertyMetadata((Brush)null));
  392. /// <summary>
  393. /// Gets or sets the Background property. This dependency property
  394. /// indicates background of the autohide childwindow.
  395. /// </summary>
  396. public Brush Background
  397. {
  398. get { return (Brush)GetValue(BackgroundProperty); }
  399. set { SetValue(BackgroundProperty, value); }
  400. }
  401. #endregion
  402. internal bool IsWin32MouseOver
  403. {
  404. get
  405. {
  406. var ptMouse = new Win32Helper.Win32Point();
  407. if (!Win32Helper.GetCursorPos(ref ptMouse))
  408. return false;
  409. Point location = this.PointToScreenDPI(new Point());
  410. Rect rectWindow = this.GetScreenArea();
  411. if (rectWindow.Contains(new Point(ptMouse.X, ptMouse.Y)))
  412. return true;
  413. var manager = Model.Root.Manager;
  414. var anchor = manager.FindVisualChildren<LayoutAnchorControl>().Where(c => c.Model == Model).FirstOrDefault();
  415. if (anchor == null)
  416. return false;
  417. location = anchor.PointToScreenDPI(new Point());
  418. if (anchor.IsMouseOver)
  419. return true;
  420. return false;
  421. }
  422. }
  423. #region AnchorableStyle
  424. /// <summary>
  425. /// AnchorableStyle Dependency Property
  426. /// </summary>
  427. public static readonly DependencyProperty AnchorableStyleProperty =
  428. DependencyProperty.Register("AnchorableStyle", typeof(Style), typeof(LayoutAutoHideWindowControl),
  429. new FrameworkPropertyMetadata((Style)null));
  430. /// <summary>
  431. /// Gets or sets the AnchorableStyle property. This dependency property
  432. /// indicates the style to apply to the LayoutAnchorableControl hosted in this auto hide window.
  433. /// </summary>
  434. public Style AnchorableStyle
  435. {
  436. get { return (Style)GetValue(AnchorableStyleProperty); }
  437. set { SetValue(AnchorableStyleProperty, value); }
  438. }
  439. #endregion
  440. }
  441. }