人人做人人澡人人爽欧美,国产主播一区二区,久久久精品五月天,羞羞视频在线观看免费

當(dāng)前位置:蘿卜系統(tǒng)下載站 > 辦公軟件教程 > 詳細(xì)頁(yè)面

excel VBA 中 Windows 剪切板的設(shè)置 基礎(chǔ)圖文教程

excel VBA 中 Windows 剪切板的設(shè)置 基礎(chǔ)圖文教程

更新時(shí)間:2024-01-24 文章作者:未知 信息來(lái)源:網(wǎng)絡(luò) 閱讀次數(shù):

Microsoft Excel是Microsoft為使用Windows和Apple Macintosh操作系統(tǒng)的電腦編寫的一款電子表格軟件。直觀的界面、出色的計(jì)算功能和圖表工具,再加上成功的市場(chǎng)營(yíng)銷,使Excel成為最流行的個(gè)人計(jì)算機(jī)數(shù)據(jù)處理軟件。

一、剪貼板概述
  首先,討論一下剪貼板是什么
  Windows的幫助文件中對(duì)剪貼板的描述是這樣的:剪貼板是從一個(gè)地方復(fù)制或移動(dòng)并打算在其他地方使用的信息的臨時(shí)存儲(chǔ)區(qū)域。可以選擇文本或圖形,然后使用“剪切”或“復(fù)制”命令將所選內(nèi)容移動(dòng)到剪貼板,在使用“粘貼”命令將該內(nèi)容插入到其他地方之前,它會(huì)一直存儲(chǔ)在剪貼板中。例如,您可能要復(fù)制網(wǎng)站上的一部分文本,然后將其粘貼到電子郵件中。大多數(shù) Windows 程序中都可以使用剪貼板。
  對(duì)于經(jīng)常使用Ctrl+C/X、Ctrl+V的Windows用戶來(lái)說(shuō),這個(gè)解釋是非常易懂并且符合人們感觀上的認(rèn)識(shí)的。
  既然我們今天討論的話題是如何在VBA程序中通過(guò)API調(diào)用剪貼板,那就先看看微軟MSDN中對(duì)于剪貼板的定義吧:剪貼板是一組用于在多個(gè)應(yīng)用程序之間交換數(shù)據(jù)的函數(shù)和消息(原文:The clipboard is a set of functions and messages that enable applications to transfer data)。
  呵呵,是不是有些暈?沒(méi)關(guān)系,因?yàn)檫@句話是針對(duì)C/C++程序員給出的說(shuō)明,我們?nèi)匀豢梢园戳?xí)慣上的理解把它當(dāng)做一個(gè)對(duì)象(使用過(guò)VB6的同志們可能更容易理解,因?yàn)閂B6中確實(shí)有一個(gè)名字叫ClipBoard的對(duì)象,它其實(shí)是VB對(duì)windows的剪貼板API函數(shù)封裝后產(chǎn)生的真正的對(duì)象)。
  然后,再來(lái)看看這個(gè)對(duì)象有什么特點(diǎn),又是如何工作的呢?概括來(lái)說(shuō),剪貼板有以下的特性(這是我個(gè)人總結(jié)的,不一定正確或精確,也不一定全面):
