C++操作Windows剪贴板
acmilan2015/07/15软件综合 IP:四川
C++操作剪贴板是调用WinAPI来实现的,常用的剪贴板操作函数有:
BOOL OpenClipboard(所有者窗口) 打开剪贴板
BOOL EmptyClipboard() 清空剪贴板
HANDLE SetClipboardData(类型, 内存块句柄) 设置剪贴板内容
HANDLE GetClipboardData(类型) 返回包含剪贴板内容的内存块句柄
BOOL CloseClipboard() 关闭剪贴板

常用的剪贴板数据类型(还包括很多其它类型,详情请参考MSDN相关内容):
CF_TEXT 一段ANSI文本
CF_OEMTEXT 一段DOS文本
CF_UNICODETEXT 一段Unicode文本
CF_LOCALE 区域标识
CF_BITMAP 位图
CF_DIB 设备无关位图

需要使用Win32内存块与剪贴板交互,常用Win32内存块操作函数(另有LocalAlloc等,功能完全相同):
HGLOBAL GlobalAlloc(分配选项, 分配内存大小) 分配全局内存并返回它的句柄或指针
HGLOBAL GlobalFree(内存块句柄) 释放全局内存
SIZE_T GlobalSize(内存块句柄) 返回全局内存的大小
LPVOID GlobalLock(内存块句柄) 获得全局内存所有权,并返回指向全局内存的指针
BOOL GlobalUnlock(内存块句柄) 释放全局内存所有权
GlobalAlloc分配选项如果是GHND,则分配可变内存,清零内存并返回全局内存句柄,需要GlobalLock以获取指针
GlobalAlloc分配选项如果是GPTR,则分配固定内存,清零内存并直接返回指针

复制(向剪贴板写内容)操作流程:
创建一块内存块
1.分配一个适当大小的内存块(GlobalAlloc,GHND)
2.锁定它并获得所有权(GlobalLock)
3.将要复制的内容拷贝到该内存
4.释放内存的所有权(GlobalUnlock)
将剪贴板内容设置为它
5.打开剪贴板(OpenClipboard)
6.清空剪贴板(EmptyClipboard)
7.将该内存块设为剪贴板的数据(SetClipboardData)
8.关闭剪贴板(CloseClipboard)

粘贴(读剪贴板内容)操作流程:
1.打开剪贴板(OpenClipboard)
2.获取包含剪贴板内容的内存块句柄(GetClipboardData)
3.锁定该内存块并获得指针(GlobalLock)
3.读取该内存的内容
4.关闭剪贴板(CloseClipboard)

示例程序:
剪贴板客户端client(),用以发送文本到剪贴板,剪贴板监视器monitor(),用以读取并监视剪贴板的变化。
包含ANSI和Unicode的示例。启动时可以选择模式:c=客户端,m=监视器;a=ANSI文本,u=Unicode文本

捕获.png

<code class="lang-cpp">// ClipboardConsole.cpp : 定义控制台应用程序的入口点。
//
  
#include "stdafx.h"
  
#include <windows.h>
#include <stdio.h>
#include <locale.h>
  
void clientA() // ANSI版剪贴板客户端(复制操作)
{
    DWORD content;
    char buf[200] = {0};
    HGLOBAL hGlobal;
  
    while (true)
    {
        fgets(buf, sizeof(buf), stdin); // 获取输入的字符串
  
        hGlobal = GlobalAlloc(GPTR, (lstrlenA(buf) + 1)); // 新建一个Win32内存块
        char *pGlobal = (char*)GlobalLock(hGlobal); // 锁定并获取它的指针
        lstrcpyA(pGlobal, buf); // 将字符串复制到它的上边
        GlobalUnlock(hGlobal); // 释放内存块所有权
  
        OpenClipboard(NULL); // 打开剪贴板(拥有者窗口为NULL)
        EmptyClipboard(); // 清空
        SetClipboardData(CF_TEXT, hGlobal); // 放置已复制到hGlobal中的ANSI文本
        CloseClipboard(); // 关闭剪贴板
    }
}
  
