【Windows編程】系列第九篇:剪貼板使用

上一篇咱們學習了常見的通用對話框,本篇來了解剪貼板的使用,它經常使用於複製粘貼功能。java

剪貼板是Windows最先就加入的功能,因爲該功能很是實用,咱們幾乎天天都會使用到。經過剪貼板,咱們就能夠將數據從一個應用程序傳遞到另外一個應用程序,是一種簡單的進程間通訊。程序員

許多文檔處理軟件都有複製、剪切、粘貼功能,這些都是用Windows剪貼板實現的,固然咱們也能夠在咱們的程序中實現本身的剪貼板功能,本篇咱們就來實現本身的剪貼板。使用剪貼板時,都是先把源數據先傳到剪貼板上,再在須要的時候從剪貼板傳輸到目的處,因此看起來咱們就是直接從源直接搬到目的處。編程

Windows的控件好比EditBox,已經在控件內部實現了複製、剪切和粘貼功能,因此咱們能直接使用。但咱們不少控件是沒有這個功能的,好比靜態文本控件,本身建立的窗口等,咱們就沒有辦法直接拷貝粘貼,這些都是須要咱們本身實現的。仍是老規矩,下面咱們先介紹剪貼板經常使用函數,而後用實例來演示基本用法。windows

  • 剪貼板經常使用函數微信

不論是複製仍是粘貼,使用剪貼板首先要打開它,打開剪貼板API函數以下:微信公衆平臺

BOOL OpenClipboard(HWND hWndNewOwner);

惟一參數hWndNewOwner是和剪貼板關聯的窗口句柄,若是該參數爲NULL,則關聯到當前任務。函數

在從源設置數據到剪貼板以前,必須先清空剪貼板,同時獲得剪貼板的佔有權。API函數以下:學習

Bool EmptyClipboard(void)

該函數沒有參數。ui

向剪貼板設置數據,也就是拷貝操做:spa

HANDLE SetClipboardData(UINT uFormat, HANDLE hMem);

參數uFormat表示要設置傳輸到剪貼板上的數據格式,預約義的格式有十幾種,咱們這裏列出幾個最經常使用的,其餘請參考MSDN:

CF_TEXT:表示要設置的格式爲以NULL結尾的ANSI字符串,及標C的字符串。這是最簡單的剪貼簿數據格式。

CF_UNICODETEXT:格式爲包含Unicode字符集的字符串。

CF_BITMAP:格式爲設備相關的位圖。

參數hMem:設置數據的句柄,通常爲GlobalAlloc函數返回的句柄。

設置完數據或者從剪貼板獲取數據以後,須要關閉剪貼板,不然其餘應用程序沒法再打開剪貼板。API函數爲:

Bool CloseClipboard(void);

該函數沒有參數。

從剪貼板獲取數據,也就是粘貼操做,API函數爲:

HANDLE GetClipboardData(UINT uFormat);

參數uFormat就是想要獲取的數據格式。

查詢剪貼板中是否有指定格式的數據:

BOOL IsClipboardFormatAvailable(UINT format);

參數format就是想要查詢的數據格式,該函數不須要打開剪貼板。

  • 剪貼板實例

以上幾個就是最主要的剪貼板相關函數:

下面咱們用這些函數來完成基本的文本複製粘貼和圖像複製粘貼功能,爲了演示,咱們設定了一幅圖和一行文本做爲數據源,同時建立兩個按鈕「copy image」和「copy text」分別用於複製圖像和文本,當點擊時複製對於的數據。

爲了程序簡潔,我用了鼠標左鍵來擡起做爲粘貼觸發,粘貼的位置就是擡起鼠標時的鼠標位置,您能夠在不一樣的地方屢次點擊後擡起鼠標來重複粘貼,具體代碼以下:

#include <windows.h>
#include <tchar.h>

#define IDC_LABEL     1000
#define IDC_COPY_IMG  1001
#define IDC_COPY_TXT  1002

