プロが教えるわが家の防犯対策術!

前回質問させていただいたのですが
質問を打ち切ってしまい そのあと試したのですが
うまくいきません。
Window画面に表示はしたくないのです。
クリップボードの画像をファイルに保存したいのですが
以下のソースでどこがおかしいでしょうか

case IDM_SAVE:

hdc = BeginPaint(hWnd, &ps);
if (IsClipboardFormatAvailable(CF_BITMAP))
{
OpenClipboard(hWnd);
hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);

hdc_mem = CreateCompatibleDC(hdc);
SelectObject(hdc_mem, hBitmap);
GetObject(hBitmap,(int)sizeof(bmp_info),&bmp_info);
width=bmp_info.bmWidth;
height=bmp_info.bmHeight;


MessageBox(NULL,"Debug 0","Debug0",MB_OK);
fopen_s(&fpt,"ClipBoard.bmp","wb");

BITMAPINFOHEADER bmih;
BITMAPFILEHEADER bmfh;
//RGBQUAD rgbquad;

DWORD filesize,bmfhsize,bmihsize;
bmfhsize=sizeof(bmfh);
bmihsize=sizeof(bmih);
//rgbquadsize=sizeof(rgbquad);

filesize=bmfhsize+bmihsize+width*height;
::ZeroMemory(&bmfh, bmfhsize);
::ZeroMemory(&bmih, bmihsize);

bmfh.bfType=0x4d42;
bmfh.bfSize=filesize;
bmfh.bfReserved1=0;
bmfh.bfReserved2=0;
bmfh.bfOffBits=bmfhsize+bmihsize;

bmih.biSize=bmihsize;
bmih.biWidth=width;
bmih.biHeight=height;
bmih.biPlanes=1;
bmih.biBitCount=32;
bmih.biClrUsed=2;
bmih.biCompression=BI_RGB;//無圧縮形式
bmih.biSizeImage=0;//BI_RGBをセットした場合、0が好ましいとMSDNに書いてあった。
bmih.biXPelsPerMeter=0;
bmih.biYPelsPerMeter=0;
bmih.biClrImportant=0;

MessageBox(NULL,"Debug 1","Debug1",MB_OK);
fwrite(&bmfh,sizeof(unsigned char),bmfhsize,fpt);
fwrite(&bmih,sizeof(unsigned char),bmihsize,fpt);
MessageBox(NULL,"Debug 2","Debug2",MB_OK);
fwrite(&bmp_info.bmBits,1,3*width*height,fpt);
MessageBox(NULL,"Debug 3","Debug3",MB_OK);

fclose(fpt);
DeleteDC(hdc_mem);
CloseClipboard();
}
EndPaint(hWnd, &ps);

break;



}
break;



画像の先頭アドレスがどこにおさめられているのかが
わかりません
fwrite(&bmp_info.bmBits,1,3*width*height,fpt);
がおかしい様なのですがよくわかりません。

よろしくおねがいします。

A 回答 (2件)

 こんばんは。


 クリップボードから取り出したHBITMAPを、新たに作成したDIBのHBITMAPに複写し、DIBのHBITMAPをセーブに使用します。
 以下は32bitの「screen shot.bmp」を作成します。参考程度に。

static void InitHDR(LPBITMAPINFOHEADER pbmih, DWORD width, DWORD height)
{
pbmih->biSize = sizeof(*pbmih);
pbmih->biPlanes = 1;
pbmih->biCompression = BI_BITFIELDS;
pbmih->biBitCount = 32;
pbmih->biWidth = width;
pbmih->biHeight= height;
}

static void InitFields(LPDWORD p)
{
p[0] = 0xff0000;
p[1] = 0xff00;
p[2] = 0xff;
}

static HBITMAP CreateDIBFrom(HBITMAP hBitmap)
{
LPBITMAPINFO pbmi = static_cast<LPBITMAPINFO>(::calloc(1, sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 3)));

BITMAP bitmap;
::GetObject(hBitmap, sizeof(bitmap), &bitmap);

::InitHDR(&pbmi->bmiHeader, bitmap.bmWidth, bitmap.bmHeight);
::InitFields(reinterpret_cast<LPDWORD>(&pbmi->bmiColors));

