1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# Copyright © 2022, 飞麦 <[email protected]>, All rights reserved. # frozen_string_literal: true require 'fiddle/import' # Clipboard only for Windows, can use both in x86 and x64 # size_t and handles must use void* (NOT uint) in Fiddle to fit the pointer size of x86 or x64 # if use size_t as return value, you need add to_i to it. module Clipboard module_function extend Fiddle::Importer include Fiddle::CParser dlload 'kernel32', 'user32' # HWND GetClipboardOwner(); extern 'void* GetClipboardOwner()' # HWND GetClipboardViewer(); extern 'void* GetClipboardViewer()' # HWND GetDesktopWindow(); extern 'void* GetDesktopWindow()' # BOOL OpenClipboard( # _In_opt_ HWND hWndNewOwner # ); extern 'int OpenClipboard(void*)' # BOOL CloseClipboard(); extern 'int CloseClipboard()' # BOOL EmptyClipboard(); extern 'int EmptyClipboard()' # Predefined Clipboard Formats CF_UNICODETEXT = 13 # HANDLE GetClipboardData( # _In_ UINT uFormat # ); extern 'void* GetClipboardData(uint)' # HANDLE SetClipboardData( # _In_ UINT uFormat, # _In_opt_ HANDLE hMem # ); extern 'void* SetClipboardData(uint, void*)' # Global Memory Flags GMEM_FIXED = 0x0000 # Don't use GMEM_MOVEABLE = 0x0002(need GlobalLock and GlobalUnlock) # HGLOBAL GlobalAlloc( # _In_ UINT uFlags, # _In_ SIZE_T dwBytes # ); extern 'void* GlobalAlloc(uint, void*)' # SIZE_T GlobalSize( # _In_ HGLOBAL hMem # ); extern 'void* GlobalSize(void*)' # void RtlCopyMemory( # _In_ PVOID Destination, # _In_ const VOID *Source, # _In_ SIZE_T Length # ); extern 'void RtlCopyMemory(void*, const void*, void*)' # DWORD GetLastError(); extern 'uint GetLastError()' def show(_str) # puts _str # uncomment only when debug nil end def clip_hwnd hwnd = GetClipboardOwner() show("GetClipboardOwner fail! Error=#{GetLastError()}") if hwnd.null? hwnd.null? ? nil : hwnd end def view_hwnd hwnd = GetClipboardViewer() show("GetClipboardViewer fail! Error=#{GetLastError()}") if hwnd.null? hwnd.null? ? nil : hwnd end def desk_hwnd GetDesktopWindow() end def find_hwnd clip_hwnd || view_hwnd || desk_hwnd end # Sometimes OpenClipboard will fail without any error, so we need retry def open_cb 999.times do hwnd = find_hwnd next unless hwnd break unless OpenClipboard(hwnd).zero? show("OpenClipboard fail! Error=#{GetLastError()}") end end def empty_cb 999.times do break unless EmptyClipboard().zero? show("EmptyClipboard fail! Error=#{GetLastError()}") end end def close_cb 999.times do break unless CloseClipboard().zero? show("CloseClipboard fail! Error=#{GetLastError()}") end end def move_it(text) text_16le = "#{text}/u0000".encode(Encoding::UTF_16LE) # must append /u0000 for text len = text_16le.bytesize hmem = GlobalAlloc(GMEM_FIXED, len) show("#GlobalAlloc fail! Error=#{GetLastError()}") if hmem.null? RtlCopyMemory(hmem, text_16le, len) hmem end def save_it(hmem) hndl = SetClipboardData(CF_UNICODETEXT, hmem) show("#SetClipboardData Error=#{GetLastError()} hmem=#{hmem.to_i} != hndl=#{hndl.to_i}") if hndl != hmem end def copy(text) open_cb empty_cb hmem = move_it(text) save_it(hmem) close_cb end def clear open_cb empty_cb close_cb end def load_it(hmem) len = GlobalSize(hmem).to_i show("GlobalSize Error=#{GetLastError()} len=#{len}") if len.zero? len -= 2 # needn't copy tail /u0000 text = ''.encode(Encoding::UTF_16LE) * (len / 2) RtlCopyMemory(text, hmem, len) text.encode(Encoding::UTF_8) end def paste open_cb hmem = GetClipboardData(CF_UNICODETEXT) text = hmem.null? ? '' : load_it(hmem) close_cb text end end |
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/280213.html