WPF怎么实现文件拖放功能winform怎么实现拖拽功能

这篇具有很好参考价值的文章主要介绍了WPF怎么实现文件拖放功能winform怎么实现拖拽功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

WPF怎么实现文件拖放功能winform怎么实现文件拖拽功能,在管理员模式下wpf winform怎么实现文件的拖拽功能

WPF实现文件拖放功能,正常情况并没有什么问题,但是如果你的程序使用管理员身份启动,你就会发现文件拖放功能就会失效。同样winform使用管理员身份启动,你就会发现文件拖放功能就会失效

解决一,管理员不给拖拽,就吧管理员启动kill掉

方案一:让你的程序使用非管理员启动,程序中需要管理员身份的操作,一般为涉及到注册表操作或驱动操作,可以考虑将这部分操作放到一个服务里单独操作,可以理解为程序分成服务与应用程序两块,需要管理员身份操作的

功能部分放到服务里实现,界面相关的操作在应用程序里实现。

这种方案也能解决,并且问题解决的比较彻底,但是项目工程量比较大的情况下,工作量就比较大了,为一个文件拖放的功能,增加了较大的工作量,得不偿失。

方案二:将需要管理员权限启动的部分做成另一个单独的exe程序,在主程序中用调用,可参考C#默认以管理员身份运行程序_刘水镜的博客-CSDN博客

方案三:提供一个折中的办法,WPF经过我较长的上网搜索及研究,没有找到合适的办法解决这个问题,但是 WinForm 通过消息Hook却能实现,所以这个折中的办法就是WPF+WinForm来解决这个问题。

主要方法详解:

下面我们将主要讲解如何使用 WPF+WinForm 解决WPF程序使用管理员身份启动后不能拖放文件的问题。

第一部分:使用 WinForm 解决使用不能拖动的问题,关键代码如下

ElevatedDragDropManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows;

public class ElevatedDragDropManager : IMessageFilter
{
    #region "P/Invoke"
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint msg, ChangeWindowMessageFilterExAction action, ref CHANGEFILTERSTRUCT changeInfo);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool ChangeWindowMessageFilter(uint msg, ChangeWindowMessageFilterFlags flags);

    [DllImport("shell32.dll")]
    private static extern void DragAcceptFiles(IntPtr hwnd, bool fAccept);

    [DllImport("shell32.dll")]
    private static extern uint DragQueryFile(IntPtr hDrop, uint iFile, [Out()]
StringBuilder lpszFile, uint cch);

    [DllImport("shell32.dll")]
    private static extern bool DragQueryPoint(IntPtr hDrop, ref POINT lppt);

    [DllImport("shell32.dll")]
    private static extern void DragFinish(IntPtr hDrop);

    [StructLayout(LayoutKind.Sequential)]
    private struct POINT
    {
        public int X;

        public int Y;
        public POINT(int newX, int newY)
        {
            X = newX;
            Y = newY;
        }

        public static implicit operator System.Drawing.Point(POINT p)
        {
            return new System.Drawing.Point(p.X, p.Y);
        }

        public static implicit operator POINT(System.Drawing.Point p)
        {
            return new POINT(p.X, p.Y);
        }
    }

    private enum MessageFilterInfo : uint
    {
        None,
        AlreadyAllowed,
        AlreadyDisAllowed,
        AllowedHigher
    }

    private enum ChangeWindowMessageFilterExAction : uint
    {
        Reset,
        Allow,
        Disallow
    }

    private enum ChangeWindowMessageFilterFlags : uint
    {
        Add = 1,
        Remove = 2
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct CHANGEFILTERSTRUCT
    {
        public uint cbSize;
        public MessageFilterInfo ExtStatus;
    }
    #endregion

    public static ElevatedDragDropManager Instance = new ElevatedDragDropManager();
    public event EventHandler<ElevatedDragDropArgs> ElevatedDragDrop;

    private const uint WM_DROPFILES = 0x233;
    private const uint WM_COPYDATA = 0x4a;

    private const uint WM_COPYGLOBALDATA = 0x49;
    private readonly bool IsVistaOrHigher = Environment.OSVersion.Version.Major >= 6;

    private readonly bool Is7OrHigher = (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1) || Environment.OSVersion.Version.Major > 6;

    public void EnableDragDrop(IntPtr hWnd)
    {
        if (Is7OrHigher)
        {
            CHANGEFILTERSTRUCT changeStruct = new CHANGEFILTERSTRUCT();
            changeStruct.cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(CHANGEFILTERSTRUCT)));
            ChangeWindowMessageFilterEx(hWnd, WM_DROPFILES, ChangeWindowMessageFilterExAction.Allow, ref changeStruct);
            ChangeWindowMessageFilterEx(hWnd, WM_COPYDATA, ChangeWindowMessageFilterExAction.Allow, ref changeStruct);
            ChangeWindowMessageFilterEx(hWnd, WM_COPYGLOBALDATA, ChangeWindowMessageFilterExAction.Allow, ref changeStruct);
        }
        else if (IsVistaOrHigher)
        {
            ChangeWindowMessageFilter(WM_DROPFILES, ChangeWindowMessageFilterFlags.Add);
            ChangeWindowMessageFilter(WM_COPYDATA, ChangeWindowMessageFilterFlags.Add);
            ChangeWindowMessageFilter(WM_COPYGLOBALDATA, ChangeWindowMessageFilterFlags.Add);
        }

        DragAcceptFiles(hWnd, true);
    }

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_DROPFILES)
        {
            HandleDragDropMessage(m);
            return true;
        }
        return false;
    }

    private void HandleDragDropMessage(Message m)
    {
        dynamic sb = new StringBuilder(260);
        uint numFiles = DragQueryFile(m.WParam, 0xffffffffu, sb, 0);
        dynamic list = new List<string>();

        for (uint i = 0; i <= numFiles - 1; i++)
        {
            if (DragQueryFile(m.WParam, i, sb, Convert.ToUInt32(sb.Capacity) * 2) > 0)
            {
                list.Add(sb.ToString());
            }
        }

        POINT p = default(POINT);
        DragQueryPoint(m.WParam, ref p);
        DragFinish(m.WParam);

        dynamic args = new ElevatedDragDropArgs();
        args.HWnd = m.HWnd;
        args.Files = list;
        args.X = p.X;
        args.Y = p.Y;

        if (ElevatedDragDrop != null)
        {
            ElevatedDragDrop(this, args);
        }
    }
}

