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;}#endregionpublic 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设置为falsethis.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.mzph.cn/news/60238.shtml

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

相关文章

JAVA-x和y的最大值

输入两个整数 x 和 y&#xff0c;请你编写一个函数&#xff0c;int max(int x, int y)&#xff0c;计算并输出 x 和 y 的最大值。 输入格式 共一行&#xff0c;包含两个整数 x 和 y 。 输出格式 共一行&#xff0c;包含一个整数&#xff0c;表示两个数中较大的那个数。 数据范围…

【MySQL】MySQL权限管理

权限范围管理权限动态权限 授权显示 GRANT 权限 撤销权限激活角色在服务器级别激活角色在用户级别激活角色在会话级别激活角色 感谢 &#x1f496; 在上一篇文章【MySQL】MySQL里的用户账户和角色是什么&#xff1f;如何管理&#xff1f;中&#xff0c;我们了解了MySQL中用户与…

【二维差分】

二维差分 #include<iostream> using namespace std; const int N 100011;int n,m,q;int a[N][N],b[N][N];int main(){cin>>n>>m>>q;for(int i1;i<n;i)for(int j1;j<m;j)cin>>a[i][j];for(int i1;i<n;i)for(int j1;j<m;j)b[i][j] …

jmeter+nmon+crontab简单的执行接口定时压测

一、概述 临时接到任务要对系统的接口进行压测&#xff0c;上面的要求就是&#xff1a;压测&#xff0c;并发2000 在不熟悉系统的情况下&#xff0c;按目前的需求&#xff0c;需要做的步骤&#xff1a; 需要有接口脚本需要能监控系统性能需要能定时执行脚本 二、观察 >针…

后端开发基础概念

后端开发基础概念 目前处于项目上手阶段&#xff0c;在学习项目过程中&#xff0c;有一些一知半解或者不明白含义的专业名词或者缩写&#xff0c;在此汇总。里面的内容很多都是基于个人理解&#xff0c;水平有限如果有出错的地方还请各位大佬批评指正。 2023年8月31日00:34:22…

恒运资本:市盈率怎么算?

市盈率&#xff08;P/E ratio&#xff09;是判别一家公司股票价格合理性的一个重要目标&#xff0c;也是投资者评估公司股票投资价值的重要参阅目标。市盈率越高&#xff0c;表明相对于公司的收益来说&#xff0c;该公司的股票定价越高。市盈率越低&#xff0c;则表明该股票被低…

App与小程序工具总结

文章目录 前言Burpsuite抓包问题LPosedJustTrustMe 绕过 SSL Pining小程序的反编译APP脱壳&#xff0c;反射大师、frida反射大师Frida 总结 前言 在进行渗透工作的时候&#xff0c;遇到过的App、小程序也不少了&#xff0c;有简单的&#xff0c;也有加固的比较不错的&#xff…

聊聊mybatis-plus的SafetyEncryptProcessor

序 本文主要研究一下mybatis-plus的SafetyEncryptProcessor SafetyEncryptProcessor mybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/SafetyEncryptProcessor.java public class SafetyEncryptProcessor implements EnvironmentPostProc…

技术深入解析与教程:网络安全技术探秘

第一章&#xff1a;引言 在当今数字化时代&#xff0c;网络安全已经成为了重要议题。随着各种信息和业务在网络上的传输与存储&#xff0c;安全问题也日益突出。本文将带您深入探讨网络安全领域中的关键技术&#xff0c;涵盖渗透测试、漏洞挖掘以及恶意软件分析等方面&#xf…

PCD点云文件外部框框坐标计算

PCD点云文件直接提取的是点云的坐标&#xff0c;不是最外面的box的坐标&#xff0c;因此可以通过&#xff1a; max_b octree.get_max_bound() min_b octree.get_min_bound()分别得到最大最小的xyz坐标&#xff0c;之后进行计算 点的序号和位置对应如下&#xff1a; 所有的…

【数据结构与算法 模版】高频题刷题模版

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【】&#xff0c;使用【】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&#xff1a;目标公…

vue 在IOS移动端中 windon.open 等跳转外部链接后,返回不触发vue生命周期、mounted等相关事件-解决方法

做了一个列表的h5页面&#xff0c;通过点击列表跳转到外部链接&#xff0c;然后返回是回到原来页面状态&#xff0c;类似缓存。发现在ios端返回后&#xff0c;vue 的mounted() 、create()、路由监听等方法都不会执行。在安卓和pc 端都能正常调用。 解决方案&#xff1a;监听pa…

一篇文章学会C#的正则表达式

https://blog.csdn.net/qq_38507850/article/details/79179128 正则表达式 一句话概括就是用来对字符串根据自己的规则进行匹配的&#xff0c;可以匹配(返回)出符合自己要求的匹配结果&#xff0c;有人说字符串类的函数也可以&#xff0c;确实是这样&#xff0c;但是字符串的函…

软考A计划-网络工程师-复习背熟-路由器与交换配置和网络安全

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

ARM DIY(五)摄像头调试

前言 今天&#xff0c;就着摄像头的调试&#xff0c;从嵌入式工程师的角度&#xff0c;介绍如何从无到有&#xff0c;一步一步地调出一款设备。 摄像头型号&#xff1a;OV2640 开发步骤 分为 2 个阶段 5 个步骤 阶段一&#xff1a; 设备树、驱动、硬件 阶段二&#xff1a; 应…

【SpringBoot】详细介绍Spring Boot中@Component

在Spring Boot中&#xff0c;Component是一个通用的注解&#xff0c;用于标识一个类是Spring框架中的组件。Component注解是Spring的核心注解之一&#xff0c;它提供了自动扫描和实例化bean的功能。 具体来说&#xff0c;Component注解的作用是将一个普通的Java类转化为Spring…

《C和指针》笔记18:前缀++ 和后缀++

C 语言里有前缀 和后缀&#xff0c;使用还是有点不同的。对应的还有--操作符&#xff0c;但它们的工作原理与此相同&#xff0c;只是它所执行的是减值操作而不是增值操作。我们只要掌握的原理&#xff0c;--的原理也就知道了。 在这里我们把符号叫做操作符&#xff0c;把它操作…

【跟小嘉学 Rust 编程】二十、进阶扩展

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…

拿来即用修改密码功能

<template><div><!-- 重置密码 --><el-dialogtitle"修改密码"v-model"state.resetPwdDialogVisible":showClose"state.firstLogin ! 1"width"550px"close"onCancel":close-on-click-modal"false&…

uniapp结合Canvas+renderjs根据经纬度绘制轨迹(二)

uniapp结合Canvasrenderjs根据经纬度绘制轨迹 文章目录 uniapp结合Canvasrenderjs根据经纬度绘制轨迹效果图templaterenderjsjs数据结构 ​ 根据官方建议要想在 app-vue 流畅使用 Canvas 动画&#xff0c;需要使用 renderjs 技术&#xff0c;把操作canvas的js逻辑放到视图层运…