クリップボードへの転送
Posted feedbacks - Nested
Flatten HiddenRでは、ファイル名に"clipboard"を指定するとクリップボードへの入出力が可能です。(Windows限定かもしれません)
1 2 3 4 | > readLines("clipboard")
[1] "クリップボード(や同等の機能)へテキストを転送するプログラムをお願いします。 また可能でしたらクリップボードのデータを取り出すプログラムもお願いします。 "
[2] ""
[3] "システムに依存する内容ですが、応用範囲が広いと思いましたので出題させてもらいました。 "
|
生憎、今のところそのような便利ライブラリはなさそうなので生のWin32APIを使わざるを得ません。
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 | module win32.clipboard;
private import std.c.windows.windows;
private import std.contracts, std.conv;
export extern(Windows) {
HGLOBAL GlobalAlloc(UINT uFlags, DWORD dwBytes);
HGLOBAL GlobalFree(HGLOBAL hMem);
LPVOID GlobalLock(HGLOBAL hMem);
BOOL GlobalUnlock(HGLOBAL hMem);
enum UINT GMEM_MOVEABLE = 2;
BOOL CloseClipboard();
BOOL EmptyClipboard();
UINT EnumClipboardFormats(UINT format);
HANDLE GetClipboardData(UINT uFormat);
BOOL OpenClipboard(HWND hWndNewOwner);
HANDLE SetClipboardData(UINT uFormat, HANDLE hMem);
enum UINT CF_UNICODETEXT = 13;
}
public static class Clipboard {
static void setText(string text) {
enforce(OpenClipboard(null));
scope(exit) CloseClipboard();
auto wtext = to!(wstring)(text);
auto data = enforce(GlobalAlloc(GMEM_MOVEABLE, wchar.sizeof * (wtext.length + 1)));
scope(failure) GlobalFree(data);
{
auto pdata = cast(wchar*)GlobalLock(data);
scope(exit) GlobalUnlock(data);
pdata[0..wtext.length] = wtext;
pdata[wtext.length] = '\0';
}
enforce(EmptyClipboard());
enforce(SetClipboardData(CF_UNICODETEXT, data));
}
static string getText() {
enforce(OpenClipboard(null));
scope(exit) CloseClipboard();
auto data = GetClipboardData(CF_UNICODETEXT);
if(!data) return null;
auto pdata = cast(const(wchar)*)GlobalLock(data);
auto wtext = pdata[0..strlen(pdata)];
GlobalUnlock(data);
return to!(string)(wtext);
}
}
private uint strlen(const(wchar)* s) {
uint len;
while(*s++) len++;
return len;
}
debug(Clipboard) {
import std.stdio;
void main() {
Clipboard.setText("test テスト");
writeln(Clipboard.getText);
}
}
|
すみません。 不注意で関係のないところへぶら下げてしまいました。
import ocean.clipboard as c
c.get() # クリップボードの中身を取得
c.set("hoge") # クリップボードに設定
c.clear() # クリップボードを空にする
として使います。
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 | from __future__ import with_statement
from contextlib import contextmanager
import ctypes
GMEM_DDESHARE = 0x2000
GMEM_MOVEABLE = 0x0002
CF_TEXT = 1
user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32
@contextmanager
def _GlobalLock(h):
p = kernel32.GlobalLock(h)
if not p:
raise WindowsError("GlobalLock() failed")
try:
yield p
finally:
kernel32.GlobalUnlock(h)
@contextmanager
def _Clipboard():
if not user32.OpenClipboard(None):
raise WindowsError("OpenClipboard() failed")
try:
yield
finally:
user32.CloseClipboard()
def set(s):
s = s.encode("mbcs")
# memory block
h = kernel32.GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, len(s) + 1)
if not h:
raise WindowsError("GlobalAlloc() failed")
try:
with _GlobalLock(h) as p:
p = (ctypes.c_char * (len(s) + 1)).from_address(p)
for i, c in enumerate(s + "\0"):
p[i] = c
# clipboard
with _Clipboard():
user32.EmptyClipboard()
user32.SetClipboardData(CF_TEXT, h)
except:
kernel32.GlobalFree(h)
raise
def get():
with _Clipboard():
h = user32.GetClipboardData(CF_TEXT)
if h:
with _GlobalLock(h) as p:
return ctypes.c_char_p(p).value.decode("mbcs")
def clear():
with _Clipboard():
user32.EmptyClipboard()
|
ちょっと簡略化。
1 2 3 4 5 6 7 8 9 10 11 12 13 | --- clipboard.py Mon Feb 11 19:47:02 2008
+++ clipboard.py Mon Jul 7 02:51:50 2008
@@ -37,9 +37,7 @@
raise WindowsError("GlobalAlloc() failed")
try:
with _GlobalLock(h) as p:
- p = (ctypes.c_char * (len(s) + 1)).from_address(p)
- for i, c in enumerate(s + "\0"):
- p[i] = c
+ (ctypes.c_char * (len(s) + 1)).from_address(p).value = s
# clipboard
with _Clipboard():
user32.EmptyClipboard()
|
see: Clipboard
1 2 3 4 5 6 | use strict;
use Clipboard;
# クリップボードに転送
Clipboard->copy('foo');
# クリップボードから取り出し
print Clipboard->paste;
|
なでしこでは、変数「クリップボード」でクリップボードの読み書きが出来ます。
また、命令としても、クリップボードからの取り出しには「クリップボード取得」、転送には「コピー」が使用できます。
1 2 3 4 5 | クリップボードは「変数経由」
クリップボード取得して表示
「命令経由」をコピー
クリップボードを表示
|
"hoge.js" などの名前で保存し、「ツール」の「キーマクロの読み込み」でキーマクロに設定したのち、Ctrl + Shift + L で実行します。
see: サクラエディタマクロ
1 2 3 4 5 6 | Editor.SelectAll();
Editor.Copy();
for (var i=0; i<3; i++) {
Editor.GoFileEnd();
Editor.Paste();
}
|
標準入力或いは、指定のファイルからクリップボードに転送します。 '-show' をつけるとクリップボードのテキストを表示
1 2 3 4 5 6 7 8 | require 'win32/clipboard'
include Win32
if ARGV.include?('-show')
print Clipboard.get_data
else
Clipboard.set_data(ARGF.read)
end
|
"hogehoge" をクリップボードに転送。 Firefox3で確認。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function copyToClipboard (copytext) {
const supstr = Components.classes["@mozilla.org/supports-string;1"].
createInstance(Components.interfaces.nsISupportsString);
const transferable = Components.classes["@mozilla.org/widget/transferable;1"].
createInstance(Components.interfaces.nsITransferable);
const iClipboard = Components.interfaces.nsIClipboard;
const clipboard = Components.classes["@mozilla.org/widget/clipboard;1"].getService(iClipboard);
supstr.data = copytext;
transferable.addDataFlavor("text/unicode");
transferable.setTransferData("text/unicode", supstr, copytext.length * 2);
return clipboard.setData(transferable, null, iClipboard.kGlobalClipboard);
}
copyToClipboard('hogehoge');
|
とりあえず、文字列の場合は以下の通り。 その他、画像やJavaのシリアライズしたオブジェクトなど、さまざまなデータを送れます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
public class Sample188 {
public static void main(String[] args) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
// クリップボードにデータを設定
StringSelection setData = new StringSelection("クリップボードにコピーされる。");
clipboard.setContents(setData, setData);
// クリップボードからデータを取得
try {
String str = (String) clipboard.getData(DataFlavor.stringFlavor);
System.out.println(str);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
|
Squeak Smalltalk で。
1 2 | Clipboard clipboardText: 'クリップボードへ'.
Clipboard clipboardText "クリップボードから"
|
クラス化してみました。 【使い方】 clip = new ClipBoard() // 中身を表示 println clip.text // セット clip.text = "新しい内容"
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 | import java.awt.Toolkit
import java.awt.datatransfer.Clipboard
import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.StringSelection
import java.awt.datatransfer.Transferable
public class ClipBoard {
def clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
public void setText(sendStr) {
def ss = new StringSelection(sendStr)
clipboard.setContents(ss, ss)
}
public getText() {
Transferable recive = clipboard.getContents(null)
def recieveStr = null
try {
recieveStr = (String) recive.getTransferData(DataFlavor.stringFlavor)
} catch (Exception e) {
recieveStr = ""
}
return recieveStr
}
}
|
MIT/GNU Scheme で書きました。 残念ながら Scheme 処理系に共通したクリップボード読み書きの方法はありません。
1 2 3 4 | ;; クリップボードへ書き込み (※ str は文字列)
(win32-clipboard-write-text str)
;; クリップボードから読み込み
(win32-clipboard-read-text)
|
今回の例では、中ボタンでのペーストではなくCTR+V系にしました。
コマンド呼び出しのライブラリには、KMRCLを利用しています。
ちなみに、日本語の文字化け問題には対応していません…。
動作:
(pbcopy "foo")
; クリップボードへ
(pbpaste)
;=> foo
see: xclip を使って pbcopy/pbpaste っぽいコマンドを再現する
1 2 3 4 5 6 7 8 9 | (defun pbcopy (string)
(declare (string string))
(kmrcl:run-shell-command
"echo ~A|xclip -selection clipboard" string))
(defun pbpaste ()
(values
(kmrcl:command-output
"~A" "xclip -selection clipboard -o")))
|
Windows用です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import Graphics.Win32.GDI.Clip
import Foreign.Ptr
import Foreign.C.String
main = do { openClipboard nullPtr
; b <- isClipboardFormatAvailable cF_TEXT
; if b
then do { p <- getClipboardData cF_TEXT
; s <- peekCString (castPtr p)
; putStrLn s
}
else return ()
; closeClipboard
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | using System;
class Program {
[STAThread]//クリップボードを利用する場合に必須の属性です。
static void Main(string[] args) {
Console.Write("クリップボードのセットする文字列を入力して下さい。:");
string setStr = Console.ReadLine();//セットする文字列を入力
System.Windows.Forms.Clipboard.SetText(setStr);//クリップボードにセット
string getStr = System.Windows.Forms.Clipboard.GetText();//クリップボードから文字列を取得
Console.WriteLine("クリップボードの内容は\n\n{0}\n\nです。", getStr);
Console.ReadLine();
}
}
|
こちらは、クリップボードへテキストを乗っけるコードです…標準入力とファイルに対応しています…
System.Win32.Mem.globalUnlockってエラーハンドリングにバグがあるようなのでc_GlobalUnlockを使っています…
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 | module Main where
import Control.Monad
import Foreign.Ptr
import Foreign.Storable
import Graphics.Win32.GDI.Types
import Graphics.Win32.GDI.Clip
import Data.Word
import System
import System.IO
import System.Win32.Types
import System.Win32.Mem
when_ f m = when f (m >> return ())
withGlobalAlloc :: GlobalAllocFlags -> DWORD -> (HGLOBAL -> IO (HGLOBAL, a) ) -> IO a
withGlobalAlloc fl cb f = do
h <- globalAlloc fl cb
(h', ret) <- f h
when_ (h' /= nullHANDLE) $ globalFree h
return ret
withGlobalLock :: HGLOBAL -> (Addr -> IO a) -> IO a
withGlobalLock h f = do
addr <- globalLock h
ret <- f addr
c_GlobalUnlock h
return ret
withClipboard :: HWND -> (IO b) -> IO b
withClipboard hwnd fn = do
openClipboard hwnd
ret <- fn
closeClipboard
return ret
publishToClipboard :: HGLOBAL -> IO (HGLOBAL, ())
publishToClipboard h = withClipboard nullHANDLE (setData h)
where
setData h = do
h' <- catch (c_SetClipboardData cF_TEXT h) (\_ -> return nullHANDLE)
return (if h' == nullHANDLE then h else nullHANDLE, ())
copyStr :: String -> Addr -> IO ()
copyStr str pv = zipWithM_ (pokeByteOff pch) [0..] $ str
where
pch = castPtr pv :: Ptr Word8
setTextToClipboard str = withGlobalAlloc gMEM_MOVEABLE (fromIntegral $ length str) $ _setTextToClipboard str
where
_setTextToClipboard :: String -> HGLOBAL -> IO (HGLOBAL, ())
_setTextToClipboard str h = do
withGlobalLock h (copyStr str)
publishToClipboard h
main = do
args <- liftM (take 1) $ getArgs >>= mapM (\path -> openFile path ReadMode)
str <- hGetContents $ head $ args ++ [stdin]
setTextToClipboard str
|
1 2 3 4 | # クリップボードにコピー
「Hello World」をコピー
# クリップボードから取得
クリップボード取得して表示
|
Tkのclipboardコマンドで実現できます。
see: clipboard manual page - Tk Built-In Commands
1 2 3 4 5 | package require Tk
clipboard clear
clipboard append "テキスト"; # 転送
clipboard get; # 取得
#=> テキスト
|
windows用のGUI版の場合です。コンソール版では 「wd」が再定義されていてうまくいきません。 clipcopy 'test test test' clippaste '' test test test
1 2 3 4 5 6 | clipcopy=:3 :0
wd 'clipcopy "',y,'"'
)
clippaste=:3 :0
wd 'clippaste'
)
|
wxPythonのClipboard機能を試してみました。 プラットフォームに依存しないのがウリです。 windows xp, Centos5.1 gnome, Mac OS X Leopardで動作を確認しました。 らくちんすぎます。 コメント: コードは、リンク先にあるwxpython.orgのコードを動くようにしただけです。 解説: 実行するとロードが跳ね上がります。 idle eventをhandleしてそこでTheClipboardの 内容をtext ctrlに貼り付けるだけ。 次のidle eventが処理されるので一瞬に して消えます。
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 | import wx
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title, wx.DefaultPosition, wx.Size(200, 150))
self.text = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.HSCROLL)
wx.EVT_IDLE(self,self.Paste)
def Paste(self, evt):
do = wx.TextDataObject()
success = str(wx.TheClipboard)
if success:
self.text.SetValue(do.GetText())
else:
self.text.SetValue("There is no data in the clipboard in the required format")
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, "Hello from wxPython")
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0)
app.MainLoop()
|
クリップボードの扱いを最初に覚えたDelphiで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | program doukaku188;
{$APPTYPE CONSOLE}
uses
ClipBrd;
var
S: String;
begin
Clipboard.AsText := 'テキスト'; { copy }
S := Clipboard.AsText; { paste }
WriteLn(S);
end.
|
Javaと同じ処理になりますが...。
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 | import java.awt.BorderLayout
import java.awt.Container
import java.awt.Dimension
import java.awt.FlowLayout
import java.awt.Toolkit
import java.awt.datatransfer.Clipboard
import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.StringSelection
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import javax.swing.JButton
import javax.swing.JFrame
import javax.swing.JMenu
import javax.swing.JMenuBar
import javax.swing.JMenuItem
import javax.swing.JPanel
import javax.swing.JTextArea
class SButton(l:String,c:ActionEvent=>Unit) extends JButton with ActionListener {
setText(l)
addActionListener(this)
override def actionPerformed(e:ActionEvent) = c(e)
}
class SMenuItem(l:String,c:ActionEvent=>Unit) extends JMenuItem with ActionListener {
setText(l)
addActionListener(this)
override def actionPerformed(e:ActionEvent) = c(e)
}
class ClipboardFrame(title:String) extends JFrame {
val mb:JMenuBar = new JMenuBar
val fm:JMenu = new JMenu("file")
val em:JMenu = new JMenu("edit")
val c:Container = getContentPane
val t:JTextArea = new JTextArea(20,40);
val p:JPanel = new JPanel;
val clipboard:Clipboard = Toolkit.getDefaultToolkit.getSystemClipboard;
c.setLayout(new BorderLayout)
c.add(t,BorderLayout.CENTER)
p.setLayout(new FlowLayout)
p.add(new SButton("copy",copy))
p.add(new SButton("paste",paste))
c.add(p,BorderLayout.SOUTH)
fm.add(new SMenuItem("quit",quit))
mb.add(fm)
em.add(new SMenuItem("copy",copy))
em.add(new SMenuItem("paste",paste))
mb.add(em)
setJMenuBar(mb)
setResizable(false)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
setTitle(title)
pack
def this() = this("clipboad")
def quit(e:ActionEvent):Unit = {
System.exit(0)
}
def copy(e:ActionEvent):Unit = {
val s:StringSelection = new StringSelection(t.getSelectedText);
clipboard.setContents(s,s);
}
def paste(e:ActionEvent):Unit = {
t.replaceSelection(clipboard.getData(DataFlavor.stringFlavor).asInstanceOf[String])
}
}
object Main extends Application {
(new ClipboardFrame).setVisible(true)
}
|
Mac OS Xには pbcopy, pbpasteの名前でシェルから クリップポードを操作するコマンドが 存在します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/env ruby -wKU
if (ARGV.length != 1)
print "Usage: handle_pb [-show] text\n"
end
if ARGV.include?('-show')
print %x{ pbpaste }
else
ENV['PB_COPY_TEXT'] = ARGV[0]
# デフォルトではpbcopyは日本語の場合Shift-JISしか扱えない
%x{ echo $PB_COPY_TEXT | nkf -s | pbcopy }
end
|
Mac OS Xには pbcopy, pbpasteの名前でシェルからクリップポードを操作するコマンドが存在します。(デフォルトではpbcopy,pbpasteは日本語の場合Shift-JISしか扱えないそうです)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/env ruby -wKU
if (ARGV.length != 1)
print "Usage: handle_pb [-show] text\n"
end
if ARGV[0] == '-show'
print %x{ pbpaste | nkf -w }
else
ENV['PB_COPY_TEXT'] = ARGV[0]
# デフォルトではpbcopyは日本語の場合Shift-JISしか扱えない
%x{ echo $PB_COPY_TEXT | nkf -s | pbcopy }
end
|
#!/usr/bin/ruby -wKSでnkfは取り除けました。 勘違いです。すいません。
#!/usr/bin/ruby -wKSでnkfは取り除けました。 勘違いです。すいません。






mattsan
#6644()
Rating6/8=0.75
クリップボード(や同等の機能)へテキストを転送するプログラムをお願いします。 また可能でしたらクリップボードのデータを取り出すプログラムもお願いします。
システムに依存する内容ですが、応用範囲が広いと思いましたので出題させてもらいました。
[ reply ]