?公開(kāi)性
剪貼板中的數(shù)據(jù)存放在全局內(nèi)存中,因此大部分的windows應(yīng)用程序都可以訪問(wèn)其中的數(shù)據(jù),在遵守相關(guān)API函數(shù)約定的前提下,應(yīng)用程序可以自由地打開(kāi)剪貼板(OpenClipboard),讀取剪貼板內(nèi)的數(shù)據(jù)(GetClipboardData)、或者清空剪貼板(EmptyClipboard)、然后設(shè)置剪貼板內(nèi)的數(shù)據(jù)(SetClipboardData),最后關(guān)閉剪貼板(CloseClipboard);
?獨(dú)占性
既然剪貼板是公開(kāi)的,那么多個(gè)程序同時(shí)訪問(wèn)必然會(huì)導(dǎo)致沖突,比如數(shù)據(jù)互相覆蓋。因此,Windows規(guī)定應(yīng)用程序?qū)糍N板的訪問(wèn)是獨(dú)占性的,當(dāng)一個(gè)應(yīng)用程序使用OpenClipboard打開(kāi)剪貼板之后,其他程序 就不可以再訪問(wèn)剪貼板,直至前一程序使用CloseClipboard關(guān)閉剪貼板 。通常我們使用剪貼板的時(shí)候不會(huì)感覺(jué)受其他程序的影響,這是因?yàn)榧糍N板內(nèi)的數(shù)據(jù)操作都是在內(nèi)存中進(jìn)行的,速度非常快,對(duì)于特大塊的數(shù)據(jù),應(yīng)用程序還可以選擇延時(shí)處理(Delayed Rendering)機(jī)制以保證速度。但是,我們?cè)趯?duì)剪貼板編程的時(shí)候要注意以下兩點(diǎn):1)每次使用完剪貼板之后一定要記得使用CloseClipBoard關(guān)閉 它;2)在OpenClipboard和CloseClipboard之間不要放置耗時(shí)很長(zhǎng)的代碼,以免影響其他程序正常工作。
設(shè)置剪貼板內(nèi)數(shù)據(jù)的應(yīng)用程序窗口被稱為剪貼板數(shù)據(jù)擁有者(ClipboardOwner),可以通過(guò)GetClipboardOwner函數(shù)獲得它的句柄。反過(guò)來(lái)說(shuō),如果一個(gè)應(yīng)用程序想向剪貼板中放入數(shù)據(jù),需要先成為ClipboardOwner。程序要成為ClipboardOwner需要先將自己的句柄傳給OpenClipboard函數(shù),如果剪貼板中已經(jīng)有數(shù)據(jù)存在,還需要先調(diào)用EmptyClipboard;
?多元性
剪貼板中可以同時(shí)存放多種格式的數(shù)據(jù),各自放在全局內(nèi)存的不同位置 ;剪貼板中的數(shù)據(jù)有標(biāo)準(zhǔn)格式/預(yù)定義格式的,如文本、位圖、Wav聲音……;也有非標(biāo)準(zhǔn)格式/用戶自定義格式,比如word中的域和公式、Excel中的圖表
?可檢索性
對(duì)于每種在剪貼板中存放過(guò)的格式,Windows都會(huì)給它分配一個(gè)獨(dú)特的長(zhǎng)整型編號(hào),通過(guò)這個(gè)編號(hào)可以知道對(duì)應(yīng)的數(shù)據(jù)格式的名稱(GetClipboardFormatName),或者 查詢對(duì)應(yīng)的數(shù)據(jù)在剪貼板中是否存在(IsClipBoardFormatAvailable),如果存在,還可以通過(guò)這個(gè)編號(hào)找到對(duì)應(yīng)的數(shù)據(jù)在內(nèi)存中存放的位置(GetClipboardData);
對(duì)于標(biāo)準(zhǔn)格式,這個(gè)編號(hào)是固定的,可以通過(guò)VB6自帶的APIViewer查詢以CF_開(kāi)頭的常量得到,比如:
Public Const CF_TEXT = 1
Public Const CF_BITMAP = 2
Public Const CF_METAFILEPICT = 3
Public Const CF_SYLK = 4
……
對(duì)于非標(biāo)準(zhǔn)格式,這個(gè)編號(hào)由提供此格式數(shù)據(jù)的應(yīng)用程序給此格式定義一個(gè)名稱,然后將此名稱傳遞給RegisterClipboardFormat函數(shù),如果此名稱已經(jīng)存在,函數(shù)將返回此名稱對(duì)應(yīng)的編號(hào),如果此名稱不存在,函數(shù)將返回一個(gè)之前未使用的編號(hào),在系統(tǒng)關(guān)機(jī)重啟之前,這個(gè)名稱和編號(hào)可以一直使用下去。
?可監(jiān)視性
有一組特別的窗口可以持續(xù)監(jiān)視剪貼板內(nèi)的數(shù)據(jù)變化,這組窗口被稱作剪貼板觀察程序(ClipboardViewer),由它們構(gòu)成的這個(gè)小圈子叫作剪貼板觀察程序鏈ClipBoardViewerChain,每當(dāng)剪貼板內(nèi)數(shù)據(jù)發(fā)生變化時(shí),windows將向消息鏈中的第一個(gè)窗口發(fā)送一個(gè)WM_DRAWCLIPBOARD消息,再由它轉(zhuǎn)發(fā)給第二個(gè)……直至消息到達(dá)消息鏈中的最后一個(gè)窗口,同樣,當(dāng)消息鏈中的成員發(fā)生變化時(shí),每個(gè)窗口都會(huì)收到一個(gè)WM_CHANGECBCHAIN消息;
通過(guò)SetClipboardViewer函數(shù),應(yīng)用程序可以將自己的窗口句柄告訴windows,從而注冊(cè)成為剪貼板觀察程序鏈中的一員;通過(guò)ChangeClipboardChain函數(shù),應(yīng)用程序可以退出剪貼板觀察程序鏈而不影響它后面的窗口繼續(xù)接收相關(guān)消息。
希望以上文字能對(duì)大家重新認(rèn)識(shí)剪貼板能夠有所幫助。休息一會(huì)兒,我們?cè)儆懻摷糍N板在Office VBA中的用途。
二、剪貼板在Excel VBA中的用途
  只要進(jìn)行了正確的API聲明,我們?cè)赩BA中也可以對(duì)剪貼板的進(jìn)行操作,以它為媒介,我們可以訪問(wèn)到通過(guò)VBA難以接觸到的數(shù)據(jù),從而給我們的VBA或Office應(yīng)用程序增加一些新奇和實(shí)用的功能。這里全是以Excel為例,在其他Office程序中原理一樣。
  下面先看三個(gè)實(shí)例,它們分別演示了剪貼板數(shù)據(jù)的讀取、寫入和監(jiān)視。

示例1:ShapeToPicture.rar(點(diǎn)擊下載)

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

說(shuō)明:這個(gè)代碼演示了如何在窗體中瀏覽工作簿中所有Shape對(duì)象,并且提供了按各種格式保存的功能。完成這個(gè)程序,并不能說(shuō)明本人對(duì)各種圖像格式有多深的認(rèn)識(shí),真正的幕后英雄是Excel,是它在我們選中工作表中的Shape對(duì)象并按下Ctrl+C后的1/1024柱香的時(shí)間內(nèi)把這個(gè)Shape換成了bmp, jpg,gif, png,emf等各種格式并放在了剪貼板中,我們所做的只是把這些數(shù)據(jù)從剪貼板中取出并簡(jiǎn)單進(jìn)行了加工,不過(guò)效果已經(jīng)很理想了,下次再有人跟你說(shuō)用把工作簿另存為網(wǎng)頁(yè)的方法可以取出xls中所有的圖形時(shí),你就可以有得吹噓了。說(shuō)正題,把這個(gè)代碼稍作修改,就可以做出一個(gè)用右鍵菜單導(dǎo)出當(dāng)前選中圖形的加載宏。我以前做過(guò)一個(gè),不過(guò)代碼不如現(xiàn)在這個(gè)嚴(yán)謹(jǐn)和通用。

