In message "[ruby-list:19218] Re: Clipbord を Ruby で使うには?", TADA Tadashi <sho / spc.gr.jp> wrote: > でも、元の質問だと、Rubyでいじった文字列を、またクリップボードに > 戻したいようなんですが、これってできるのでしょうか。GlobalAllocで > 確保した領域に、RubyのStringの内容をコピーするところがわからない。 > ハンドルをGlobalLockしてみても、戻ってきた値は長さが8しかないし(謎)。 > 拡張モジュールを書かないとダメなのかな。 できてるみたいです。私はこんなんで二台のマシンでクリップボード内容の やりとりをしています。 (clipbrd.rb) #!/usr/local/bin/ruby require 'Win32API' module Clipboard # Clipboard API $OpenClipboard = Win32API.new('user32', 'OpenClipboard', ['I'], 'I'); $CloseClipboard = Win32API.new('user32', 'CloseClipboard', [], 'I'); $EmptyClipboard = Win32API.new('user32', 'EmptyClipboard', [], 'I'); $IsClipboardFormatAvailable = Win32API.new('user32', 'IsClipboardFormatAvailable', ['I'], 'I'); $GetClipboardData = Win32API.new('user32', 'GetClipboardData', ['I'], 'I'); $SetClipboardData = Win32API.new('user32', 'SetClipboardData', ['I', 'I'], 'I'); # Predefined Clipboard Formats CF_TEXT = 1; CF_BITMAP = 2; CF_METAFILEPICT = 3; CF_SYLK = 4; CF_DIF = 5; CF_TIFF = 6; CF_OEMTEXT = 7; CF_DIB = 8; CF_PALETTE = 9; CF_PENDATA = 10; CF_RIFF = 11; CF_WAVE = 12; CF_UNICODETEXT = 13; CF_ENHMETAFILE = 14; CF_HDROP = 15; CF_LOCALE = $10; CF_MAX = 17; # memory manager API $GlobalAlloc = Win32API.new('kernel32', 'GlobalAlloc', ['I','I'], 'I'); $GlobalSize = Win32API.new('kernel32', 'GlobalSize', ['I'], 'I'); $GlobalLock = Win32API.new('kernel32', 'GlobalLock', ['I'], 'P'); $GlobalUnlock = Win32API.new('kernel32', 'GlobalUnlock', ['I'], 'I'); $GlobalFree = Win32API.new('kernel32', 'GlobalFree', ['I'], 'I'); # Global Memory Flags GMEM_FIXED = 0; GMEM_MOVEABLE = 2; GMEM_NOCOMPACT = 0x10; GMEM_NODISCARD = 0x20; GMEM_ZEROINIT = 0x40; GMEM_MODIFY = 0x80; GMEM_DISCARDABLE = 0x100; GMEM_NOT_BANKED = 0x1000; GMEM_SHARE = 0x2000; GMEM_DDESHARE = 0x2000; GMEM_NOTIFY = 0x4000; GMEM_LOWER = GMEM_NOT_BANKED; GMEM_VALID_FLAGS = 32626; GMEM_INVALID_HANDLE = 0x8000; GHND = GMEM_MOVEABLE + GMEM_ZEROINIT; GPTR = GMEM_FIXED + GMEM_ZEROINIT; $lstrcpy = Win32API.new('kernel32', 'lstrcpyA', ['P', 'P'], 'P'); $lstrlen = Win32API.new('kernel32', 'lstrlenA', ['P'], 'I'); $lstrcpyIP = Win32API.new('kernel32', 'lstrcpyA', ['I', 'P'], 'P'); $lstrcpyPI = Win32API.new('kernel32', 'lstrcpyA', ['P', 'I'], 'P'); $GlobalLockI = Win32API.new('kernel32', 'GlobalLock', ['I'], 'I'); def GetText result = "" if $OpenClipboard.Call(0) != 0 if (h = $GetClipboardData.Call(CF_TEXT)) != 0 if (p = $GlobalLock.Call(h)) != 0 result = p; $GlobalUnlock.Call(h); end end $CloseClipboard.Call; end return result; end def SetText(text) if (text == nil) || (text == "") return end if $OpenClipboard.Call(0) != 0 $EmptyClipboard.Call(); len = $lstrlen.Call(text); hmem = $GlobalAlloc.Call(GMEM_DDESHARE, len+1); pmem = $GlobalLockI.Call(hmem); $lstrcpyIP.Call(pmem, text); $SetClipboardData.Call(CF_TEXT, hmem); $GlobalUnlock.Call(hmem); $CloseClipboard.Call; end end end include Clipboard; # sample: # require 'clipbrd'; # print Clipboard.GetText; # Clipboard.SetText("aaaaa\nbbbbb\n"); (clipserver.rb) #!/usr/local/bin/ruby require 'socket' require 'clipbrd' Port = 4445 gs = TCPserver.open(Port) addr = gs.addr addr.shift printf("server is on %d\n", addr.join(":")) # for ^C trap Thread.start do while TRUE print "|\b"; STDOUT.flush sleep 1 print "-\b"; STDOUT.flush sleep 1 end end # server thread while TRUE newsc = gs.accept #print(newsc, " is accepted\n") print(newsc.peeraddr.join(":"), " is accepted\n") Thread.start do sc = newsc #sc.gets #print $_; STDOUT.flush str = Clipboard.GetText #print str; STDOUT.flush sc.write(str + "\n") sc.close end end (clipclient.rb) #!/usr/local/bin/ruby require 'socket' require 'clipbrd' Port = 4445 host=(if ARGV.length == 1; ARGV.shift; else "localhost"; end) STDERR.print("Trying ", host, " ..."); STDERR.flush sc = TCPsocket.open(host, Port) STDERR.print("connect."); STDERR.flush str = "" #sc.write("HELLO\n") while sc.gets str = str + $_ end sc.close print str Clipboard.SetText("[#{host}]\n"+str)