65.9K
CodeProject 正在变化。 阅读更多。
Home

关于剪贴板你需要知道的一切...

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (44投票s)

1999年11月23日

2分钟阅读

viewsIcon

416884

downloadIcon

5858

本文将告诉你关于剪贴板你需要知道的一切...

引言

将剪贴板支持添加到 VC++ / MFC 应用程序非常简单。本文涵盖了让你的应用程序与剪贴板交互的基本步骤。其中包含以下示例:

读取和写入文本

以下源代码演示了如何将文本(包含在 CString "source" 中)放置到剪贴板上。

CString source; 
//put your text in source
if(OpenClipboard())
{
	HGLOBAL clipbuffer;
	char * buffer;
	EmptyClipboard();
	clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.GetLength()+1);
	buffer = (char*)GlobalLock(clipbuffer);
	strcpy(buffer, LPCSTR(source));
	GlobalUnlock(clipbuffer);
	SetClipboardData(CF_TEXT,clipbuffer);
	CloseClipboard();
}

下面的源代码演示了相反的操作,即如何从剪贴板检索文本。

char * buffer = NULL;
//open the clipboard
CString fromClipboard;
if ( OpenClipboard() ) 
{
	HANDLE hData = GetClipboardData( CF_TEXT );
	char * buffer = (char*)GlobalLock( hData );
	fromClipboard = buffer;
	GlobalUnlock( hData );
	CloseClipboard();
}

读取和写入 WMF(增强)数据

将图像写入和从剪贴板读取可以非常有用,而且非常容易!以下示例将增强型元文件写入剪贴板。

if ( OpenClipboard() )
{
	EmptyClipboard();

	//create the metafile DC
	CMetaFileDC * cDC = new CMetaFileDC();
	cDC->CreateEnhanced(GetDC(),NULL,NULL,"the_name");

	//call draw routine here that makes GDI calls int cDC

	//close meta CMetafileDC and get its handle
	HENHMETAFILE handle = cDC->CloseEnhanced();

	//place it on the clipboard
	SetClipboardData(CF_ENHMETAFILE,handle);
	CloseClipboard();

	//delete the dc
	delete cDC;
}

这是相反的操作。我们从剪贴板获取元文件并将其绘制到我们自己的客户端 DC 中(只是一个测试,实际上你想要创建一个副本)。

if ( OpenClipboard() )
{
	//Get the clipboard data
	HENHMETAFILE handle = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE);

	//play it into a DC (our own DC in this example)
	CClientDC dc(this);
	CRect client(0,0,200,200);
	dc.PlayMetaFile(handle,client);		

	//close the clipboard
	CloseClipboard();
}

读取和写入位图

读取和写入位图只是稍微复杂一些。基本思路仍然相同。这是一个将位图保存到剪贴板的示例。

if ( OpenClipboard() )
{
	EmptyClipboard();
	//create some data
	CBitmap * junk = new CBitmap();
	CClientDC cdc(this);
	CDC dc;
	dc.CreateCompatibleDC(&cdc);
	CRect client(0,0,200,200);
	junk->CreateCompatibleBitmap(&cdc,client.Width(),client.Height());
	dc.SelectObject(junk);

	//call draw routine here that makes GDI calls
	DrawImage(&dc,CString("Bitmap"));

	//put the data on the clipboard
	SetClipboardData(CF_BITMAP,junk->m_hObject);
	CloseClipboard();

	//copy has been made on clipboard so we can delete
	delete junk;
}

与其它示例一样,这是一个从剪贴板获取位图的示例。在这个简单的示例中,我们将直接将其 Blt 到客户端 DC。

if ( OpenClipboard() )
{
	//Get the clipboard data
	HBITMAP handle = (HBITMAP)GetClipboardData(CF_BITMAP);
	CBitmap * bm = CBitmap::FromHandle(handle);

	CClientDC cdc(this);
	CDC dc;
	dc.CreateCompatibleDC(&cdc);
	dc.SelectObject(bm);
	cdc.BitBlt(0,0,200,200,&dc,0,0,SRCCOPY);

	CloseClipboard();
}

设置和使用你自己的自定义格式

通过使用 RegisterClipboardFormat() API,你可以复制和粘贴任何类型的数据。这在应用程序之间移动数据时非常有用。假设我们有一个结构

struct MyFormatData
{
	long val1;
	int val2;
};

我们想将其移动到剪贴板上。我们可以按如下方式复制:

UINT format = RegisterClipboardFormat("MY_CUSTOM_FORMAT");
if(OpenClipboard())
{
	//make some dummy data
	MyFormatData data;
	data.val1 = 100;
	data.val2 = 200;

	//allocate some global memory
	HGLOBAL clipbuffer;
	EmptyClipboard();
	clipbuffer = GlobalAlloc(GMEM_DDESHARE, sizeof(MyFormatData));
	MyFormatData * buffer = (MyFormatData*)GlobalLock(clipbuffer);

	//put the data into that memory
	*buffer = data;

	//Put it on the clipboard
	GlobalUnlock(clipbuffer);
	SetClipboardData(format,clipbuffer);
	CloseClipboard();
}

要将其读回,我们执行相反的操作:

//second call with just get format already registered
UINT format = RegisterClipboardFormat("MY_CUSTOM_FORMAT");
MyFormatData data;
if ( OpenClipboard() ) 
{
	//get the buffer
	HANDLE hData = GetClipboardData(format);
	MyFormatData * buffer = (MyFormatData *)GlobalLock( hData );

	//make a local copy
	data = *buffer;

	GlobalUnlock( hData );
	CloseClipboard();
}

获取剪贴板更改的通知

每当剪贴板发生更改时,通过窗口消息获得通知非常有用。为此,你使用 SetClipboardViewer(),然后捕获 WM_DRAWCLIPBOARD

In your initialization code call:
	SetClipboardViewer();  //add us to clipboard change notification chain

In your message map add:
	ON_MESSAGE(WM_DRAWCLIPBOARD, OnClipChange)  //clipboard change notification

Which is declared as:
	afx_msg void OnClipChange();  //clipboard change notification

Finally implement:
void CDetectClipboardChangeDlg::OnClipChange() 
{
	//do something here, for example
	CTime time = CTime::GetCurrentTime();
	SetDlgItemText(IDC_CHANGED_DATE,time.Format("%a, %b %d, %Y -- %H:%M:%S"));

	DisplayClipboardText();
}

将数据粘贴到另一个应用程序的窗口

我发现的一个有用的事情是将文本复制到剪贴板(如上所述),然后将其“粘贴”到另一个应用程序!我编写了一个不错的本地化应用程序,它使用第三方语言翻译包使用了这种技术。

只需获取目标窗口的句柄并向其发送“粘贴”消息即可。

	SendMessage(m_hTextWnd, WM_PASTE, 0, 0);

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.