Files
FancyInput/FancyInput/Common/Utility.cs
T
2026-09-02 20:08:33 +08:00

134 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace FancyInput.Common
{
public class Utility
{
public static bool TrySetClipboardText(string text, out string errorDetail)
{
if (TrySetClipboardTextViaWin32(text, out var win32Error))
{
errorDetail = string.Empty;
return true;
}
errorDetail = win32Error == 0 ? "Win32 未知错误" : $"Win32 0x{win32Error:X8}";
return false;
}
private static bool TrySetClipboardTextViaWin32(string text, out int win32Error)
{
const int maxOpenRetries = 12;
const int openRetryDelayMs = 10;
const uint cfUnicodeText = 13;
const uint gmemMoveable = 0x0002;
const uint gmemZeroInit = 0x0040;
win32Error = 0;
var opened = false;
var hGlobal = IntPtr.Zero;
try
{
for (var i = 0; i < maxOpenRetries; i++)
{
if (OpenClipboard(IntPtr.Zero))
{
opened = true;
break;
}
win32Error = Marshal.GetLastWin32Error();
Thread.Sleep(openRetryDelayMs);
}
if (!opened)
{
return false;
}
if (!EmptyClipboard())
{
win32Error = Marshal.GetLastWin32Error();
return false;
}
var bytes = Encoding.Unicode.GetBytes(text + '\0');
hGlobal = GlobalAlloc(gmemMoveable | gmemZeroInit, (UIntPtr)bytes.Length);
if (hGlobal == IntPtr.Zero)
{
win32Error = Marshal.GetLastWin32Error();
return false;
}
var target = GlobalLock(hGlobal);
if (target == IntPtr.Zero)
{
win32Error = Marshal.GetLastWin32Error();
return false;
}
try
{
Marshal.Copy(bytes, 0, target, bytes.Length);
}
finally
{
GlobalUnlock(hGlobal);
}
if (SetClipboardData(cfUnicodeText, hGlobal) == IntPtr.Zero)
{
win32Error = Marshal.GetLastWin32Error();
return false;
}
// Ownership has transferred to the clipboard.
hGlobal = IntPtr.Zero;
return true;
}
finally
{
if (opened)
{
CloseClipboard();
}
if (hGlobal != IntPtr.Zero)
{
GlobalFree(hGlobal);
}
}
}
[DllImport("user32.dll", SetLastError = true)]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool CloseClipboard();
[DllImport("user32.dll", SetLastError = true)]
private static extern bool EmptyClipboard();
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GlobalFree(IntPtr hMem);
}
}