关于C#监视剪贴板信息

2023-11-08

1、常规方法

在C#中,有一个常规检测剪贴板的方法,用的是 System.Windows.Forms.Clipboard;

使用起来很简单,代码如下:

/// <summary>
/// 设置剪贴板的文本内容
/// </summary>
/// <param name="s">文本内容</param>
public static void SetText(string s)
{
        Clipboard.SetDataObject(s ?? "");
}

/// <summary>
/// 获取剪贴板中的文本内容
/// </summary>
/// <returns>返回剪贴板文本</returns>
public static string GetText()
{
        IDataObject iData = Clipboard.GetDataObject();
        return (string)iData.GetData(DataFormats.Text);
}

/// <summary>
/// 获取剪贴板位图格式数据(比如从画图软件里复制的图片……)
/// </summary>
/// <returns>位图</returns>
public static Bitmap GetBitmap()
{
        IDataObject iData = Clipboard.GetDataObject();
        //确定此实例中存储的数据是否与指定的格式关联,或是否可以转换成指定的格式
        if (iData.GetDataPresent(DataFormats.Bitmap))
        {
                Bitmap bt = (Bitmap)iData.GetData(DataFormats.Bitmap);
                return bt;
        }
        return null;
}

2、通知检测剪贴板

常规方法没有通知来告诉我们有数据,所以再来一个带通知的方案:

这个代码比较长……

public partial class Form2 : Form
{
    IntPtr nextClipboardViewer;
    public Form2()
    {
        InitializeComponent();
        nextClipboardViewer = (IntPtr)SetClipboardViewer((int)Handle);
    }

    /// <summary>
    /// 要处理的 WindowsSystem.Windows.Forms.Message。
    /// </summary>
    /// <param name="m"></param>
    protected override void WndProc(ref Message m)
    {
        // defined in winuser.h
        const int WM_DRAWCLIPBOARD = 0x308;
        const int WM_CHANGECBCHAIN = 0x030D;

        switch (m.Msg)
        {
            case WM_DRAWCLIPBOARD:
                DisplayClipboardData();
                SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                break;
            case WM_CHANGECBCHAIN:
                if (m.WParam == nextClipboardViewer)
                    nextClipboardViewer = m.LParam;
                else
                    SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }
    /// <summary>
    /// 显示剪贴板内容
    /// </summary>
    public void DisplayClipboardData()
    {
        try
        {
            IDataObject iData = new DataObject();
            iData = Clipboard.GetDataObject();

            if (iData.GetDataPresent(DataFormats.Rtf))
                richTextBox1.Rtf = (string)iData.GetData(DataFormats.Rtf);
            else if (iData.GetDataPresent(DataFormats.Text))
                richTextBox1.Text = (string)iData.GetData(DataFormats.Text);
            else
                richTextBox1.Text = "[Clipboard data is not RTF or ASCII Text]";
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
        }
    }

    /// <summary>
    /// 关闭程序,从观察链移除
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Form2_FormClosed(object sender, FormClosedEventArgs e)
    {
        ChangeClipboardChain(Handle, nextClipboardViewer);
    }

    #region WindowsAPI
    /// <summary>
    /// 将CWnd加入一个窗口链,每当剪贴板的内容发生变化时,就会通知这些窗口
    /// </summary>
    /// <param name="hWndNewViewer">句柄</param>
    /// <returns>返回剪贴板观察器链中下一个窗口的句柄</returns>
    [DllImport("User32.dll")]
    protected static extern int SetClipboardViewer(int hWndNewViewer);

    /// <summary>
    /// 从剪贴板链中移出的窗口句柄
    /// </summary>
    /// <param name="hWndRemove">从剪贴板链中移出的窗口句柄</param>
    /// <param name="hWndNewNext">hWndRemove的下一个在剪贴板链中的窗口句柄</param>
    /// <returns>如果成功,非零;否则为0。</returns>
    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);

    /// <summary>
    /// 将指定的消息发送到一个或多个窗口
    /// </summary>
    /// <param name="hwnd">其窗口程序将接收消息的窗口的句柄</param>
    /// <param name="wMsg">指定被发送的消息</param>
    /// <param name="wParam">指定附加的消息特定信息</param>
    /// <param name="lParam">指定附加的消息特定信息</param>
    /// <returns>消息处理的结果</returns>
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
    #endregion
}

认真看一下并不难理解,这种带通知的方式更方便操作。

3、代码