?

示例2: MSFlexGrid.rar (點(diǎn)擊下載)

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

說(shuō)明:這個(gè)代碼演示的是向放入數(shù)據(jù),在userform窗體上的FlexGrid中選擇一個(gè)單元格區(qū)域,然后通過(guò)右鍵或快捷鍵可以復(fù)制和剪切數(shù)據(jù),回到Excel工作表后可直接粘貼。當(dāng)然,跟華麗的Excel比起來(lái),這個(gè)就有點(diǎn)槑了,不過(guò)這至少提供了一種在窗體上的表格和Excel工作表之間交換數(shù)據(jù)的思路,這種操作方式也更符合大多數(shù)用戶的習(xí)慣。
示例3: clipboardviewer.rar (點(diǎn)擊下載)
這是一個(gè)監(jiān)控剪貼板數(shù)據(jù)變化的示例,很簡(jiǎn)單的一個(gè)功能:當(dāng)剪貼板內(nèi)數(shù)據(jù)發(fā)生變化時(shí),在窗體左側(cè)的列表中顯示當(dāng)前剪貼板內(nèi)可用的數(shù)據(jù)格式,如果里面有文本,則將文本顯示在TextBox中,像迅雷的監(jiān)視剪貼板大致也是這個(gè)原理。

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程


  看完之后,你可能對(duì)Windows剪貼板產(chǎn)生了一些興趣。當(dāng)然,剪貼板在VBA中的使用不止于此,套用一句廣告詞,哪啥來(lái)著?心有多大,舞臺(tái)就有多大。接下來(lái),剪貼板之旅正式開(kāi)始,我們理論實(shí)踐相結(jié)合,先逐個(gè)認(rèn)識(shí)相關(guān)的API函數(shù),最后讓他們一起協(xié)作幫我們完成某個(gè)目的。

三、如何操作剪貼板內(nèi)的數(shù)據(jù)
1.讀取剪貼板內(nèi)的數(shù)據(jù),這一節(jié)主要說(shuō)說(shuō)幾個(gè)相關(guān)的剪貼板函數(shù)和內(nèi)存函數(shù)
  要讀取剪貼板,首先要打開(kāi)剪貼板,用OpenClipboard函數(shù),格式如下:

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

如果OpenclipBoardData函數(shù)調(diào)用成功,我們接下來(lái)就可以用GetClipboardData讀取里面的數(shù)據(jù)了。來(lái)看看GetClipboardData函數(shù)的樣子。

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

前面說(shuō)過(guò),剪貼板內(nèi)可以同時(shí)存放多種格式的數(shù)據(jù)。Windows不會(huì)一次性地把這些數(shù)據(jù)全交到你手中,它一次只會(huì)給你一種格式的數(shù)據(jù),只要你向它提供了這種數(shù)據(jù)格式對(duì)應(yīng)的編碼,也就是括號(hào)內(nèi)的長(zhǎng)整型變量wFormat。關(guān)于剪貼板格式的話題,我們?cè)诤竺娴南嚓P(guān)函數(shù)中單獨(dú)討論。目前你可以把它想象為股票代碼,要從股票軟件那里查詢股票行情,要向軟件提供這個(gè)代碼,你提供的代碼不同,軟件返回的數(shù)據(jù)也不一樣。
  可能很多人要問(wèn),如果調(diào)用成功,返回的這個(gè)句柄代表什么,又怎么利用呢?按照小fisher的觀察,至少有下面三種情況:
1.如果這個(gè)格式對(duì)應(yīng)的是GDI對(duì)象(比如CF_BITMAP, CF_METAFILEPICT,CF_PALETTE,CF_PENDATA等),這個(gè)返回值就是這個(gè)GDI對(duì)象的句柄,對(duì)于這個(gè)句柄,我們可以使用相關(guān)的GDI函數(shù)創(chuàng)建一個(gè)它的副本,然后使用其他GDI函數(shù)操作它就可以了。關(guān)于GDI的話題,要細(xì)講起來(lái)用的篇幅恐怕比剪貼板還要多,在后面的小節(jié)“利用從剪貼板中取出的數(shù)據(jù)”里對(duì)于用到的幾個(gè)GDI函數(shù)會(huì)給出一些簡(jiǎn)單的說(shuō)明,感興趣的同志們也可以從網(wǎng)上或MSDN中查找相關(guān)的說(shuō)明,這里我推薦一個(gè)英文的教程,里面講解得非常細(xì)致和系統(tǒng),網(wǎng)址是http://edais.mvps.org/Tutorials/GDI/DC/index.html;
2.如果是其他格式,這通常是一個(gè)內(nèi)存對(duì)象的句柄;
3.應(yīng)該還有一些特殊情況(比如對(duì)于剪貼板內(nèi)的DataObject格式,這個(gè)返回值指向的是一個(gè)長(zhǎng)整型數(shù)字,估計(jì)是個(gè)內(nèi)存指針類型),由于我自己也沒(méi)研究,所以目前不討論。

  這里我們重點(diǎn)探討一下第二種情況。現(xiàn)在我們得到的是一個(gè)內(nèi)存對(duì)象的句柄,要在VB(A)中使用它,就需要將它的二進(jìn)制數(shù)據(jù)讀取到我們?cè)赩B(A)中聲明的變量、字符串或數(shù)組中。假設(shè)我們已經(jīng)定義好了一個(gè)動(dòng)態(tài)的字節(jié)數(shù)組,Dim bytClipData() as Byte,用來(lái)存放從剪貼板中獲取的二進(jìn)制數(shù)據(jù)。通常,我們馬上就會(huì)想到CopyMemory函數(shù),這個(gè)函數(shù)聲明方式如下:

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