static TCHAR szAppName[] = TEXT("Clipboard Demo");
static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
     HWND     hWnd;
     MSG      msg;
     WNDCLASS wndclass;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
     wndclass.lpfnWndProc   = WndProc;
     wndclass.cbClsExtra    = 0;
     wndclass.cbWndExtra    = 0;
     wndclass.hInstance     = hInstance;
     wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
     wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
     wndclass.lpszMenuName  = NULL;
     wndclass.lpszClassName = szAppName;

     if (!RegisterClass(&wndclass))
     {
          MessageBox (NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
          return 0;
     }
     
     hWnd = CreateWindow(szAppName,            // window class name
                          szAppName,           // window caption
                          WS_OVERLAPPEDWINDOW, // window style
                          CW_USEDEFAULT,       // initial x position
                          CW_USEDEFAULT,       // initial y position
                          400,              // initial x size
                          300,              // initial y size
                          NULL,             // parent window handle
                          NULL,             // window menu handle
                          hInstance,        // program instance handle
                          NULL);            // creation parameters
     
     ShowWindow(hWnd, iCmdShow);
     UpdateWindow(hWnd);
     
     while (GetMessage(&msg, NULL, 0, 0))
     {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
     }

     return msg.wParam;
}

static int DrawBmp(HDC hDC, int xDst, int yDst, int width, int height, int BytesPerPixel, unsigned char *pPixels)
{
	int ret = -1;
	HDC hdcMem;
	BITMAPINFO bmi;
	BYTE *pBits = NULL;
	
	memset(&bmi, 0x00, sizeof(BITMAPINFO));
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = width;
	bmi.bmiHeader.biHeight = height;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = BytesPerPixel*8;
	bmi.bmiHeader.biCompression = BI_RGB;
	
	hdcMem = CreateCompatibleDC(hDC);
	if (hdcMem)
	{
		HBITMAP hBitmap = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&pBits, NULL, 0);
		if (hBitmap)
		{
			HGDIOBJ hOldBmp = SelectObject(hdcMem, hBitmap);
			memcpy(pBits, pPixels, width * height * BytesPerPixel);
			BitBlt(hDC, xDst, yDst, width, height, hdcMem, 0, 0, SRCCOPY);
			SelectObject(hdcMem, hOldBmp);
			DeleteObject(hBitmap);
			ret = 0;
		}
		DeleteDC(hdcMem);
	}
	
	return ret;
}