public class ElevatedDragDropArgs : EventArgs
{
    public IntPtr HWnd
    {
        get { return m_HWnd; }
        set { m_HWnd = value; }
    }
    private IntPtr m_HWnd;
    public List<string> Files
    {
        get { return m_Files; }
        set { m_Files = value; }
    }
    private List<string> m_Files;
    public int X
    {
        get { return m_X; }
        set { m_X = value; }
    }
    private int m_X;
    public int Y
    {
        get { return m_Y; }
        set { m_Y = value; }
    }

    private int m_Y;
    public ElevatedDragDropArgs()
    {
        Files = new List<string>();
    }
}

Form1.cs

注:需要将Form1窗口的AllowDrop属性设置为false,否则无法拖动文件。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FileDragDrop
{
    public partial class FileDragDrop : Form
    {
        public FileDragDrop()
        {
            InitializeComponent();
            //this.AllowDrop设置为false
            this.AllowDrop = false;
            ElevatedDragDropManager filter = new ElevatedDragDropManager();
            //开启拖放功能
            filter.EnableDragDrop(this.Handle);
            //添加消息过滤器
            Application.AddMessageFilter(filter);
            //设置拖放结束回调
            filter.ElevatedDragDrop += this.ElevatedDragDrop;
        }

        //拖放结束事件
        private void ElevatedDragDrop(System.Object sender, ElevatedDragDropArgs e)
        {
            try
            {
                if (e.HWnd == this.Handle)
                {
                    foreach (string file in e.Files)
                    {
                        //拖动文件
                        MessageBox.Show("ElevatedDragDrop File=" + (file) + "!");
                    }
                }
            }
            catch (Exception ex)
            {
                //异常信息
                MessageBox.Show("ElevatedDragDrop error=" + (ex.TargetSite?.Name) + "!");
            }
        }
    }
}

最终的效果:

WPF怎么实现文件拖放功能winform怎么实现拖拽功能,winform,wpf,wpf,winform

 文章来源地址https://www.toymoban.com/news/detail-685490.html

WinForm项目代码链接:

GitHub - zhaobangyu/C-SHAP at WinForm

第二部分:WPF+WinForm的组合使用

效果图:

WPF怎么实现文件拖放功能winform怎么实现拖拽功能,winform,wpf,wpf,winform

 ​WPF+WinForm项目代码链接:

https://github.com/zhaobangyu/C-SHAP/tree/WPF/FileDragDrop

补充

这个直接使用没问题。但如果关闭这个页面重新打开就会有问题。这个拖拽事件一直绑定的第一次创建时的handle。

原因是要在关闭的时候重新释放消息过滤器

 借鉴自https://www.cnblogs.com/whr2071/p/15922643.html

大体的报错范围是,在父窗体中进行释放,可以新建接收拖放的窗口,但窗口句柄与接收放置的句柄匹配不上,触发不了后续事件。在子窗体中进行释放,父窗体中的操作会直接报错“无法访问已释放的对象”。

最后,当我放弃第一个链接的方法去寻找其他解决办法时,看到了第二个链接。发现我没有释放消息过滤器,也就是

Application.RemoveMessageFilter(this);