只有這個(gè)函數(shù)還不夠,對(duì)于數(shù)據(jù)的源(即內(nèi)存對(duì)象)我們目前只知道它的句柄,而CopyMemory需要的是它的位置和字節(jié)長(zhǎng)度,所以還要借助另外三個(gè)內(nèi)存函數(shù):

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程
excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程
excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

OK,有了這幾個(gè)內(nèi)存API函數(shù),我們就可以將剪貼板中所存放的內(nèi)存對(duì)象復(fù)制到自己定義的變量、數(shù)組或字符串中了。為了加深印象,我們用圖形重現(xiàn)一下整個(gè)工作流程:

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

理清了思路,你現(xiàn)在可以嘗試寫一個(gè)讀取剪貼板內(nèi)文本的過(guò)程了
第1題:寫一個(gè)讀取剪貼板內(nèi)文本的過(guò)程,如果剪貼板內(nèi)有文本格式的數(shù)據(jù),則通過(guò)對(duì)話框?qū)⒋宋谋緝?nèi)容顯示給用戶,否則提示用戶當(dāng)前剪貼板內(nèi)沒(méi)有文本
要求:使用剪貼板API函數(shù)
如果你能獨(dú)立完成,那么恭喜你已經(jīng)掌握了這些函數(shù)的使用要領(lǐng),如果出錯(cuò)了也不要在灰心,下面是參考答案,跟你自己的代碼對(duì)照一下,看哪里有出入,然后最小化這個(gè)網(wǎng)頁(yè)窗口,回到你的程序中重新修改過(guò)再試驗(yàn),相信你會(huì)成功!
特別提醒:如果CopyMemory使用不當(dāng),會(huì)造成Excel關(guān)閉重啟,所以在運(yùn)行代碼前注意要保存文件

Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Declare Function CloseClipboard Lib "user32" () As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Private Const CF_TEXT = 1
Private Sub GetClipText()
Dim hMem As Long
Dim lpData As Long
Dim nClipSize As Long
Dim bytClipData() As Byte
Dim sClipString As String

If OpenClipboard(ByVal 0&) Then '如果OpenClipboard函數(shù)返回非0值,說(shuō)明成功打開(kāi)剪貼板
hMem = GetClipboardData(CF_TEXT) '獲取剪貼板中以文本格式存在的內(nèi)存對(duì)象的句柄
If CBool(hMem) Then '如果剪貼板中對(duì)應(yīng)的格式不存在,此時(shí)的hMem會(huì)是0(Null),這里用CBool把它轉(zhuǎn)換成Boolean類型加以判斷
lpData = GlobalLock(hMem) '獲取內(nèi)存對(duì)象第一個(gè)字節(jié)的內(nèi)存地址
nClipSize = GlobalSize(hMem) '獲取內(nèi)存對(duì)象的字節(jié)長(zhǎng)度
ReDim bytClipData(1 To nClipSize) '修改緩沖字節(jié)數(shù)組的長(zhǎng)度,確保能夠容納內(nèi)存對(duì)象的全部數(shù)據(jù)
CopyMemory bytClipData(1), ByVal lpData, nClipSize '復(fù)制內(nèi)存對(duì)象的數(shù)據(jù)到字節(jié)數(shù)組中,注意Byval的用法
sClipString = StrConv(bytClipData, vbUnicode) '將字節(jié)轉(zhuǎn)化成字符串
MsgBox "當(dāng)前剪貼板內(nèi)的文本是:" & vbCrLf & sClipString '將結(jié)果顯示給用戶
Else
MsgBox "當(dāng)前剪貼板內(nèi)沒(méi)有文本"
End If
CloseClipboard
End If
End Sub
可能很多朋友會(huì)問(wèn):要讀取剪貼板內(nèi)文本,使用下面3行代碼就行了,為什么要花費(fèi)這么大力氣使用API呢?
Private Sub GetClipText()
  Dim objData As New DataObject '需要引用“Microsoft Forms 2.0 Object Library”
  objData.GetFromClipboard
  MsgBox "當(dāng)前剪貼板內(nèi)的文本是:" & objData.GetText
End Sub

是的,單就題目本身而言,使用MSForms.DataObject更合適。但DataObject目前只支持文本操作,所以它的GetFromClipboard方法只能用于讀取剪貼板內(nèi)文本,而通過(guò)剪貼板API函數(shù),我們可以使用剪貼板內(nèi)全部格式的數(shù)據(jù),下面我們就轉(zhuǎn)入剪貼板數(shù)據(jù)格式的討論。

2. 關(guān)于剪貼板格式(Clipboard Formats)

