2012-11-10 57 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;