楼主 xmyjk |
一、 何为WINDOWS剪贴板
剪贴板是内存中的一块连续可变的区域,使得在各种应用程序之间,实现数据交换和共享信息。在WINDOWS的运行窗口,键入clipbrd,可以弹出官方的“剪贴簿查看程序”,实现对剪贴板内数据的监控。如下图:
它的工作原理和流程,用通俗的语言举例,例如我们在IE中复制了网页中我们喜欢的一张图片,那描述这张图片的数据,将存放在剪贴板所在的特定内存区域中。一旦,我们在WORD中黏贴了这张图片,其实是WORD这个应用程序,访问了剪贴板,读取了这张图片的数据,然后乾坤大挪移到我们的WORD文档中进行储存。因为都是在内存中操作,所以速度非常快。 |
2楼 xmyjk |
二、WINDOWS剪贴板的数据格式
既然:剪贴板是用于多个应用程序之间交换数据的,那存放在剪贴板的数据,是怎样的呢?
◆首先,由于存放在全局内存中,他们是公开的,应用程序们可以访问到的,并能交换所需的数据的。
◆其次,既然是公共的数据,那这些数据是有规范标准,是系统/用户已经预先设定格式,可以在不同的应用程序中进行交换。 例如我在网页复制了一段文字,既可以黏贴到记事本,也可黏贴到WORD。这说明了,这些数据是具有某些标准格式的,符合系统或程序间的设定的格式的。
◆进而,应用程序们都可以访问这些数据,那么,这些数据就必然是多元的。这就类似我们EXCEL的选择性黏贴。我们复制了单元格的一个公式,可以相对的黏贴这个公式,也可以仅黏贴值,还可以黏贴成图片。 这说明了,剪贴板中是可以同时存放多种格式的数据。我们移交给剪贴板的某个数据或消息,将在剪贴板内,自动以尽可能多种的以预设过数据格式进行呈现(取决于发起复制或剪贴的应用程序,不同应用程序不同上下文环境,处理数据格式范围不同,放进剪贴板数据格式类别也不同)。微软建议,当向剪贴板中放入数据时,首先放入最能描述所要传递的信息的数据,因为它所包含的信息最接近原始数据所要表达的信息。当从剪贴板中读取数据时,将按顺序枚举所有的数据格式,如果该数据格式在目标应用程序可用,则进行黏贴,否则继续枚举,直至有可用数据。 即使上传的数据结构自身就非常简单,就例如记事本的文本,剪贴板也能按照一些标准的预设格式,在内存中自动转换,生成多个剪贴板数据格式,以便多种程序的交换。就例如,我们仅仅在记事本复制了一小段文字,剪贴板也能按照如下几个格式,自动进行多样化存放。如下图:
翻阅了下资料,有四类数据,剪贴板是自带转化功能的(剪贴板格式名称请参与下面的介绍): (1)CF_TEXT、CF_UNICODETEXT与CF_OEMTEXT这三个文本格式相互之间; (2)CF_METAFILEPICT和CF_ENHMETAFILE这两个图元文件相互之间; (3)CF_BITMAP、CF_DIB与CF_DIBV5这三个位图数据格式相互之间; (4)如果CF_DIB与CF_DIBV5的数据格式,将自动转化CF_PALETTE的数据格式,这个是单向的,反之不成立。 总之,剪贴板的数据是以多种数据格式进行呈现的。
◆最后,这些数据格式,是能被检索查询的,如果新的应用程序,需要新的数据格式,也可以使用API的RegisterClipboardFormat函数进行注册。这些已经预设或者注册过的,剪贴板存放过的数据格式,WINDOWS都会用一个长整形的编号,像字典一样,进行记录。通过这个编号,我们可以获取对应格式的数据。 对于WINDOWS系统初始的标准格式,这个编号是固定的,如下图:
如果是非系统标准格式的,允许运用RegisterClipboardFormat函数,用数据格式的名称,去注册这个格式,如果注册成功,将得到新的剪贴板数据格式对应的编号。如果重名,将直接返回已有这个数据格式名称对应的格式编号。 |
3楼 xmyjk |
三、获取剪贴板数据的套路和主要API的剪贴板函数简介
一般而言,获取剪贴板数据的大致步骤如下(按需增减): (一)用OpenClipboard打开剪贴板- Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
参数hwnd:用来传递目前打开剪贴板的窗口的句柄。如果它修改了剪贴板内的数据,它就会成为剪贴板数据拥有窗口即ClipboardOwner,这样其他程序可以使用GetClipboardOwner去获取它。如果只是读取剪贴板内的数据,可以传递一个0&;如果要向剪贴板内写入数据,则必须指定有效的hwnd,否则不能成功调用SetClipboardData函数; 如果调用成功,将返回剪贴板的句柄。失败返回0。
(二)EnumClipboardFormats加while来循环出一个可用的剪贴板格式- Declare Function EnumClipboardFormats Lib "user32" (ByVal wFormat As Long) As Long
参数:wFormat表示剪贴板内已知可用的标准剪贴板格式或注册剪贴板格式的编号。在枚举的最开始,向函数传入0值,将返回第一个可用的剪贴板格式编号,将该返回值传给下一次函数调用,将得到下一个可用的剪贴板格式编号。以此循环,直至 返回0,可以枚举所有的可用的数据格式。
或用IsClipboardFormatAvailable或GetPriorityClipboardFormat判断可用格式的存在- Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long
参数:wFormat标准剪贴板格式或注册剪贴板格式的编号 如果剪贴板中存在相应格式的数据,则返回一个非0值否则返回0。 如果一个应用程序可以处理多种数据格式,运行传入数组的API函数:- Declare Function GetPriorityClipboardFormat Lib "user32" (lpPriorityList As Long, ByVal nCount As Long) As Long
参数:lpPriorityList指向数组第一个元素的地址,这个数组中需按优先级别存放多个剪贴板格式编号;nCount表示数组内元素的个数; 如果剪贴板内存在一种或多种数组中列出的格式,则返回优先级别靠前的剪贴板格式编号;如果剪贴板内有数据但不包含数组中列出的任何一种格式,则返回-1;如果剪贴板为空,则返回0。- Dim arrf()
- Dim f As Long
- arrf = Array(49290, 49386, 1)
- f = GetPriorityClipboardFormat(arrf(0), 3)
(三)使用GetClipboardData获得剪贴板的内存块首地址- Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
参数:wFormat表示将要取出的数据格式的编号; 如果成功,返回剪贴板中以指定格式存放的数据对象的句柄;失败,返回0; 一般而言,返回的内存对象的句柄,但是如果数据是一个图像格式,返回的将是一个GDI对象的句柄,例如,位图格式的返回位图GDI对象句柄,图元文件返回的是图元文件对象的句柄等。GDI对象另贴再解析。先按返回内存对象的句柄进行后续讲解。
(四)用GlobalLock锁定剪贴板那内存块- Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
参数hMem是内存对象的句柄; 成功,返回值是内存对象所占用内存的第一个字节的内存地址;失败,返回0
(五)GlobalSize可以用来获取该内存块的大小- Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
参数hMem是内存对象的句柄; 成功,返回是内存对象所占用内存的字节长度,失败返回值0
(六)用CopyMemory将二进制数据取出来并赋值给字节数组- Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
参数:Destination是要赋值的数组第一个元素的内存地址;Source是来源的第一个字节的内存地址;Length是要复制的数据的长度;
(七)处理数据,转换数据格式等等 呵呵,这个就按需处理了。文本的,转换成文本数据,图片的,转换成图片,二进制的转换16进制翻译,等等
(八)使用GlobalUnlock解除锁定- Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
参数hMem是内存对象的句柄; 被解锁,则返回0
(九)CloseClipboard关闭剪贴板- Declare Function CloseClipboard Lib "user32"() As Long
成功,返回一个非0值;失败返回0
有了上述的套路,我们就可以随意的读取剪贴板的相应数据了。 |
4楼 xmyjk |
简易剪贴板查看程序.zip
查看程序码源:- Option Explicit
- Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
- Private Declare Function CloseClipboard Lib "user32" () As Long
- Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
- Private Declare Function EmptyClipboard Lib "user32" () As Long
- Private Declare Function EnumClipboardFormats Lib "user32" (ByVal wFormat As Long) As Long
- Private Declare Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long
- Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
- Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
- Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
- Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
- Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
- Private Declare Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" (ByVal hemfSrc As Long, ByVal lpszFile As String) As Long
- Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
- Private Type GUID
- Data1 As Long
- Data2 As Integer
- Data3 As Integer
- Data4(0 To 7) As Byte
- End Type
- Private Type uPicDesc
- Size As Long
- Type As Long
- hPic As Long
- hPal As Long
- End Type
- Private Sub CommandButton1_Click()
- ListBox1.Clear
- TextBox1.Value = ""
- Set Image1.Picture = Nothing
- TextBox1.Visible = True
- Image1.Visible = False
- listclpformate
- End Sub
- Private Sub ListBox1_Click()
- TextBox1.Visible = False
- Image1.Visible = False
- Dim hMem As Long, ClpData As Long, ClpSize As Long, byt() As Byte, clptext As String, fv As Long, hp As Long, f As Long
- If ListBox1.ListIndex <> 0 Then
- fv = ListBox1.List(ListBox1.ListIndex)
- OpenClipboard 0&
- Select Case fv
- Case 1, 7, 13
- hMem = GetClipboardData(1)
- If hMem <> 0 Then
- ClpData = GlobalLock(hMem)
- ClpSize = GlobalSize(hMem)
- If ClpData <> 0 And ClpSize > 0 Then
- ReDim byt(0 To ClpSize - 1) As Byte
- CopyMemory byt(0), ByVal ClpData, ByVal ClpSize
- clptext = StrConv(byt, vbUnicode)
- End If
- GlobalUnlock hMem
- End If
- TextBox1.Visible = True
- TextBox1.Text = clptext
- Case 2, 8, 3, 14
- Select Case fv
- Case 2, 8
- f = 2
- hMem = GetClipboardData(2)
- hp = CopyImage(hMem, 0&, 0, 0, &H4)
- Case Else
- f = 14
- hMem = GetClipboardData(14)
- hp = CopyEnhMetaFile(hMem, vbNullString)
- End Select
- If hMem <> 0 Then
- Dim uPicInfo As uPicDesc, IID_IDispatch As GUID, IPic As IPictureDisp
- With IID_IDispatch
- .Data1 = &H7BF80980
- .Data2 = &HBF32
- .Data3 = &H101A
- .Data4(0) = &H8B
- .Data4(1) = &HBB
- .Data4(2) = &H0
- .Data4(3) = &HAA
- .Data4(4) = &H0
- .Data4(5) = &H30
- .Data4(6) = &HC
- .Data4(7) = &HAB
- End With
- With uPicInfo
- .Size = Len(uPicInfo)
- .Type = IIf(f = 2, 1, 4)
- .hPic = hp
- End With
- OleCreatePictureIndirect uPicInfo, IID_IDispatch, True, IPic
- Image1.Visible = True
- Set Image1.Picture = IPic
- End If
- Case Else
- hMem = GetClipboardData(fv)
- If hMem <> 0 Then
- ClpData = GlobalLock(hMem)
- ClpSize = GlobalSize(hMem)
- If ClpData <> 0 And ClpSize > 0 Then
- ReDim byt(0 To ClpSize - 1) As Byte
- CopyMemory byt(0), ByVal ClpData, ByVal ClpSize
- clptext = BinArrayToHex(byt)
- End If
- GlobalUnlock hMem
- End If
- clptext = clptext & vbCrLf & vbCrLf & "识别可能文本:" & vbCrLf & StrConv(byt, vbUnicode)
- TextBox1.Visible = True
- TextBox1.Text = clptext
- End Select
- CloseClipboard
- End If
- End Sub
- Sub listclpformate()
- Dim fname As String, f As Long, d
- Set d = CreateObject("scripting.dictionary")
- OpenClipboard 0&
- f = EnumClipboardFormats(0)
- Do While f <> 0
- Select Case f
- Case 1
- fname = "文本"
- Case 2
- fname = "位图"
- Case 3
- fname = "MetaFilePict图片"
- Case 4
- fname = "SYLK"
- Case 5
- fname = "Dif"
- Case 6
- fname = "Tiff"
- Case 7
- fname = "OEM文本"
- Case 8
- fname = "DIB位图"
- Case 9
- fname = "Pallette"
- Case 10
- fname = "PenData"
- Case 11
- fname = "Riff"
- Case 12
- fname = "Wave"
- Case 13
- fname = "Unicode文字"
- Case 14
- fname = "增强型图元文件"
- Case 15
- fname = "HDrop"
- Case 16
- fname = "区域设置"
- Case 17
- fname = "DIBV5位图"
- Case 18
- fname = "Max"
- Case 128
- fname = "CF_OWNERDISPLAY"
- Case 129
- fname = "显示文本"
- Case 130
- fname = "CF_DSPBITMAP"
- Case 131
- fname = "CF_DSPMETAFILEPICT"
- Case 142
- fname = "CF_DSPENHMETAFILE"
- Case 512
- fname = "CF_PRIVATEFIRST"
- Case 767
- fname = "CF_PRIVATELAST"
- Case 768
- fname = "CF_GDIOBJFIRST"
- Case 1023
- fname = "CF_GDIOBJLAST"
- Case Else:
- fname = Space(255)
- GetClipboardFormatName f, fname, 255
- fname = Trim(fname)
- If fname <> "" Then
- fname = Left(fname, Len(fname) - 1)
- End If
- End Select
- d(fname) = f
- f = EnumClipboardFormats(f)
- Loop
- CloseClipboard
- If d.Count > 0 Then
- Dim arr(), i&, k, it
- ReDim arr(0 To d.Count, 0 To 1)
- k = d.keys
- it = d.items
- arr(0, 0) = "格式编码"
- arr(0, 1) = "格式名称"
- For i = 1 To d.Count
- arr(i, 0) = it(i - 1)
- arr(i, 1) = k(i - 1)
- Next
- ListBox1.List = arr
- End If
- End Sub
- Private Sub UserForm_Initialize()
- TextBox1.Visible = True
- Image1.Visible = False
- listclpformate
- End Sub
- Private Function BinArrayToHex(Bin() As Byte) As String
- Dim iLoop As Long
- Dim sResult As String
- Dim m&
- m = 1
- sResult = Space((UBound(Bin) - LBound(Bin) + 1) * 4)
- For iLoop = LBound(Bin) To UBound(Bin)
- Mid(sResult, (iLoop - LBound(Bin)) * 4 + 1, 2) = Right("0" & Hex(Bin(iLoop)), 2)
- If m = 16 Then Mid(sResult, (iLoop - LBound(Bin)) * 4 + 3, 2) = vbCrLf: m = 0
- m = m + 1
- Next iLoop
- BinArrayToHex = Trim(sResult)
- End Function
|
5楼 xmyjk |
四、如何监控剪贴板
(较难,作为拓展补充,以下涉及的知识,需要有WINDOWS消息传递机制和拦截WINDOWS消息的基础知识(或者再另贴讲吧)。涉及到相关的API,就不详细阐述,读者可自行查阅API手册。)
WINDOWS剪贴板观察器(Clipboard Viewer)是一个显示剪贴板当前内容的窗口。剪贴板观察链(Clipboard Viewer Chain)是一系列相互独立的剪贴板观察窗口,是保存Clipboard Viewer窗口以及他们之间的前后向关系的一个Windows系统链表,它们都能够监控并读取当前发送到剪贴板的内容。
如何将我们的程序,注册成一个系统认可并可实时刷新的剪贴板监视程序呢? 首先,使用SetClipboardViewer函数向剪贴板观察链中加入一个观察窗口。该函数需要传递的参数是观察窗口的句柄。返回值也是链条下一个窗口句柄。当一个窗口注册为Clipboard Viewer后,他会被加入Clipboard Viewer Chain,并得到链表中下一个Viewer窗口的句柄,该句柄必须保存以在响应消息时使用。Windows正是通过Clipboard Viewer Chain保证了所有Clipboard Viewer能接收和响应剪贴板变化消息。当剪贴板的内容发生变化时,该窗口会接收到一个WM_DRAWCLIPBOARD的消息。 然后,响应WM_DRAWCLIPBOARD消息处理剪贴板内容的变化。 最后,在程序退出或关闭时需要调用ChangeClipboardChain函数来将自己从观察链中删除。然后调用SendMessage函数把这些消息传递到观察链中的下一个观察窗口。
另外,窗口都是有自己的窗口程序,来相应WINDOWS之间的消息传递,我们要把我们的窗体程序,注册成为相应剪贴板消息的监视程序,还需要如下步骤: 首先,先用一个句柄,用GetWindowLong函数记录原来的窗口程序; 然后,用SetWindowLong函数,设置相应剪贴板消息的监视程序和窗口进行绑定; 接着,循环处理WINDOWS系统发来的消息,如果是剪贴板相关的消息,就来用我们写的剪贴板查看程序来处理,如果是非剪贴板查看的其他消息,就用CallWindowProc函数调用窗口原来的窗口程序处理消息。 最后,当结束时,再次使用SetWindowLong将原窗口程序还原。 不过,我做出来的程序,在WINDOWS XP的系统环境下,会造成EXCEL崩溃,但是在WIN7环境下,程序没有任何问题。或许我的理解在某方面还是有偏差的吧。待查证补充。也请大家指点。 |
6楼 xmyjk |
简易剪贴板监视查看程序.zip
剪贴板监视工具,标准模块代码:- Option Explicit
- Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
- Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
- Private Const WM_DRAWCLIPBOARD = &H308
- Private Const WM_CHANGECBCHAIN = &H30D
- Public PrevProc As Long
- Public hwnd As Long
- Public hwndNextViewer As Long
- Sub lo()
- UserForm1.Show 0
- End Sub
- Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
- Select Case uMsg
- Case WM_CHANGECBCHAIN
- If wParam = hwndNextViewer Then
- hwndNextViewer = lParam
- ElseIf hwndNextViewer <> 0 Then
- SendMessage hwndNextViewer, uMsg, wParam, lParam
- End If
- Case WM_DRAWCLIPBOARD
- UserForm1.ListBox1.Clear
- UserForm1.TextBox1.Value = ""
- Set UserForm1.Image1.Picture = Nothing
- UserForm1.TextBox1.Visible = True
- UserForm1.Image1.Visible = False
- UserForm1.listclpformate
- SendMessage hwndNextViewer, uMsg, wParam, lParam
- End Select
- WindowProc = CallWindowProc(PrevProc, hwnd, uMsg, wParam, lParam)
- End Function
窗体代码:- Option Explicit
- Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
- Private Declare Function CloseClipboard Lib "user32" () As Long
- Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
- Private Declare Function EmptyClipboard Lib "user32" () As Long
- Private Declare Function EnumClipboardFormats Lib "user32" (ByVal wFormat As Long) As Long
- Private Declare Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long
- Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
- Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
- Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
- Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
- Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
- Private Declare Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" (ByVal hemfSrc As Long, ByVal lpszFile As String) As Long
- Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
- Private Type GUID
- Data1 As Long
- Data2 As Integer
- Data3 As Integer
- Data4(0 To 7) As Byte
- End Type
- Private Type uPicDesc
- Size As Long
- Type As Long
- hPic As Long
- hPal As Long
- End Type
- Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
- Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
- Private Declare Function SetClipboardViewer Lib "user32" (ByVal hwnd As Long) As Long
- Private Declare Function ChangeClipboardChain Lib "user32" (ByVal hwnd As Long, ByVal hWndNext As Long) As Long
- Const GWL_WNDPROC = (-4)
- Private Sub ListBox1_Click()
- TextBox1.Visible = False
- Image1.Visible = False
- Dim hMem As Long, ClpData As Long, ClpSize As Long, byt() As Byte, clptext As String, fv As Long, hp As Long, f As Long
- If ListBox1.ListIndex <> 0 Then
- fv = ListBox1.List(ListBox1.ListIndex)
- OpenClipboard 0&
- Select Case fv
- Case 1, 7, 13
- hMem = GetClipboardData(1)
- If hMem <> 0 Then
- ClpData = GlobalLock(hMem)
- ClpSize = GlobalSize(hMem)
- If ClpData <> 0 And ClpSize > 0 Then
- ReDim byt(0 To ClpSize - 1) As Byte
- CopyMemory byt(0), ByVal ClpData, ByVal ClpSize
- clptext = StrConv(byt, vbUnicode)
- End If
- GlobalUnlock hMem
- End If
- TextBox1.Visible = True
- TextBox1.Text = clptext
- Case 2, 8, 3, 14
- Select Case fv
- Case 2, 8
- f = 2
- hMem = GetClipboardData(2)
- hp = CopyImage(hMem, 0&, 0, 0, &H4)
- Case Else
- f = 14
- hMem = GetClipboardData(14)
- hp = CopyEnhMetaFile(hMem, vbNullString)
- End Select
- If hMem <> 0 Then
- Dim uPicInfo As uPicDesc, IID_IDispatch As GUID, IPic As IPictureDisp
- With IID_IDispatch
- .Data1 = &H7BF80980
- .Data2 = &HBF32
- .Data3 = &H101A
- .Data4(0) = &H8B
- .Data4(1) = &HBB
- .Data4(2) = &H0
- .Data4(3) = &HAA
- .Data4(4) = &H0
- .Data4(5) = &H30
- .Data4(6) = &HC
- .Data4(7) = &HAB
- End With
- With uPicInfo
- .Size = Len(uPicInfo)
- .Type = IIf(f = 2, 1, 4)
- .hPic = hp
- End With
- OleCreatePictureIndirect uPicInfo, IID_IDispatch, True, IPic
- Image1.Visible = True
- Set Image1.Picture = IPic
- End If
- Case Else
- hMem = GetClipboardData(fv)
- If hMem <> 0 Then
- ClpData = GlobalLock(hMem)
- ClpSize = GlobalSize(hMem)
- If ClpData <> 0 And ClpSize > 0 Then
- ReDim byt(0 To ClpSize - 1) As Byte
- CopyMemory byt(0), ByVal ClpData, ByVal ClpSize
- clptext = BinArrayToHex(byt)
- End If
- GlobalUnlock hMem
- End If
- TextBox1.Visible = True
- TextBox1.Text = clptext
- End Select
- CloseClipboard
- End If
- End Sub
- Sub listclpformate()
- Dim fname As String, f As Long, d
- Set d = CreateObject("scripting.dictionary")
- OpenClipboard 0&
- f = EnumClipboardFormats(0)
- Do While f <> 0
- Select Case f
- Case 1
- fname = "文本"
- Case 2
- fname = "位图"
- Case 3
- fname = "MetaFilePict图片"
- Case 4
- fname = "SYLK"
- Case 5
- fname = "Dif"
- Case 6
- fname = "Tiff"
- Case 7
- fname = "OEM文本"
- Case 8
- fname = "DIB位图"
- Case 9
- fname = "Pallette"
- Case 10
- fname = "PenData"
- Case 11
- fname = "Riff"
- Case 12
- fname = "Wave"
- Case 13
- fname = "Unicode文字"
- Case 14
- fname = "增强型图元文件"
- Case 15
- fname = "HDrop"
- Case 16
- fname = "区域设置"
- Case 17
- fname = "DIBV5位图"
- Case 129
- fname = "显示文本"
- Case Else:
- fname = Space(255)
- GetClipboardFormatName f, fname, 255
- fname = Trim(fname)
- If fname <> "" Then
- fname = Left(fname, Len(fname) - 1)
- End If
- End Select
- d(fname) = f
- f = EnumClipboardFormats(f)
- Loop
- CloseClipboard
- If d.Count > 0 Then
- Dim arr(), i&, k, it
- ReDim arr(0 To d.Count, 0 To 1)
- k = d.keys
- it = d.items
- arr(0, 0) = "格式编码"
- arr(0, 1) = "格式名称"
- For i = 1 To d.Count
- arr(i, 0) = it(i - 1)
- arr(i, 1) = k(i - 1)
- Next
- ListBox1.List = arr
- End If
- End Sub
- Sub UserForm_Initialize()
- TextBox1.Visible = True
- Image1.Visible = False
- listclpformate
- hwnd = FindWindow(vbNullString, Me.Caption)
- hwndNextViewer = SetClipboardViewer(hwnd)
- PrevProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
- End Sub
- Private Function BinArrayToHex(Bin() As Byte) As String
- Dim iLoop As Long
- Dim sResult As String
- Dim m&
- m = 1
- sResult = Space((UBound(Bin) - LBound(Bin) + 1) * 4)
- For iLoop = LBound(Bin) To UBound(Bin)
- Mid(sResult, (iLoop - LBound(Bin)) * 4 + 1, 2) = Right("0" & Hex(Bin(iLoop)), 2)
- If m = 16 Then Mid(sResult, (iLoop - LBound(Bin)) * 4 + 3, 2) = vbCrLf: m = 0
- m = m + 1
- Next iLoop
- BinArrayToHex = Trim(sResult)
- End Function
- Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
- ChangeClipboardChain hwnd, hwndNextViewer
- SetWindowLong hwnd, GWL_WNDPROC, PrevProc
- End Sub
|
7楼 xmyjk |
五、其他补遗
(一)剪贴板数据格式注册函数 Declare Function RegisterClipboardFormat Lib "user32" Alias "RegisterClipboardFormatA" (ByVal lpString As String) As Long 参数lpString表示指定要注册的剪贴板格式的名称 注册成功,则返回该剪贴板格式所对应的编号,失败,则返回0; 如果被注册的剪贴板格式名称已经存在,并不会重新注册一个新的剪贴板格式,而是返回原有的同名剪贴板格式编号。
(二)获取剪贴板数据格式名称的API函数 Declare Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long 参数:wFormat表示剪贴板格式的编码;lpString表示用于接收剪贴板格式名称的缓冲字符串;nMaxCount:缓冲字符串的字节长度,超出部分将被截去。 成功, 返回lpString中储存相关格式名称的字节数,否则返回0
(三)将数据上传剪贴板的API函数 Declare Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As Long) As Long 参数:wFormat表示剪贴板格式的编码;hMem表示上传的数据对象的句柄
(四)其他功能函数 CountClipboardFormats:返回剪贴板可用数据格式的个数 EmptyClipboard:清空剪贴板 GetClipboardOwner:获取当前剪贴板是属于哪一个窗口的句柄 GetClipboardSequenceNumber:返回剪贴板序号 GetClipboardViewer:返回剪贴板监控程序所属窗口的句柄 GetOpenClipboardWindow:返回打开剪贴板的那个窗口句柄
(五) 另外,如果是纯文本格式数据对剪贴板的访问,可以使用DATAOBJECT,可参阅我以前写过的一个帖子。 如何运用VBA实现复制指定选择的单元格区域的数据,使粘贴到QQ后出现的是文本形式的 http://www.exceltip.net/thread-26337-1-1.html
|
8楼 bishunbiao |
只能仰视啦,收藏下 |
9楼 herelazy |
太牛啦**!仰望中! |
10楼 千年一梦遥 |
太牛啦**!仰望中! |
11楼 xyf2210 |
太牛啦**!仰望中! |
12楼 CheryBTL |
哇~~~师傅太牛了****
|
13楼 YESS95 |
烧香,膜拜,…… |
14楼 水星钓鱼 |
仰望,膜拜,精华 |
15楼 yjzstar |
仰望加收藏 |
16楼 白米饭 |
仰望中,有点晕 |
17楼 冬冬WarmUp |
太牛啦**!仰望中! |
18楼 dhf327 |
好东西,学习学习 |