所謂數(shù)據(jù)格式,是指為了便于儲(chǔ)存、分析、交換和顯示數(shù)據(jù)而規(guī)定的擺放數(shù)據(jù)的方式。我們知道,在計(jì)算機(jī)中,所有數(shù)據(jù)都是以0或1構(gòu)成的位構(gòu)成的,在大多數(shù)的編程語(yǔ)言中,數(shù)據(jù)的最小單位是字節(jié),它由8個(gè)位構(gòu)成,它可以表示0-255之間256個(gè)數(shù)值,要用這256個(gè)數(shù)值表示各種各樣的信息,比如文字、圖形、音頻、視頻等,就需要給代表每種信息的一串字節(jié)規(guī)定一個(gè)固定的結(jié)構(gòu)和擺放規(guī)則,否則如果只是把所有數(shù)據(jù)羅列到一起,就會(huì)帶來(lái)解析上的困難。如果這種結(jié)構(gòu)和規(guī)則被普遍接受,它就會(huì)成為一種通用的數(shù)據(jù)格式。通常每種數(shù)據(jù)格式都會(huì)包含一個(gè)簡(jiǎn)單的易于識(shí)別的字節(jié)特征,比如我們的磁盤中的各種文件,就有文本格式、位圖格式、超文本格式等成百上千種格式,假如我們用UltraEdit之類十六進(jìn)制編輯器打開(kāi)一個(gè)沒(méi)有后綴名的文件,如果發(fā)現(xiàn)它的前四個(gè)字節(jié)是47 49 46 38("GIF8"),它很有可能是一個(gè)gif格式圖片,假如我們對(duì)gif格式的規(guī)定有全面的了解,那不但可以100%判斷它是或不是一個(gè)有效的gif格式圖片,還能把它所代表的圖形顯示到屏幕上。對(duì)于用戶來(lái)說(shuō),對(duì)不同格式的文件可以使用相應(yīng)的程序打開(kāi),對(duì)于程序來(lái)說(shuō),對(duì)不同格式的數(shù)據(jù)可以使用相應(yīng)的解析方式加以解讀,從而挖掘其中攜帶的信息。

  剪貼板里可以同時(shí)存放多種格式的數(shù)據(jù),我們將他們統(tǒng)稱為剪貼板格式(Clipboard Formats)。為了區(qū)別各種格式,windows給每種剪貼板格式都分配了一個(gè)特有的長(zhǎng)整型數(shù)字,我們稱作剪貼板格式編號(hào)(Clipboard Format Number),同時(shí),為了便于人們記憶和使用,除了少數(shù)幾個(gè)通用的標(biāo)準(zhǔn)格式,大部分?jǐn)?shù)據(jù)格式還對(duì)應(yīng)一個(gè)英文名稱,叫作剪貼板格式名稱(Clipboard Format Name),這個(gè)名稱是大小寫敏感的,即CSV和Csv在剪貼板中代表兩種不同的格式,它們的剪貼板格式編號(hào)也不會(huì)相同。剪貼板格式的編號(hào)和名稱是由Windows系統(tǒng)分配和管理的,對(duì)于常用的格式,windows對(duì)它們的編號(hào)進(jìn)行了預(yù)定義,這些格式被稱為標(biāo)準(zhǔn)格式或預(yù)定義格式(Standard/Predefined Clipboard Formats),見(jiàn)下面的列表:

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

 注意:標(biāo)準(zhǔn)剪貼板格式是沒(méi)有對(duì)應(yīng)的剪貼板格式名稱的。
  如果應(yīng)用程序需要向剪貼板中放入的數(shù)據(jù)不能以上述格式表示或者不能轉(zhuǎn)化為上述格式時(shí),它可以使用注冊(cè)剪貼板格式(Registered Clipboard Formats),也就是說(shuō),它可以自行為這個(gè)數(shù)據(jù)格式定義一個(gè)名稱,然后使用RegisterClipboardFormat函數(shù)注冊(cè)這個(gè)名稱,如果注冊(cè)成功,它將得到這個(gè)新建的剪貼板格式對(duì)應(yīng)的編號(hào)。RegisterClipboardFormat函數(shù)的聲明方式如下:

Declare Function RegisterClipboardFormat Lib "user32" Alias "RegisterClipboardFormatA" (ByVal lpString As String) As Long
作用: 注冊(cè)一個(gè)新的剪貼板格式,如果注冊(cè)成功,這個(gè)格式可以當(dāng)作有效剪貼板格式使用
參數(shù): lpString字符串;指定要注冊(cè)的剪貼板格式的名稱
返回值: 如果注冊(cè)成功,則返回該剪貼板格式所對(duì)應(yīng)的編號(hào)如果注冊(cè)失敗,則返回0
說(shuō)明: 如果被注冊(cè)的剪貼板格式名稱已經(jīng)存在,并不會(huì)重新注冊(cè)一個(gè)新的剪貼板格式,而是返回原有的同名剪貼板格式編號(hào)。這個(gè)函數(shù)不需要使用OpenClipboard。


  這和工商登記有點(diǎn)類似,假設(shè)你要開(kāi)辦一家公司,那么你首先要給公司取個(gè)名字,然后到工商部門去注冊(cè),如果這個(gè)公司名沒(méi)有被其他人注冊(cè),那么注冊(cè)成功后工商部門會(huì)告訴你一個(gè)工商注冊(cè)號(hào),這個(gè)號(hào)碼與所有其他公司都是不同的;但有一點(diǎn)不同,在現(xiàn)實(shí)中,如果你要注冊(cè)的這個(gè)公司名稱已經(jīng)被注冊(cè)了,你只能另選其他名稱重新登記,而在剪貼板機(jī)制中,所有公司名(剪貼板格式名稱)和工商登記號(hào)(剪貼板格式編號(hào))都是公用的,只要有一個(gè)人(應(yīng)用程序)在工商部門(windows操作系統(tǒng))中注冊(cè)了一個(gè)公司,所有人(應(yīng)用程序)都可以使用此公司名稱和工商登記號(hào),如果有人嘗試注冊(cè)一個(gè)已經(jīng)存在的公司名稱,他可以沿用這個(gè)公司原有的工商注冊(cè)號(hào)。

  這里提供一個(gè)山寨版的剪貼板查看工具,運(yùn)行它以后,你可以隨意到其他程序中復(fù)制不同的對(duì)象,然后在左側(cè)列表中可以看到當(dāng)前剪貼板內(nèi)所有數(shù)據(jù)格式的編號(hào)和對(duì)應(yīng)的名稱,如果格式對(duì)應(yīng)的是一個(gè)內(nèi)存對(duì)象,工具右側(cè)的表格中可以顯示它存儲(chǔ)的十六進(jìn)制數(shù)據(jù),它還允許你將這些十六進(jìn)制的數(shù)據(jù)保存為文件,然后到UltraEdit等專門的工具中去分析。

