2012-11-10 55 views
3

的WPF程序下面提出了一个窗口,该窗口看起来像这样:黑色正方形外与DrawingContext.DrawRectangle块鼠标绘制一个矩形

enter image description here

鼠标运动导致窗口标题与被更新鼠标的位置。当鼠标进入广场时停止更新。

我希望MouseMove即使在鼠标在广场上时也能继续触发。有没有办法做到这一点?

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 

namespace Wpf_Particle_Demo 
{ 
    class DrawingVisualElement : FrameworkElement 
    { 
     public DrawingVisual visual; 

     public DrawingVisualElement() { visual = new DrawingVisual(); } 

     protected override int VisualChildrenCount { get { return 1; } } 

     protected override Visual GetVisualChild(int index) { return visual; } 
    } 

    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      var canvas = new Canvas(); 

      Content = canvas; 

      var element = new DrawingVisualElement(); 

      canvas.Children.Add(element); 

      CompositionTarget.Rendering += (s, e) => 
       { 
        using (var dc = element.visual.RenderOpen()) 
         dc.DrawRectangle(Brushes.Black, null, new Rect(0, 0, 50, 50)); 
       }; 

      MouseMove += (s, e) => Title = e.GetPosition(canvas).ToString(); 
     } 
    } 
} 
+0

为什么你使用这样一个奇怪的代码来绘制一个矩形?为什么不在XAML中做一个矩形对象? –

回答

2

您需要Capture鼠标,这将让你的Canvas继续应对MouseMove事件,尝试这样的事情,只要它会更新你的坐标用鼠标按下

public partial class MainWindow : Window 
{ 

    public MainWindow() 
    { 
     InitializeComponent(); 


     var canvas = new Canvas(); 
     Content = canvas; 

     var element = new DrawingVisualElement(); 

     canvas.Children.Add(element); 
     CompositionTarget.Rendering += (s, e) => 
     { 
      using (var dc = element.visual.RenderOpen()) 
       dc.DrawRectangle(Brushes.Black, null, new Rect(0, 0, 50, 50)); 
     }; 

     Mouse.Capture(canvas); 
     MouseDown += (s, e) => Mouse.Capture((UIElement)s); 
     MouseMove += (s, e) => Title = e.GetPosition(canvas).ToString(); 
     MouseUp += (s, e) => Mouse.Capture(null); 

    } 

第二种方法

public MainWindow() 
{ 
    InitializeComponent(); 
    var canvas = new Canvas(); 
    Content = canvas; 

    DrawingVisualElement element = new DrawingVisualElement(); 
    Grid myElement = new Grid(); 
    canvas.Children.Add(myElement); 

    CompositionTarget.Rendering += (s, e) => 
    { 
     using (var dc = element.visual.RenderOpen()) 
     { 
      dc.DrawRectangle(Brushes.Black, null, new Rect(100, 0, 50, 50)); 
     } 

     DrawingImage myImage = new DrawingImage(element.visual.Drawing); 
     myElement.Height = myImage.Height; 
     myElement.Width = myImage.Width; 
     myElement.Background = new ImageBrush(myImage); 
    }; 


    MouseMove += (s, e) => Title = e.GetPosition(canvas).ToString(); 
} 

使用钩一定要放一个using System.Windows.Interop;

public partial class MainWindow : Window 
{ 


    public MainWindow() 
    { 
     InitializeComponent(); 
     var canvas = new Canvas(); 
     Content = canvas; 

     var element = new DrawingVisualElement(); 
     canvas.Children.Add(element); 

     CompositionTarget.Rendering += (s, e) => 
     { 
      using (var dc = element.visual.RenderOpen()) 
      { 
       dc.DrawRectangle(Brushes.Black, null, new Rect(0, 0, 50, 50)); 
      } 
     }; 
     this.SourceInitialized += new EventHandler(OnSourceInitialized); 
    } 

    void OnSourceInitialized(object sender, EventArgs e) 
    { 
     HwndSource source = (HwndSource)PresentationSource.FromVisual(this); 
     source.AddHook(new HwndSourceHook(HandleMessages)); 

    } 
    IntPtr HandleMessages(IntPtr hwnd, int msg,IntPtr wParam, IntPtr lParam, ref bool handled) 
    { 
     if (msg == 0x200) 
      Title = Mouse.GetPosition(this).ToString(); // because I did not want to split the lParam into High/Low values for Position information 
     return IntPtr.Zero; 
    } 
} 
+0

有趣的,谢谢马克。我想在没有按下鼠标按钮的情况下完成此操作。我可以通过将'Mouse.Capture'放入'MouseMove'事件处理程序中来实现。然而,然后有趣的事情发生......例如,不能使用鼠标关闭窗口! :-)另外,即使鼠标移动到画布外,标题get也被更新,例如,进入窗口标题。 – dharmatech

+1

@dharmatech这个问题让我玩大部分的下午,我有另一个使用网格作为容器的例子,也是拦截WM_MOUSEMOVE方法的一个例子。我会发布他们看看他们是否工作 –

+1

我欣赏它马克。谢谢! – dharmatech

3

到目前为止,最简单的方法是到窗口,PreviewMouseDown上使用的“隧道”事件。它首先被传送到窗口并沿着层次结构向上运行。因此,您在窗口中拥有哪些其他元素并不重要。在代码中:

public partial class Window1 : Window { 
    public Window1() { 
     InitializeComponent(); 
     this.PreviewMouseMove += new MouseEventHandler(Window1_PreviewMouseMove); 
    } 
    void Window1_PreviewMouseMove(object sender, MouseEventArgs e) { 
     this.Title = e.GetPosition(this).ToString(); 
    } 
} 
+0

在示例程序中,我将'MouseMove'更改为'PreviewMouseMove',但这似乎没有什么区别。 – dharmatech

0

答案非常简单。所有你需要的是设置element.IsHitTestVisible = false;