Reputation: 943
I want to handle events such as OnMouseMove or MouseWheel during a drag/drop operation.
However, as far as I can tell from this MSDN topic on Drag/Drop, the only events that fire during a drag/drop operation are GiveFeedback, QueryContinueDrag, Drag Enter/Leave/Over, and their Preview* counterparts. Essentially, handling these events allows me to get the mouse position, or see if the user presses Ctrl, Shift, Alt, Esc, or presses or releases one of the mouse buttons.
What I'd like, though, is to handle other events during a drag/drop operation, such as MouseWheel. Specifically what I want to do is to let the user scroll the contents of a window (using the mouse wheel) while dragging something over it. I've tried writing handlers for these other events, both bubbling and tunneling versions, as well as attaching them to various levels of the control hierarchy, but as far as I can tell, none of them are firing.
I'm aware there's a partial solution (described here, for example) where you use DragOver to scroll the contents of a window when the mouse position is near the top or bottom of the window. But that's not what I want to do.
I came across an article that implies it is possible to handle (for example) the OnMouseMove event during a drag operation. I say that because the code in the article is a variant of the approach described above, but it handles OnMouseMove instead of DragOver. However, I tried adapting this approach and still cannot get the OnMouseMove event to fire while dragging. I've added my code below. It's in F#, so I used the F# XAML type provider from FSharpx.
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
Upvotes: 0
Views: 1735
Reputation: 6766
I know this is an old question, but I had to do something similar and my solution also works for this problem. I figure I might as well link it here just in case. It's not the simplest solution but it works perfectly.
I ended up a using hooks via p/invoke to get at the native window messages before they were consumed by the drag and drop operation. By using the WH_MOUSE hook I was able to intercept the WM_MOUSEMOVE message and track the mouse without WPF's Mouse and DragDrop events. This should work for all mouse messages including WM_MOUSEWHEEL.
You can check out my question where I ended up posting my own answer. I included most of the source code with it:
WPF - Track mouse during Drag & Drop while AllowDrop = False
Upvotes: 1
Reputation: 2323
I think you can do this more effectively with PreviewDragEnter, PreviewDragOver, and Drop. I wrote a blog topic on writing your own Drag-and-Drop Textbox that should help get you started. You can add the scrolling functionality from there:
http://xcalibur37.wordpress.com/2011/12/10/wpf-drag-and-drop-textbox-for-windows-explorer-files/
The code:
/// <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();
}
}
}
The blog topic gives you a broken-down analysis of each section.
Upvotes: 1