excel VBA 中 Windows 剪切板的操作 基礎(chǔ)教程

由于剪貼板內(nèi)的數(shù)據(jù)是由收到“復(fù)制”或“剪切”命令的應(yīng)用程序放進(jìn)去的,而各種應(yīng)用程序所處理的數(shù)據(jù)格式范圍也不一樣,因此,不同的應(yīng)用程序在不同的上下文環(huán)境中放進(jìn)剪貼板的數(shù)據(jù)格式種類也不同。這個(gè)很容易理解,當(dāng)我們使用word選中一段文字后選擇復(fù)制命令時(shí),word放入剪貼板的肯定是與文本有關(guān)的格式,而在畫圖中選中圖片的一部分后選擇復(fù)制命令時(shí),畫圖程序放入剪貼板的肯定是與圖形相關(guān)的格式。同時(shí),對(duì)于收到“粘貼”命令后讀取和使用剪貼板內(nèi)數(shù)據(jù)的應(yīng)用程序來(lái)說(shuō),它需要先判斷剪貼板內(nèi)是否存在自己可解讀的數(shù)據(jù)格式。比如我們選中某個(gè)網(wǎng)頁(yè)圖片后使用復(fù)制命令,這時(shí)瀏覽器會(huì)把網(wǎng)頁(yè)圖片的數(shù)據(jù)以相關(guān)的圖形格式存放在剪貼板中,此時(shí)在可以解讀和處理圖片的程序(比如畫圖、phtoshop或word)中,粘貼按鈕是可用的,而在另外的程序中粘貼按鈕是灰色/不可用的。這是因?yàn)檫@些程序在顯示編輯菜單之前使用與剪貼板格式相關(guān)的幾個(gè)API函數(shù)預(yù)先判斷一下剪貼板內(nèi)是否有自己可以處理的數(shù)據(jù)格式。接下來(lái)我們就看看如何使用API函數(shù)獲取與剪貼板格式相關(guān)的信息。

  如果一個(gè)應(yīng)用程序只對(duì)剪貼板內(nèi)格式名稱為PNG的數(shù)據(jù)感興趣,并且它已經(jīng)獲得了PNG剪貼板格式的編號(hào),假設(shè)是49538,那判斷它自己是否可以使用粘貼命令的最簡(jiǎn)單的辦法是使用IsClipboardFormatAvailable(49538),然后根據(jù)返回值確定剪貼板內(nèi)是否包含PNG格式數(shù)據(jù),這個(gè)函數(shù)定義如下:

Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long
作用: 判斷剪貼板內(nèi)是否存在指定格式的數(shù)據(jù)
參數(shù): wFormat標(biāo)準(zhǔn)剪貼板格式或注冊(cè)剪貼板格式的編號(hào)
返回值: 如果剪貼板中存在相應(yīng)格式的數(shù)據(jù),則返回一個(gè)非0值否則返回0
說(shuō)明:


  如果一個(gè)應(yīng)用程序可以處理多種數(shù)據(jù)格式,比如Word,它可以處理富文本(Rich Text Format)、超文本(HTML Format)和純文本(CF_TEXT),并且當(dāng)剪貼板可以提供多種格式時(shí)優(yōu)先考慮包含更多格式信息的富文本和超文本,然后是純文本,只有前面的格式不存在時(shí)才考慮后面的格式,那么它不必使用3次IsClipboardFormatAvailable來(lái)分別判斷,因?yàn)橛辛硗庖粋(gè)功能相似但允許傳入數(shù)組的API函數(shù)GetPriorityClipboardFormat,這個(gè)函數(shù)定義如下:

Declare Function GetPriorityClipboardFormat Lib "user32" (lpPriorityList As Long, ByVal nCount As Long) As Long
作用: 這個(gè)函數(shù)返回指定數(shù)組中第一個(gè)可用的剪貼板格式
參數(shù): lpPriorityList指向一個(gè)數(shù)組的指針,這個(gè)數(shù)組中按優(yōu)先級(jí)別存放多個(gè)剪貼板格式編號(hào)
nCount
數(shù)組內(nèi)元素的個(gè)數(shù)
返回值: 如果剪貼板內(nèi)存在一種或多種數(shù)組中列出的格式,則返回優(yōu)先級(jí)別最靠前的剪貼板格式編號(hào)如果剪貼板內(nèi)有數(shù)據(jù)但不包含數(shù)組中列出的任何一種格式,則返回-1
如果剪貼板為空,則返回Null
說(shuō)明: 這個(gè)函數(shù)不需要OpenClipboard在VB中,如果API需要一個(gè)數(shù)組的指針,那么應(yīng)該向它傳遞數(shù)組第一個(gè)元素,并且不要使用byval


  接著上面的話題,假設(shè)三種格式對(duì)應(yīng)的編號(hào)分別為Rich Text Format:49465,HTML Format:49363和CF_TEXT:1,它可以使用下列代碼一次得到需要的剪貼板格式:

