【问题标题】:WPF: Drag and drop a file into the whole window (titlebar and window borders included)WPF:将文件拖放到整个窗口中(包括标题栏和窗口边框)
【发布时间】:2014-11-29 11:15:24
【问题描述】:

在 WinForms 和其他应用程序(例如 Windows 记事本)中,您可以将(例如文件)拖放到整个窗口中 - 这包括标题栏和窗口边框。

在 WPF 中,您只能将文件拖到窗口画布中 - 尝试将其拖到标题栏或窗口边框上会导致“否”光标。

如何让普通的WPF窗口(SingleBorderWindow WindowStyle等)接受拖放到整个窗口?

【问题讨论】:

    标签: c# wpf drag-and-drop


    【解决方案1】:

    不同之处在于,当您设置 AllowDrop="true" 时,WPF 不会调用 OS DragAcceptFiles API。 DragAcceptFiles 将整个窗口注册为放置目标。

    您需要 pinvoke 并有一个小窗口程序来处理丢弃消息。

    这是我制作的一个小测试程序,允许 WPF 窗口在任何地方接受拖放。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
         const int WM_DROPFILES = 0x233;
    
        [DllImport("shell32.dll")]
        static extern void DragAcceptFiles(IntPtr hwnd, bool fAccept);
    
        [DllImport("shell32.dll")]
        static extern uint DragQueryFile(IntPtr hDrop, uint iFile, [Out] StringBuilder filename, uint cch);
    
        [DllImport("shell32.dll")]
        static extern void DragFinish(IntPtr hDrop);
    
    
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
    
            var helper = new WindowInteropHelper(this);
            var hwnd = helper.Handle;
    
            HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
             source.AddHook(WndProc);
    
            DragAcceptFiles(hwnd, true);
        }
    
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_DROPFILES) 
            {
                handled = true;
                return HandleDropFiles(wParam);
            }
    
            return IntPtr.Zero;
        }
    
        private IntPtr HandleDropFiles(IntPtr hDrop)
        {
            this.info.Text = "Dropped!";
    
            const int MAX_PATH = 260;
    
            var count = DragQueryFile(hDrop, 0xFFFFFFFF, null, 0);
    
            for (uint i = 0; i < count; i++)
            {
                int size = (int) DragQueryFile(hDrop, i, null, 0);
    
                var filename = new StringBuilder(size + 1);
                DragQueryFile(hDrop, i, filename, MAX_PATH);
    
                Debug.WriteLine("Dropped: " + filename.ToString());
            }
    
            DragFinish(hDrop);
    
            return IntPtr.Zero;
        }
    }
    

    【讨论】:

    • 效果很好!有没有什么方法可以设置拖动效果(光标),并获得相当于 DragEnter 和 DragLeave 事件的效果?
    • 为此,我认为您需要通过实现 IDropTarget 完全转向使用 OLE 拖放。这篇文章有很多我认为的:ookii.org/Blog/opening_files_via_idroptarget_in_net
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    • 2013-11-04
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多