欢迎光临散文网 会员登陆 & 注册

C#使用WinApi监控和获取剪切板数据

2023-08-10 18:05 作者:bili_17711389278  | 我要投稿

[DllImport("user32.dll")]

        public static extern int OpenClipboard(IntPtr hWndNewOwner);


        [DllImport("user32.dll")]

        public static extern int CloseClipboard();


        [DllImport("user32.dll")]

        public static extern uint EnumClipboardFormats(uint format);

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]

        public static extern int GetClipboardFormatNameW(int format, StringBuilder buffer, int maxLength);

        [DllImport("user32.dll")]

        public static extern bool IsClipboardFormatAvailable(int format);

        [DllImport("user32.dll")]

        public static extern IntPtr GetClipboardData(uint uFormat);

        [DllImport("Kernel32.dll")]

        public static extern IntPtr GlobalLock(IntPtr hMem);


        [DllImport("Kernel32.dll")]

        public static extern bool GlobalUnlock(IntPtr hMem);

        [DllImport("kernel32.dll", SetLastError = true)]

        public static extern uint GlobalSize([In] IntPtr hMem);


        [DllImport("user32.dll")]

        public static extern uint GetClipboardSequenceNumber();


        //输出内容:

        //Current clipboard sequence number: 1037

        //剪切板内容改变!

        //fmt: 13         ---     CF_UNICODETEXT

        //fmt: 16         ---     CF_LOCALE

        //fmt: 1          ---     CF_TEXT

        //fmt: 7          ---     CF_OEMTEXT

        //获取剪切板内容 CF_UNICODETEXT: 这是测试数据

        static void Main(string[] args)

        {

            uint sequenceNumber;

            uint tmpSN = 0;

            bool f = true;


            while (true)

            {

                sequenceNumber = GetClipboardSequenceNumber();

                if (f)

                {          

                    f = false;

                }

                else if (sequenceNumber == tmpSN)

                {

                    continue;

                }

                tmpSN = sequenceNumber;

                Console.WriteLine("Current clipboard sequence number: " + sequenceNumber);

                OpenClipboard(IntPtr.Zero);

                uint fmt = 0;

                Console.WriteLine("剪切板内容改变!");

                while ((fmt = EnumClipboardFormats(fmt)) != 0)

                {

                    // 定义缓冲区和最大长度

                    StringBuilder buffer = new StringBuilder(256);

                    int maxLength = buffer.Capacity;

                    string fmtName = "";

                    switch (fmt)

                    {

                        case 2:

                            fmtName = "CF_BITMAP";

                            break;

                        case 8:

                            fmtName = "CF_DIB";

                            break;

                        case 17:

                            fmtName = "CF_DIBV5";

                            break;

                        case 5:

                            fmtName = "CF_DIF";

                            break;

                        case 0x0082:

                            fmtName = "CF_DSPBITMAP";

                            break;

                        case 0x008E:

                            fmtName = "CF_DSPENHMETAFILE";

                            break;

                        case 0x0083:

                            fmtName = "CF_DSPMETAFILEPICT";

                            break;

                        case 0x0081:

                            fmtName = "CF_DSPTEXT";

                            break;

                        case 14:

                            fmtName = "CF_ENHMETAFILE";

                            break;

                        case 0x0300:

                            fmtName = "CF_GDIOBJFIRST";

                            break;

                        case 0x03FF:

                            fmtName = "CF_GDIOBJLAST";

                            break;

                        case 15:

                            fmtName = "CF_HDROP";

                            break;

                        case 16:

                            fmtName = "CF_LOCALE";

                            break;

                        case 3:

                            fmtName = "CF_METAFILEPICT";

                            break;

                        case 7:

                            fmtName = "CF_OEMTEXT";

                            break;

                        case 0x0080:

                            fmtName = "CF_OWNERDISPLAY";

                            break;

                        case 9:

                            fmtName = "CF_PALETTE";

                            break;

                        case 10:

                            fmtName = "CF_PENDATA";

                            break;

                        case 0x0200:

                            fmtName = "CF_PRIVATEFIRST";

                            break;

                        case 0x02FF:

                            fmtName = "CF_PRIVATELAST";

                            break;

                        case 11:

                            fmtName = "CF_RIFF";

                            break;

                        case 4:

                            fmtName = "CF_SYLK";

                            break;

                        case 1:

                            fmtName = "CF_TEXT";

                            break;

                        case 6:

                            fmtName = "CF_TIFF";

                            break;

                        case 13:

                            fmtName = "CF_UNICODETEXT";

                            break;

                        case 12:

                            fmtName = "CF_WAVE";

                            break;

                        default:

                            //对于不是标准的剪切板格式

                            // 调用GetClipboardFormatNameW函数获取剪贴板格式名称

                            int result = GetClipboardFormatNameW((int)fmt, buffer, maxLength);


                            if (result > 0)

                            {

                                fmtName = buffer.ToString();

                                // 输出剪贴板格式名称

                                // Console.WriteLine("剪贴板格式 " + fmt + " 的名称是:" + buffer.ToString());

                            }

                            else

                            {

                                buffer.Clear();

                                buffer.Append("[Error]");

                                fmtName = buffer.ToString();

                                //Console.WriteLine("无法获取剪贴板格式 " + fmt + " 的名称");

                            }

                            break;

                    }


                    Console.WriteLine("fmt: " + fmt.ToString().PadRight(8) + "\t" + "---" + "\t" + fmtName);

                }


                if (IsClipboardFormatAvailable(13))//CF_UNICODETEXT

                {

                    IntPtr hCpData = GetClipboardData(13);

                    IntPtr pGlobal = GlobalLock(hCpData);


                    byte[] bf = new byte[GlobalSize(pGlobal)];

                    if (pGlobal != IntPtr.Zero)

                    {

                        Marshal.Copy(pGlobal, bf, 0, bf.Length);

                        GlobalUnlock(pGlobal);

                        Console.WriteLine("获取剪切板内容 CF_UNICODETEXT: " + System.Text.Encoding.Unicode.GetString(bf));// bf.ToString() 不行,只会输出 System::char[]


                    }

                    else

                    {

                        Console.WriteLine("pGlobal 为 Null!");

                    }

                }


                CloseClipboard();

                //窗口程序可用 AddClipboardFormatListener 来注册监听器,这样就不用使用死循环来检测剪切板数据是否变化了

                //BOOL AddClipboardFormatListener(

                //    [in] HWND hwnd//要放置在剪贴板格式侦听器列表中的窗口的句柄。

                //);

                System.Threading.Thread.Sleep(1000); 

                Console.WriteLine();

            }


        }


C#使用WinApi监控和获取剪切板数据的评论 (共 条)

分享到微博请遵守国家法律