我需要做一些事情,如谷歌地图做(但 WPF
):
I need to do something like Google Maps does (but in WPF
):
单击鼠标右键
在地图上我有一个文本菜单。
在 RightDoubleClicking
我有放大还原操作。
when RightClick
on the map I have a ContextMenu.
when RightDoubleClicking
I have the UnZoom action.
所以,很明显,这是在WPF有点困难... 挣扎和搜索了很多之后,阅人认为孔潘说:我们不能predict未来(我问自己怎样谷歌predict吧),我决定将等待的 SystemInformation.DoubleClickTime 的,然后才显示一个文本菜单。
So, apparently, this is a little difficult in WPF... After struggling and searching a lot, read people that compains that "we can't predict the future" (I ask myself how does Google predict it), I decided to "wait" SystemInformation.DoubleClickTime and only then display a contextMenu.
当然,这并不理想,甚至人类的观察的,但我不知道其他的方法。
Surely, this is not ideal, even human-observable, but I don't know other method.
所以,我有以下code中的问题是(我有一个自定义的画布):
So, the problem that I have with the following code is (I have a custom Canvas):
ContextMenuEventArgs lastContextMenuEventArgs = null;
bool? lastContextMenuEventArgsHandled = null;
protected override void OnContextMenuOpening(ContextMenuEventArgs e)
{
lastContextMenuEventArgs = e;
lastContextMenuEventArgsHandled = e.Handled;
e.Handled = true;
//base.OnContextMenuOpening(e);
}
bool rightMouseClickedOnce = false;
protected override void OnPreviewMouseRightButtonUp(MouseButtonEventArgs e)
{
//base.OnPreviewMouseRightButtonUp(e);
Console.WriteLine(">>>>>>>>>>> OnPreviewMouseRightButtonUp");
if (!rightMouseClickedOnce)
{
rightMouseClickedOnce = true;
Thread thread = new Thread(
new System.Threading.ThreadStart(
delegate()
{
Thread.Sleep(System.Windows.Forms.SystemInformation.DoubleClickTime);
this.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Background,
new Action(
delegate()
{
if (rightMouseClickedOnce)
{
Console.WriteLine(">>>>>>>>>>> Right Click");
rightMouseClickedOnce = false;
base.OnPreviewMouseRightButtonUp(e);
if (lastContextMenuEventArgsHandled.HasValue)
{
Console.WriteLine(">>>>>>>>>>> lastContextMenuEventArgsHandled");
lastContextMenuEventArgs.Handled = lastContextMenuEventArgsHandled.Value;
base.OnContextMenuOpening(lastContextMenuEventArgs);
lastContextMenuEventArgsHandled = null;
}
//if (this.ContextMenu != null)
//{
// this.ContextMenu.PlacementTarget = this;
// this.ContextMenu.IsOpen = true;
//}
}
}
));
}
));
thread.Start();
}
else if (rightMouseClickedOnce)
{
Console.WriteLine(">>>>>>>>>>> Right Double Click");
rightMouseClickedOnce = false;
base.OnPreviewMouseRightButtonUp(e);
this.OnMouseRightDoubleClick(e);
}
}
一切都很正常,但是有一点问题: base.OnContextMenuOpening(lastContextMenuEventArgs);
似乎并没有工作...
Everything works great but a little problem: base.OnContextMenuOpening(lastContextMenuEventArgs);
does not seem to work...
我在
if (this.ContextMenu != null)
{
this.ContextMenu.PlacementTarget = this;
this.ContextMenu.IsOpen = true;
}
和工作,但终于开放,开放永远是父(画布)此块子文本菜单元素的ContextMenu。
and that worked, but finally this blocks child contextMenu elements from opening, and open always the parent (canvas) contextMenu.
我可以只调用contextmenu事件?
Can I just invoke the contextMenu event?
我不知道很多关于WPF,但你可以从游标显示菜单,也就是说,一个像素路程,查看用户是否再次右键点击在同一地点,并在系统中双击时间?我在游戏中使用类似的技术,一旦它执行不够好。 一个菜单淡入(可选,出来了,太)动画可以使它变得更好。
I don't know much about WPF, but can you show the menu, say, a pixel away from the cursor and see if the user right-clicks again in the same spot and in the system double click time? I've used a similar technique once in a game and it performed nice enough. A menu "fade in" (optionally, out, too) animation could make it even better.