ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年4月27日(土) 16:39

全ての表示時間は UTC+09:00 です




新しいトピックを投稿する  トピックへ返信する  [ 5 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2005年7月19日(火) 00:40 
オフライン

登録日時: 2005年7月17日(日) 09:36
記事: 36
お住まい: 千葉県松戸市
コード:
Dim X As String
X="A"
OpenClipboard(0)
EmptyClipboard()
SetClipboardData(CF_TEXT,VarPtr(X))
CloseClipboard()
これではクリップボードの中身が空のままのようです。何が間違っているのでしょうか?


通報する
ページトップ
投稿記事Posted: 2005年7月19日(火) 06:58 
クリップボードに貼り付けた(内容を指し示す)ポインタは、
プログラムが終了後も有効である必要があります。

しかし、Dim宣言によって確保されたバッファは、
プログラム終了と同時にすべて開放されます(無効になる)。
よってそのバッファのポインタも無効になります。

したがって、クリップボードに渡すポインタ(が表すバッファ)は、
GlobalAlloc()を利用して別途確保する必要があります。

具体的にはこんな感じです。
コード:
Dim X As String 
Dim retAns As Long
X="A" 
retAns = WsSetClipStr( StrPtr( X ) )

End


'クリップボードに文字列を貼り付ける。
Function WsSetClipStr( pBuffer As BytePtr ) As Long
	Dim nSize As Long
	Dim hGlobalMem As DWord
	Dim pGlobalMemForClipText As BytePtr

	'クリップボードを開く
	While ( OpenClipboard(0)=FALSE )
		Sleep (1)
	Wend

	'クリップボードを空にする。
	EmptyClipboard()

	'貼り付ける文字列の大きさを得て、クリップボード用のバッファを確保
	nSize = lstrlen( pBuffer )
	hGlobalMem = GlobalAlloc( GHND Or GMEM_SHARE, nSize + 1 )
	pGlobalMemForClipText = GlobalLock(hGlobalMem)
		pGlobalMemForClipText = lstrcpy( pGlobalMemForClipText, pBuffer )
	GlobalUnlock( hGlobalMem )
	SetClipboardData( CF_TEXT, hGlobalMem )

	'クリップボードを閉じる
	CloseClipboard()

	WsSetClipStr = TRUE
EndFunction

蛇足ですが、クリップボード用のバッファは移動可能メモリである必要が
ある(・・・ほんとか?)ので、GHNDを指定して、操作時はGlobalLock()で
メモリオブジェクトをロックしておく必要があります。


参考までに、7さんがクリップボードの文字列操作用のクラスを作られています。
http://www.discoversoft.net/forum/viewtopic.php?t=54
もしVer4.xを御利用でしたら、そちらを使うのが楽かも知れません。
(私はVer3.x派なもので^^;)
コード:


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年7月20日(水) 09:18 
オフライン

登録日時: 2005年7月17日(日) 09:36
記事: 36
お住まい: 千葉県松戸市
淡幻星様のプログラムでうまくいきました。ありがとうございます。
ただ、ひとつ気になったのが
コード:
hGlobalMem = GlobalAlloc( GHND Or GMEM_SHARE, nSize + 1 )
ここで、GMEM_SHAREという定数がヘルプファイルに載っていなかったのですが、
   GHND Or GMEM_SHARE

   GHND
だけにしても正常に動作しました。GMEM_SHAREという定数はどんなものなのでしょうか。
また、Dim宣言によって確保されたものではクリップボードに貼り付けてもプログラム終了と同時に無効になってしまうとのことですが、次のプログラムは正常に動作しました。
コード:
   Dim hDC As Long
   Dim hBmp As Long
   Dim hOrgDC As Long

   hOrgDC=GetDC(0)
   hDC=CreateCompatibleDC(hOrgDC)
   hBmp=CreateCompatibleBitmap(hOrgDC,100,100)
   SelectObject(hDC,hBmp)
   ReleaseDC(0,hOrgDC)

   '---描画処理---

   OpenClipboard(0)
   EmptyClipboard()
   SetClipboardData(CF_BITMAP,hBmp)
   CloseClipboard()
   DeleteDC(hDC)
   DeleteObject(hBmp)
文字列の場合とビットマップの場合とではクリップボードの使い方が異なるのでしょうか。


通報する
ページトップ
投稿記事Posted: 2005年7月20日(水) 11:10 
オフライン

登録日時: 2005年7月19日(火) 07:02
記事: 183
お住まい: 宮城県
>GHNDだけにしても正常に動作しました。
>GMEM_SHAREという定数はどんなものなのでしょうか。
実は私も GMEM_SHARE は意味もわからず使ってました(サンプルプログラム丸写し/爆)。
ちゃんと調べてみたところ、今時の(正確にはWin95以降?)のWindosであれば、 GHND のみで良いみたいです。私の見たサンプルでは、Windows 3.xやそれ以前との互換性のために GHND Or GMEM_SHARE としてあったみたいです。
ちなみに、
引用:
GMEM_SHARE
ダイナミックデータエクスチェンジ (DDE) 対話のためにDDE 関数が使用するメモリを確保します。Windows 3.x とは異なり、このメモリはグローバルには共有されませんが互換性のために使用できます。
だそうです。spi_system.sbp 内で定義されています。
DDE 関数は、ActiveX の前世の前世とでも思ってください。


>文字列の場合とビットマップの場合とでは
>クリップボードの使い方が異なるのでしょうか。
一緒です(そのはず)。・・・が、おかしいですね。
DeleteObject( hBmp )した時点で消えるのが普通だと思うんですが。
考えられる要因としては、APIを呼び出しているが故かもしれません。
hBmp の指し示すバッファ自体はプログラム側としてはノータッチ(終了時にも開放はされない)ですよね。なのでDeleteObject(hBmp) で明示的に開放してやる必要があるんですが、これはAPIです。よってシステムと強く関連している可能性があります。SetClipboardData( CF_BITMAP, hBmp )をした時点で、hBmp の所有権はシステムに移るので、それゆえにDeleteObject()をしても開放されず、有効のままクリップボードに残るのかもしれません。


デバイスコンテキスト周りは詳しくないので、間違っていたら、ごめんなさい。

そういえば、以前にも
引用:
最終行の「DeleteObject」なのですが、使用した方が良いのでしょうか?
私は、クリップボードの内容であり共有であるため削除してはいけないのでは?と思うのですが、この行を実行してもクリップボードの内容は消えません。
しかもDeleteObjectの戻り値が1になっているようです。
という記事(投稿者hiraさん)がありましたね。このときはこれに対するレスはありませんでしたが、詳しい方いらっしゃいましたら、ぜひお願いします。


通報する
ページトップ
投稿記事Posted: 2005年7月21日(木) 21:42 
オフライン

登録日時: 2005年7月03日(日) 10:37
記事: 27
お住まい: 愛知県岡崎市
> DeleteObject( hBmp )した時点で消えるのが普通だと思うんですが。
GetClipboardData関数(API)の説明を読む限りでは、
どうやらSetClipboardData関数(API)で受けたビットマップハンドルを元に、
グローバルなメモリの領域にコピーしているっぽいですね。
何故にビットマップだけやるのかは疑問ですが..

>
引用:
> 最終行の「DeleteObject」なのですが、使用した方が良いのでしょうか?
> 私は、クリップボードの内容であり共有であるため削除してはいけないのでは?と思うのですが、この行を実行してもクリップボードの内容は消えません。
> しかもDeleteObjectの戻り値が1になっているようです。
>
> という記事(投稿者hiraさん)がありましたね。このときはこれに対するレスはありませんでしたが、詳しい方いらっしゃいましたら、ぜひお願いします。
仕様では、1が返る事自体は問題ありません。
しっかりと削除されています。

が、DeleteObject関数(API)が内部で何をやっているか、ですね。
恐らくそのハンドルの指す場所以降のオブジェクトサイズ分の
メモリブロックを開放しているだけでしょう。
そうなると、たまたま同じアドレスにアクセスすると、
まだまだ見られたりするのかもしれませんね。
※質問内容がクリップボード周りなので、この回答はアテになりませんが..

_________________
# まけイヌ (losedog2)
# Home : http://www50.tok2.com/home/losedog2/
# Mail : losedog2@yahoo.co.jp


通報する
ページトップ
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 5 件の記事 ] 

全ての表示時間は UTC+09:00 です


オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[9人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean