クリップボードの文字列操作

オープンソース形式でコードを共有するフォーラムです。お役立ちコード、あなたも投稿してみませんか?
返信する
メッセージ
作成者
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

クリップボードの文字列操作

#1 投稿記事 by 7 »

コード: 全て選択

Declare Function IsClipboardFormatAvailable Lib "user32.dll" (ByVal wFormat As Long) As Long
Class CClipboard
Protected
	c_hWnd As HWND
Public
	Sub CClipboard(ByVal hWnd As HWND)
		c_hWnd=hWnd
	End Sub

	Function clear() As Long
	clear=FALSE
		If OpenClipboard(c_hWnd) Then
			EmptyClipboard()
			CloseClipboard()
			clear=TRUE
		End If
	End Function

	Function setText(ByVal lpString As BytePtr) As Long
	Dim hMem As HGLOBAL
	Dim lpStr As BytePtr
	setText=FALSE
		hMem=GlobalAlloc(GHND,lstrlen(lpString)+1)
		If hMem Then
			lpStr=GlobalLock(hMem)
			If lpStr Then
				lstrcpy(lpStr,lpString)
				GlobalUnlock(hMem)
				If OpenClipboard(c_hWnd) Then
					EmptyClipboard()
					SetClipboardData(CF_TEXT,hMem)
					CloseClipboard()
					setText=TRUE
				End If
			End If
			GlobalFree(hMem)
		End If
	End Function

	Function getText() As BytePtr
	Dim hMem As HGLOBAL
	getText=NULL
		If IsClipboardFormatAvailable(CF_TEXT) Then
			If OpenClipboard(c_hWnd) Then
				hMem=GetClipboardData(CF_TEXT)
				getText=GlobalLock(hMem)
				GlobalUnlock(hMem)
				CloseClipboard()
			End If
		End If
	End Function
End Class
ちゃんと投稿出来るかな…。
ハイテク過ぎてよく分かりません。

コード: 全て選択

Dim cpBrd As CClipboard(NULL)
	cpBrd.setText("setText")
	MessageBox(0,cpBrd.getText(),"getText",MB_OK)
	cpBrd.clear()
tom

Re: クリップボードの文字列操作

#2 投稿記事 by tom »

7サン
こんにちは,tomです.

>Function clear() As Long
はEmptyClipboard()だだけではおかしくならないですか?
SetClipboardDataも使用しないとうまくいかなかったような・・・

>Function setText(ByVal lpString As BytePtr) As Long
のGlobalFree(hMem)は,使用しては駄目だったような気がします.