Dim lFormats()
Dim lFormatFristAvailable As Long
lFormats = Array(49465, 49363, 1)
lFormatFristAvailable = GetPriorityClipboardFormat(lFormats(0), 3)

運(yùn)行代碼之后lFormatFristAvailable的值可能是49465、46363、1、0、-1,這些值具體代碼什么含義應(yīng)該不需要再多說(shuō)了吧。
  如果應(yīng)用程序只知道自己可以處理的剪貼板格式的名稱,而不知道它的編號(hào),它可以通過(guò)兩種方法得到對(duì)應(yīng)的編號(hào):
  1) 使用前面提到的RegisterClipboardFormat函數(shù);
  2) 使用EnumClipBoardFormats函數(shù)獲取剪貼板內(nèi)所有可用格式的編號(hào),然后使用GetClipboardFormatName函數(shù)取得該編號(hào)對(duì)應(yīng)的格式名稱
  但如果應(yīng)用程序需要列出剪貼板內(nèi)所有可用格式的編號(hào)和名稱時(shí),就只能通過(guò)后面兩個(gè)函數(shù)了,這兩個(gè)函數(shù)常組合在一起使用。

Declare Function EnumClipboardFormats Lib "user32" (ByVal wFormat As Long) As Long
作用: 這個(gè)函數(shù)可以列舉出當(dāng)前剪貼板內(nèi)所有可用的數(shù)據(jù)格式
參數(shù): wFormat代表剪貼板內(nèi)已知可用的標(biāo)準(zhǔn)剪貼板格式或注冊(cè)剪貼板格式的編號(hào)
在列舉過(guò)程最開(kāi)始,向函數(shù)傳入0值,函數(shù)將返回第一個(gè)可用的剪貼板格式編號(hào),將返回值傳給下一次函數(shù)調(diào)用,可以得到下一個(gè)可用的剪貼板格式編號(hào)。
返回值: 如果調(diào)用成功,則返回wFormat之后第一個(gè)可用的剪貼板格式編號(hào)如果調(diào)用失敗,則返回0
說(shuō)明: 這個(gè)函數(shù)需要事先使用OpenClipboard成功打開(kāi)剪貼板
這個(gè)函數(shù)返回的剪貼板格式的順序與ClipboardOwner放入數(shù)據(jù)時(shí)的順序一樣。微軟建議,當(dāng)向剪貼板中放入數(shù)據(jù)時(shí),首先放入最能描述所要傳遞的信息的數(shù)據(jù),當(dāng)從剪貼板中讀取數(shù)據(jù)時(shí),盡量使用程序能夠解讀的最靠前的格式的數(shù)據(jù),因?yàn)樗男畔⒆罱咏紨?shù)據(jù)所要表達(dá)的信息。


  如果你以前使用過(guò)FindWindowEx,那么使用起這個(gè)函數(shù)來(lái)肯定容易上手。如果沒(méi)有使用過(guò)也沒(méi)有關(guān)系,形象點(diǎn)地比喻,這有點(diǎn)像我們上學(xué)時(shí)上體育課,假如應(yīng)用程序是新來(lái)的體育老師,他對(duì)班里的同學(xué)(剪貼板內(nèi)可用的數(shù)據(jù)格式)一個(gè)也不認(rèn)識(shí),那么他可以讓班里的同學(xué)站成一隊(duì),然后問(wèn)班長(zhǎng)(Windows操作系統(tǒng)):“排頭的同學(xué)學(xué)號(hào)是多少?”(對(duì)應(yīng)代碼:lFormat=EnumClipBoardFormats(0) ),班長(zhǎng)回答:“是5號(hào)”(這時(shí)lFormat=5),老師又問(wèn):“5號(hào)同學(xué)后面的同學(xué)學(xué)號(hào)是多少?”(對(duì)應(yīng)代碼:lFormat=EnumClipBoardFormats(lFormat) ),班長(zhǎng)回答:“5號(hào)后面是7號(hào)”,“那7號(hào)后面呢?”……這樣一直問(wèn)下去,直到班長(zhǎng)回答:“99號(hào)同學(xué)是最后一位,后面沒(méi)有了”,這樣就完成了一次列舉,老師可以把得到的學(xué)號(hào)依次記到本子上,下次在需要的時(shí)候不必再問(wèn)班長(zhǎng)。當(dāng)然聰明點(diǎn)的老師可以這樣告訴班長(zhǎng):“把排頭到排尾的同學(xué)學(xué)號(hào)依次報(bào)給我”,這樣對(duì)應(yīng)的是一個(gè)do……loop until循環(huán)。
  按照號(hào)碼記憶是容易弄混的,通常老師要知道學(xué)生的名字,這樣他就要給班長(zhǎng)一張紙,上面有某個(gè)學(xué)號(hào),讓班長(zhǎng)把這個(gè)學(xué)生的名字寫到紙上,這種情況相當(dāng)于使用GetClipboardFormatName函數(shù),函數(shù)這樣聲明:

