1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
4 namespace System.Activities.Presentation.Hosting
8 using System.Windows.Interop;
10 using System.Diagnostics.CodeAnalysis;
11 using Microsoft.Tools.Common;
13 public delegate void WindowMessage(int msgId, IntPtr parameter1, IntPtr parameter2 );
15 [Fx.Tag.XamlVisible(false)]
16 public class WindowHelperService
18 HwndSource hwndSource;
19 WindowMessage listeners;
21 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "hwnd is a well known name.")]
22 public WindowHelperService(IntPtr hwnd)
24 this.ParentWindowHwnd = hwnd;
27 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "hwnd is a well known name.")]
28 public IntPtr ParentWindowHwnd
34 internal FrameworkElement View
40 public bool TrySetWindowOwner(DependencyObject source, Window target)
43 Fx.Assert(target != null, "Target window cannot be null");
48 //try the easy way first
49 Window owner = Window.GetWindow(source);
59 IntPtr ownerHwnd = Win32Interop.GetActiveWindow();
60 if (ownerHwnd == IntPtr.Zero)
62 ownerHwnd = this.ParentWindowHwnd;
64 WindowInteropHelper interopHelper = new WindowInteropHelper(target);
65 interopHelper.Owner = ownerHwnd;
73 public bool RegisterWindowMessageHandler(WindowMessage callback)
78 throw FxTrace.Exception.AsError(new ArgumentNullException("callback"));
81 //if there are no other callbacks registered - create initial multicast delegate
82 //and hookup message processing
83 if (null == this.listeners)
85 this.listeners = (WindowMessage)Delegate.Combine(callback);
86 this.HookupMessageProcessing();
88 //otherwise, check if callback is not in the list already
91 Delegate[] initial = this.listeners.GetInvocationList();
92 //if it isn't - add it to callback list
93 if (-1 == Array.IndexOf<Delegate>(initial, callback))
95 Delegate[] combined = new Delegate[initial.Length + 1];
96 combined[initial.Length] = callback;
97 Array.Copy(initial, combined, initial.Length);
99 this.listeners = (WindowMessage)Delegate.Combine(combined);
109 public bool UnregisterWindowMessageHandler(WindowMessage callback)
112 if (null == callback)
114 throw FxTrace.Exception.AsError(new ArgumentNullException("callback"));
116 //if there are any callbacks
117 if (null != this.listeners)
119 Delegate[] list = this.listeners.GetInvocationList();
120 //check if given delegate belongs to the list
121 if (-1 != Array.IndexOf<Delegate>(list, callback))
123 //if list contained 1 element - there is nobody listening for events - remove hook
124 if (list.Length == 1)
126 this.hwndSource.RemoveHook(new HwndSourceHook(OnMessage));
129 this.listeners = (WindowMessage)Delegate.Remove(this.listeners, callback);
135 System.Diagnostics.Debug.WriteLine("UnregisterWindowMessageHandler - callback not in list");
140 internal static void TrySetWindowOwner(DependencyObject owner, EditingContext editingContext, Window wnd)
142 if (null != editingContext)
144 WindowHelperService service = editingContext.Services.GetService<WindowHelperService>();
147 service.TrySetWindowOwner(owner, wnd);
152 void HookupMessageProcessing()
154 //try to create hwnd source object
155 if (null == this.hwndSource)
157 //first - try to create it using ParentWindow handle
158 if (IntPtr.Zero != this.ParentWindowHwnd)
160 this.hwndSource = HwndSource.FromHwnd(this.ParentWindowHwnd);
162 //if didn't succeed - (either handle is null or we are hosted in [....] app)
163 //try to create hwnd source out of designer's view
164 if (null == this.hwndSource)
166 this.hwndSource = HwndSource.FromVisual(this.View) as HwndSource;
169 Fx.Assert(null != this.hwndSource, "HwndSource should not be null!");
170 if (null != this.hwndSource)
172 //register for event notifications
173 this.hwndSource.AddHook(new HwndSourceHook(OnMessage));
177 IntPtr OnMessage(IntPtr hwnd, int msgId, IntPtr wParam, IntPtr lParam, ref bool handled)
179 //notify all listeners about window message
180 this.listeners(msgId, wParam, lParam);