PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Libraries/Fluent Ribbon Control Suite 1.3/Sources/Fluent/Fluent/RibbonPopup.cs

#
C# | 318 lines | 210 code | 40 blank | 68 comment | 40 complexity | 928ab7f62f8df6a96c2dd7ee77532260 MD5 | raw file
  1. #region Copyright and License Information
  2. // Fluent Ribbon Control Suite
  3. // http://fluent.codeplex.com/
  4. // Copyright Ĺ  Degtyarev Daniel, Rikker Serg. 2009-2010. All rights reserved.
  5. //
  6. // Distributed under the terms of the Microsoft Public License (Ms-PL).
  7. // The license is available online http://fluent.codeplex.com/license
  8. #endregion
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Diagnostics.CodeAnalysis;
  12. using System.Linq;
  13. using System.Windows;
  14. using System.Windows.Controls;
  15. using System.Windows.Controls.Primitives;
  16. using System.Windows.Input;
  17. using System.Windows.Interop;
  18. using System.Windows.Media;
  19. namespace Fluent
  20. {
  21. /// <summary>
  22. /// Represents popup. This popup has Microsoft Office behavior
  23. /// </summary>
  24. [SuppressMessage("Microsoft.Design", "CA1049")]
  25. public class RibbonPopup : Popup
  26. {
  27. #region Static Methods
  28. // Currently opened popups
  29. static readonly List<RibbonPopup> openedPopups = new List<RibbonPopup>();
  30. /// <summary>
  31. /// Returns active popup
  32. /// </summary>
  33. /// <returns>Active popup or null if no popup is opened</returns>
  34. internal static RibbonPopup GetActivePopup()
  35. {
  36. if(openedPopups.Count==0) return null;
  37. return openedPopups[openedPopups.Count - 1];
  38. }
  39. /// <summary>
  40. /// Closes all currently opened popups
  41. /// </summary>
  42. public static void CloseAll()
  43. {
  44. ClosePopups(0);
  45. }
  46. // TODO: maybe rename CollapseCurrent -> CloseCurrent
  47. /// <summary>
  48. /// Closes the current popup
  49. /// </summary>
  50. public static void CollapseCurrent()
  51. {
  52. if (openedPopups.Count > 0) ClosePopups(openedPopups.Count - 1);
  53. }
  54. #endregion
  55. #region Fields
  56. // Current HwndSource of this Popup
  57. HwndSource hwndSource;
  58. // TODO: comment this field (isFirstMouseUp)
  59. bool isFirstMouseUp;
  60. #endregion
  61. #region Properties
  62. #endregion
  63. #region Constructors
  64. /// <summary>
  65. /// Default constructor
  66. /// </summary>
  67. public RibbonPopup()
  68. {
  69. Focusable = false;
  70. ToolTip = new ToolTip();
  71. (ToolTip as ToolTip).Template = null;
  72. AddHandler(RibbonControl.ClickEvent, new RoutedEventHandler(OnClick));
  73. }
  74. private void OnClick(object sender, RoutedEventArgs e)
  75. {
  76. IsOpen = false;
  77. }
  78. static RibbonPopup()
  79. {
  80. IsOpenProperty.AddOwner(typeof(RibbonPopup), new FrameworkPropertyMetadata(OnIsOpenChanged));
  81. }
  82. private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  83. {
  84. if (!(bool)e.NewValue)
  85. {
  86. RibbonPopup popup = d as RibbonPopup;
  87. if (openedPopups.Contains(popup)) openedPopups.Remove(popup);
  88. }
  89. }
  90. #endregion
  91. #region Overrides
  92. /// <summary>
  93. /// Responds to the condition in which the value of the Popup.IsOpen property
  94. /// changes from false to true.
  95. /// </summary>
  96. /// <param name="e">The event arguments.</param>
  97. protected override void OnOpened(EventArgs e)
  98. {
  99. base.OnOpened(e);
  100. isFirstMouseUp = true;
  101. PopupAnimation = PopupAnimation.None;
  102. if(Child!=null)hwndSource = (HwndSource)PresentationSource.FromVisual(this.Child);
  103. if (hwndSource != null)
  104. {
  105. hwndSource.AddHook(WindowProc);
  106. // Set popup non-topmost to fix bug with tooltips
  107. NativeMethods.Rect rect = new NativeMethods.Rect();
  108. if (NativeMethods.GetWindowRect(hwndSource.Handle, ref rect))
  109. {
  110. NativeMethods.SetWindowPos(hwndSource.Handle, new IntPtr(-2), rect.Left, rect.Top, (int) this.Width,
  111. (int) this.Height,
  112. NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE |
  113. NativeMethods.SWP_NOACTIVATE);
  114. }
  115. }
  116. openedPopups.Add(this);
  117. Activate();
  118. }
  119. /// <summary>
  120. /// Provides class handling for the PreviewMouseLeftButtonDown event
  121. /// </summary>
  122. /// <param name="e">The event data</param>
  123. protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
  124. {
  125. isFirstMouseUp = false;
  126. base.OnPreviewMouseLeftButtonDown(e);
  127. }
  128. /// <summary>
  129. /// Provides class handling for the System.Windows.UIElement.PreviewMouseLeftButtonUp event.
  130. /// </summary>
  131. /// <param name="e">The event data.</param>
  132. protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
  133. {
  134. if (Mouse.Captured == this)
  135. {
  136. Mouse.Capture(null);
  137. e.Handled = true;
  138. }
  139. if (isFirstMouseUp)
  140. {
  141. e.Handled = true;
  142. isFirstMouseUp = false;
  143. }
  144. }
  145. /// <summary>
  146. /// Responds when the value of the Popup.IsOpen property changes from to true to false.
  147. /// </summary>
  148. /// <param name="e">The event data.</param>
  149. protected override void OnClosed(EventArgs e)
  150. {
  151. if (openedPopups.Contains(this)) openedPopups.Remove(this);
  152. PopupAnimation = PopupAnimation.None;
  153. if(openedPopups.Count==0)
  154. {
  155. Window wnd = Window.GetWindow(this);
  156. if (wnd!=null) wnd.Focus();
  157. }
  158. base.OnClosed(e);
  159. }
  160. /// <summary>
  161. /// Invoked when an unhandled System.Windows.Input.Keyboard.KeyDown attached event
  162. /// reaches an element in its route that is derived from this class.
  163. /// Implement this method to add class handling for this event.
  164. /// </summary>
  165. /// <param name="e">The System.Windows.Input.KeyEventArgs that contains the event data.</param>
  166. protected override void OnKeyDown(KeyEventArgs e)
  167. {
  168. if (e.Key == Key.Escape)
  169. {
  170. e.Handled = true;
  171. IsOpen = false;
  172. return;
  173. }
  174. if ((e.Key==Key.System)&&((e.SystemKey == Key.LeftAlt)||(e.SystemKey == Key.RightAlt)||(e.SystemKey == Key.F10)))
  175. {
  176. if (e.SystemKey != Key.F10)
  177. {
  178. ClosePopups(0);
  179. }
  180. else e.Handled = true;
  181. return;
  182. }
  183. base.OnKeyDown(e);
  184. }
  185. #endregion
  186. #region Private methods
  187. private static void ClosePopups(int index)
  188. {
  189. for (int i = openedPopups.Count - 1; i >= index; i--)
  190. {
  191. openedPopups[i].PopupAnimation = PopupAnimation.Fade;
  192. openedPopups[i].IsOpen = false;
  193. //openedPopups[i].hwndSource = null;
  194. //if (openedPopups.Contains(openedPopups[i])) openedPopups.Remove(openedPopups[i]);
  195. }
  196. }
  197. internal void Activate()
  198. {
  199. if (hwndSource != null)
  200. {
  201. if (hwndSource.Handle!=IntPtr.Zero) NativeMethods.SetActiveWindow(hwndSource.Handle);
  202. }
  203. }
  204. /// <summary>
  205. /// Window function
  206. /// </summary>
  207. /// <param name="hwnd"></param>
  208. /// <param name="msg"></param>
  209. /// <param name="wParam"></param>
  210. /// <param name="lParam"></param>
  211. /// <param name="handled"></param>
  212. /// <returns></returns>
  213. private IntPtr WindowProc(
  214. IntPtr hwnd,
  215. int msg,
  216. IntPtr wParam,
  217. IntPtr lParam,
  218. ref bool handled)
  219. {
  220. switch (msg)
  221. {
  222. case 0x0006/*WM_ACTIVATE*/:
  223. {
  224. if (((short)wParam.ToInt32()) == 0)
  225. {
  226. // BUG: Fix for MessageBox: without parent messagebox closes
  227. if (hwndSource != null)
  228. {
  229. if (NativeMethods.GetWindowLongPtr(lParam, NativeMethods.GWL_HWNDPARENT) ==
  230. hwndSource.Handle)
  231. break;
  232. if (openedPopups.Count(x => x.hwndSource.Handle == lParam) == 0)
  233. {
  234. ClosePopups(0);
  235. }
  236. }
  237. }
  238. else
  239. {
  240. int index = openedPopups.IndexOf(this);
  241. ClosePopups(index + 1);
  242. Window wnd = Window.GetWindow(this);
  243. if (wnd != null)
  244. {
  245. IntPtr parentHwnd = (new WindowInteropHelper(wnd)).Handle;
  246. NativeMethods.SendMessage(parentHwnd, 0x0086, new IntPtr(1), IntPtr.Zero);
  247. }
  248. }
  249. break;
  250. }
  251. case 0x0021/*WM_MOUSEACTIVATE*/:
  252. {
  253. int index = openedPopups.IndexOf(this);
  254. ClosePopups(index + 1);
  255. Window wnd = Window.GetWindow(this);
  256. if (wnd != null)
  257. {
  258. IntPtr parentHwnd = (new WindowInteropHelper(wnd)).Handle;
  259. NativeMethods.SendMessage(parentHwnd, 0x0086, new IntPtr(1), IntPtr.Zero);
  260. }
  261. break;
  262. }
  263. case 0x0002/*WM_DESTROY*/:
  264. {
  265. /*if ((hwndSource != null) && (!hwndSource.IsDisposed))
  266. {
  267. // Remove hook
  268. hwndSource.RemoveHook(WindowProc);
  269. hwndSource = null;
  270. }*/
  271. break;
  272. }
  273. }
  274. return IntPtr.Zero;
  275. }
  276. #endregion
  277. }
  278. }