Windows剪貼板復制消息和內容截取


@


Windows剪貼板復制消息和內容截取

解決了什么問題

在Windows應用開發的過程中,根據需求有時候會需要監控一下剪貼板,看看剪貼板的內容是否是我們應用程序感興趣的內容。
比如下載器,往往會監控剪貼板內是否有下載鏈接,然后彈出下載頁面
本文將一探究竟,自己實現一個當剪貼板內容有更新時立即通知到我們程序


實現思路

當剪貼板有新的內容產生時,Windows會給關注的窗口推送剪貼板內容更新消息,我們需要在我們窗口中先注冊監聽剪貼板相關消息,我們需要關注的是剪貼板有新的內容進入的時候怎么做的問題,所以本文主要關注 WM_DRAWCLIPBOARD 消息。
關於windows剪貼板每個消息的含義,可以查看微軟的文檔 WM_DRAWCLIPBOARD 消息說明和接收該消息需要的操作.

實現過程

1. 監聽剪貼板內容更新消息

SetClipboardViewer(); // 在本程序中打開的窗口中監聽剪貼板消息

2. 捕獲剪貼板消息

代碼部分示例:

	BEGIN_MSG_MAP(Window)
		MESSAGE_HANDLER(WM_DRAWCLIPBOARD, OnClipboardMessage)
	END_MSG_MAP()

WM_DRAWCLIPBOARD 是剪貼板內容發生變動時的窗口消息,在本窗體中監聽該消息,當觸發這個消息時,可以獲取一下剪貼板的內容。本實例中使用這個回調函數 OnClipboardMessage 來處理。

3. 獲取剪貼板內容

獲取剪貼板文本信息

CString result; //存放剪貼板文本信息
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard())
{
	HANDLE hClipboard = GetClipboardData(CF_UNICODETEXT);
	if (hClipboard)
	{
		wchar_t* ptr = reinterpret_cast<wchar_t*>(GlobalLock(hClipboard)); 
		if (ptr != NULL) 
		{ 
			result = ptr;
			GlobalUnlock(hClipboard); 
		} 
	}		
	CloseClipboard();
}

獲取剪貼板文件復制消息

if (IsClipboardFormatAvailable(CF_HDROP) && OpenClipboard())
{
	HDROP hDrop = HDROP(::GetClipboardData(CF_HDROP)); //獲取剪切板中復制的文件列表相關句柄
	if (hDrop)
	{
		WCHAR szFilePathName[MAX_PATH + 1] = { 0 };
		UINT nNumOfFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); //得到文件個數
		// 考慮到用戶可能同時選中了多個對象(可能既包含文件也包含文件夾),以要循環處理
		for (UINT i = 0; i < nNumOfFiles; ++i)
		{
			memset(szFilePathName, 0, MAX_PATH + 1);
			DragQueryFile(hDrop, i, szFilePathName, MAX_PATH);  //得到文件名
			std::wstring ss = szFilePathName;
			std::wcout << TEXT("文件:") << ss << std::endl; // 打印復制的文件名
		}
	}
	CloseClipboard();
}

剪貼板粘貼消息的一些思考

由於沒有剪貼板粘貼時觸發的相應消息,在粘貼時,是由應用進程來讀取剪貼板內容來完成的粘貼操作,所以無法像捕獲消息一樣通過監聽消息來直接捕獲到粘貼操作。

根據日常的粘貼操作情況,需要捕獲鍵盤 CTRL+V 消息,或者hook粘貼板讀取函數
鍵盤鈎子通過SetWindowsHookEx()或RegisterRawInputDevices()可以監視Ctrl+V擊鍵。經由消息掛鈎SetWindowsHookEx()可以監視與粘貼的窗口消息,如WM_PASTE,EM_PASTESPECIAL,WM_COMMAND等,但即使是這樣,也沒有檢測每一個可能的粘貼操作的保證。

可能不得不求助於將代碼注入目標進程,以直接掛鈎查詢剪貼板數據的各種 Win32 API 函數。然后,當目標進程嘗試在任何類型的粘貼操作期間檢索數據時,可以修改這個過程(例如讓應用程序認為沒有可粘貼的數據):

CountClipboardFormats()
EnumClipboardFormats()
IsClipboardFormatAvailable()
GetPriorityClipboardFormat()
GetUpdatedClipboardFormats()
GetClipboardData() 和 OleGetClipboard()

參考:https://stackoverflow.com/questions/46699066/clipboard-viewer-doesnt-get-paste-notification


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM