狂自私

导航

python-剪贴板的操作-文件相关(复制文件到剪贴板,剪切文件到剪贴板)

  1. 读取有没有文件被复制或剪切
import win32clipboard

a = ""
clip = win32clipboard.RegisterClipboardFormat("Preferred DropEffect")
#返回的clip 就是我们将要代入GetClipboardData函数的该数据结构的代码
if win32clipboard.OpenClipboard() == None:
    try:
        #尝试以文件的格式读取剪贴板内容
        clip_ = win32clipboard.GetClipboardData(win32clipboard.CF_HDROP)
        if clip_ != None:
            #获取标志位
            a = win32clipboard.GetClipboardData(clip)
    finally:
        win32clipboard.CloseClipboard()
if a[0] == 2:
    print("剪切")
elif a[0] == 5:
    print("复制")
else:
    print(a[0])    

关于“clip = win32clipboard.RegisterClipboardFormat("Preferred DropEffect")”,其中Preferred DropEffect是系统定义的一个关于如何处理文件(复制,移动等)的剪贴板格式字符串,我们在这里同样注册这个,不会与系统发生冲突,重复注册也只是会返回第一次注册的句柄值;收到这篇博客的启发:传送门:如何与资源管理器互动剪切/拷贝/粘贴文件_xuyongbeijing2008的专栏-CSDN博客

我做了更详细的测试:

#这些函数相关的作用,请参考:http://timgolden.me.uk/pywin32-docs/win32clipboard.html
import
win32clipboard
win32clipboard.OpenClipboard()
format = 0
str_list = []
try:
    while True:
        ret = win32clipboard.EnumClipboardFormats(format)  #获取当前剪贴板上的数据格式
        if ret == 0:
            print("ret={}".format(ret))
            break
        ret_str = win32clipboard.GetClipboardFormatName(ret)  #以字符串形式返回格式名称
        print("format={}\tstring={}".format(format,ret_str))
        
        conten_str = win32clipboard.GetClipboardData(ret)  #获取数据
        print("\t{}".format(conten_str))
        str_list.append(conten_str)
        format = ret
except Exception as e:
    ctypes.GetLastError()
finally:
    win32clipboard.CloseClipboard()

这是在文件资源管理器上做了剪切文件的操作在运行代码的输出:

format=0 string=DataObject
format=49161 string=Shell IDList Array
b"\x01\x00\x00\x00\x0c\x00\x00\x00\x15\x01\x00\x00\x14\x00\x1fP\xe0O\xd0 \xea:i\x10\xa2\xd8\x08\x00+00\x9d\x19\x00/D:\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x001\x00\x00\x00\x00\x009T\xaa<\x10\x00python\x00\x00>\x00\t\x00\x04\x00\xef\xbe9T\xa1<9T\xaa<.\x00\x00\x00\xca\x01\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe2\xef\x0f\x00p\x00y\x00t\x00h\x00o\x000\x00\xac)\x9c\x00p\x00y\x00t\x00h\x00o\x00n\x00_\x00c\x00l\x00a\x00s\x00s\x00_\x00e\x00v\x00e\x00r\x00y\x00t\x00h\x00i\x00n\x00g\x00\x00\x00&\x00\x00\x00\x84\x002\x00%\x04\x00\x00OT\xf7L \x00python_everything.spec\x00\x00^\x00\t\x00\x04\x00\xef\xbeJT\xc1AOT\xf7L.\x00\x00\x00:\n\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\xd9j\x00p\x00y\x00t\x00h\x00o\x00n\x00_\x00e\x00v\x00e\x00r\x00y\x00t\x00h\x00i\x00n\x00g\x00.\x00s\x00p\x00e\x00c\x00\x00\x00&\x00\x00\x00"
format=49390 string=DataObjectAttributes
format=50001 string=DataObjectAttributesRequiringElevation
b'0\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00'
format=50000 string=Shell Object Offsets
b'I\x04\x00\x00\x17\x03\x00\x00'
format=49391 string=Preferred DropEffect
b'\x02\x00\x00\x00'
format=49399 string=AsyncFlag
b'\x01\x00\x00\x00'

 

  1. 实现复制文件操作,复制操作可以不用设置标志位
#参考:https://chowdera.com/2021/10/20211031055535475l.html
#这其实是一个结构体,用以记录文件的各种信息。
class DROPFILES(ctypes.Structure):
    _fields_ = [
        ("pFiles", ctypes.c_uint),
        ("x", ctypes.c_long),
        ("y", ctypes.c_long),
        ("fNC", ctypes.c_int),
        ("fWide", ctypes.c_bool),
    ]

