我想在拖放操作期间处理诸如OnMouseMove或MouseWheel之类的事件。
但是,据我所知this MSDN topic on Drag/Drop,在拖放操作期间触发的唯一事件是GiveFeedback,QueryContinueDrag,Drag Enter / Leave / Over以及它们的Preview *对应物。从本质上讲,处理这些事件可以让我获取鼠标位置,或者查看用户是按下Ctrl,Shift,Alt,Esc,还是按下或释放其中一个鼠标按钮。
但我想要的是在拖放操作期间处理其他事件,例如MouseWheel。具体来说,我想要做的是让用户滚动窗口的内容(使用鼠标滚轮),同时拖动它上面的东西。我已经尝试为这些其他事件编写处理程序,包括冒泡和隧道版本,以及将它们附加到控件层次结构的各个级别,但据我所知,它们都没有被触发。
我知道有一个部分解决方案(例如描述here),当鼠标位置靠近窗口的顶部或底部时,您可以使用DragOver滚动窗口的内容。但这不是我想要做的。
我遇到article,意味着可以在拖动操作期间处理(例如)OnMouseMove事件。我这样说是因为文章中的代码是上述方法的变体,但它处理的是OnMouseMove而不是DragOver。但是,我尝试采用这种方法,但仍然无法在拖动时触发OnMouseMove事件。我在下面添加了我的代码。它在F#中,所以我使用了FSharpx中的F# XAML type provider。
MainWindow.xaml:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" Width="900">
<DockPanel Name="panel1">
<StatusBar Name="status1" DockPanel.Dock="Bottom">
<TextBlock Name="statustext1" />
</StatusBar>
</DockPanel>
</Window>
Program.fs:
(*
Added references: PresentationCore, PresentationFramework, System.Xaml, UIAutomationTypes, WindowsBase.
*)
// STAThread, DateTime
open System
// Application
open System.Windows
// TextBox
open System.Windows.Controls
// XAML type provider
open FSharpx
type MainWindow = XAML<"MainWindow.xaml">
type TextBox2 (status : TextBlock) as this =
inherit TextBox () with
member private this.preview_mouse_left_button_down (args : Input.MouseButtonEventArgs) = do
this.CaptureMouse () |> ignore
base.OnPreviewMouseLeftButtonDown args
// Fires while selecting text with the mouse, but not while dragging.
member private this.preview_mouse_move (args : Input.MouseEventArgs) =
if this.IsMouseCaptured then do status.Text <- sprintf "mouse move: %d" <| DateTime.Now.Ticks
do base.OnPreviewMouseMove args
member private this.preview_mouse_left_button_up (args : Input.MouseButtonEventArgs) = do
if this.IsMouseCaptured then do this.ReleaseMouseCapture ()
base.OnPreviewMouseLeftButtonUp args
do
this.PreviewMouseLeftButtonDown.Add this.preview_mouse_left_button_down
this.PreviewMouseMove.Add this.preview_mouse_move
this.PreviewMouseLeftButtonUp.Add this.preview_mouse_left_button_up
let load_window () =
let win = MainWindow ()
let t = new TextBox2 (win.statustext1)
do
t.TextWrapping <- TextWrapping.Wrap
t.AcceptsReturn <- true
t.Height <- Double.NaN
win.panel1.Children.Add t |> ignore
win.Root
[<STAThread>]
(new Application () ).Run(load_window () ) |> ignore
答案 0 :(得分:1)
我认为您可以通过 PreviewDragEnter , PreviewDragOver 和 Drop 更有效地完成此操作。我写了一篇关于编写自己的拖放文本框的博客主题,这应该有助于您入门。您可以从那里添加滚动功能:
http://xcalibur37.wordpress.com/2011/12/10/wpf-drag-and-drop-textbox-for-windows-explorer-files/
代码:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
// Initialize UI
InitializeComponent();
// Loaded event
this.Loaded += delegate
{
TextBox1.AllowDrop = true;
TextBox1.PreviewDragEnter += TextBox1PreviewDragEnter;
TextBox1.PreviewDragOver += TextBox1PreviewDragOver;
TextBox1.Drop += TextBox1DragDrop;
};
}
/// <summary>
/// We have to override this to allow drop functionality.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void TextBox1PreviewDragOver(object sender, DragEventArgs e)
{
e.Handled = true;
}
/// <summary>
/// Evaluates the Data and performs the DragDropEffect
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TextBox1PreviewDragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
}
/// <summary>
/// The drop activity on the textbox.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TextBox1DragDrop(object sender, DragEventArgs e)
{
// Get data object
var dataObject = e.Data as DataObject;
// Check for file list
if (dataObject.ContainsFileDropList())
{
// Clear values
TextBox1.Text = string.Empty;
// Process file names
StringCollection fileNames = dataObject.GetFileDropList();
StringBuilder bd = new StringBuilder();
foreach (var fileName in fileNames)
{
bd.Append(fileName + "\n");
}
// Set text
TextBox1.Text = bd.ToString();
}
}
}
博客主题为您提供了每个部分的细分分析。
答案 1 :(得分:1)
我知道这是一个老问题,但是我必须做类似的事情,我的解决方案也可以解决此问题。我认为最好还是在这里链接它,以防万一。这不是最简单的解决方案,但效果很好。
我最终通过p / invoke使用hooks来获取本机窗口消息,然后再通过拖放操作消耗它们。通过使用WH_MOUSE挂钩,我能够拦截WM_MOUSEMOVE消息并跟踪鼠标,而没有WPF的Mouse和DragDrop事件。这应该适用于所有鼠标消息,包括WM_MOUSEWHEEL。
您可以在我最后发表自己的答案的地方查看我的问题。我包括了大多数源代码:
WPF - Track mouse during Drag & Drop while AllowDrop = False