当我把这个加到我的工程中,一切问题就解决了。

 WPF怎么实现文件拖放功能winform怎么实现文件拖拽功能,在管理员模式下wpf winform怎么实现文件的拖拽功能

 

到了这里,关于WPF怎么实现文件拖放功能winform怎么实现拖拽功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • wpf DataGrid 实现拖拽变换位置,双击拖拽向下自动滚动

    DataGrid_Drop事件是在拖放操作中释放拖动的对象时触发的事件。 使用VisualTreeHelper.HitTest方法获取鼠标释放位置的目标元素。 循环向上遍历VisualTree,直到找到DataGridRow为止。 如果找到DataGridRow,则获取其索引。 检查索引是否有效,如果无效则返回。 交换CmdButtons列表中的拖拽行

    2024年01月18日
    浏览(26)
  • [C#] WinForm/WPF 实现数据库连接与操作(MySQL)

    目录 🌿前言 🌿MySQL数据库简介 🌿数据库的基本概念 🌿ADO.NET体系结构 数据提供程序(.NET Framework Data Provider) 程序数据集(DataSet) 🌿数据库的访问形式 🌿数据库的连接 🌿实现增查改删(CRUD)操作 CRUD SQL常用语句 程序实现数据读取操作 程序实现增删改操作 数据库的使用在涉及

    2024年02月09日
    浏览(33)
  • 如何在WPF中使用Winform控件

            要在WPF中使用WInform组件,必须将WInform组件放在宿主WindowsFormsHost中.  WindowsFormsHost 是WPF的一个控件,它允许在WPF应用程序中托管Windows Forms控件。 要使用 WindowsFormsHost 控件,您需要在WPF项目中添加对 WindowsFormsIntegration 程序集的引用。这是如何做的步骤: 在解决方案

    2024年02月12日
    浏览(31)
  • WPF 与 Winform 的区别以及应用场景

    一、WPF框架以及应用场景 ​ WPF框架 ​ 1.1、WPF与WinForm ​ WPF :https://github.com/dotnet/wpf ​ SilverLight : Web富客户端 ​ 1.2、异/同点 ​ 共同点:最终的输出结果都是客户端应用,实现 人机交互。 ​ 异同点: ​ 界面渲染不一样 ​ 业务逻辑控制不一样(界面设计,色彩、尺寸比

    2024年02月09日
    浏览(26)
  • 按照Vue写WPF(0):功能实现

    我最近学了WPF之后我终于知道为什么WPF学习曲线那么陡峭了。因为WPF没有组件化的思想,或者说没有按照Vue一样去模板化开发。 为什么我推荐Vue的想法呢。因为Vue最大的特点就是模板化,让Vue工程师去写同样的功能,大部分人写的结果都一样。Vue这种套路化的开发大大降低了

    2024年02月16日
    浏览(24)
  • 浅谈WPF之控件拖拽与拖动

    使用过office的visio软件画图的小伙伴都知道,画图软件分为两部分,左侧图形库,存放各种图标,右侧是一个画布,将左侧图形库的图标控件拖拽到右侧画布,就会生成一个新的控件,并且可以自由拖动。那如何在WPF程序中,实现类似的功能呢?今天就以一个简单的小例子,

    2024年02月05日
    浏览(42)
  • Winform/WPF利用CefSharp集成vue开发

    有时候因为各种原因,可能在开发winform或wpf项目的时候需要嵌入web项目,而目前vue在web开发中还是非常流行的,今天有空琢磨了一下怎么在winform中集成vue进行开发,当然,winform能实现,wpf也是一样的。 目前希望达到的效果是,能够在winform中显示web界面,并且能够与vue中的

    2024年02月08日
    浏览(27)
  • WPF鼠标、键盘、拖拽事件、用行为封装事件

    本文主要介绍了WPF中常用的鼠标事件、键盘事件以及注意事项,同时使用一个案例讲解了拓展事件。除此之外,本文还讲述如何用行为(Behavior)来封装事件。 Windows中的事件通过消息机制来完成,也就是Windows系统来捕获用户输入(如鼠标点击、键盘输入),然后Windows发送一

    2024年01月23日
    浏览(26)
  • C#开发winform&wpf后台捕获鼠标移动事件

    做 WPF和winform的时候,可以在界面上设置鼠标移动事件来检测鼠标移动,如果项目为后期改造这样做的话改动量很大,今天通过另外一种后台调用windows api的方式进行快速捕获和触发,提高开发效率分享给大家。

    2024年02月16日
    浏览(32)
  • Visual Studio 2022 WinForm/Wpf打包安装程序

    方法1.手动下载安装包: Microsoft Visual Studio Installer Projects 2022 方法2.Visual Studio中安装 菜单栏中选中【扩展】-【管理扩展】-【联机】中搜索Microsoft Visual Studio Installer并安装 在当前解决方案下添加-新建项目-Setup Project 项目添加成功之后,将需要打包的项目生成后的bin目录下的

    2024年02月04日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包