pDropFiles = DROPFILES()
pDropFiles.pFiles = ctypes.sizeof(DROPFILES)
pDropFiles.fWide = True
a = bytes(pDropFiles)

#获取文件绝对路径
filepaths_list = [文件路径1,文件路径2,]
files = ("\0".join(filepaths_list)).replace("/", "\\")
data = files.encode("U16")[2:] + b"\0\0"        #结尾一定要两个\0\0字符,这是规定!

'''
对于多个文本路径,我们如何将其转换为我们需要的Unicode 双字节形式呢?
首先,我们要知道Unicode编码采用UCS-2格式直接存储,而UTF-16恰好对应于UCS-2的,即UCS-2指定的码位通过大端或小端的方式直接保存。UTF-16 有三种类型:UTF-16,UTF-16BE(大端序),UTF-16LE(小端序).UTF-16 通过以名称BOM(字节顺序标记,U + FEFF)启动文件来指示该文件仍然是小端序。
我们只需要把python String使用UTF-16编码后,去掉前两个字节,得到相应的Unicode双字节。
'''
win32clipboard.OpenClipboard()  #打开剪贴板(独占)
try:
    #若要将信息放在剪贴板上,首先需要使用 EmptyClipboard 函数清除当前的剪贴板内容
    win32clipboard.EmptyClipboard() #清空当前的剪贴板信息
    win32clipboard.SetClipboardData(win32clipboard.CF_HDROP,bytes(pDropFiles)+data) #设置当前剪贴板数据
except Exception as e:
    print(str(e))
finally:
    win32clipboard.CloseClipboard() #无论什么情况,都关闭剪贴板
  1. 实现剪切文件
#这其实是一个结构体,用以记录文件的各种信息。
        class DROPFILES(ctypes.Structure):
            _fields_ = [
                ("pFiles", ctypes.c_uint),
                ("x", ctypes.c_long),
                ("y", ctypes.c_long),
                ("fNC", ctypes.c_int),
                ("fWide", ctypes.c_bool),   #指示文件是否包含 ANSI 或 Unicode 字符。如果值为零,则文件包含 ANSI 字符。否则,它包含 Unicode 字符。
            ]

        pDropFiles = DROPFILES()
        pDropFiles.pFiles = ctypes.sizeof(DROPFILES)
        pDropFiles.fWide = True
        #获取文件绝对路径
        filepaths_list = []
        files = ("\0".join(filepaths_list)).replace("/", "\\")
        data = files.encode("U16")[2:] + b"\0\0"        #结尾一定要两个\0\0字符,这是规定!就是构造NULL字符

        '''
        对于多个文本路径,我们如何将其转换为我们需要的Unicode 双字节形式呢?
        首先,我们要知道Unicode编码采用UCS-2格式直接存储,而UTF-16恰好对应于UCS-2的,即UCS-2指定的码位通过大端或小端的方式直接保存。UTF-16 有三种类型:UTF-16,UTF-16BE(大端序),UTF-16LE(小端序).UTF-16 通过以名称BOM(字节顺序标记,U + FEFF)启动文件来指示该文件仍然是小端序。
        我们只需要把python String使用UTF-16编码后,去掉前两个字节,得到相应的Unicode双字节。
        '''
        win32clipboard.OpenClipboard()  #打开剪贴板(独占)
        try:
            #若要将信息放在剪贴板上,首先需要使用 EmptyClipboard 函数清除任何以前的剪贴板内容
            win32clipboard.EmptyClipboard() #清空当前的剪贴板信息,否则不能写入

            uDropEffect = win32clipboard.RegisterClipboardFormat("Preferred DropEffect")  #注册格式
            
            win32clipboard.SetClipboardData(win32clipboard.CF_HDROP,bytes(pDropFiles)+data) #设置当前剪贴板数据
            win32clipboard.SetClipboardData(uDropEffect,b'\x02\x00\x00\x00')  #写入代表剪切操作的数据
            err = ctypes.windll.kernel32.GetLastError()
            if err == 0:
                self.__statusBar.config(text="剪切成功!", fg="green")
            else:
                self.__statusBar.config(text="剪切失败!errorCode={}".format(err), fg="red")
        except Exception as e:
            exc_type, exc_value, exc_traceback_obj = sys.exc_info()
            traceback.print_tb(exc_traceback_obj)
            self.__statusBar.config(text="剪切失败!", fg="red")
        finally:
            win32clipboard.CloseClipboard() #无论什么情况,都关闭剪贴板

 

posted on 2022-02-16 13:54  狂自私  阅读(3083)  评论(0编辑  收藏  举报