LPVOID pvBits = NULL;
HBITMAP hDIB = ::CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pvBits, NULL, 0);
if(hDIB)
{
HDC hDCDest = ::CreateCompatibleDC(NULL);
HDC hDCSrc = ::CreateCompatibleDC(NULL);

::SelectObject(hDCDest, hDIB);
::SelectObject(hDCSrc, hBitmap);

::BitBlt(hDCDest, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hDCSrc, 0, 0, SRCCOPY);

::DeleteDC(hDCDest);
::DeleteDC(hDCSrc);
}

::free(pbmi);
return hDIB;
}

static BOOL SaveDIB(LPSTR strFileName, HBITMAP hBitmap)
{
DIBSECTION dib;
::GetObject(hBitmap, sizeof(dib), &dib);

BITMAPFILEHEADER bmfh = {0};
bmfh.bfType= 0x4d42;
bmfh.bfOffBits= sizeof(bmfh) + sizeof(dib.dsBmih) + sizeof(dib.dsBitfields);
bmfh.bfSize= bmfh.bfOffBits + dib.dsBmih.biSizeImage;

FILE* fp = ::fopen(strFileName, "wb");
if(fp == NULL)return FALSE;

::fwrite(&bmfh, sizeof(bmfh), 1, fp);
::fwrite(&dib.dsBmih, sizeof(dib.dsBmih), 1, fp);
::fwrite(dib.dsBitfields, sizeof(dib.dsBitfields), 1, fp);
::fwrite(dib.dsBm.bmBits, dib.dsBmih.biSizeImage, 1, fp);
::fclose(fp);

return TRUE;
}

//ウィンドウプロシージャの中で、
case IDM_SAVE:
if(!::IsClipboardFormatAvailable(CF_BITMAP))
break;

::OpenClipboard(hWnd);
try
{
HBITMAP hBitmap = static_cast<HBITMAP>(::GetClipboardData(CF_BITMAP));
if(hBitmap == NULL)
throw TEXT("クリップボードからビットマップを取れなかった");

HBITMAP hDIB = ::CreateDIBFrom(hBitmap);
if(hDIB == NULL)
throw TEXT("DIBへの変換に失敗した");

const BOOL bResult = ::SaveDIB("screen shot.bmp", hDIB);

::DeleteObject(hDIB);

if(bResult == FALSE)
throw TEXT("セーブに失敗した");

}
catch(LPCTSTR lpctstrError)
{
::MessageBox(hWnd, lpctstrError, TEXT("失敗しました"), IDOK);
}

::CloseClipboard();
break;
    • good
    • 0
この回答へのお礼

こんばんは
ソースコードありがとうございました。
上記ソースコードで実装したところうまくいきました!
まさにもとめていたものそのものです。
本当にありがとうございました!

お礼日時:2009/10/08 22:02

 こんにちは。



 チョッと今は時間が御座いませんので、手短に書くと、bmp_info.bmBitsがNULLになっているのではないでしょうか。
 クリップボードから取り出したHBITMAPはDDBの筈です。DDBはGetObject()APIで、画像データへのポインタを返さない様になっています。

 クリップボードから取り出したHBITMAPと同じ「width x height」を持つDIBSectionを作成し、BitBltにてビットプロック転送をした後、DIBSectionのHBITMAPから画像データへのポインタを取り出してセーブしてみて下さい。

 その他、パッと見で気付いた点を挙げますと、

(1)
 bmih.biClrUsed=2;
 ではなく
 bmih.biClrUsed=0;

(2)
 bmih.biBitCount=32;
 の時
 bmih.biCompression=BI_BITFIELDS;
 で、RGBQUAD x 3の拡張割り当てと、ビットフィールドの設定が必要です。

 bmih.biBitCount=24;
 の時
 bmih.biCompression=BI_RGB;
 とするのが望ましいです。

(3)
 hdc = BeginPaint(hWnd, &ps);
 EndPaint(hWnd, &ps);
 は不要です。

 と言ったところです。
    • good
    • 0
この回答へのお礼

ご指摘ありがとうございました
大変参考になりましたm(__)m

お礼日時:2009/10/08 22:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!