void monitorA() // ANSI版剪贴板监视器(粘贴操作)
{
    DWORD content;
    HGLOBAL hGlobal;
    char *recstr = NULL;
  
    while (true) {
        OpenClipboard(NULL); // 打开剪贴板,所属窗口为NULL
        if (hGlobal = GetClipboardData(CF_TEXT)) // 获取包含剪贴板内容的Win32内存块句柄(ANSI文本)
        {
            char *pGlobal = (char*)GlobalLock(hGlobal); // 锁定它并获得内存块指针
            if (recstr == NULL || lstrcmpA(pGlobal, recstr) != 0) // 如果获得了新的字符串
            {
                free(recstr); // 释放以前的字符串
                recstr = (char*)malloc(GlobalSize(hGlobal)); // 分配一个新的缓冲区
                if (recstr != NULL)
                {
                    lstrcpyA(recstr, pGlobal); // 复制新的字符串
                    fputs(recstr, stdout); // 显示该字符串
                }
            }
        }
        CloseClipboard(); // 关闭剪贴板
        Sleep(500); // 延时等待
    }
}
  
void clientW() // Unicode版剪贴板客户端(复制操作)
{
    DWORD content;
    wchar_t wbuf[200] = {0}; // wchar_t
    HGLOBAL hGlobal;
  
    while (true)
    {
        fgetws(wbuf, sizeof(wbuf)/sizeof(wchar_t), stdin); // fgetws sizeof(wchar_t)
          
        hGlobal = GlobalAlloc(GHND, (lstrlenW(wbuf) + 1) * sizeof(wchar_t)); // lstrlenW sizeof(wchar_t)
        wchar_t *pGlobal = (wchar_t*)GlobalLock(hGlobal); // wchar_t
        lstrcpyW(pGlobal, wbuf); // lstrcpyW
        GlobalUnlock(hGlobal);
  
        OpenClipboard(NULL);
        EmptyClipboard();
        SetClipboardData(CF_UNICODETEXT, hGlobal); // Unicode文本CF_UNICODETEXT
        CloseClipboard();
    }
}
  
void monitorW() // Unicode版剪贴板监视器(粘贴操作)
{
    DWORD content;
    HGLOBAL hGlobal;
    wchar_t *recstr = NULL; // wchar_t
  
    while (true) {
        OpenClipboard(NULL);
        if (hGlobal = GetClipboardData(CF_UNICODETEXT)) // Unicode文本CF_UNICODETEXT
        {
            wchar_t *pGlobal = (wchar_t *)GlobalLock(hGlobal); // wchar_t
            if (recstr == NULL || lstrcmpW(pGlobal, recstr) != 0) // lstrcmpW
            {
                free(recstr);
                recstr = (wchar_t*)malloc(GlobalSize(hGlobal)); // wchar_t
                if (recstr != NULL)
                {
                    lstrcpyW(recstr, pGlobal); // lstrcpyW
                    fputws(recstr, stdout); // fputws
                }
            }
        }
        CloseClipboard();
        Sleep(500);
    }
}
  
int main(int argc, char* argv[])
{
    char mode[2], charset[2];
      
    setlocale(LC_CTYPE, ""); // 获取系统的区域设定,显示wchar_t需要
  
    printf("模式(【m】onitor或【c】lient):");
    scanf("%1s", mode);
    printf("字符集(【a】nsi或【u】nicode):");
    scanf("%1s", charset);
  
    if (mode[0] == 'm') {
        if (charset[0] == 'a') {
            monitorA();
        } else {
            monitorW();
        }
    } else {
        if (charset[0] == 'a') {
            clientA();
        } else {
            clientW();
        }
    }
  
    return 0;
}</locale.h></stdio.h></windows.h></code>

[修改于 8年10个月前 - 2015/07/23 02:40:50]

来自:计算机科学 / 软件综合
1
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,5年3个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}