| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- # -*- coding: utf-8 -*-
- # *****************************************************************************
- # Copyright (C) 2003-2006 Jack Trainor.
- # Copyright (C) 2006-2020 Jorgen Stenarson. <jorgen.stenarson@bostream.nu>
- # Copyright (C) 2020 Bassem Girgis. <brgirgis@gmail.com>
- #
- # Distributed under the terms of the BSD License. The full license is in
- # the file COPYING, distributed as part of this software.
- # *****************************************************************************
- ###################################
- #
- # Based on recipe posted to ctypes-users
- # see archive
- # http://aspn.activestate.com/ASPN/Mail/Message/ctypes-users/1771866
- #
- #
- ##########################################################################
- #
- # The Python win32clipboard lib functions work well enough ... except that they
- # can only cut and paste items from within one application, not across
- # applications or processes.
- #
- # I've written a number of Python text filters I like to run on the contents of
- # the clipboard so I need to call the Windows clipboard API with global memory
- # for my filters to work properly.
- #
- # Here's some sample code solving this problem using ctypes.
- #
- # This is my first work with ctypes. It's powerful stuff, but passing
- # arguments in and out of functions is tricky. More sample code would have
- # been helpful, hence this contribution.
- #
- ##########################################################################
- import ctypes
- import ctypes.wintypes as wintypes
- from ctypes import (
- addressof,
- c_buffer,
- c_char_p,
- c_int,
- c_size_t,
- c_void_p,
- c_wchar_p,
- cast,
- create_unicode_buffer,
- sizeof,
- windll,
- wstring_at,
- )
- from typing import Union
- from pyreadline3.keysyms.winconstants import CF_UNICODETEXT, GHND
- from pyreadline3.unicode_helper import ensure_unicode
- OpenClipboard = windll.user32.OpenClipboard
- OpenClipboard.argtypes = [wintypes.HWND]
- OpenClipboard.restype = wintypes.BOOL
- EmptyClipboard = windll.user32.EmptyClipboard
- GetClipboardData = windll.user32.GetClipboardData
- GetClipboardData.argtypes = [wintypes.UINT]
- GetClipboardData.restype = wintypes.HANDLE
- GetClipboardFormatName = windll.user32.GetClipboardFormatNameA
- GetClipboardFormatName.argtypes = [wintypes.UINT, c_char_p, c_int]
- SetClipboardData = windll.user32.SetClipboardData
- SetClipboardData.argtypes = [wintypes.UINT, wintypes.HANDLE]
- SetClipboardData.restype = wintypes.HANDLE
- EnumClipboardFormats = windll.user32.EnumClipboardFormats
- EnumClipboardFormats.argtypes = [c_int]
- CloseClipboard = windll.user32.CloseClipboard
- CloseClipboard.argtypes = []
- GlobalAlloc = windll.kernel32.GlobalAlloc
- GlobalAlloc.argtypes = [wintypes.UINT, c_size_t]
- GlobalAlloc.restype = wintypes.HGLOBAL
- GlobalLock = windll.kernel32.GlobalLock
- GlobalLock.argtypes = [wintypes.HGLOBAL]
- GlobalLock.restype = c_void_p
- GlobalUnlock = windll.kernel32.GlobalUnlock
- GlobalUnlock.argtypes = [c_int]
- _strncpy = ctypes.windll.kernel32.lstrcpynW
- _strncpy.restype = c_wchar_p
- _strncpy.argtypes = [c_wchar_p, c_wchar_p, c_size_t]
- def _enum() -> None:
- OpenClipboard(0)
- q = EnumClipboardFormats(0)
- while q:
- q = EnumClipboardFormats(q)
- CloseClipboard()
- def _get_format_name(format_str: str) -> bytes:
- buffer = c_buffer(100)
- bufferSize = sizeof(buffer)
- OpenClipboard(0)
- GetClipboardFormatName(format_str, buffer, bufferSize)
- CloseClipboard()
- return buffer.value
- def get_clipboard_text() -> str:
- text = ""
- if OpenClipboard(0):
- h_clip_mem = GetClipboardData(CF_UNICODETEXT)
- if h_clip_mem:
- text = wstring_at(GlobalLock(h_clip_mem))
- GlobalUnlock(h_clip_mem)
- CloseClipboard()
- return text
- def set_clipboard_text(text: Union[str, bytes]) -> None:
- buffer = create_unicode_buffer(ensure_unicode(text))
- buffer_size = sizeof(buffer)
- h_global_mem = GlobalAlloc(GHND, c_size_t(buffer_size))
- GlobalLock.restype = c_void_p
- lp_global_mem = GlobalLock(h_global_mem)
- _strncpy(
- cast(lp_global_mem, c_wchar_p),
- cast(addressof(buffer), c_wchar_p),
- c_size_t(buffer_size),
- )
- GlobalUnlock(c_int(h_global_mem))
- if OpenClipboard(0):
- EmptyClipboard()
- SetClipboardData(CF_UNICODETEXT, h_global_mem)
- CloseClipboard()
- if __name__ == "__main__":
- txt = get_clipboard_text() # display last text clipped
- print(txt)
|