両方うろ覚えですみません(^^;;
tak
記事: 162
登録日時: 2005年5月31日(火) 07:49

Re: クリップボードの文字列操作

#3 投稿記事 by tak »

> >Function clear() As Long
> はEmptyClipboard()だだけではおかしくならないですか?
> SetClipboardDataも使用しないとうまくいかなかったような・・・
僕の環境ではEmptyClipboard()を呼び出した時点でクリップボードはクリアされました。
カーネルが違えば動作も違うかもしれないので、確実なことは言えませんが・・・

> >Function setText(ByVal lpString As BytePtr) As Long
> のGlobalFree(hMem)は,使用しては駄目だったような気がします.
確か、CloseClipboard()を呼び出してクリップボードの所有者がなくなればGlobalFree()でメモリ領域をシステムに返還しなければならなかったとおもいます。

僕の方こそうろ覚えなのですが(爆)
tom

Re: クリップボードの文字列操作

#4 投稿記事 by tom »

takさん
こんばんは,tomです

> 僕の環境ではEmptyClipboard()を呼び出した時点でクリップボードはクリアされました。
> カーネルが違えば動作も違うかもしれないので、確実なことは言えませんが・・・
クリアはされるのですが,その後のクリップボード関連が変?になったと思います.

> 確か、CloseClipboard()を呼び出してクリップボードの所有者がなくなればGlobalFree()でメモリ領域をシステムに返還しなければならなかったとおもいます。
あら,そうでしたか(^^;
クリップボードの場合はGlobalFree()をしないで後ろに任せるようにしていました.

> 僕の方こそうろ覚えなのですが(爆)
本当に私もうろ覚えで申し訳ないです.
結構前にクリップボードを試しただけなので(^^;;
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: クリップボードの文字列操作

#5 投稿記事 by イグトランス »

> > >Function setText(ByVal lpString As BytePtr) As Long
> > のGlobalFree(hMem)は,使用しては駄目だったような気がします.
> 確か、CloseClipboard()を呼び出してクリップボードの所有者がなくなればGlobalFree()でメモリ領域をシステムに返還しなければならなかったとおもいます。
>
> 僕の方こそうろ覚えなのですが(爆)

私もTomさんの方が正しいと思います。実際Microsoftのサンプルでもそうなっていますし。
http://msdn.microsoft.com/library/en-us ... pboard.asp
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

Re: クリップボードの文字列操作

#6 投稿記事 by 7 »

> 私もTomさんの方が正しいと思います。実際Microsoftのサンプルでもそうなっていますし。
GlobalFree()してはいけないんですね。
クリップボードに文字列が設定された場合GlobalFree()しないように、setText()関数を書き換えました。

コード: 全て選択

	Function setText(ByVal lpString As BytePtr) As Long
	Dim hMem As HGLOBAL
	Dim lpStr As BytePtr
	setText=FALSE
		hMem=GlobalAlloc(GHND,lstrlen(lpString)+1)
		If hMem Then
			lpStr=GlobalLock(hMem)
			If lpStr=NULL Then
				GlobalFree(hMem)
			Else
				lstrcpy(lpStr,lpString)
				GlobalUnlock(hMem)
				If OpenClipboard(c_hWnd) Then
					EmptyClipboard()
					SetClipboardData(CF_TEXT,hMem)
					CloseClipboard()
					setText=TRUE
				End If
			End If
		End If
	End Function
クリップボードの初期化についてですが(clear)、以前C++のコードで見たのをIf文を交えて再現しました。

コード: 全て選択

OpenClipboard(0)
EmptyClipboard()
CloseClipboard()
ですので、問題が有るのか分かりません…。
とりあえず、自分はクリップボードが変になることにはなっていません。
実はsetImg()関数も有ったんですが、その時はクリップボードを使おうとしたら「クリップボードの内容が可笑しい」というエラーダイアログは出ましたが…。
ゲスト

Re: クリップボードの文字列操作

#7 投稿記事 by ゲスト »

> クリップボードの初期化についてですが(clear)、以前C++のコードで見たのをIf文を交えて再現しました。
>

コード: 全て選択

OpenClipboard(0)
> EmptyClipboard()
> CloseClipboard()
> ですので、問題が有るのか分かりません…。
> とりあえず、自分はクリップボードが変になることにはなっていません。
> 実はsetImg()関数も有ったんですが、その時はクリップボードを使おうとしたら「クリップボードの内容が可笑しい」というエラーダイアログは出ましたが…。

すみません,初期化の方は私の勘違いだと思います(^^;
お手数かけました<(_ _)>
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

getText() As BytePtr の部分で

#8 投稿記事 by 淡幻星 »

テストしてないので恐縮なのですが、
(Ver4.xはまだインストールしてません^^;)

Function getText() As BytePtr
の部分で
getText=GlobalLock(hMem)
ってしてますけど、GlobalUnlock()された時点で、
getText As BytePtrの有効性は不確実なものになる上に、
CloseClipboard()によって他のアプリからのアクセスが許可されるので、
getText As BytePtrが実際に利用される前に、
クリップボードの中身が書き換えられる危険性がありませんか?

そんなわけで、getText()には、有効なバッファを引数で渡すか、

コード: 全て選択


Function getText( pBuffer As BytePtr ) As Long
	Dim hMem As HGLOBAL
	Dim pRowClip As BytePtr
	getText=FALSE
	If IsClipboardFormatAvailable(CF_TEXT) Then
		If OpenClipboard(c_hWnd) Then
			hMem = GetClipboardData( CF_TEXT )
				pRowClip = GlobalLock( hMem )
				lstrcpy( pBuffer, pRowClip )
			GlobalUnlock(hMem)
			CloseClipboard()
			getText = TRUE
		End If
	End If
End Function
もしくは、String型を利用した方が良いと思うのですが、どうでしょうか?

コード: 全て選択


Function getText() As String
	Dim hMem As HGLOBAL
	Dim pRowClip As BytePtr
	getText=""
	If IsClipboardFormatAvailable(CF_TEXT) Then
		If OpenClipboard(c_hWnd) Then
			hMem = GetClipboardData( CF_TEXT )
				pRowClip = GlobalLock( hMem )
				getText = pRowClip ' BytePtr型→String型の代入はlstrcpy()動作となるはず・・・。⇔逆は単純にポインタのコピー(たぶん)。
			GlobalUnlock(hMem)
			CloseClipboard()
		End If
	End If
End Function
・・・勘違いだったらすいません。
「違うよ」って言う方いらっしゃいましたら、ぜひ指摘ください。
私もよくわかっていませんので<GlobalLock周り。
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

#9 投稿記事 by 7 »

自分も負けじと書いてみました。
「クリップボードの文字列操作」から離れて「クリップボードの操作」にしてしまった方が良いのかも...ということで以下のようになりました。
クリップボードビューアのことは考えていません。
返信する