static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hDC;
	static HBITMAP hBmp;
	static BITMAP  bm;

	switch (message)
	{
	case WM_CREATE:
		CreateWindow(TEXT("STATIC"), TEXT("你好,World!"), WS_CHILD|WS_VISIBLE, 10, 160, 100, 20, hWnd, (HMENU)IDC_LABEL, NULL, NULL);
		CreateWindow(TEXT("BUTTON"), TEXT("copy image"), WS_CHILD|WS_VISIBLE, 10, 190, 100, 20, hWnd, (HMENU)IDC_COPY_IMG, NULL, NULL);
		CreateWindow(TEXT("BUTTON"), TEXT("copy text"), WS_CHILD|WS_VISIBLE, 10, 220, 100, 20, hWnd, (HMENU)IDC_COPY_TXT, NULL, NULL);
		hBmp = (HBITMAP)LoadImage(NULL, TEXT("start.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
		GetObject(hBmp, sizeof(BITMAP), &bm);
		return 0;

	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			hDC = BeginPaint(hWnd, &ps);
			HDC hMemDC = CreateCompatibleDC(hDC);
			HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBmp);
			BitBlt(hDC, 10, 10, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
			DeleteDC(hMemDC);
			EndPaint(hWnd, &ps);
		}
		return 0;

	case WM_COMMAND:
		{
			int id = LOWORD(wParam);
			switch (id)
			{
			case IDC_COPY_IMG:
				{
					BOOL ret;
					BYTE *pData = NULL;
					BITMAPINFO bmpInfo;

					bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
					bmpInfo.bmiHeader.biWidth = bm.bmWidth;
					bmpInfo.bmiHeader.biHeight = bm.bmHeight;
					bmpInfo.bmiHeader.biPlanes = 1;
					bmpInfo.bmiHeader.biBitCount = 32;
					bmpInfo.bmiHeader.biCompression = BI_RGB;

					HDC hClientDC = GetDC(hWnd);
					HDC hMemDC = CreateCompatibleDC(hClientDC);
					HBITMAP hBitmap = CreateDIBSection(hMemDC, &bmpInfo, DIB_RGB_COLORS, (void **)&pData, NULL, 0);
					SelectObject(hMemDC, hBitmap);
					ret = BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hClientDC, 10, 10, SRCCOPY);
					DeleteDC(hMemDC);

					LONG len = bm.bmWidth * bm.bmHeight * 4;
					HGLOBAL hClipData = GlobalAlloc(GHND, len);
					BYTE *pClipData = (BYTE *)GlobalLock(hClipData);
					memcpy(pClipData, pData, len);
					ret = GlobalUnlock(hClipData);

					ret = OpenClipboard(hWnd);
					ret = EmptyClipboard();
					SetClipboardData(CF_BITMAP, hClipData);
					ret = CloseClipboard();

					DeleteObject(hBitmap);
					ReleaseDC(hWnd, hClientDC);

					MessageBox(hWnd, TEXT("image has been copy into clipboard"), TEXT("info"), MB_OK);
				}
				break;

			case IDC_COPY_TXT:
				{
					BOOL ret;
					TCHAR buf[256];

					GetWindowText(GetDlgItem(hWnd, IDC_LABEL), buf, _countof(buf));
					int len = _tcslen(buf) + 1;

					HGLOBAL hClipData = GlobalAlloc(GHND, len * sizeof(TCHAR));
					TCHAR *pClipData = (TCHAR *)GlobalLock(hClipData);
					memcpy(pClipData, buf, len * sizeof(TCHAR));
					pClipData[len-1] = (TCHAR)0;
					ret = GlobalUnlock(hClipData);

					ret = OpenClipboard(hWnd);
					ret = EmptyClipboard();
					SetClipboardData(CF_TEXT, hClipData);
					ret = CloseClipboard();

					MessageBox(hWnd, TEXT("text has been copy into clipboard"), TEXT("info"), MB_OK);
				}
				break;

			default:
				break;
			}
		}
		return 0;

	case WM_LBUTTONUP:
		{
			BOOL ret;
			WORD xPos = LOWORD(lParam); 
			WORD yPos = HIWORD(lParam);

			ret = IsClipboardFormatAvailable(CF_BITMAP);
			if (ret)
			{
				ret = OpenClipboard(hWnd);
				HGLOBAL hglb = GetClipboardData(CF_BITMAP);
				//len = GlobalSize(hglb);
				BYTE *pClipData = (BYTE *)GlobalLock(hglb);
				HDC hClientDC = GetDC(hWnd);
				DrawBmp(hClientDC, xPos, yPos, bm.bmWidth, bm.bmHeight, 4, pClipData);
				GlobalUnlock(hglb);
				CloseClipboard();
				ReleaseDC(hWnd, hClientDC);
			}

			ret = IsClipboardFormatAvailable(CF_TEXT);
			if (ret)
			{
				ret = OpenClipboard(hWnd);
				HGLOBAL hglb = GetClipboardData(CF_TEXT);
				TCHAR *pClipData = (TCHAR *)GlobalLock(hglb);
				HDC hClientDC = GetDC(hWnd);
				int len = _tcslen(pClipData);
				//len = GlobalSize(hglb);
				TextOut(hClientDC, xPos, yPos, pClipData, len);
				GlobalUnlock(hglb);
				CloseClipboard();
				ReleaseDC(hWnd, hClientDC);
			}
		}
		return 0;

	case WM_DESTROY:
		DeleteObject(hBmp);
		PostQuitMessage(0);
		return 0 ;
	}

	return DefWindowProc (hWnd, message, wParam, lParam);
}

示例中在設置剪貼板時,須要用GlobalAlloc函數分配全局內存,設置和獲取數據前須要GlobalLock函數鎖定內存通常拷貝數據,使用後再用GlobalUnlock函數解鎖內存,這幾個函數在使用剪貼板基本成了討論,照葫蘆畫瓢就好了,要了解詳細參數請查看MSDN。本示例程序程序運行後,分別點擊了拷貝圖像和拷貝文本本隨意點擊,效果以下:

clipboard

總的來講剪貼板的基本應用仍是比較簡單,相關的其餘或更多的信息請查看MSDN。對本文有什麼疑議請給我留言。

更多經驗交流能夠加入Windows編程討論QQ羣454398517

 

關注微信公衆平臺:程序員互動聯盟(coder_online),你能夠第一時間獲取原創技術文章,和(java/C/C++/Android/Windows/Linux)技術大牛作朋友,在線交流編程經驗,獲取編程基礎知識,解決編程問題。程序員互動聯盟,開發人員本身的家。

【Windows編程】系列第八篇:建立通用對話框

轉載請註明出處http://www.coderonline.net/?p=1815,謝謝合做!

相關文章
相關標籤/搜索