用小提琴将Ruby复制到剪贴板
我正试图用Fiddle模块将字符串复制到剪贴板,但此代码失败用小提琴将Ruby复制到剪贴板,ruby,winapi,clipboard,fiddle,Ruby,Winapi,Clipboard,Fiddle,我正试图用Fiddle模块将字符串复制到剪贴板,但此代码失败 require'fiddle'; user32 = Fiddle.dlopen 'USER32.dll'; $openClipboard = Fiddle::Function.new(user32['OpenClipboard'],[Fiddle::TYPE_INT],Fiddle::TYPE_INT); $closeClipboard = Fiddle::Function.new(user32['CloseClipboard'],[
require'fiddle';
user32 = Fiddle.dlopen 'USER32.dll';
$openClipboard = Fiddle::Function.new(user32['OpenClipboard'],[Fiddle::TYPE_INT],Fiddle::TYPE_INT);
$closeClipboard = Fiddle::Function.new(user32['CloseClipboard'],[],Fiddle::TYPE_INT);
$emptyClipboard = Fiddle::Function.new(user32['EmptyClipboard'],[],Fiddle::TYPE_INT);
$setClipboardData = Fiddle::Function.new(user32['SetClipboardData'],[Fiddle::TYPE_INT,Fiddle::TYPE_VOIDP],Fiddle::TYPE_VOIDP);
class Clipboard
def initialize
@closed = false;
puts "openClipboard : #{$openClipboard.call(0)}";
puts "emptyClipboard : #{$emptyClipboard.call}";
end
def data=(d)
return 'Cannot write to closed clipboard' if @closed;
puts "setClipboardData : #{$setClipboardData.call(1,d)}"; # 1 is CF_TEXT
end
def close
return 'Already closed' if @closed;
@closed = true;
puts "closeClipboard : #{$closeClipboard.call}";
end
end
c = Clipboard.new
puts 'going to write';
gets;
c.data = 'red'; # Should write 'red' to the clipboard
p 'after writing to the clipboard';
gets;
c.close;
p 'closed';
gets
但它在#data=方法中失败了。
(这只是一次尝试在翻译代码)。
关于如何在不使用外部gem/库的情况下实现这一点,您有什么想法吗?无法帮助您使用fiddle,因为Ruby 1.9.3不支持dlopen方法。 在我的脚本库中,我发现了这个工作示例。 在 在我的gems列表中找不到open3,所以我想它是标准库的一部分。无论如何,要在这样的层次上与操作系统交互,你需要某种宝石,无论是否合并,小提琴也是宝石
require 'open3'
module Clipboard; end
module Clipboard::Windows
extend self
CF_TEXT = 1
CF_UNICODETEXT = 13
GMEM_MOVEABLE = 2
# get ffi function handlers
begin
require 'ffi'
rescue LoadError
raise LoadError, 'Could not load the required ffi gem, install it with: gem install ffi'
end
module User32
extend FFI::Library
ffi_lib "user32"
ffi_convention :stdcall
attach_function :open, :OpenClipboard, [ :long ], :long
attach_function :close, :CloseClipboard, [ ], :long
attach_function :empty, :EmptyClipboard, [ ], :long
attach_function :get, :GetClipboardData, [ :long ], :long
attach_function :set, :SetClipboardData, [ :long, :long ], :long
end
module Kernel32
extend FFI::Library
ffi_lib 'kernel32'
ffi_convention :stdcall
attach_function :lock, :GlobalLock, [ :long ], :pointer
attach_function :unlock, :GlobalUnlock, [ :long ], :long
attach_function :size, :GlobalSize, [ :long ], :long
attach_function :alloc, :GlobalAlloc, [ :long, :long ], :long
end
# see http://www.codeproject.com/KB/clipboard/archerclipboard1.aspx
def paste(_ = nil)
ret = ""
if 0 != User32.open( 0 )
hclip = User32.get( CF_UNICODETEXT )
if hclip && 0 != hclip
pointer_to_data = Kernel32.lock( hclip )
data = ""
# Windows Unicode is ended by to null bytes, so get the whole string
size = Kernel32.size( hclip )
data << pointer_to_data.get_bytes( 0, size - 2 )
if RUBY_VERSION >= '1.9'
ret = data.force_encoding("UTF-16LE").encode(Encoding.default_external) # TODO catch bad encodings
else # 1.8: fallback to simple CP850 encoding
require 'iconv'
utf8 = Iconv.iconv( "UTF-8", "UTF-16LE", data)[0]
ret = Iconv.iconv( "CP850", "UTF-8", utf8)[0]
end
if data && 0 != data
Kernel32.unlock( hclip )
end
end
User32.close( )
end
ret || ""
end
def clear
if 0 != User32.open( 0 )
User32.empty( )
User32.close( )
end
paste
end
def copy(data_to_copy)
if ( RUBY_VERSION >= '1.9' ) && 0 != User32.open( 0 )
User32.empty( )
data = data_to_copy.encode("UTF-16LE") # TODO catch bad encodings
data << 0
handler = Kernel32.alloc( GMEM_MOVEABLE, data.bytesize )
pointer_to_data = Kernel32.lock( handler )
pointer_to_data.put_bytes( 0, data, 0, data.bytesize )
Kernel32.unlock( handler )
User32.set( CF_UNICODETEXT, handler )
User32.close( )
else # don't touch anything
Open3.popen3( 'clip' ){ |input,_,_| input << data_to_copy } # depends on clip (available by default since Vista)
end
paste
end
end
Clipboard::Windows.copy("test")
puts Clipboard::Windows.paste
Ruby 2.2.3中不包括FFI,即使是剪贴板gem也需要FFI,无论如何,谢谢,我已经知道了如何做的基本概念。
#gem install clipboard
require 'clipboard'
Clipboard.copy("This is a sentence that has been copied to your clipboard")
puts Clipboard.paste