My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)

时间:2022-12-16 22:45:31

众所周知,Silverlight默认并不支持右键点击和滚轮操作。微软曾经在它的DeepZoom解决方案中给出了一套对于滚轮操作的支持方案(包括一个Helper类,其实中含有NestedType,还有一个EventArgs类),但是至今仍然没有比较正式的对于右键的支持,所以我依照微软的思路,做了对于右键支持的通用类,希望能够对大家有所帮助。今天要介绍的,是这个通用方法的全局侦测的版本,即无论用户点击Application内的哪个元素,都全触发事件,至于是否处理,则交给程序员判断。还有一个为特定UI元素监视右键点击的模式,我会在下一篇中介绍。无疑下一个版本将更加面向对象,但是我认为这个版本也是有一定价值的。

首先,在HostPage中设置Silverlight对象的WindowLess属性为true,在asp.net中:

< asp:Silverlight  ID ="Xaml1"  Windowless ="true"  runat ="server"  Windowless ="true"  Source ="~/ClientBin/MyApp.xap"  MinimumVersion ="2.0.31005.0"  Width ="100%"  Height ="100%"   />

在Html中:

My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)Code

 

这样,余下的工作就可以通过Silverlight中ManagedCode同Javascript的操作来实现了。在这里,首先提出一个类,它能帮助我们计算出任何一个UIElement从Application的RootVisual的平移值。这个类我写成了静态类,并且写成Extension Method,其实用普通的静态类,同样也是可行的。

My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)Code
然后,我介绍一下EventArgs类。其实这个类,只不过是传递了鼠标在Silverlight Application上点击点的绝对定位值,为了方便起见,我在里面加入了几个方法,包括命中测试和被点击到的所有UIElement的可遍历集合。
 1 My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)public   sealed   class  MouseRightClickEventArgs : EventArgs
 2 My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)     {
 3My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        internal MouseRightClickEventArgs(double x, double y)
 4My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        {
 5My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            m_XOffset = x;
 6My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            m_YOffset = y;
 7My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        }

 8My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)
 9My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        private double m_XOffset;
10My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        private double m_YOffset;
11My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)
12My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        public Point GetPosition(UIElement relativeTo)
13My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        {
14My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            if (relativeTo != null)
15My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            {
16My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                Point p = relativeTo.TransformFromRootVisual();
17My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                return new Point(m_XOffset - p.X, m_YOffset - p.Y);
18My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            }

19My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            return new Point(m_XOffset, m_YOffset);
20My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        }

21My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)
22My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        public IEnumerable<UIElement> FindElementsInHitPoint()
23My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        {
24My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            return VisualTreeHelper.FindElementsInHostCoordinates(GetPosition(null), Application.Current.RootVisual);
25My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        }

26My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)
27My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        public bool HitTest(UIElement relativeTo)
28My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        {
29My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            foreach (UIElement element in FindElementsInHitPoint())
30My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            {
31My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                if (element == relativeTo)
32My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                    return true;
33My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            }

34My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            return false;
35My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        }

36My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)
37My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        private bool m_Handled;
38My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        // Summary:
39My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        //     If you don't want to see the Silverlight Configuration,
40My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        //     set it as true
41My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        public bool Handled
42My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        {
43My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            get return this.m_Handled; }
44My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            set this.m_Handled = value; }
45My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        }

46My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)    }
剩余的任务,就是向Javascript中AttachEvent:
 1 My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)public   sealed   class  RightClickHelper:IDisposable
 2 My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)     {
 3My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        public event EventHandler<MouseRightClickEventArgs> RightClick;
 4My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        public RightClickHelper()
 5My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        {
 6My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            //if (!(Application.Current.Host.Settings.Windowless && HtmlPage.IsEnabled))
 7My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                //throw new NotSupportedException("Must set the Windowless of the plug-in as true");
 8My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            HtmlPage.Document.AttachEvent("oncontextmenu"this.OnContextMenu);
 9My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        }

10My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)
11My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        private void OnContextMenu(object sender, HtmlEventArgs e)
12My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        {
13My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            if (RightClick != null)
14My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            {
15My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                MouseRightClickEventArgs evtArgs = new MouseRightClickEventArgs(e.OffsetX, e.OffsetY);
16My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                RightClick(this, evtArgs);
17My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                if (evtArgs.Handled)
18My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)                    e.PreventDefault();
19My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)            }

20My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        }

21My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)
22My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)        IDisposable Members
28My Silverlight系列(11)—— Silverlight中的右键事件点击模拟(全局版本)    }

这样,创建一个RightClickHelper的对象,它将侦测全局的右键点击事件,然后将它们提交给程序员,程序员可调用RightClickEventArgs中的方法进行命中测试,并且判断这次点击是否受理。上面提到的为特点的UI元素加入右键点击的帮助类,只是将EventArgs中的相应方法封装进去,在类内部做出判断后再提交给程序员。这种更加面向对象的方式,我将会在下一篇文章中给出。