[runtime] Fix corlib out of date error with disabled COM
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Hosting / WindowHelperService.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4 namespace System.Activities.Presentation.Hosting
5 {
6     using System;
7     using System.Windows;
8     using System.Windows.Interop;
9     using System.Runtime;
10     using System.Diagnostics.CodeAnalysis;
11     using Microsoft.Tools.Common;
12
13     public delegate void WindowMessage(int msgId, IntPtr parameter1, IntPtr parameter2 );
14
15     [Fx.Tag.XamlVisible(false)]
16     public class WindowHelperService
17     {
18         HwndSource hwndSource;
19         WindowMessage listeners;
20
21         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "hwnd is a well known name.")]
22         public WindowHelperService(IntPtr hwnd)
23         {
24             this.ParentWindowHwnd = hwnd;
25         }
26
27         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "hwnd is a well known name.")]
28         public IntPtr ParentWindowHwnd
29         {
30             get;
31             private set;
32         }
33
34         internal FrameworkElement View
35         {
36             get;
37             set;
38         }
39
40         public bool TrySetWindowOwner(DependencyObject source, Window target)
41         {
42             bool result = false;
43             Fx.Assert(target != null, "Target window cannot be null");
44             if (null != target)
45             {
46                 if (source != null)
47                 {
48                     //try the easy way first
49                     Window owner = Window.GetWindow(source);
50                     if (null != owner)
51                     {
52                         target.Owner = owner;
53                         result = true;
54                     }
55                 }
56                 //no - it didn't work
57                 if (!result)
58                 {
59                     IntPtr ownerHwnd = Win32Interop.GetActiveWindow();
60                     if (ownerHwnd == IntPtr.Zero)
61                     {
62                         ownerHwnd = this.ParentWindowHwnd;
63                     }
64                     WindowInteropHelper interopHelper = new WindowInteropHelper(target);
65                     interopHelper.Owner = ownerHwnd;
66                     result = true;
67                 }
68             }
69
70             return result;
71         }
72
73         public bool RegisterWindowMessageHandler(WindowMessage callback)
74         {
75             bool result = true;
76             if (null == callback)
77             {
78                 throw FxTrace.Exception.AsError(new ArgumentNullException("callback"));
79             }
80
81             //if there are no other callbacks registered - create initial multicast delegate 
82             //and hookup message processing
83             if (null == this.listeners)
84             {
85                 this.listeners = (WindowMessage)Delegate.Combine(callback);
86                 this.HookupMessageProcessing();
87             }
88                 //otherwise, check if callback is not in the list already
89             else 
90             {
91                 Delegate[] initial = this.listeners.GetInvocationList();
92                 //if it isn't - add it to callback list
93                 if (-1 == Array.IndexOf<Delegate>(initial, callback))
94                 {
95                     Delegate[] combined = new Delegate[initial.Length + 1];
96                     combined[initial.Length] = callback;
97                     Array.Copy(initial, combined, initial.Length);
98
99                     this.listeners = (WindowMessage)Delegate.Combine(combined);
100                 }
101                 else
102                 {
103                     result = false;
104                 }
105             }
106             return result;
107         }
108
109         public bool UnregisterWindowMessageHandler(WindowMessage callback)
110         {
111             bool result = false;
112             if (null == callback)
113             {
114                 throw FxTrace.Exception.AsError(new ArgumentNullException("callback"));
115             }
116             //if there are any callbacks
117             if (null != this.listeners)
118             {
119                 Delegate[] list = this.listeners.GetInvocationList();
120                 //check if given delegate belongs to the list
121                 if (-1 != Array.IndexOf<Delegate>(list, callback))
122                 {
123                     //if list contained 1 element - there is nobody listening for events - remove hook
124                     if (list.Length == 1)
125                     {
126                         this.hwndSource.RemoveHook(new HwndSourceHook(OnMessage));
127                     }
128                     //yes - remove it
129                     this.listeners = (WindowMessage)Delegate.Remove(this.listeners, callback);
130                     result = true;
131                 }
132             }
133             if (!result)
134             {
135                 System.Diagnostics.Debug.WriteLine("UnregisterWindowMessageHandler - callback not in list");
136             }
137             return result;
138         }
139
140         internal static void TrySetWindowOwner(DependencyObject owner, EditingContext editingContext, Window wnd)
141         {
142             if (null != editingContext)
143             {
144                 WindowHelperService service = editingContext.Services.GetService<WindowHelperService>();
145                 if (null != service)
146                 {
147                     service.TrySetWindowOwner(owner, wnd);
148                 }
149             }
150         }
151
152         void HookupMessageProcessing()
153         {
154             //try to create hwnd source object
155             if (null == this.hwndSource)
156             {
157                 //first - try to create it using ParentWindow handle
158                 if (IntPtr.Zero != this.ParentWindowHwnd)
159                 {
160                     this.hwndSource = HwndSource.FromHwnd(this.ParentWindowHwnd);
161                 }
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)
165                 {
166                     this.hwndSource = HwndSource.FromVisual(this.View) as HwndSource;
167                 }
168             }
169             Fx.Assert(null != this.hwndSource, "HwndSource should not be null!");
170             if (null != this.hwndSource)
171             {
172                 //register for event notifications
173                 this.hwndSource.AddHook(new HwndSourceHook(OnMessage));
174             }
175         }
176
177         IntPtr OnMessage(IntPtr hwnd, int msgId, IntPtr wParam, IntPtr lParam, ref bool handled)
178         {
179             //notify all listeners about window message
180             this.listeners(msgId, wParam, lParam);
181             return IntPtr.Zero;
182         }
183
184     }
185 }