C# 拖放功能在 Windows 7 上不起作用

问题描述 投票:0回答:7

我有一个使用 C# winforms 的项目已经有一段时间了。我在windows 7发布之前实现了拖放功能。工作起来就像一个魅力。但是,当使用 Windows 7 时,它不起作用。该事件甚至没有被触发。

AllowDrop
设置为 true。订阅
DragEnter
时,它不会在 Windows 7 中被调用(不确定 Vista 是否如此)。但在 XP 上它完全可以工作。该程序以管理权限运行。

Windows 7 和 XP 中的拖放有什么区别吗?不知道是否相关,但我使用的是 x64

c# .net windows-7 drag-and-drop
7个回答
80
投票

源进程和目标进程需要具有兼容的安全级别/权限。例如,如果您的源是 Explorer 并且它以用户级别权限运行,但您的目标应用程序以管理员(提升)级别权限运行,您将无法拖放,因为这被视为安全问题,因为目标是以更高级别的权限运行。


19
投票

它被称为UIPI,用户界面权限隔离。 旨在防止以受限权限运行的程序利用输入注入漏洞。 它可以被禁用,你需要这样做:

  • 修改清单,将
    <requestedExecutionLevel>
    元素的 uiAccess 属性设置为 true。
  • 将程序的 EXE 存储在 c:\windows 或 c:\program files 的子目录中
  • 使用来自有效代码签名机构的证书对您的 EXE 进行签名

从来没有真正尝试过这个,ymmv。


1
投票

从您的应用程序中,使用以下值调用 ChangeWindowMessageFilter,以允许在提升的应用程序和非提升的应用程序(如资源管理器)之间拖放:

ChangeWindowMessageFilter (WM_DROPFILES, MSGFLT_ADD);
ChangeWindowMessageFilter (WM_COPYDATA, MSGFLT_ADD);
ChangeWindowMessageFilter (0x0049, MSGFLT_ADD);

1
投票

对 dmex 帖子的一个小补充。 下面定义变量和常量。

private const uint WM_DROPFILES = 0x233;
private const uint WM_COPYDATA = 0x004A;
private const uint WM_COPYGLOBALDATA = 0x0049;
private const uint MSGFLT_ADD = 1;

此外,如果您的应用程序位于 Windows 7 上,您可能需要考虑使用

ChangeWindowMessageFilterEx
。我还认为 OLE 拖放可能不使用 Windows 消息传递。所以它根本不会影响这一点。


1
投票

这可能是无关的,但我在 Windows 8 中遇到了奇怪的拖放问题。它会工作一段时间,然后停止工作。 我无法在资源管理器、编辑器等之间进行拖放操作。事实证明,当我与运行 Windows 7 的 Hyper-V VM 交互时,我的拖放功能发生了改变(或者可能是ctrl-alt-end 击键以模拟 Hyper-V 的 crtl-alt-delete)。 无论如何,一旦出现问题,以下方法就可以解决它:

我在这里找到了问题的解决方案: 修复拖放功能在 Windows 7 Vista XP 中不起作用

基本上解决方案是:

左键单击资源管理器中的文件,按住鼠标按钮的同时,按 [Esc],然后按 [Ctrl],然后释放鼠标按钮。 我必须假设这是重置某些辅助功能设置或其他内容。


1
投票

在从 VS 2015 和 Windows 7 x64 调试桌面 C# 应用程序时,我遇到了同样的问题。 这是由于桌面上 VS IDE 的快捷方式应用了管理员权限(参见屏幕截图)。取消选中此选项拖放事件会正确引发。

感谢 TimLloyd 的帮助。

enter image description here


0
投票

这里

注意:控件的AllowDrop 必须设置为false

提升班:

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

namespace Drag_n_Drop
{
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;
protected ElevatedDragDropManager()
{
Application.AddMessageFilter(this);
}

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

用途:

using Drag_n_Drop;
//...

private void Form1_Load(object sender, EventArgs e)
{
// Вызываем EnableDragDrop() для каждого дискриптора элемента формы, для которого нужно использовать функция DnD
// в данном примере это сама форма и label1
ElevatedDragDropManager.Instance.EnableDragDrop(this.Handle);
ElevatedDragDropManager.Instance.EnableDragDrop(label1.Handle);
ElevatedDragDropManager.Instance.ElevatedDragDrop += Form1_ElevatedDragDrop;
}
private void Form1_ElevatedDragDrop(System.Object sender, ElevatedDragDropArgs e)
{
if (e.HWnd == this.Handle || e.HWnd == label1.Handle)
{
string filelist = String.Empty;
foreach (string file in e.Files)
{
filelist += file + Environment.NewLine;
}
MessageBox.Show(filelist);
}
}
© www.soinside.com 2019 - 2024. All rights reserved.