Declare Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long
作用: 給出指定剪貼板格式編號(hào)所對(duì)應(yīng)的剪貼板格式名稱,函數(shù)將把此名稱復(fù)制到指定的緩沖區(qū)中。
參數(shù): wFormat:剪貼板格式的名稱
lpString:
[輸出]用于接收剪貼板格式名稱的緩沖字符串
nMaxCount:
緩沖字符串的字節(jié)長(zhǎng)度,如果剪貼板格式名稱的文本長(zhǎng)度超出nMaxCount數(shù)值,超出部分將被截去
返回值: 如果函數(shù)調(diào)用成功,返回值是復(fù)制到lpString中的字節(jié)數(shù)目如果函數(shù)調(diào)用失敗,返回0
說(shuō)明:


  這里又有一個(gè)在VB中不常見(jiàn)的概念,緩沖字符串(有時(shí)候是緩沖字節(jié)數(shù)組或是其他結(jié)構(gòu))。
  在API中,函數(shù)的返回值通常是Long型,所以字符串的賦值通常不是向VB中那樣strOut=strFunction(),而是先定義一個(gè)字符串變量,然后用String函數(shù)或Space函數(shù)使它具備足夠的長(zhǎng)度以容納將要獲得的字符,然后將它以參數(shù)的形式傳遞給函數(shù),函數(shù)運(yùn)行過(guò)程中將把要獲取的字符串復(fù)制進(jìn)這個(gè)字符串中,這種方式在API中很常用,我們要習(xí)慣它。
  最后,發(fā)一個(gè)在立即窗口中輸出剪貼板內(nèi)所有可用格式編號(hào)和名稱的過(guò)程作為本節(jié)的結(jié)束:

Public Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function CloseClipboard Lib "user32" () As Long
Public Declare Function EnumClipboardFormats Lib "user32" (ByVal wFormat As Long) As Long
Public Declare Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long
Public Const CF_TEXT = 1
Public Const CF_BITMAP = 2
Public Const CF_METAFILEPICT = 3
Public Const CF_SYLK = 4
Public Const CF_DIF = 5
Public Const CF_TIFF = 6
Public Const CF_OEMTEXT = 7
Public Const CF_DIB = 8
Public Const CF_PALETTE = 9
Public Const CF_PENDATA = 10
Public Const CF_RIFF = 11
Public Const CF_WAVE = 12
Public Const CF_UNICODETEXT = 13
Public Const CF_ENHMETAFILE = 14
Public Const CF_HDROP = 15
Public Const CF_LOCALE = 16
Public Const CF_MAX = 17
Dim lFormat As Long
Public Sub ListClipFormats()
  IF OpenClipboard (byval 0&) Then
    lFormat = EnumClipboardFormats(0)
    If lFormat <> 0 Then
      Do While lFormat <> 0
        debug.print lFormat & vbTab & ": " & GetFormatName(lFormat)
        lFormat = EnumClipboardFormats(lFormat)
      Loop
    End If
    CloseClipboard
  End If
End Sub
Public Function GetFormatName(lFormat As Long) As String
  Select Case lFormat
  Case 1
    GetFormatName = "CF_Text"
  Case 2
    GetFormatName = "CF_Bitmap"
  Case 3
    GetFormatName = "CF_MetaFilePict"
  Case 4
    GetFormatName = "CF_SYLK"
  Case 5
    GetFormatName = "CF_Dif"
  Case 6
    GetFormatName = "CF_Tiff"
  Case 7
    GetFormatName = "CF_OEMText"
  Case 8
    GetFormatName = "CF_DIB"
  Case 9
    GetFormatName = "CF_Pallette"
  Case 10
    GetFormatName = "CF_PenData"
  Case 11
    GetFormatName = "CF_Riff"
  Case 12
    GetFormatName = "CF_Wave"
  Case 13
    GetFormatName = "CF_UnicodeText"
  Case 14
    GetFormatName = "CF_EnhMetaFile"
  Case 15
    GetFormatName = "CF_HDrop"
  Case 16
    GetFormatName = "CF_Locale"
  Case 17
    GetFormatName = "CF_Max"
  Case Else:
    Dim sBuffer As String
    sBuffer = String(100, Chr(0))
    GetClipboardFormatName lFormat, sBuffer, 100
    GetFormatName = Trim(sBuffer)
  End Select
End Function


Excel整體界面趨于平面化,顯得清新簡(jiǎn)潔。流暢的動(dòng)畫和平滑的過(guò)渡,帶來(lái)不同以往的使用體驗(yàn)。

溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!

本類教程下載

系統(tǒng)下載排行

網(wǎng)站地圖xml | 網(wǎng)站地圖html
主站蜘蛛池模板: 前郭尔| 通山县| 聂荣县| 延川县| 德安县| 安化县| 庄浪县| 永安市| 日照市| 乐昌市| 博罗县| 堆龙德庆县| 朝阳市| 台南县| 阿瓦提县| 玛纳斯县| 博爱县| 巴里| 穆棱市| 宾川县| 平果县| 鄂尔多斯市| 昌平区| 盐边县| 抚宁县| 县级市| 乌拉特后旗| 德兴市| 麻江县| 东阳市| 济源市| 县级市| 开江县| 英德市| 宁乡县| 沅江市| 五台县| 科技| 江安县| 西乌珠穆沁旗| 弥渡县|