另外代码打了个包(Form1是方案一,Form2是方案二) 
下载

 

 

from: 

https://blog.csdn.net/arrowzz/article/details/56689111

=======================

MoreWindows工作笔记12】WM_DRAWCLIPBOARD 监视剪切板

2013年12月31日 16:00:23

阅读数:21767

有很多程序会监视剪贴板,比如迅雷,这样当你复制一个迅雷下载链接时,迅雷就可以自动启动并创建一个新的下载任务。下面我们就来看看如何实现这个技术。

 

实现这个技术一共需要4步:

第一步:Add the window to the clipboard viewer chain.

通过SetClipboardViewer()传入窗口句柄,所有监视剪贴板的窗口句柄会组成一个链表(后来者靠前)。这样当剪贴板内容发生变化时,Windows系统给给这些窗口发生消息。

 

第二步:Process the WM_CHANGECBCHAIN message.

当这个监视剪贴板的窗口句柄链表发生变化时,会收到这个消息。每个窗口都应该给下一个窗口传递消息。

这个消息的wParamlParam说明如下:

wParam表示

A handle to the window being removedfrom the clipboard viewer chain

lParam表示

A handle to the next window in thechain following the window being removed. This parameter is NULL if thewindow being removed is the last window in the chain。

 

第三步:Process the WM_DRAWCLIPBOARD message.

当剪贴板数据发送变化时,窗口会依次收到这个消息。

 

第四步:Remove the window from the clipboard viewer chain before itis destroyed.

当窗口关闭时,应该调用ChangeClipboardChain()来通知Windows系统将自己从监视剪贴板的窗口句柄链表中移除。

 

代码如下(下载地址:http://download.csdn.net/download/morewindows/6793027

 

[cpp] view plain copy

  1. <code class="language-cpp">// 【MoreWindows工作笔记12】WM_DRAWCLIPBOARD 监视剪切板  
  2. // http://blog.csdn.net/morewindows/article/details/17655429  
  3. // By MoreWindows( http://blog.csdn.net/MoreWindows )  
  4. BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)  
  5. {  
  6.   static HWND s_hwnd_new_clipboard_viewer = NULL;  
  7.   static HWND s_hwnd_edit_clipboard_info = NULL;  
  8.   
  9.     switch (message)  
  10.     {  
  11.     case WM_INITDIALOG:  
  12.     // 4-1 Add the window to the clipboard viewer chain.   
  13.     s_hwnd_new_clipboard_viewer = SetClipboardViewer(hDlg);  
  14.     // 把hwnd加入监视链,返回上一个加入的窗口句柄,如果是第一个,则返回值为NULL。新加的窗口在链条头部,成为“当前监视器”  
  15.         CenterWindow(hDlg);  
  16.     s_hwnd_edit_clipboard_info = GetDlgItem(hDlg, IDC_EDIT_CLIPBOARD_INFO);  
  17.         return FALSE;  
  18.   
  19.   // 4-2 Process the WM_CHANGECBCHAIN message.   
  20.   case WM_CHANGECBCHAIN:  
  21.     if ((HWND)wParam == s_hwnd_new_clipboard_viewer)  
  22.       s_hwnd_new_clipboard_viewer = (HWND)lParam;  
  23.     else  
  24.       SendMessage(s_hwnd_new_clipboard_viewer, message, wParam, lParam);  
  25.   
  26.   // 4-3 Process the WM_DRAWCLIPBOARD message.   
  27.   case WM_DRAWCLIPBOARD:  //剪切板内容发生变化  
  28.     if (OpenClipboard(hDlg)) {  
  29.       UINT clipboard_format = EnumClipboardFormats(0);  
  30.       HGLOBAL global_memory = GetClipboardData(clipboard_format);  
  31.       DWORD data_size = GlobalSize(global_memory);  
  32.       CloseClipboard();  
  33.       WCHAR clipboard_info[1024];  
  34.       swprintf(clipboard_info, L"Clipboard\r\n Data Format = %x\r\n Data Address = 0x%x\r\n Data Size = %d", clipboard_format, global_memory, data_size);  
  35.       if (clipboard_format == CF_UNICODETEXT) {  
  36.         LPCWSTR clipboard_data = (LPCWSTR)GlobalLock(global_memory);  
  37.         if (clipboard_data != NULL) {  
  38.           wcscat(clipboard_info, L"\r\nData: \r\n");  
  39.           WCHAR buffer[1024];  
  40.           DWORD data_size = GlobalSize(global_memory);  
  41.           for (size_t i = 0; i < data_size; i++)  
  42.             buffer[i] = clipboard_data[i];  
  43.           buffer[data_size] = L'\0';  
  44.           wcscat(clipboard_info, buffer);  
  45.         }  
  46.       }  
  47.       SetWindowTextW(s_hwnd_edit_clipboard_info, clipboard_info);  
  48.     }  
  49.     return FALSE;  
  50.   
  51.     case WM_COMMAND:  
  52.         switch (LOWORD(wParam))  
  53.         {  
  54.         case IDOK:  
  55.         case IDCANCEL:  
  56.       // 4-4 Remove the window from the clipboard viewer chain before it is destroyed.   
  57.       ChangeClipboardChain(hDlg, s_hwnd_new_clipboard_viewer);  
  58.             EndDialog(hDlg, FALSE);  
  59.             return TRUE;  
  60.         }  
  61.         break;  
  62.     }  
  63.     return FALSE;  
  64. }</code>  

 

