【Windows】WinForms程序调用WinRT的API清空剪切板

发布时间 2023-11-11 20:08:00作者: Akatsuki-

首先这是.NET Framework 4.6项目才用的方法,高版本直接安装Microsoft.Windows.SDK.Contracts包来使用就行了。

此代码实现了手动调用API获取WinRT的剪切板对象,并通过虚函数指针调用ClearHistory方法清空剪切板历史记录(Win+V)。

 1 using System;
 2 using System.Runtime.CompilerServices;
 3 using System.Runtime.InteropServices;
 4 
 5 namespace Win10ClipboardApiTest
 6 {
 7     public static class Clipboard
 8     {
 9         private enum RO_INIT_TYPE
10         {
11             RO_INIT_SINGLETHREADED = 0,
12             RO_INIT_MULTITHREADED = 1,
13         }
14 
15         [DllImport("api-ms-win-core-winrt-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
16         private static extern IntPtr RoInitialize(RO_INIT_TYPE initType);
17 
18         [DllImport("api-ms-win-core-winrt-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
19         private static extern IntPtr RoUninitialize();
20 
21         [DllImport("api-ms-win-core-winrt-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
22         private static extern IntPtr RoGetActivationFactory(IntPtr activatableClassId, byte[] iid, out IntPtr factory);
23 
24         [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
25         private static extern IntPtr WindowsCreateString([MarshalAs(UnmanagedType.LPWStr)] string sourceString, int length, out IntPtr hstring);
26 
27         [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
28         private static extern IntPtr WindowsDeleteString(IntPtr hstring);
29 
30         [MethodImpl(MethodImplOptions.AggressiveInlining)]
31         private static bool IsSucceeded(IntPtr result) => (long)result >= 0L;
32 
33         // Class Windows.ApplicationModel.DataTransfer.Clipboard
34         private static readonly string RuntimeClass_Windows_ApplicationModel_DataTransfer_Clipboard = "Windows.ApplicationModel.DataTransfer.Clipboard";
35 
36         // Interface is a part of the implementation of type Windows.ApplicationModel.DataTransfer.Clipboard
37         private static readonly byte[] IID_IClipboardStatics2 = Guid.Parse("D2AC1B6A-D29F-554B-B303-F0452345FE02").ToByteArray();
38 
39         // IClipboardStatics2::ClearHistory
40         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
41         private delegate IntPtr IClipboardStatics2ClearHistoryDelegate(IntPtr instance, out byte result);
42 
43         // A helper to read the virtual function pointer from virtual table of the instance.
44         private static T GetVirtualMethodPointer<T>(IntPtr instance, int index)
45         {
46             var table = Marshal.ReadIntPtr(instance);
47             var pointer = Marshal.ReadIntPtr(table, index * IntPtr.Size);
48             return Marshal.GetDelegateForFunctionPointer<T>(pointer);
49         }
50 
51         public static void ClearHistory()
52         {
53             if (IsSucceeded(RoInitialize(RO_INIT_TYPE.RO_INIT_SINGLETHREADED)))
54             {
55                 if (IsSucceeded(WindowsCreateString(RuntimeClass_Windows_ApplicationModel_DataTransfer_Clipboard, RuntimeClass_Windows_ApplicationModel_DataTransfer_Clipboard.Length, out IntPtr classId)))
56                 {
57                     if (IsSucceeded(RoGetActivationFactory(classId, IID_IClipboardStatics2, out IntPtr instance)))
58                     {
59                         var method = GetVirtualMethodPointer<IClipboardStatics2ClearHistoryDelegate>(instance, 7);
60                         method.Invoke(instance, out byte result);
61                         Marshal.Release(instance);
62                     }
63 
64                     WindowsDeleteString(classId);
65                 }
66 
67                 RoUninitialize();
68             }
69         }
70     }
71 }