ビットマップをクリップボードにセット – プログラミング – Home

ビットマップをクリップボードにセット
 
通知
すべてクリア

[解決済] ビットマップをクリップボードにセット


お茶
 お茶
(@お茶)
ゲスト
結合: 21年前
投稿: 42
Topic starter  

クリップボードにCreateDIBSection()で作成したHBITMAPを送りたいのですが、
うまくいきません。
クリップブック(CLIPBRD.EXE)では
「現在の形式の情報は表示されないか、またはメモリ不足のため情報が表示されません」
と出ます。
実際、Paintに貼り付けようとするとエラーが出ます。
クリップボードに送るコードは以下のようになっています。

BITMAPINFO bmpInfo;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = 32;
bmpInfo.bmiHeader.biHeight = 32;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biSizeImage = 32 * 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;

DWORD *pBits;
HDC hdc = GetDC(hWnd);
HBITMAP hBitmap = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS,
(void **)&pBits, NULL, 0);
ReleaseDC(hWnd, hdc);

ZeroMemory(pBits, sizeof(DWORD)*32*32);

OpenClipboard(hWnd);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBitmap);
CloseClipboard();

ご覧の通り、32bppの32*32の黒く塗りつぶしたイメージを送ってます。
この程度のサイズ、メモリ不足とは考えられません。
一体何が原因なのでしょうか?

環境はWinXP SP2 + VC++6.0SP6 MFC未使用です。


引用未解決
トピックタグ
とおりすがり
 とおりすがり
(@とおりすがり)
ゲスト
結合: 23年前
投稿: 180
 

CreateDIBSectionはよく知らないが、検索した使い方となんか違うような気がする。
CreateDIBSectionでぐぐってあなたの使い方と比較してみたらいいのでは?

確認だけどCreateDIBSectionがうまく動くかどうか、試してないってことはないよね。


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

> bmpInfo.bmiHeader.biBitCount = 32;
> bmpInfo.bmiHeader.biSizeImage = 32 * 32;

32 * 32 ドットの画像で、各ドット 4 バイト(32ビット)ならば、SizeImage は 32 *
32 * 4 では?


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

あと、BITMAPINFO::bmiColors には色情報が入って無くてもいいんだっけ?


返信引用
お茶
 お茶
(@お茶)
ゲスト
結合: 21年前
投稿: 42
Topic starter  

お二人とも、ありがとうございます。

> 32 * 32 ドットの画像で、各ドット 4 バイト(32ビット)ならば、SizeImage は 32
> * 32 * 4 では?

あ、確かにそうですね。
でも実はCreateDIBSectionはBI_RGBの場合、サイズは必要ないようです。
実際、上で作ったHBITMAPをCompatibleDCにSelectObjectして確認しております。

実は問題はそこではなく、DIBの場合はSetClipboardData()にCF_DIBで渡さなければ
いけないようです。(もちろんGetClipboardData()もCF_DIBで受け取ります)

という訳で問題は無事解決いたしました。

どうもありがとうございました。


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

> でも実はCreateDIBSectionはBI_RGBの場合、サイズは必要ないようです。

そうなの?
じゃあ、確保するメモリのサイズは何を元に決まるのかしら?

> DIBの場合はSetClipboardData()にCF_DIBで渡さなければいけないようです

そうなの?
CF_DIB は BITMAPINFO 構造体をセットするように見えるんだけど。

http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/winui/winui/windowsuserinterface/dataexchange/clipboard/clipboardformats.asp


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

> でも実はCreateDIBSectionはBI_RGBの場合、サイズは必要ないようです。

というか、現状、32 * 32 * 1、つまり1bpp モノクロビットマップになってない?
黒1色だからいいようなものの、3色以上だと破綻しない?


返信引用
お茶
 お茶
(@お茶)
ゲスト
結合: 21年前
投稿: 42
Topic starter  

> そうなの?
> じゃあ、確保するメモリのサイズは何を元に決まるのかしら?

サイズはBITMAPINFOHEADERのWidthとHeightとBitCountから求められます。
MSDNにも

> Specifies the size, in bytes, of the image. This may be set to zero for
> BI_RGB bitmaps.

とあります。

CF_DIBですが、BITMAPINFOHEADERの直後にビットデータを置きます。
送るデータはHGLOBALです。
よってこんな感じになります。

HGLOBAL = GlobalAlloc(GHND | GMEM_SHARE,
sizeof(BITMAPINFOHEADER) + 32 * 32 * sizeof(DWORD));

BITMAPINFOHEADER *pBmpInfoHeader = (BITMAPINFOHEADER *)GlobalLock(hGlobal);
ZeroMemory(pBmpInfoHeader, sizeof(BITMAPINFOHEADER));
pBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
pBmpInfoHeader->biWidth = 32;
pBmpInfoHeader->biHeight = 32;
pBmpInfoHeader->biPlanes = 1;
pBmpInfoHeader->biBitCount = 32;
pBmpInfoHeader->biCompression = BI_RGB;

DWORD *pBits = (DWORD *)(pBmpInfoHeader + 1);
for(int y=0; y<32; ++y){
for(int x=0; x<32; ++x) pBits[y*32+x] = (red << 16) + (green << 8) + blue;
}

GlobalUnlock(hGlobal);

if(OpenClipboard(GetHWND()) != 0){
EmptyClipboard();
SetClipboardData(CF_DIB, hGlobal);
CloseClipboard();
}

これでOKです。
まぁ、上下反転してますけど・・・


返信引用
お茶
 お茶
(@お茶)
ゲスト
結合: 21年前
投稿: 42
Topic starter  

あ、分かると思いますが一応修正。

> HGLOBAL = GlobalAlloc(GHND | GMEM_SHARE,
> sizeof(BITMAPINFOHEADER) + 32 * 32 * sizeof(DWORD));

HGLOBAL hGlobal = GlobalAlloc(GHND | GMEM_SHARE,
sizeof(BITMAPINFOHEADER) + 32 * 32 * sizeof(DWORD));


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

> サイズはBITMAPINFOHEADERのWidthとHeightとBitCountから求められます。

これは失礼いたしました。

> CF_DIBですが、BITMAPINFOHEADERの直後にビットデータを置きます。
> 送るデータはHGLOBALです。

あ、CreateDIBSection 使うのやめちゃったんだ。


返信引用
お茶
 お茶
(@お茶)
ゲスト
結合: 21年前
投稿: 42
Topic starter  

> あ、CreateDIBSection 使うのやめちゃったんだ。

はい、結局CreateDIBSection()で作ったHBITMAPをクリップボードに送る手段は不明で
す。(DDBに変換すればよさそうですが・・・)

上の方法は代替案ですが、今回はこれでOKです。
ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました