クリップボード



クリップボードとは、異なるプロセス間でのデータのやり取りに使用される保存領域で、テキストのコピーをした時などに格納される場所です。
テキストだけでなく、ビットマップデータ等をやり取りすることも可能です。
hspext.dllにクリップボード関連の命令がいくつかありますが、これをAPIを使ってやってみようと思います。

テキストの場合は、メモリオブジェクトというものを使用しなければなりません。
メモリオブジェクトはデータを持つメモリを一つのオブジェクトとして扱うものです。

まずクリップボード関係のAPIから…

OpenClipboard … クリップボードを開く
(クリップボードを開くウィンドウハンドル)
戻り値:成功すれば1、失敗すれば0。
ウィンドウハンドルは0を指定すれば問題ありません。

EmptyClipboard … クリップボードの中身を初期化
引数なし
戻り値:成功すれば1、失敗すれば0。
クリップボードにデータをセットする場合はその前に必ずEmptyClipboardを呼び出してください。

GetClipboardData … クリップボードからデータを取得
(データ形式)
戻り値:成功すればメモリオブジェクトのハンドル、失敗すれば0。
取得したメモリオブジェクトは解放する必要はありません。

SetClipboardData … クリップボードにデータをセット
(データ形式,
データが格納されているメモリオブジェクトのハンドル)
戻り値:成功すればデータのハンドル、失敗すれば0。
メモリオブジェクトはGlobalAlloc関数で作成します。

CloseClipboard … クリップボードを閉じる
引数なし
戻り値:成功すれば1、失敗すれば0。
開いたら必ず閉じるように。

と、ここまでがクリップボード関係の関数になります。
次に、メモリオブジェクトに関する関数

GlobalAlloc … ヒープからメモリ確保
(メモリ確保の方法,
確保するバイト数)
戻り値:固定メモリの場合はメモリブロックのポインタ、移動可能メモリの場合はメモリオブジェクトのハンドル、失敗すれば0。
ここでは確保の方法にGHNDを指定し、0で初期化した移動可能メモリ領域を作成します。

GlobalLock … メモリオブジェクトを固定(ロック)
(メモリオブジェクトのハンドル)
戻り値:成功すればメモリブロックのポインタ、失敗すれば0。
移動可能メモリオブジェクトのままではアクセスできないので、一時的に固定させます。

GlobalUnlock … メモリオブジェクトの固定(ロック)を解除
(メモリオブジェクトのハンドル)
戻り値:多重ロックがかけられるので、成功した場合は残りロック数、それ以外は0。
再び移動可能に戻します。

GlobalSize … メモリオブジェクトが使用できるバイト数を取得
(メモリオブジェクトのハンドル)
戻り値:成功すれば使用バイト数、失敗すれば0。

GlobalFree … メモリオブジェクトを解放
(メモリオブジェクトのハンドル(固定メモリの場合はメモリブロックのポインタ))
戻り値:成功すれば0、失敗すれば引数がそのまま返る。
今回は使用していません。クリップボードに渡すと解放する必要が無い(というか解放してはいけない)からです。

あともうひとつ

RtlMoveMemory … メモリブロックのコピー
(コピー先メモリブロック開始アドレス,
コピー元メモリブロック開始アドレス, コピーするメモリブロックのバイト数)
戻り値:なし?(どこを見ても戻り値の部分は宣言されてなかったので…)
memcpy命令と似たようなものです。標準命令にはポインタからデータを取得できる命令は無いのでこれを使用しました。

クリップボードから文字列データを取得するには、

OpenClipboardでクリップボードを開く

GetClipboardDataでデータ取得

CloseClipboardでクリップボードを閉じる

GlobalSizeでメモリブロックのバイト数を取得

GlobalLockでメモリオブジェクトをロック

RtlMoveMemoryでメモリブロックをコピー

GlobalUnlockでメモリオブジェクトのロックを解除


という流れになります。
クリップボードに文字列データをセットするには、

GlobalAllocでグローバルメモリオブジェクトを作成

GlobalLockでメモリオブジェクトをロック

RtlMoveMemoryでメモリブロックをコピー

GlobalUnlockでメモリオブジェクトのロックを解除

OpenClipboardでクリップボードを開く

EmptyClipboardでクリップボードの中身を空にする

SetClipboardDataでクリップボードへデータをセット

CloseClipboardでクリップボードを閉じる


となります。
以下サンプル

#include "llmod.as"

#define CF_TEXT 1	;文字列形式
#define CF_BITMAP 2	;ビットマップ形式

#module

#define GHND 0x42	;移動可能メモリ + メモリを0で初期化

#deffunc getclipboard val,int
	mref hobj,16		;クリップボードのデータを格納する数値型変数
	mref format,1		;データ形式
	mref state,64

	prm=0
	dllproc "OpenClipboard",prm,1,D_USER	;クリップボードを開く
	if dllret@=0 : state=1 : return

	dllproc "GetClipboardData",format,1,D_USER	;データ取得
	hobj=dllret@

	dllproc "CloseClipboard",prm,0,D_USER	;クリップボードを閉じる

	if hobj {
		state=0
	} else {
		state=2
	}
return

#deffunc setclipboard val,int
	mref hobj,16		;クリップボードにセットするデータ
	mref format,1		;データ形式
	mref state,64

	prm=0
	dllproc "OpenClipboard",prm,1,D_USER	;クリップボードを開く
	if dllret@=0 : state=1 : return

	dllproc "EmptyClipboard",prm,0,D_USER	;クリップボードの中身を初期化

	prm=format,hobj
	dllproc "SetClipboardData",prm,2,D_USER	;クリップボードにデータをセット

	dllproc "CloseClipboard",prm,0,D_USER	;クリップボードを閉じる

	state=0
return

#deffunc getmemobj val,val,int
	mref data,24	;データを格納する文字列型変数
	mref memsize,17	;メモリサイズ
	mref hobj,2	;メモリオブジェクトハンドル
	mref state,64

	dllproc "GlobalSize",hobj,1,D_KERNEL	;メモリブロックのバイト数
	if dllret@=0 : state=1 : return
	if dllret@>memsize : memsize=dllret@ : state=2 : return
	memsize=dllret@

	dllproc "GlobalLock",hobj,1,D_KERNEL	;メモリを固定
	cbdata=dllret@

	getptr pdata,data
	prm=pdata,cbdata,memsize
	dllproc "RtlMoveMemory",prm,3,D_KERNEL	;メモリブロックのコピー

	dllproc "GlobalUnlock",hobj,1,D_KERNEL	;メモリの固定を解除

	state=0
return

#deffunc setmemobj val,val,int
	mref hobj,16	;メモリオブジェクトハンドルを格納する変数
	mref data,25	;メモリオブジェクトに格納するデータ
	mref memsize,2	;メモリサイズ

	prm=GHND,memsize
	dllproc "GlobalAlloc",prm,2,D_KERNEL	;メモリオブジェクト作成
	hobj=dllret@

	dllproc "GlobalLock",hobj,1,D_KERNEL	;メモリを固定
	cbdata=dllret@

	getptr pdata,data
	prm=cbdata,pdata,memsize
	dllproc "RtlMoveMemory",prm,3,D_KERNEL	;メモリブロックのコピー

	dllproc "GlobalUnlock",hobj,1,D_KERNEL	;メモリの固定を解除
return

#global

	screen 0,200,100

	sdim txt,1000
	objmode 1,1
	mesbox txt,200,80,1,1000
	objsize 100,20
	button "クリップボードへコピー",*set
	pos 100,80 : button "クリップボードを取得",*get
	stop

*set
	strlen length,txt
	setmemobj hglobal,txt,length+1	;+1は終了コードの分
	setclipboard hglobal,CF_TEXT
	if stat : dialog "クリップボードを開けませんでした"
	stop

*get
	getclipboard hglobal,CF_TEXT
	if stat=1 : dialog "クリップボードを開けませんでした" : stop
	if stat=2 : dialog "データ形式が文字列ではありません" : stop

	memsize=1000
	getmemobj txt,memsize,hglobal
	if stat=1 : dialog "メモリオブジェクトではありません" : stop
	if stat=2 : dialog "データサイズが1000バイトを超えています。",,""+memsize+"B" : stop
	objprm 0,txt
	stop

実行して、「クリップボードを取得」ボタンを押すと、クリップボードの文字列をエディットボックスに表示します。
「クリップボードへコピー」ボタンを押すとエディットボックスに書かれている文字列をクリップボードへコピーします。
定義した命令は、

getclipboard … クリップボードからデータを取得
(取得したデータを格納する数値型変数,
取得するデータ形式)
データ形式は文字列の場合はCF_TEXT(=1)を指定してください。
またシステム変数statに結果を返します。
stat=0 : 正常に取得できました
stat=1 : クリップボードを開けませんでした
stat=2 : データ形式が違います


setclipboard … クリップボードへデータをセット
(セットするデータを格納した数値型変数,
セットするデータ形式)
データ形式は文字列の場合はCF_TEXT(=1)を指定してください。
システム変数statに結果を返します。
stat=0 : 正常にセットできました
stat=1 : クリップボードを開けませんでした


getmemobj … メモリオブジェクトからデータを取得
(取得したデータを格納する文字列型変数,
変数のメモリサイズを格納した変数,
メモリオブジェクトハンドル)
文字列形式の場合はメモリオブジェクトで送られてくるので、この命令でオブジェクトのデータを取得することが出来ます。
第1引数のメモリサイズが足りない場合、statに2を返し、第2引数の数値型変数に必要なメモリサイズが返ります。
システム変数statに結果を返します。
stat=0 : 正常取得
stat=1 : メモリオブジェクトではありません(サイズが0の時)
stat=2 : データのサイズが文字列変数のメモリサイズより大きいです


setmemobj … メモリオブジェクトを作成
(メモリオブジェクトハンドルを格納する数値型変数, メモリオブジェクトに格納するデータを持つ文字列型変数, メモリサイズ)
第2引数のデータを持つメモリオブジェクトを作成します。
クリップボードに文字列を送る場合はメモリオブジェクトでなければならないのでこれを使用してください。
システム変数statに結果を返します。

クリップボードにはさまざまな種類のデータがセットできるので、この命令だけでは対応できないかもしれません。
ビットマップの場合は直接ビットマップハンドルが送られてくるので、メモリオブジェクトあれこれは必要なかったりします。


戻る 次へ