版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、I剪貼簿濤兒軟件工作室整理編譯Microsoft Windows剪貼簿允許把數據從一個程序傳送到另一個程序中。它的原理相對而言比較簡單,把數據存放到剪貼簿上的程序或從剪貼簿上取出數據的程序都無須太多的負擔。Windows 98和MicrosoftWindows NT都提供了剪貼簿瀏覽程序,該程序可以顯示剪貼簿的目前內容。許多處理文件或者其它數據的程序都包含一個 Edit菜單,其中包括Cut、Copy和Paste選項。 當使用者選擇Cut或者Copy時,程序將數據傳送給剪貼簿。這個數據使用某種格式,如文字、位圖(一種按位排列的矩形數組,其中的位與平面顯示的圖素相對應)或者metafile (用二
2、進制元數值內容表示的繪圖命令集)等。當使用者從菜單中選擇 Paste時,程序檢查剪貼簿中包含的數據,看看使用的是否是 程序可以接受的一種格式。如果是,那么數據將從剪貼簿傳送到程序中。如果使用者不發(fā)岀明確的指令,程序就不能把數據送入或移岀剪貼簿。例如,在某個程序中執(zhí)行剪下或復制(或者按Ctrl-X 及Ctrl-C )操作的使用者,應該能夠假定數據將儲存在剪貼簿上,直到下次剪下或復制操作 為止。回憶一下第十和第一章所示的POPPA程序的修訂版中,我們加上了 Edit菜單,但是在那邊這菜單的作 用只是發(fā)送消息給編輯控件而已。多數情況下,處理剪貼簿并不方便,您必須自己呼叫剪貼簿傳輸函數。本章集中討論將
3、文字傳入和移岀剪貼簿。在后面的章節(jié)里,我將向您展示如何用剪貼簿處理位圖(第十四、十五和十六章)和metafile (第十八章)。剪貼簿的簡單使用我們由分析把數據傳送到剪貼簿(剪下或復制)和存取剪貼簿數據(粘貼)的程序代碼開始。標準剪貼簿數據格式Windows支持不同的預先定義剪貼簿格式,這些格式在WINUSER.H定義成以CF為前綴的標識符。首先介紹三種能夠儲存在剪貼簿上的文字數據型態(tài),以及一個與剪貼簿格式相關的數據型態(tài):* CF_TEXT以NULL!吉尾的ANSI字符集字符串。它在每行末尾包含一個carriage return 和linefeed字符,這是最簡單的剪貼簿數據格式。傳送到剪貼簿
4、的數據存放在整體內存塊中,并且是利用內存塊句柄進行傳送的(我將簡短地討論此項概念)。這個內存塊專供剪貼簿使用,建立它的程序不應該繼 續(xù)使用它。* CF_OEMTEX含有文字數據(與 CF_TEXT類似)的內存塊。但是它使用的是OEM字符集。通常Windows程序不必關心這一點;它只有與在窗口中執(zhí)行MS-DOSi序一起使用剪貼簿時才會使用。* CF_UNICODETEX含有Unicode文字的內存塊。與 CF_TEXT類似,它在每一行的末尾包含一個 carriage return 和linefeed 字符,以及一個 NULL字符(兩個 0字節(jié))以表示數據結束。 CF_UNICODETEX只支援
5、Windows NT。* CF_LOCAL一個國家地區(qū)標識符的句柄。表示剪貼簿文字使用的國別地區(qū)設定。下面是兩種附加的剪貼簿格式,它們在概念上與CF_TEXT格式相似(也就是說,它們都是文字數據),但是它們不需要以NULL結尾,因為格式已經定義了數據的結尾?,F在已經很少使用這些格式了: CF_SYLK包含Microsoft符號連結數據格式的整體內存塊。這種格式用在Microsoft的Multiplan 、Chart和Excel程序之間交換數據,它是一種ASCII碼格式,每一行都用 carriagereturn 和 linefeed 結尾。* CF_DIF包含數據交換格式(DIF)之數據的整體內
6、存塊。這種格式是由Software Arts 公司提出的,用于把數據送到 VisiCalc 電子表格程序中。這也是一種ASCII碼格式,每一行都使用carriagereturn 和 linefeed 結尾。下面三種剪貼簿格式與位圖有關。所謂位圖就是數據位的矩形數組,其中的數據位與輸岀設備的圖素相對 應。 第十四和 第十五章將詳細討論位圖以及這些位圖剪貼簿的格式: CF_BITMAF與設備相關的位圖格式。位圖是通過位圖句柄傳送給剪貼簿的。同樣,在把這個位圖傳送 給剪貼簿之后,程序不應該再繼續(xù)使用這個位圖。 CF_DIB定義一個設備無關位圖(在 第十五章中描述)的內存塊。這種內存塊是以位圖信息結構
7、開始 的,后面跟著可用的顏色表和位圖數據位。 CF_PALETT調色盤句柄。它通常與 CF_DIB配合使用,以定義與設備相關的位圖所使用的顏色調色 盤。在剪貼簿中,還有可能以工業(yè)標準的TIFF格式儲存的位圖數據: CF_TIFF含有標號圖像文件格式 仃IFF)數據的整體內存塊。這種格式由Microsoft、Aldus公司和Hewlett-Packard 公司以及一些硬件廠商推薦使用。這一格式可從Hewlett-Packard的網站上獲得。下面是兩個metafile 格式,我將在第十八章詳細討論。一個 metafile就是一個以二進制格式儲存的畫圖命令* CF_METAFILEPIC1以舊的 m
8、etafile 格式存放的圖片。 CF_ENHMETAFIL增強型 metafile (32 位 Windows 支持的)句柄最后介紹幾個混合型的剪貼簿格式:* CF_PENDAT與 Windows的筆式輸入擴充功能聯合使用。* CF_WAV聲音(波形)文件。* CF_RIFF使用資源交換文件格式( Resource Interchange File Format)的多媒體數據。CF_HDRO與拖放服務相關的文件列表。內存配置程序向剪貼簿傳輸一些數據的時候,必須配置一個內存塊,并且將這塊內存交給剪貼簿處理。在本書早期的程序中需要配置內存時,我們只需使用標準C執(zhí)行時期鏈接庫所支持的 malloc
9、函數。但是,由于在 Windows中執(zhí)行的應用程序之間必須要共享剪貼簿所儲存的內存塊,這時malloc函數就有些不適任這項任務了。實際上,我們必須把早期 Windows所開發(fā)的內存配置函數再拿出來使用,那時的操作系統(tǒng)在16位的實際模式內存結構中執(zhí)行?,F在的 Windows仍然支持這些函數,您還可以使用它們,但不是必須使用這些函數就是了。要用 Windows API來配置一個內存塊,可以呼叫:hGlobal = GlobalAlloc (uiFlags, dwSize);此函數有兩個參數:一系列可能的旗標和內存塊的字節(jié)大小。函數傳回一個HGLOBA型態(tài)的句柄,稱為整體內存塊句柄或整體句柄。傳回值
10、為NULL表示不能配置足夠的內存。雖然GlobalAlloc 的兩個參數略有不同,但它們都是32位的無正負號整數。如果將第一個參數設定為0,那么您就可以更有效地使用旗標GMEM_FIXEJD在這種情況下,GlobalAlloc 傳回的整體句柄實際是指向所配置內存塊的指針。如果不喜歡將內存塊中的每一位都初始化為0,那么您也能夠使用旗標GMEM,_ZEROIN。在Windows表頭文件中,簡潔的 GPTR旗標定義為 GMEM_FIXE和GMEM_ZEROIN旗標的組合:#define GPTR (GMEM_FIXED | GMEM_ZEROINIT)下面是一個重新配置函數:hGlobal = Gl
11、obalReAlloc (hGlobal, dwSize, uiFlags);如果內存塊擴大了,您可以用GMEM_ZEROI N旗標將新的字節(jié)設為 0。下面是獲得內存塊大小的函數:dwSize = GlobalSize (hGlobal);釋放內存塊的函數:GlobalFree (hGlobal);在早期16位的Windows中,因為 Windows不能在物理內存中移動內存塊,所以禁止使用GMEM_FIXE旗標。在32位的Windows中,GMEM_FIXE旗標很常見。這是因為它將傳回一個虛擬地址,并且操作系統(tǒng)也能夠通過改 變內存頁映像表在物理內存中移動內存塊。因此為16位的Windows寫程
12、序時,GlobalAlloc 推薦使用GMEM_MOVEAB旗標。在Windows的表頭文件中還定義了一個簡寫標識符,用此標識符可以在可移動的內存之 外填0:#define GHND (GMEM_MOVEABLE | GMEM_ZEROINIT)GMEM_MOVEAB旗標允許 Windows在虛擬內存中移動一個內存塊。這不是說將在物理內存中移動內存塊,只是 應用程序用于讀寫這塊內存的地址可以被變動。盡管GMEM_MOVEA是曰6位Windows的通則,但是它的作用現在已經少得多了。如果您的應用程序頻繁地配 置、重新配置以及釋放不同大小的內存塊,應用程序的虛擬地址空間將會變得支離破碎??梢韵胂蟮?/p>
13、到,最后 虛擬內存地址空間就會被用完。如果這是個可能會發(fā)生的問題,那么您將希望內存是可移動的。下面就介紹如 何讓內存塊成為可搬移位置的。首先定義一個指標(例如,一個int型態(tài)的)和一個 GLOBALHAND型態(tài)的變量:int * p ;GLOBALHANDLE hGlobal ;然后配置內存。例如:hGlobal = GlobalAlloc (GHND, 1024);與處理其它 Windows句柄一樣,您不必擔心數字的實際意義,只要照著作就好了。需要存取內存塊時,可以呼 叫:p = (int *) GlobalLock (hGlobal);Windows將固定虛擬內存中的地址,不再移動那塊內存
14、。存此函數將句柄轉換為指標。在內存塊被鎖定期間, 取結束后呼叫:GlobalUnlock (hGlobal);Windows程序寫作者的這將使Windows可以在虛擬內存中移動內存塊。要真正確保此程序正常運作(體驗早期 痛苦經歷),您應該在單一個消息處理期間鎖定和解鎖內存塊。在釋放內存時,呼叫 GlobalFree應使用句柄而不是指標。如果您現在不能存取句柄,可以使用下面的函數:hGlobal = GlobalHandle (p);在解鎖之前,您能夠多次鎖定一個內存塊。Windows保留一個鎖定次數,而且在內存塊可被自由移動之前,每次鎖定都需要相對應的解鎖。當Windows在虛擬內存中移動一個
15、內存塊時,不需要將字節(jié)從一個位置復制到另一個,只需巧妙地處理內存頁映像表。通常,讓32位Windows為您的程序配置可移動的內存塊,其唯一確實的理由只是避免虛擬內存的空間碎裂出現。使用剪貼簿時,也應該使用可移動內存。為剪貼簿配置內存時,您應該以GMEM_MOVEAB和B3MEM_SHAR旗f呼叫GlobalAlloc 函數。GMEM_SHARE標使得其它應用程序也可以使用那塊內存。將文字傳送到剪貼簿讓我們想象把一個 ANSI字符串傳送到剪貼簿上,并且我們已經有了指向這個字符串的指針(pString)?,F在希望傳送這個字符串的iLength字符,這些字符可能以 NULL結尾,也可能不以 NULL
16、結尾。首先,通過使用 GlobalAlloc 來配置一個足以儲存字符串的內存塊,其中還包括一個終止字符NULLhGlobal = GlobalAlloc (GHND | GMEM_SHARE, iLength + 1);如果未能配置到內存塊,hGlobal的值將為NULL。如果配置成功,則鎖定這塊內存,并得到指向它的一個指標:pGlobal = GlobalLock (hGlobal);將字符串復制到內存塊中:for (i = 0 ; i wLength ; i+)*pGlobal+ = *pString+ ;由于GlobalAlloc 的GHND旗標已使整個內存塊在配置期間被清除為零,所以不
17、需要增加結尾的NULL。以下敘述為內存塊解鎖:GlobalUnlock (hGlobal);現在就有了表示以NULL結尾的文字所在內存塊的內存句柄。為了把它送到剪貼簿中,打開剪貼簿并把它清 空:OpenClipboard (hwnd);EmptyClipboard ();利用CF_TEXT標識符把內存句柄交給剪貼簿,關閉剪貼簿:SetClipboardData (CF_TEXT, hGlobal);CloseClipboard ();工作告一段落。下面是關于此過程的一些規(guī)則:* 在處理同一個消息的過程中呼叫OpenClipboard和CloseClipboard 。不需要時,不要打開剪貼簿。*
18、 不要把鎖定的內存句柄交給剪貼簿。* 當呼叫SetClipboardData 后,請不要再繼續(xù)使用該內存塊。它不再屬于使用者程序,必須把句柄看 成是無效的。如果需要繼續(xù)存取數據,可以制作數據的副本,或從剪貼簿中讀取它(如下節(jié)所述)。您也可以在SetClipboardData 呼叫和CloseClipboard 呼叫之間繼續(xù)使用內存塊,但是不要使用傳遞 給SetClipboardData 函數的整體句柄。事實上,此函數也傳回一個整體句柄,必需鎖定這些代碼以 存取內存。在呼叫CloseClipboard 之前,應先為此句柄解鎖。從剪貼簿上取得文字CF_TEXT格式從剪貼簿上取得文字只比把文字傳送到
19、剪貼簿上稍微復雜一些。您必須首先確定剪貼簿是否含有 的數據,最簡單的方法是呼叫bAvailable = IsClipboardFormatAvailable (CF_TEXT);如果剪貼簿上含有 CF_TEXT數據,這個函數將傳回 TRUE(非零)。我們在第十章的POPPAD程序中已使用了這個函數,用它來確定 Edit菜單中Paste項是被啟用還是被停用的。IsClipboardFormatAvailable 是少數幾個不需先打開剪貼簿就可以使用的剪貼簿函數之一。但是,如果您之后想再打開剪貼簿以取得這個文字,就應該再做一次檢查(使用同樣的函數或其它方法),以便確定CF_TEXT數據是否仍然留在
20、剪貼簿中。為了傳送岀文字,首先打開剪貼簿:OpenClipboard (hwnd);會得到代表文字的內存塊代號:hGlobal = GetClipboardData (CF_TEXT);如果剪貼簿不包含 CF_TEXT格式的數據,此句柄就為NULL這是確定剪貼簿是否含有文字的另一種方法。如果GetClipboardData 傳回NULL則關閉剪貼簿,不做其它任何工作。從GetClipboardData 得到的句柄并不屬于使用者程序一它屬于剪貼簿。僅在GetClipboardData 和CloseClipboard 呼叫之間這個句柄才有效。您不能釋放這個句柄或更改它所引用的數據。如果需要繼續(xù)存取
21、 這些數據,必須制作這個內存塊的副本。這里有一種將數據復制到使用者程序中的方法。首先,配置一塊與剪貼簿數據塊大小相同的內存塊,并配置一 個指向該塊的指標:pText = (char *) malloc (GlobalSize (hGlobal);再次呼叫hGlobal ,而hGlobal是從GetClipboardData 呼叫傳回的整體句柄?,F在鎖定句柄,獲得一個指向 剪貼簿塊的指標:pGlobal = GlobalLock (hGlobal);現在就可以復制數據了:strcpy (pText, pGlobal);或者,您可以使用一些簡單的 C程序代碼:while (*pText+ = *p
22、Global+);在關閉剪貼簿之前先解鎖內存塊:GlobalUnlock (hGlobal);CloseClipboard ();現在您有了一個叫做 pText的指針,以后程序的使用者就可以用它來復制文字了打開和關閉剪貼簿在任何時候,只有一個程序可以打開剪貼簿。呼叫OpenClipboard的作用是當一個程序使用剪貼簿時,防止剪貼簿的內容發(fā)生變化。OpenClipboard傳回BOOL直,它說明是否已經成功地打開了剪貼簿。如果另一個應用程序沒有關閉剪貼簿,那么它就不能被打開。如果每個程序在響應使用者的命令時都盡快地、遵守規(guī)范地打開 然后關閉剪貼簿,那么您將永遠不會遇到不能打開剪貼簿的問題。但是
23、,在不遵守規(guī)范程序和優(yōu)先權式多任務環(huán)境中,總會發(fā)生一些問題。即使在您的程序將某些東西放入剪貼 簿和使用者啟動一個 Paste選項期間,您的程序并沒有失去輸入焦點,但是您也不能假定您放入的東西仍 然在那里,一個背景程序有可能已經在這段期間存取過剪貼簿了。而且,請留意一個與消息框有關的更微妙問題:如果不能配置足夠的內存來將內容復制到剪貼簿,那么您可能 希望顯示一個消息框。但是,如果這個消息框不是系統(tǒng)模態(tài)的,那么使用者可以在顯示消息框期間切換到另一 個應用程序中。您應該使用系統(tǒng)模態(tài)的消息框,或者在您顯示消息框之前關閉剪貼簿。如果您在顯示一個對話框時將剪貼簿保持為打開狀態(tài),那么您還可能遇到其它問題,對
24、話框中的編輯字段會使 用剪貼簿進行文字的剪貼。剪貼簿和Unicode迄今為止,我只討論了用剪貼簿處理ANSI文字(每個字符對應一個字節(jié))。我們用CF_TEXT標識符時就是這種格式。您可能對 CF_OEMTEX和CF_UNICODETEX還不熟悉吧。我有一些好消息:在處理您所想要的文字格式時,您只需呼叫SetClipboardData 和GetClipboardData ,Windows將處理剪貼簿中所有的文字轉換。例如,在Windows NT中,如果一個程序用 SetClipboardData 來處理CF_TEXT剪貼簿數據型態(tài),程序也能用CF_OEMTEX呼叫GetClipboardData
25、 。同樣地,剪貼簿也能將CF_OEMTEX數據轉換為 CF_TEXT在 Windows NT中,轉換發(fā)生在 CF_UNICODETEXTCF_TEXT和CF_OEMTEX之間。程序應該使用對程序本身而言最方便的一種文字格式來呼叫SetClipboardData。同樣地,程序應該用程序需要的文字格式來呼叫GetClipboardData。我們已經知道,本書附上的程序在編寫時可以帶有或不帶UNICODES識符。如果您的程序也依此編寫,那么在定義了UNICODES識符之后,程序將執(zhí)行帶有CF_UNICODETEX參數的SetClipboardData以及 GetClipboardData 呼叫,而不
26、是 CF_TEXTCLIPTEXT程序,如程序12-1所示,展示了一種可行的方法。程序 12-1 CLIPTEXTCLIPTEXT.C/*CLIPTEXT.C - The Clipboard and Text(c) Charles Petzold, 1998*/#include #include resource.hLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);#ifdef UNICODE#define CF_TCHAR CF_UNICODETEXTTCHAR szDefaultText= TEXT (Default Text -
27、Unicode Version);TCHAR szCaption= TEXT (Clipboard Text Transfers - Unicode Version);#else#define CF TCHAR CF TEXTTCHAR szDefaultText = TEXT (Default Text - ANSI Version);TCHAR szCaption= TEXT (Clipboard Text Transfers - ANSI Version);#endifint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst
28、ance,PSTR szCmdLine, int iCmdShow)static TCHAR szAppName = TEXT (ClipText);HACCELhAccel ;HWNDhwnd ;MSGmsg ;WNDCLASSwndclass ;wndclass.style=CS_HREDRAW | CS_VREDRAW ;wndclass .l pfnWndProc=WndProc ;wndclass.cbCIsExtra=0 ;wndclass.cbWndExtra=0 ;wndclass.hInstance=hInstance ;wndclass.hIcon=LoadIcon (NU
29、LL, IDI_APPLICATION);wndclass.hCursor=LoadCursor (NULL, IDC_ARROW);wndclass.hbrBackground=(HBRUSH) GetStockObject (WHITE_BRUSH)wndclass .l pszMenuName=szAppName ;wndclass .l pszClassName=szAppName ;if (!RegisterClass (&wndclass)MessageBox ( NULL, TEXT (This program requires Windows NT!), szAppName,
30、MB_ICONERROR); return 0 ;hwnd = CreateWindow (szAppName, szCaption,WS_OVERLAPPEDWINDOW,CWJJSEDEFAULT, CW_USEDEFAULT,CWJJSEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL);ShowWindow (hwnd, iCmdShow);UpdateWindow (hwnd);hAccel = LoadAccelerators (hInstance, szAppName);while (GetMessage (&msg, NULL
31、, 0, 0)if (!TranslateAccelerator (hwnd, hAccel, &msg)TranslateMessage (&msg);DispatchMessage (&msg);return msg.wParam ;LRESULT CALLBACK WndProc ( HWND hwnd, UINT message, WPARAM wParam,LPARAM IParam)static PTSTRpText ;BOOLbEnable ;HGLOBALhGlobalHDChdc ;PTSTRpGlobal ;PAINTSTRUCTps ;RECTrect ;switch (
32、message)case WM_CREATE:SendMessage (hwnd, WM_COMMAND, IDM_EDIT_RESET, 0);return 0 ;case WM_INITMENUPOPUP:EnableMenultem (HMENU) wParam,IDM_EDIT_PASTE,IsClipboardFormatAvailable (CF_TCHAR) ? MF_ENABLED : MF_GRAYED); bEnable = pText ? MF_ENABLED : MF_GRAYED ;EnableMenuItem(HMENU)wParam,IDM_EDIT_CUT,bE
33、nable);EnableMenuItem(HMENU)wParam,IDM_EDIT_COPY,bEnable)EnableMenuItem(HMENU)wParam,IDM_EDIT_CLEAR,bEnable);break ;case WM_COMMAND:switch (LOWORD (wParam)case IDM_EDIT_PASTE:OpenClipboard (hwnd);if (hGlobal = GetClipboardData (CF_TCHAR)pGlobal = GlobalLock (hGlobal);if (pText)free (pText);pText = N
34、ULL ;pText = malloc (GlobalSize (hGlobal);lstrcpy (pText, pGlobal);InvalidateRect (hwnd, NULL, TRUE);CloseClipboard ();return 0 ;case IDM_EDIT_CUT:case IDM_EDIT_COPY:if (! pText) return 0 ;hGlobal = GlobalAlloc (GHND | GMEM_SHARE,(lstrlen (pText) + 1) * sizeof (TCHAR);pGlobal = GlobalLock (hGlobal);
35、lstrcpy (pGlobal, pText);GlobalUnlock (hGlobal);OpenClipboard (hwnd);EmptyClipboard ();SetClipboardData (CF_TCHAR, hGlobal); CloseClipboard ();if ( LOWORD (wParam) = IDM_EDIT_COPY) return 0 ;/ fall through for IDM_EDIT_CUTcase IDM_EDIT_CLEAR:if (pText)free (pText);pText = NULL ;InvalidateRect (hwnd,
36、 NULL, TRUE);return 0 ;case IDM_EDIT_RESET:if (pText)free (pText);pText = NULL ;pText = malloc (lstrlen (szDefaultText) + 1) * sizeof (TCHAR);Istrcpy (pText, szDefaultText);InvalidateRect (hwnd, NULL, TRUE);return 0 ;break ;case WM_PAINT:hdc = BeginPaint (hwnd, &ps);GetClientRect (hwnd, & rect);if (
37、pText != NULL)DrawText (hdc, pText, -1, & rect, DT_EXPANDTABS | DT_WORDBREAK);EndPaint (hwnd, &ps);return 0 ;case WM_DESTROY:if ( pText)free (pText);PostQuitMessage (0);return 0 ;return DefWindowProc (hwnd, message, wParam, lParam);CLIPTEXT.RC(摘錄)/Microsoft Developer Studio generated resource script
38、.#include resource.h#include afxres.h/ MenuCLIPTEXT MENU DISCARDABLEBEGINPOPUP &EditBEGINMENUITEM Cu& ttCtrl+X,IDM_EDIT_CUTMENUITEM &CopytCtrl+C,IDM EDIT COPYIDM EDIT PASTEMENUITEM De&letetDel,IDM EDIT CLEARMENUITEM SEPARATORMENUITEM &Reset,IDM EDIT RESETENDEND/ AcceleratorCLIPTEXT ACCELERATORS DISC
39、ARDABLEBEGINC,IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERTV,IDM_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERTVK_DELETE,IDM_EDIT_CLEAR, VIRTKEY, NOINVERTX,IDM_EDIT_CUT, VIRTKEY, CONTROL, NOINVERTENDRESOURCE.H (摘錄)/ Microsoft Developer Studio generated include file./ Used by ClipText.rc#define IDM_EDIT_CUT 4000
40、1#define IDM_EDIT_COPY40002#define IDM_EDIT_PASTE40003#define IDM EDIT CLEAR40004MENUITEM &PastetCtrl+V,#define IDM_EDIT_RESET40005這是在 Windows NT下執(zhí)行Unicode版和ANSI版程序的概念,而且可以看到,剪貼簿是如何在兩種字符集之間 轉換的。注意CLIPTEXT.C頂部的#ifdef 敘述。如果定義了 UNICODES識符,那么CF_TCHAR我命名的一種常 用的剪貼簿格式)就等于CF_UNICODETEXT否則,它就等于 CF_TEXT程序后面呼叫
41、的IsClipboardFormatAvailable 、GetClipboardData 和 SetClipboardData 函數都使用 CF_TCHA來指定數據型 態(tài)。在程序的開始部分(以及您從 Edit菜單中選擇Reset選項時),靜態(tài)變量 pText包含一個指針,在 Unicode版的程序中,指針指向Unicode字符串Default Text -Unicode version ;在非 Unicode版的程序中,指針指向Default Text - ANSI version 。您可以用Cut或Copyj命令將字符串傳遞給剪貼 簿,用Cut或Delete J命令從程序中刪除字符串。 P
42、aste J命令將剪貼簿中的文字內容復制到pText o在WM_PAIN消息處理期間,pText將字符串顯示在程序的顯示區(qū)域。如果您先在Unicode版的CLIPTEXT中選擇了Copyj命令,然后在非 Unicode版中選擇Paste j命令,那么 您就能看到文字已經從 Unicode轉換成了 ANSI。類似地,如果您執(zhí)行相反的操作,那么文字就會從ANSI轉換成 Unicode。復雜的剪貼簿用法我們已經看到,在將數據準備好之后,從剪貼簿傳輸數據時需要四個呼叫:OpenClipboard(hwnd);EmptyClipboard();SetClipboardData(iFormat, hGlo
43、bal);CloseClipboard();存取這些數據需要三個呼叫OpenClipboard (hwnd);hGlobal = GetClipboardData (iFormat);其它行程序CloseClipboard ();在GetClipboardData 和CloseClipboard 呼叫之間,可以復制剪貼簿數據或以其它方式來使用它。很多應用程 序都需要采用這種方法,但也可以用更復雜的方式來使用剪貼簿。利用多個數據項當打開剪貼簿并把數據傳送給它時,必須先呼叫EmptyClipboard,通知 Windows釋放或刪除剪貼簿上的內容。不能在現有的剪貼簿內容中附加其它東西。所以,從這種
44、意義上說,剪貼簿每次只能保留一個數據項。但是,可以在 EmptyClipboard 和CloseClipboard 呼叫之間多次呼叫 SetClipboardData ,每次都使用不同的 剪貼簿格式。例如,如果想在剪貼簿中儲存一個很短的文字字符串,可以把這個文字寫入metafile ,也可以把這個文字寫入位圖。把位圖選進內存設備內容中,并把這個字符串寫進位圖中。利用這種方法可以使字符串 不僅能為從剪貼簿上讀取文字的程序所使用,也可以為從剪貼簿上讀取位圖和metafile的程序所使用。當然,這些程序并不能知道m(xù)etafile 或位圖實際上包含了一個字符串。如果想把一些句柄寫到剪貼簿上,對每個句柄
45、均可以呼叫SetClipboardData :OpenClipboard(hwnd);EmptyClipboard();SetClipboardData(CF_TEXT, hGlobalText);SetClipboardData(CF_BITMAP, hBitmap);SetClipboardData(CF_METAFILEPICT, hGlobaIMFP)CloseClipboard();當這三種格式的數據同時位于剪貼簿上時,用CF_TEXT CF_BITMAP或 CF_METAFILEPIC參數呼叫IsClipboardFormatAvailable 將傳回TRUE通過下列呼叫程序可以存
46、取這些代碼:hGlobalText = GetClipboardData (CF_TEXT);hBitmap = GetClipboardData (CF_BITMAP);hGlobaIMFP = GetClipboardData (CF_METAFILEPICT);下一次程序呼叫EmptyClipboard 時,Windows將釋放或刪除剪貼簿上保留的所有三個句柄。在將不同的文字格式、不同的位圖格式或者不同的metafile 格式添加到剪貼簿時,不要使用這種技術。只使用一種文字格式、一種位圖格式以及一種metafile 格式。就像我所說的那樣,Windows將在CF_TEXTCF_OEMTE
47、X和 CFJJNICODETEX之間轉換,也可以在 CF_BITMAP和 CF_DIB之間,以及在 CF_METAFILEPICT和 CF_ENHMETAFIL之間進行轉換。透過首先打開剪貼簿,然后呼叫EnumClipboardFormats,程序可以確定剪貼簿儲存的所有格式。開始時設定變量iFormat為0:iFormat = 0 ;OpenClipboard (hwnd);現在從0值開始逐次進行連續(xù)的 EnumClipboardFormats呼叫。函數將為目前在剪貼簿中的每種格式傳回一個 正的iFormat值。當函數傳回0時,表示完成:while (iFormat = EnumClipbo
48、ardFormats (iFormat)各個iFormat值的處理方式CloseClipboard ();您可以通過下面的呼叫來取得目前在剪貼簿中之不同格式的個數:iCount = CountClipboardFormats ();延遲提岀 當把數據放入剪貼簿中時,一般來說要制作一份數據的副本,并將包含這份副本的內存塊句柄傳給剪貼簿。對 非常大的數據項來說,這種方法會浪費內存空間。如果使用者不想把數據粘貼到另一個程序里,那么,在被其 它內容取代之前,它將一直占據著內存空間。通過使用一種叫做延遲提岀的技術可以避免這個問題。實際上,直到另一個程序需要數據,程序才提供這份數據。為此,不將數據句柄傳給
49、Windows,而是在SetClipboardData 呼叫中使用NULLOpenClipboard(hwnd);EmptyClipboard();SetClipboardData(iFormat, NULL);CloseClipboard();可以有多個使用不同iFormat值的SetClipboardData 呼叫,對其中某些呼叫可使用NULL值。而對其他一些則使用實際的句柄值。前面的過程比較簡單,以下的過程就要稍微復雜一些了。當另一個程序呼叫GetClipboardData 時,Windows將檢查那種格式的句柄是否為 NULL。如果是,Windows將給剪貼簿所有者(您的程序)發(fā)送一個
50、消息,要 求取得數據的實際句柄,這時您的程序必須提供這個句柄。更具體地說,剪貼簿所有者是將數據放入剪貼簿的最后一個窗口。當一個程序呼叫OpenClipboard時,Windows儲存呼叫這個函數時所用的窗口句柄,這個句柄標示打開剪貼簿的窗口。一旦收到一個EmptyClipboard呼叫,Windows就使這個窗口作為新的剪貼簿所有者。使用延遲提出技術的程序在它的窗口消息處理程序中必須處理三個消息:WM_RENDERFORMATWM_RENDERALLFORMATSM_DESTROYCLIPBOARD另一個程序呼叫 GetClipboardData 時,Windows給窗口消 息處理程序發(fā)送一個
51、 WM_RENDERFORMAT,wParam的值是所要求的格式。在處理WM_RENDERFORMAT時,不要打開或清空剪貼簿。為wPara m所指定的格式建立一個整體內存塊,把數據傳給它,并用正確的格式和相應句柄呼叫SetClipboardData 。很明顯地,為了在處理 WM_RENDERFORMAT確地構造出此數據,需要 在程序中保留這些信息。當另一個程序呼叫EmptyClipboard時,Windows給您的程序發(fā)送一個wm_destroyclipboard,告訴您不再需要構造剪貼簿數據的信息。您的程序不再是剪貼簿的所有者。如果程序在它自己仍然是剪貼簿所有者的時候就要終止執(zhí)行,并且剪貼
52、簿上仍然包含著該程序用SetClipboardData 設定的NULL數據句柄,它將收到 WM_RENDERALLFORMATS這時,應該打開剪貼簿,清 空它,把數據加載內存塊中,并為每種格式呼叫SetClipboardData ,然后關閉剪貼簿。 WM_RENDERALLFORMATS消息是窗口消息處理程序最后收到的消息之一。它后面跟有WM_DESTROYCLIPBOAR息 (由于已經提出了所有數據),然后是正常的 WM_DESTROY息。如果您的程序只能向剪貼簿傳輸一種格式的數據(例如文字),那么您可以把WM_RENDERALLFORM和TSWM_RENDERFORMAT吉合在一起。這些程
53、序代碼應該類似下面這樣:caseWM_RENDERALLFORMATS :OpenClipboard (hwnd);EmptyClipboard ();/ fall through case WM_RENDERFORMAT :/將文字放入整體內存塊SetClipboardData (CF_TEXT, hGlobal);if (message = WM_RENDERALLFORMATS)CloseClipboard ();return 0 ;如果您的程序使用好幾種剪貼簿格式,那么您可能想為wParam所要求的格式處理 WM_ RENDERFORMAT非程序在存放構造數據所需的信息時遇到困難,否則
54、不需要處理WM_DESTROYCLIPBO消息。自訂數據格式到目前為止,我們僅處理了Windows定義的標準剪貼簿資料格式。但是,您可能想用剪貼簿來儲存自訂數據格式。許多文書處理程序使用這種技術來儲存包含著字體和格式化信息的文字。初看之下,這個概念似乎是沒有意義的。如果剪貼簿的作用是在應用程序之間傳送數據,那么,為什么剪貼簿 中要含有只有一個應用程序才能理解的數據呢?答案很簡單:剪貼簿允許在同一個程序的內部(或者可能在一 個程序中的不同執(zhí)行實體之間)傳送數據。很明顯地,這些執(zhí)行實體能理解它們自己的自訂數據格式。有幾種使用自訂數據格式的方法。最簡單的方法用到一種表面上是標準剪貼簿格式(文字、位圖
55、或 metafile )的數據,可是該數據實際上只對您的程序有意義。這種情況下,在SetClipboardData 和GetClipboardData 呼叫中可使用下列 wFormat 值:CF_DSPTEXTCF_DSPBITMAPCF_DSPMETAFILEPIC或 CF_DSPENHMETAFIUE?母DSP代表顯示器)。這些格式允許Windows按文字、位圖或 metafile 來瀏覽或顯示資料。但是,另一個使用常規(guī)的CF_TEXT CF_BITMAP CF_DIB CF_METAFILEPIC或 CF_ENHMETAFIL格式呼叫GetClipboardData 的程序將不能取得這個數據。如果用其中一種格式把數據放入剪貼簿中,則必須使用同樣的格式讀岀數據。但是,如何知道數據是來自程序 的另一個執(zhí)行實體,還是來自使用其中某種數據格式的另一個程序呢?這里有一種方法,可以透過下列呼叫首 先獲得剪
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 臘肉委托合同范例
- 2024年度文案策劃與撰寫服務合同2篇
- 2024版保潔設備采購與清潔技術改造合同
- 2024年新款汽車國內公路物流運輸服務協(xié)議版B版
- 2024年度人工智能產業(yè)抵押擔保協(xié)議示范2篇
- 2024版化妝品店鋪轉讓合同模板3篇
- 2024年煤礦租賃經營與安全生產培訓服務合同3篇
- 延期付款賒銷合同范例
- 2024版房地產分銷合作傭金結算協(xié)議匯編3篇
- 2024年度蜀山新天地B幢0健身服務合同2篇
- 2024建筑消防設施維護保養(yǎng)技術規(guī)范
- 電流互感器的結構及原理 電流互感器的結構及原理
- 關于強化煤炭生產行業(yè)稅務稽查的思考
- 2023-2024學年遼寧省沈陽市鐵西區(qū)牛津上海版(三起)四年級上冊期末學業(yè)水平測試英語試卷
- 新視野大學英語(第四版)讀寫教程1(思政智慧版)課件 Unit 6 Winning is not everything Section B
- 湖南省株洲市2023屆高三教學質量統(tǒng)一檢測(一)物理答案
- 粵教版科學三年級上冊全冊試卷(含答案)
- 學校教研工作組織機構(5篇范例)
- 電工高級工理論題庫(題庫大全)
- 《汽車傳感器》課件
- 分享會之蹲馬步管理工坊
評論
0/150
提交評論