0

我想在拖放操作期间处理诸如 OnMouseMove 或 MouseWheel 之类的事件。

但是,据我从有关 Drag/Drop 的 MSDN 主题中可以看出,在拖放操作期间触发的唯一事件是 GiveFeedback、QueryContinueDrag、Drag Enter/Leave/Over 以及它们的 Preview* 对应事件。从本质上讲,处理这些事件可以让我获得鼠标位置,或者查看用户是否按下了 Ctrl、Shift、Alt、Esc,或者按下或释放了鼠标按钮之一。

不过,我想要的是在拖放操作期间处理其他事件,例如 MouseWheel。具体来说,我想做的是让用户滚动窗口的内容(使用鼠标滚轮),同时在窗口上拖动一些东西。我已经尝试为这些其他事件编写处理程序,包括冒泡和隧道版本,以及将它们附加到控制层次结构的各个级别,但据我所知,它们都没有触发。

我知道有一个部分解决方案(例如,在此处描述),当鼠标位置靠近窗口的顶部或底部时,您可以使用 DragOver 滚动窗口的内容。但这不是我想做的。

我遇到了一篇文章,其中暗示可以在拖动操作期间处理(例如) OnMouseMove 事件。我这么说是因为文章中的代码是上述方法的变体,但它处理的是 OnMouseMove 而不是 DragOver。但是,我尝试采用这种方法,但仍然无法在拖动时触发 OnMouseMove 事件。我在下面添加了我的代码。它在 F# 中,所以我使用了FSharpx的F# XAML 类型提供程序。

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>

程序.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
4

2 回答 2

1

我认为您可以使用PreviewDragEnterPreviewDragOverDrop更有效地做到这一点。我写了一个关于编写自己的拖放文本框的博客主题,它应该可以帮助你入门。您可以从那里添加滚动功能:

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();
        }
    }
}

博客主题为您提供每个部分的细分分析。

于 2013-05-11T14:12:06.253 回答
1

我知道这是一个老问题,但我必须做类似的事情,我的解决方案也适用于这个问题。我想我不妨在这里链接它以防万一。这不是最简单的解决方案,但效果很好。

我最终通过 p/invoke 使用钩子来获取本地窗口消息,然后再被拖放操作消耗。通过使用 WH_MOUSE 钩子,我能够拦截 WM_MOUSEMOVE 消息并在没有 WPF 的 Mouse 和 DragDrop 事件的情况下跟踪鼠标。这应该适用于所有鼠标消息,包括 WM_MOUSEWHEEL。

您可以查看我的问题,我最终在其中发布了自己的答案。我包含了大部分源代码:
WPF - Track mouse during Drag & Drop while AllowDrop = False

于 2019-08-08T23:16:04.093 回答