BrowserMouseHelper.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. using System.Linq;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using Microsoft.Phone.Controls;
  5. using System.Windows.Input;
  6. using System.Diagnostics;
  7. using System.Windows.Media;
  8. using System;
  9. using System.Collections.Generic;
  10. namespace SolitaireHTML5
  11. {
  12. public class BrowserMouseHelper
  13. {
  14. /**
  15. *
  16. * Full Script below, in use it is minified.
  17. */
  18. /*
  19. private static string mouseScript =
  20. @"(function(win,doc){
  21. Object.defineProperty( MouseEvent.prototype, 'pageX', {
  22. configurable: true,
  23. get: function(){ return this.clientX }
  24. });
  25. Object.defineProperty( MouseEvent.prototype, 'pageY', {
  26. configurable: true,
  27. get: function(){ return this.clientY }
  28. });
  29. win.onNativeMouseEvent = function(type,x,y){
  30. try {
  31. var xMod = screen.logicalXDPI / screen.deviceXDPI;
  32. var yMod = screen.logicalYDPI / screen.deviceYDPI;
  33. var evt = doc.createEvent('MouseEvents');
  34. var xPos = doc.body.scrollLeft + Math.round(xMod * x);
  35. var yPos = doc.body.scrollTop + Math.round(yMod * y);
  36. var element = doc.elementFromPoint(xPos,yPos);
  37. evt.initMouseEvent(type, true, true, win, 1, xPos, yPos, xPos, yPos, false, false, false, false, 0, element);
  38. var canceled = element ? !element.dispatchEvent(evt) : !doc.dispatchEvent(evt);
  39. return canceled ? 'true' : 'false';
  40. }
  41. catch(e) { return e;}
  42. }
  43. })(window,document);";
  44. */
  45. private static string MinifiedMouseScript = "(function(f,a){Object.defineProperty(MouseEvent.prototype,'pageX',{configurable:!0,get:function(){return this.clientX}});Object.defineProperty(MouseEvent.prototype,'pageY',{configurable:!0,get:function(){return this.clientY}});f.onNativeMouseEvent=function(g,h,i)"
  46. + "{try{var j=screen.logicalXDPI/screen.deviceXDPI,k=screen.logicalYDPI/screen.deviceYDPI,b=a.createEvent('MouseEvents'),c=a.body.scrollLeft+Math.round(j*h),d=a.body.scrollTop+Math.round(k*i),e=a.elementFromPoint(c,d);b.initMouseEvent(g,!0,!0,"
  47. + "f,1,c,d,c,d,!1,!1,!1,!1,0,e);return(e?!e.dispatchEvent(b):!a.dispatchEvent(b))?'true':'false'}catch(l){return l}}})(window,document);";
  48. private WebBrowser _browser;
  49. /// <summary>
  50. /// Gets or sets whether to suppress the scrolling of
  51. /// the WebBrowser control;
  52. /// </summary>
  53. public bool ScrollDisabled { get; set; }
  54. private bool userScalable = true;
  55. private double maxScale = 2.0;
  56. private double minScale = 0.5;
  57. protected Border border;
  58. private bool firstMouseMove = false;
  59. public BrowserMouseHelper(ref WebBrowser browser)
  60. {
  61. _browser = browser;
  62. browser.Loaded += new RoutedEventHandler(browser_Loaded);
  63. }
  64. private void browser_Loaded(object sender, RoutedEventArgs e)
  65. {
  66. var border0 = VisualTreeHelper.GetChild(_browser, 0);
  67. var border1 = VisualTreeHelper.GetChild(border0, 0);
  68. var panZoom = VisualTreeHelper.GetChild(border1, 0);
  69. var grid = VisualTreeHelper.GetChild(panZoom, 0);
  70. border = VisualTreeHelper.GetChild(grid, 0) as Border;
  71. if (border != null)
  72. {
  73. border.ManipulationStarted += Border_ManipulationStarted;
  74. border.ManipulationDelta += Border_ManipulationDelta;
  75. border.ManipulationCompleted += Border_ManipulationCompleted;
  76. border.DoubleTap += Border_DoubleTap;
  77. border.Hold += Border_Hold;
  78. border.MouseLeftButtonDown += Border_MouseLeftButtonDown;
  79. }
  80. _browser.LoadCompleted += Browser_LoadCompleted;
  81. }
  82. void ParseViewportMeta()
  83. {
  84. string metaScript = "(function() { return document.querySelector('meta[name=viewport]').content; })()";
  85. try
  86. {
  87. string metaContent = _browser.InvokeScript("eval", new string[] { metaScript }) as string;
  88. string[] arr = metaContent.Split(new[] { ' ', ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
  89. Dictionary<string, string> metaDictionary = new Dictionary<string, string>();
  90. foreach (string val in arr)
  91. {
  92. string[] keyVal = val.Split('=');
  93. metaDictionary.Add(keyVal[0], keyVal[1]);
  94. }
  95. this.userScalable = false; // reset to default
  96. if (metaDictionary.ContainsKey("user-scalable"))
  97. {
  98. this.userScalable = metaDictionary["user-scalable"] == "yes";
  99. }
  100. this.maxScale = 2.0;// reset to default
  101. if (metaDictionary.ContainsKey("maximum-scale"))
  102. {
  103. this.maxScale = double.Parse(metaDictionary["maximum-scale"]);
  104. }
  105. this.minScale = 0.5;// reset to default
  106. if (metaDictionary.ContainsKey("minimum-scale"))
  107. {
  108. this.minScale = double.Parse(metaDictionary["minimum-scale"]);
  109. }
  110. }
  111. catch (Exception)
  112. {
  113. }
  114. }
  115. void Browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
  116. {
  117. ParseViewportMeta();
  118. try
  119. {
  120. _browser.InvokeScript("execScript", MinifiedMouseScript);
  121. }
  122. catch (Exception)
  123. {
  124. Debug.WriteLine("BrowserHelper Failed to install mouse script in WebBrowser");
  125. }
  126. }
  127. bool InvokeSimulatedMouseEvent(string eventName, Point pos)
  128. {
  129. bool bCancelled = false;
  130. try
  131. {
  132. string strCancelled = _browser.InvokeScript("onNativeMouseEvent", new string[] { eventName, pos.X.ToString(), pos.Y.ToString() }) as string;
  133. if (bool.TryParse(strCancelled, out bCancelled))
  134. {
  135. return bCancelled;
  136. }
  137. }
  138. catch (Exception)
  139. {
  140. // script error
  141. }
  142. return bCancelled;
  143. }
  144. #region Hold
  145. void Border_Hold(object sender, GestureEventArgs e)
  146. {
  147. Debug.WriteLine("Border_Hold");
  148. e.Handled = true;
  149. }
  150. #endregion
  151. #region DoubleTap
  152. void Border_DoubleTap(object sender, GestureEventArgs e)
  153. {
  154. Debug.WriteLine("Border_DoubleTap");
  155. e.Handled = true;
  156. }
  157. #endregion
  158. #region MouseEvents
  159. void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  160. {
  161. border.MouseMove += new MouseEventHandler(Border_MouseMove);
  162. border.MouseLeftButtonUp += new MouseButtonEventHandler(Border_MouseLeftButtonUp);
  163. firstMouseMove = true;
  164. Point pos = e.GetPosition(_browser);
  165. InvokeSimulatedMouseEvent("mousedown", pos);
  166. }
  167. void Border_MouseMove(object sender, MouseEventArgs e)
  168. {
  169. Point pos = e.GetPosition(_browser);
  170. bool retVal = InvokeSimulatedMouseEvent("mousemove", pos);
  171. // only the return value from the first mouse move event should be used to determine if scrolling is prevented.
  172. if (firstMouseMove)
  173. {
  174. //ScrollDisabled = retVal;
  175. }
  176. }
  177. void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  178. {
  179. border.MouseMove -= new MouseEventHandler(Border_MouseMove);
  180. border.MouseLeftButtonUp -= new MouseButtonEventHandler(Border_MouseLeftButtonUp);
  181. Point pos = e.GetPosition(_browser);
  182. e.Handled = InvokeSimulatedMouseEvent("mouseup", pos);
  183. //ScrollDisabled = false;
  184. }
  185. #endregion
  186. #region ManipulationEvents
  187. void Border_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
  188. {
  189. if (ScrollDisabled)
  190. {
  191. e.Handled = true;
  192. e.Complete();
  193. }
  194. }
  195. private void Border_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
  196. {
  197. // optionally suppress zoom
  198. if ((ScrollDisabled || !userScalable) && (e.DeltaManipulation.Scale.X != 0.0 || e.DeltaManipulation.Scale.Y != 0.0))
  199. {
  200. e.Handled = true;
  201. e.Complete();
  202. }
  203. // optionally suppress scrolling
  204. if (ScrollDisabled && (e.DeltaManipulation.Translation.X != 0.0 || e.DeltaManipulation.Translation.Y != 0.0))
  205. {
  206. e.Handled = true;
  207. e.Complete();
  208. }
  209. }
  210. private void Border_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
  211. {
  212. // suppress zoom
  213. if (!userScalable && e.FinalVelocities != null)
  214. {
  215. if (e.FinalVelocities.ExpansionVelocity.X != 0.0 ||
  216. e.FinalVelocities.ExpansionVelocity.Y != 0.0)
  217. {
  218. e.Handled = true;
  219. }
  220. }
  221. }
  222. #endregion
  223. }
  224. }