运行程序,复制《【霍比特人2:史矛革之战】》的下载链接,然后程序会显示:

 

 

最后再列一下目录,方便大家查看。

1.《【MoreWindows工作笔记9】OleGetClipboard 访问剪切板的文本内容》

http://blog.csdn.net/morewindows/article/details/17655053

2.《【MoreWindows工作笔记10】OleGetClipboard 访问剪切板上的文件信息》

http://blog.csdn.net/morewindows/article/details/17655057

3.《【MoreWindows工作笔记11】EnumClipboardFormats剪切板内容的数据格式》

http://blog.csdn.net/morewindows/article/details/17655299

4.《【MoreWindows工作笔记12】WM_DRAWCLIPBOARD 监视剪切板》

http://blog.csdn.net/morewindows/article/details/17655429

 

from:https://blog.csdn.net/morewindows/article/details/17655429/ chang e c b chai n

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于C#监视剪贴板信息 的相关文章

  • 什么定义了类型的大小?

    ISO C 标准规定 sizeof char lt sizeof short lt sizeof int lt sizeof long 我在 BIT Linux mint 19 1 上使用 GCC 8 大小为long int is 8 我正
  • Visual Studios 2015 中的“恢复 NuGet 包”没有执行任何操作

    我将解决方案从 SVN 拉入 Visual Studios 2015 代码中的一些 使用 引用出现错误 因此我尝试在右键单击 解决方案 中的解决方案时运行 恢复 NuGet 包 选项探索者 这没有任何作用 我必须手动进入 nuget 管理器
  • 在 WCF 上重用我的 PagedList 对象

    问题 我有一个自定义集合PagedList
  • Boost MPI 在监听列表时不会释放资源?

    这是一个后续问题如何释放 boost mpi request https stackoverflow com questions 44078901 how do i free a boostmpirequest 我在监听列表而不是单个项目时
  • 信号与信号2

    我的应用程序可能会受益于使用 boost 的信号库之一而不是本土解决方案 该应用程序是多线程的 但执行信号处理的部分是单线程的 如果多线程不是问题 是否有任何理由更喜欢 Boost Signals2 而不是 Boost Signal Boo
  • 头文件中实现的函数的静态与内联

    我想到的方式inline在 C 中用于链接 作用域 我把它放在同一个篮子里extern and static对于全局对象 通常 对于在头文件中实现的函数 我的首选解决方案是将其设为静态 In Foo h static void foo Do
  • 如何使用c#从数据桶中获取所有文档?

    如何获取数据桶中的所有文档 我尝试过一个示例 但我只能获得一个特定的文档 这是我的代码 CouchbaseClient oclient oclient new CouchbaseClient vwspace data bucket name
  • 如何从不同的线程访问控件?

    如何从创建控件的线程以外的线程访问控件 避免跨线程错误 这是我的示例代码 private void Form1 Load object sender EventArgs e Thread t new Thread foo t Start p
  • 选择initializer_list迭代器定义

    Why std initializer list
  • C# 中的抽象类和接口类有什么不同?

    C 中的抽象类和接口类有什么不同 An 接口不是类 它只是一个contract定义了public一个类的成员must实施 抽象类只是一个类 您从中可以cannot创建一个实例 通常您会使用它来定义一个基类 该基类定义了一些virtual方法
  • 为什么 BinaryFormatter 可以序列化 Action<> 但 Json.net 不能

    尝试序列化 反序列化 Action 尝试我的 1天真 JsonConvert SerializeObject myAction JsonConvert Deserialize
  • 如何在 C++ 和 QML 应用程序中使用 qrc?

    我在 Windows7 上用 c qnd Qt Creator QML 编写了 Qt Quick Desktop 应用程序 现在 我必须部署它 并且我需要隐藏 qml 文件和图像 意味着 将它们放入资源等中 我读到有一个很好的方法可以使用
  • asp.net core http 如果没有内容类型标头,则删除 `FromBody` 忽略

    我在 http 中使用 bodyDELETE要求 我知道目前删除主体是非标准的 但是允许的 使用时出现问题HttpClient它不允许删除请求的正文 我知道我可以使用SendAsync 但我宁愿让我的 API 更加灵活 我希望这个机构是可选
  • 如何在 C++ 运行时更改 QML 对象的属性?

    我想在运行时更改 QML 对象的文本 我尝试如下 但文本仍然为空 这是后端类 class BackEnd public QObject Q OBJECT Q PROPERTY QString userFieldText READ userF
  • Windows 上本机 C++ 应用程序中的自动死代码检测?

    背景 我有一个用原生 C 编写的应用程序 花了几年的时间 大约有 60 KLOC 有很多函数和类已经死了 可能有 10 15 就像下面提出的类似的基于 Unix 的问题 我们最近开始对所有新代码进行单元测试 并尽可能将其应用于修改后的代码
  • 使用 dateTimePicker 在 DataGridView 中编辑日期

    我有一个DateTime我的 WinForms 中的专栏DataGridView 目前只能通过手动输入日期来编辑该字段 例如 2010 09 02 需要什么才能拥有一个DateTimePicker 或同等 用作编辑器 DataGridVie
  • 使用 cmake 将两种解决方案合二为一

    我有两个单独的 Visual Studio 2013 解决方案 我想将它们迁移到一个解决方案中 因为第一个解决方案 使用 Qt 充当第二个解决方案的 GUI 最后 我希望有一个结构如下的单一解决方案 Solution All Build P
  • 在特定线程上运行工作

    我想要一个特定的线程 任务队列并在该单独的线程中处理任务 应用程序将根据用户的使用情况创建任务并将其排队到任务队列中 然后单独的线程处理任务 即使队列为空 保持线程活动并使用它来处理排队任务也至关重要 我尝试过几种实现TaskSchedul
  • 如果仅使用第一个元素,是否必须为整个结构分配内存?

    我有一个结构 其中第一个元素被测试 并且根据其值 结构的其余部分将被读取或不会被读取 在第一个元素的值指示结构的其余部分不会被读取的情况下 我是否必须为整个结构或仅第一个元素分配足够的内存 struct element int x int
  • 使用C标准数学库精确计算标准正态分布的CDF

    标准 C 数学库不提供计算标准正态分布 CDF 的函数 normcdf 然而 它确实提供了密切相关的函数 误差函数 erf 和互补误差函数 erfc 计算 CDF 的最快方法通常是通过误差函数 使用预定义常量 M SQRT1 2 来表示 d

