RaUI/Source/MyDb/FileFuns/ElevatedDragDropManager.cs
zilinsoft 3262955f2f ### 2023-11-07更新
------
#### RaUIV4    V4.0.2311.0701
- *.[全新]整合了MyDb、ryControls、MyDb_MySQL等dll文件到RaUI一个项目。
- *.[新增]新增ApkOp类,可以轻松获取APK信息。
- *.[新增]新增JsonExt扩展类,让Json操作更简单。
- *.[新增]新增WebP类,可以支持webp格式的图片。
- *.[改进]ryQuickSQL中的AddField方法改为自动替换已存在的同名值。
- *.[修复]ryQuickSQL中的AddFieldCalc方法无法正常计算的BUG。
2023-11-07 16:37:53 +08:00

244 lines
7.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
/// <summary>
/// 给控件增加拖放功能的类
/// </summary>
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
/// <summary>
/// 拖放实例
/// </summary>
public static ElevatedDragDropManager Instance = new ElevatedDragDropManager();
/// <summary>
/// 高级拖放事件
/// </summary>
public event EventHandler<ElevatedDragDropArgs> ElevatedDragDrop;
private const uint WM_DROPFILES = 0x233;
private const uint WM_COPYDATA = 0x4a;
private const uint WM_COPYGLOBALDATA = 0x49;
/// <summary>
///
/// </summary>
public readonly static bool IsVistaOrHigher = Environment.OSVersion.Version.Major >= 6;
/// <summary>
///
/// </summary>
public readonly static bool Is7OrHigher = (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1) || Environment.OSVersion.Version.Major > 6;
/// <summary>
///
/// </summary>
public ElevatedDragDropManager()
{
Application.AddMessageFilter(this);
}
/// <summary>
///
/// </summary>
public void Remove()
{
Application.RemoveMessageFilter(this);
}
/// <summary>
/// 使管理员方式运行时支持拖放
/// </summary>
/// <param name="hWnd"></param>
public static void AdminDragEnable(IntPtr hWnd)
{
if (Is7OrHigher)
{
CHANGEFILTERSTRUCT changeStruct = new CHANGEFILTERSTRUCT
{
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);
}
}
/// <summary>
/// 使支持拖放属性
/// </summary>
/// <param name="hWnd"></param>
public void EnableDragDrop(IntPtr hWnd)
{
if (Is7OrHigher)
{
CHANGEFILTERSTRUCT changeStruct = new CHANGEFILTERSTRUCT
{
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);
}
/// <summary>
///
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_DROPFILES)
{
HandleDragDropMessage(m);
return true;
}
return false;
}
private void HandleDragDropMessage(Message m)
{
var sb = new StringBuilder(260);
uint numFiles = DragQueryFile(m.WParam, 0xffffffffu, sb, 0);
var 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;
DragQueryPoint(m.WParam, ref p);
DragFinish(m.WParam);
var args = new ElevatedDragDropArgs
{
HWnd = m.HWnd,
Files = list,
X = p.X,
Y = p.Y
};
ElevatedDragDrop?.Invoke(this, args);
}
}
/// <summary>
///
/// </summary>
public class ElevatedDragDropArgs : EventArgs
{
/// <summary>
///
/// </summary>
public IntPtr HWnd { get; set; }
/// <summary>
///
/// </summary>
public List<string> Files { get; set; }
/// <summary>
///
/// </summary>
public int X { get; set; }
/// <summary>
///
/// </summary>
public int Y { get; set; }
/// <summary>
///
/// </summary>
public ElevatedDragDropArgs()
{
Files = new List<string>();
}
}