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

news2024/11/16 23:38:39

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) + "!");
            }
        }
    }
}

最终的效果:

 

WinForm项目代码链接:

GitHub - zhaobangyu/C-SHAP at WinForm

第二部分: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怎么实现文件的拖拽功能

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/933632.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

捕鱼船识别检测算法

捕鱼船识别检测预警系统通过yolov5python网络模型图像识别分析技术&#xff0c;捕鱼船识别检测预警算法利用河道两岸的摄像头实时监测水域中的捕鱼船活动&#xff0c;一旦系统识别到违规捕捞行为&#xff0c;立即发出预警信号&#xff0c;立即发出预警信号&#xff0c;确保及时…

Abaqus软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Abaqus是一款专业的有限元分析软件&#xff0c;广泛应用于工程领域&#xff0c;特别是机械、汽车、航空航天、材料科学等领域。它具有强大的有限元分析功能&#xff0c;可以模拟各种复杂的物理和力学问题&#xff0c;为工程师提…

openCV实战-系列教程8:直方图与傅里叶变换(直方图定义/均衡化原理/均衡化效果/傅里叶概述/频域变换结果/低通与高通滤波)、原理解析、源码解读

打印图像直接用这个函数&#xff1a; import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows()1、直方图 1.1 基本定义…

开源软件的崛起:历史与未来

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

VictoriaLogs:一款超低占用的 ElasticSearch 替代方案

image.png 背景 前段时间我们想实现 Pulsar 消息的追踪流程&#xff0c;追踪实现的效果图如下&#xff1a; 实现其实比较简单&#xff0c;其中最重要的就是如何存储消息。 消息的读取我们是通过 Pulsar 自带的 BrokerInterceptor 实现的&#xff0c;对这个感兴趣的朋友后面会单…

Harbour.Space Scholarship Contest 2023-2024 (Div. 1 + Div. 2) A ~ D

比赛链接 A 正常枚举就行&#xff0c;从最后一位往前枚举&#xff0c;-1、-2、-3...这样 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing namespace std;typedef pair<int, int> PII; typedef long l…

开源软件的可访问性:让技术更加包容

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Pico如何使用C/C++选择哪个I2C控制器,以及SDA和SCL针脚

本文一开始讲述了解决方案&#xff0c;后面是我做的笔记&#xff0c;用来讲述我的发现流程和探究的 Pico I2C 代码结构。 前提知识 首先要说明一点&#xff1a;Pico 有两个 I2C&#xff0c;也就是两套 SDA 和 SCL。这点你可以在针脚图中名字看出&#xff0c;比如下图的 Pin 4…

【CHI】(十四)Link Handshake

1.Link layer Credit 本节介绍了链接层信用证&#xff08;L-Credit&#xff09;机制。信息通过使用L-Credit在接口通道传输。要将一个flit从 Transmitter传输到Receiver&#xff0c;Transmitter必须获得L-Credit。 1.1L-Credit flow control 通过将LCRDV信号置起&#xff0c;…

聊聊近况,一个字【累】

首发博客地址 https://blog.zysicyj.top/ 1 最近生活状态真的是一团糟呀&#xff0c;我们家是承包了二十亩葡萄园的&#xff0c;但是只有我爸妈忙活&#xff0c;今年还好我小舅在这边帮忙&#xff0c;不然我的时间还要被压缩的更厉害&#xff0c;写博客学习那肯定是不敢想的了。…

MacOS goland go1.21 debug问题

安装dlv brew install dlv 安装之后在终端会显示所在目录 类似/usr/local/Cellar/delve/1.21.0/bin 配置goland 在文件系统中找到goland 右击选择show package contents -> Contents -> plugins -> go 尝试替换 其中对应系统 的 dlv 结果还是不行 然后打开应用gol…

汤普森采样(Thompson sampling): Beta分布直观理解(可视化)

本文是博客《汤普森采样(Thompson sampling):理论支持》得附录&#xff0c;进一步理解直观理解Beta分布。 1、曝光(αβ)比较大&#xff0c;且点击(α)比较好的情况&#xff0c;可见现在返回的值大部分在0.8左右。 2、曝光(αβ)比较大&#xff0c;且点击(α)比较小的情况&am…

C++数据结构学习——栈

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、栈二、C语言实现1.声明代码2.实现增删查改代码3.测试代码 总结 前言 栈&#xff08;Stack&#xff09;是计算机科学中一种常见的数据结构&#xff0c;它是…

系统架构设计、Linux、 C++、Java、Python、Andorid、iOS等技术笔记目录分享 - 最全讲解

架构设计师应具备的专业素质&#xff1a; 掌握业务领域的知识、掌握技术知识、掌握设计技能、掌握编程技能、具备沟通能力、具备决策能力、知道组织策略、应是谈判专家。 →点击 笔者主页&#xff0c;欢迎关注哦&#xff08;互相学习&#xff0c;共同成长&#xff09; 笔者看…

Linux网络编程:Web服务器

文章目录&#xff1a; 一&#xff1a;超文本编辑语言HTML 二&#xff1a;HTTP超文本传输协议 1.请求和响应消息流程 myhttpd.c getline函数,&#xff1a;用于读取http协议头 2.错误 2.1 处理出错返回disconnect 2.2 错误页面展示send_error 3.写出http应答协议头 写…

网络安全新闻与事件分析:关注当前的网络安全事件、漏洞披露和攻击趋势,分析其背后的技术细节和影响。

第一章&#xff1a;引言 随着数字化时代的不断发展&#xff0c;网络安全已经成为我们生活和工作中不可忽视的一部分。每时每刻&#xff0c;都有各种各样的网络安全事件、漏洞披露和攻击活动在全球范围内发生。作为IT从业者&#xff0c;我们有责任紧跟网络安全的最新动态&#…

开发智能应用的新范式:大数据、AI和云原生如何构建智能软件

文章目录 1.利用大数据实现智能洞察2. 集成人工智能和机器学习3. 云原生架构的弹性和灵活性4. 实现实时处理和响应5. 数据安全和隐私保护6. 可解释性和透明性7. 持续创新和迭代8. 数据伦理和合规性 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &a…

Inventor软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Inventor软件是一款由Autodesk公司开发的三维计算机辅助设计&#xff08;CAD&#xff09;软件&#xff0c;主要用于机械设计和工程领域。它基于参数化建模技术&#xff0c;可以创建出复杂的三维模型&#xff0c;并且提供了丰富的…

Apache Poi 实现Excel多级联动下拉框

由于最近做的功能&#xff0c;需要将接口返回的数据列表&#xff0c;输出到excel中&#xff0c;以供后续导入&#xff0c;且网上现有的封装&#xff0c;使用起来都较为麻烦&#xff0c;故参考已有做法封装了工具类。 使用apache poi实现excel联动下拉框思路 创建隐藏单元格&a…

23.树表和哈希表的查找

当表插入、删除操作频繁时&#xff0c;为维护表的有序性&#xff0c;需要移动表中很多记录。基于此&#xff0c;我们可以改用动态查找表——几种特殊的树。表结构在查找过程中动态生成。对于给定值key&#xff0c;若表中存在&#xff0c;则成功返回&#xff1b;否则&#xff0c…