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

发布于 2024-09-01 04:23:17 字数 294 浏览 3 评论 0原文

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

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

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

I have had a project for quite a while using C# winforms. I implemented a drag-drop function before windows 7 was released. Worked like a charm. However, when using windows 7 it does not work. The event doesn't even get triggered.

AllowDrop is set to true. When subscribing to DragEnter it does not get called in windows 7 (not sure about vista). But on XP it works all the way. The program is run with administritave priviliges.

Is there any difference in the drag drop in windows 7 vs xp? Don't know if it's relevant, but I'm using x64

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

懵少女 2024-09-08 04:23:17

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

The source and target processes need to have compatible security levels/privileges. For example, if your source is Explorer and it is running with user level privileges, but your target application is running with administrator (elevated) level permission, you will not be able to drag&drop as this is seen as a security issue as the target is running with a higher level of privileges.

℉服软 2024-09-08 04:23:17

它称为 UIPI,即用户界面权限隔离。旨在防止以受限权限运行的程序利用输入注入漏洞。它可以被禁用,您需要执行以下操作:

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

从未真正尝试过此操作,ymmv。

It is called UIPI, User Interface Privilege Isolation. Designed to prevent input injection exploits from programs that run with restricted privileges. It can be disabled, you'll need to do this:

  • Modify the manifest, set the uiAccess attribute for the <requestedExecutionLevel> element to true.
  • Store your program's EXE in a subdirectory of c:\windows or c:\program files
  • Sign your EXE with a certificate from an valid code signing authority

Never actually tried this, ymmv.

自此以后,行同陌路 2024-09-08 04:23:17

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

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

From your application, call ChangeWindowMessageFilter with the following values to allow dragging and dropping to/from your elevated application and non-elevated applications like Explorer:

ChangeWindowMessageFilter (WM_DROPFILES, MSGFLT_ADD);
ChangeWindowMessageFilter (WM_COPYDATA, MSGFLT_ADD);
ChangeWindowMessageFilter (0x0049, MSGFLT_ADD);
予囚 2024-09-08 04:23:17

对 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;

另外,您可能需要考虑使用 ChangeWindowMessageFilterEx< /code>如果您的应用程序位于 Windows 7 上。我还认为 OLE 拖放可能不使用 Windows 消息传递。所以它根本不会影响这一点。

A Minor addition to dmex's post.
The following defines the variables and the constant.

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

Also, you may want to consider using ChangeWindowMessageFilterEx if you're application is on Windows 7. I also believe that OLE drag and drop may not use Windows messaging. So it wouldn't effect that at all.

眼泪淡了忧伤 2024-09-08 04:23:17

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

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

基本上,解决方案是:

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

It may be unrelated, but I was having whacky Drag-n-Drop issues with Windows 8. It would work for a while and then stop working. I couldn't drag-n-drop between Explorer, in an editor, etc. It turns out that when I interacted with a Hyper-V VM running windows 7, my drag-n-drop ability was altered (or perhaps it was the ctrl-alt-end keystroke to simulate crtl-alt-delete to Hyper-V). In any event, one the issue occurred, the following resolved it:

I found the resolution to my problem here:
Fix Drag Drop Functionality Not Working In Windows 7 Vista XP

Basically the solution was:

Left-Click on a file in explorer, and while holding down the mouse button, press [Esc] then [Ctrl], then release the mouse button. I have to assume that this is resetting some accessibility setting or something.

叹倦 2024-09-08 04:23:17

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

感谢蒂姆劳埃德的帮助。

输入图片此处描述

I had same problem when debugging a desktop C# application from VS 2015 and Windows 7 x64 as S.O.
It was due to the administrator permission applied over the shortcut of my VS IDE in the desktop (see screenshot). Unchecking this option Drag & Drop events raise properly.

Thanks to TimLloyd for his help.

enter image description here

ぃ双果 2024-09-08 04:23:17

来自此处

注意:控件的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);
}
}

From here

NOTE: AllowDrop for control must be set to false

Elevated class:

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

Usage:

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);
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文