随机推荐

  • 微信小程序-图片宽高设置

    微信小程序中 有很做组件都是有默认宽高的 比如 image组件默认宽度320px 度240px 这些默认设置常常会对我们的页面布局造成影响
  • 【实验室学习】时钟分频器,2、3、4、8分频 verilog实现

    0引言 记录时钟分频器的Verilog代码编写 主要掌握分频器设计思路 1设计 2 3 4 8分频 2 4 8分频设计较为容易 2分频 设计一个1位的寄存器 当原时钟上升沿时取反即可 代码展示 timescale 1ns 1ps modul
  • 详解HTTP协议

    HTTP 协议 几乎是每个人上网用的第一个协议 同时也是很容易被人忽略的协议 根据TCP IP模型 网络分层分为四层 应用层 传输层 网络层 网络接口层 数据链路层 物理层 HTTP协议属于应用层的一种协议 http www baidu c
  • 深度学习中30个关于数据的问题

    1 下面的数据是线性可分的嘛 否 2 下面哪个是通用的模型逼近器 A Kernel SVM B Neural Networks C Boosted Decision Trees D All of the above D 以上所有都可以得到一
  • java生成三位随机数_java工具类(三)之生成若干位随机数

    java 生成若干位随机数的问题 在一次编程的过程中偶然碰到一个小问题 就是需要生成一个4位数的随机数 如果是一个不到4位大的数字 前面可以加0来显示 因为要求最后是一个4位的整数 不带小数点 当时就想到了几个办法 一 用Math rand
  • ADC0832的AD模数转换原理及编程

    作者简介 嵌入式领域优质创作者 博客专家 个人主页 咸鱼弟 系列专栏 单片机设计专栏 目录 一 描述 二 模数转换原理 三 模数转换的过程 四 八位串行A D转换器ADC0832简介 五 ADC0832特点 六 芯片接口说明 七 ADC08
  • TongWeb及应用系统安全加固

    前言 本文档主要面向运维人员说明常见的TongWeb6 TongWeb7安全加固的配置方法 TongWeb配置 一 首先建议TongWeb升级到最新版本 早期版本存在一些代码级安全漏洞 无法通过配置解决 截止2021年4月15日TongWe
  • codeblocks安装后出现问题的可能解决办法

    昨天在写cf的时候遇到了一个问题 因为办公室这台电脑我是刚用 没有装过codeblocks之前 在用到花括号构造的时候报错 如图 不能直接用花括号了 这我能忍 按照以往的经验来说 是compiler出现了问题 于是设置了一下 看起来好像对了
  • msvcr120.dll丢失的解决方法,win10系统dll报错解决方法

    今天 我将和大家分享一个在win10系统中经常遇到的问题 msvcr120 dll丢失 相信很多朋友在使用电脑的过程中都会遇到这个问题 那么如何解决呢 接下来 就让我为大家详细讲解一下解决方法 首先 我们来了解一下msvcr120 dll文
  • Kazantzis-Kravaris-Luenberger ( KKL )非线性观测器

    The formulation of the observer design problem is realized via a system of singular first order linear PDEs and a rather
  • 【Python搞搞轻量Blog】第二发 Flask入门(2)

    上一篇文章 Flask入门 中创建了一个非常简单的Web应用 但从最简单中又稍微深入的说了一下Flask 基于Werkzeug 使用模板 利用HTML 如何快速利用写好的HTML呢 第一步 在和主应用的同级目录下 创建一个名为 templa
  • [算法]PRML学习笔记1.2.6贝叶斯曲线拟合(Bayesian curve fitting)

    参考文献 Pattern Recognition and Machine Learning Published by Springer January 2006 https www microsoft com en us research
  • 【Vue 学习】修改页面默认的标题

    修改页面默认的标题 一般是在 public index html 里面进行设置网页标题 如下 Vue 的脚手架使用了读取配置文件的方式来设置网页标题 如下 配置文件的内容如下 总结 直接修改 public index html 文件 修改配
  • FPN(特征金字塔)图解

    FPN 看了mask RCNN的源代码 其中用到fpn 根据源代码画了个图 当然FPN重要的是它的思想 有一些超参数可以根据自己的框架进行调整
  • [HFSS]Floquet port激励及主从边界设置(实例)

    Floquet port激励及主从边界设置 1 Floquet port简介 2 基本模型建立 3 主从边界设置 4 wave port 设置 5 floquet port 设置 6 Analysis setup 7 验证 仿真 8 结果演
  • Python标准库、模块、包的区别

    文章目录 模块 包 标准库 第三方库 自定义模块 模块 模块可定义为一个包含python定义和语句的 py文件 模块中包含python代码以及python函数 类或python变量 一个模块可以被其他 py文件导入使用 也可以单独作为脚本文
  • 3.3 Git 分支 - 分支管理

    3 3 Git 分支 分支管理 版本说明 版本 作者 日期 备注 0 1 loon 2019 3 23 初稿 目录 文章目录 3 3 Git 分支 分支管理 版本说明 目录 分支管理 分支管理 现在已经创建 合并 删除了一些分支 让我们看看
  • 51单片机的几种中断的用法

    1 外部中断0 外部中断0实验 实现现象 下载程序后按下K3按键可以对D1小灯状态取反 注意事项 无 include reg52 h 此文件中定义了单片机的一些特殊功能寄存器 typed
  • gitlab可以访问,但git clone连接超时不能下载

    因此 我们可以把 http wozhendetainanle map 地址后面加上 git后缀 更改为 http wozhendetainanle map git 此时使用就可以下载了
  • 关于C#监视剪贴板信息

    1 常规方法 在C 中 有一个常规检测剪贴板的方法 用的是 System Windows Forms Clipboard 使用起来很简单 代码如下