ウィンドウのビットマップ保存

[戻る]
kool-fox 2008/07/04(金) 16:04:09
お世話になります。

VC6 MFC ダイアログベース

でプログラムを作成しています。

今回教えていただきたいのは、ボタンを押すと画面をキャプチャーしてビットマップで保
存する方法です。
いろいろなサイトでビットマップ保存する仕方が書いてありますが、どこにソースを書き
込めばいいかわかりません。

以下ソースです。
///////////////////////////////////////////////////////
void CPict_line_2Dlg::OnButton4() 
{
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    CDC    *pDC;    // デバイスコンテキスト
    CDC     DCMem;    // メモリデバイスコンテキスト
    HBITMAP    hBitmap;// ビットマップハンドル
    HBITMAP    Soh;    // ビットマップハンドル
    CRect    rect;    // ダイアログ領域

    // ハードコピーするウィンドウを決定する
    CWnd    *pWnd = AfxGetApp()->m_pMainWnd;

    // 指令されたウィンドウの領域を取得する
    pWnd->GetWindowRect(&rect);

    // ディスプレイ デバイスコンテキスト作成
    pDC = pWnd->GetWindowDC();    // 注)GetDC()は、クライアント領域になる
    LPBITMAPINFO    lpbi;
    LPTSTR        lpBits = NULL;

    #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)

    // Fill in the BITMAPINFOHEADER
    lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
    lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    lpbi->bmiHeader.biWidth = rect.Width(); 
    lpbi->bmiHeader.biHeight = rect.Height(); 
    lpbi->bmiHeader.biPlanes = 1;
    lpbi->bmiHeader.biBitCount = 24;
    lpbi->bmiHeader.biCompression = BI_RGB;
    lpbi->bmiHeader.biSizeImage = WIDTHBYTES(rect.Width()) * rect.Height();
    lpbi->bmiHeader.biXPelsPerMeter = 0;
    lpbi->bmiHeader.biYPelsPerMeter = 0;
    lpbi->bmiHeader.biClrUsed = 0;
    lpbi->bmiHeader.biClrImportant = 0;

    hBitmap = CreateDIBSection(pDC->m_hDC, lpbi, DIB_RGB_COLORS, (void **)&lpBits,
NULL, 0);

    // DSPメモリ デバイスコンテキスト作成
    DCMem.CreateCompatibleDC(pDC);
    Soh = (HBITMAP)SelectObject(DCMem.m_hDC, hBitmap);

    // ビットマップ複写
    DCMem.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);

}
///////////////////////////////////////////////////////


よろしくお願いします。

まえだ 2008/07/04(金) 18:50:14
OnButton4()
が分からないってこと?

ドルドル 2008/07/05(土) 00:09:47
 kool-fox さん。
 2点ほど述べさせていただきます。
 
1 GetDIBits()を調べてみてください。あとMFCを使われているので CBitmapクラスな
どで検索すればサンプルとか見つかると思います。

2 ソースみて思ったのですが、ビットマップのファイルフォーマットはご存じです
か?? 例えば下記のdefine定義が意味していること、BITMAPINFOHEADERが表すことなど
です
>  #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)

 もし、そのあたりがご存じないようでしたら、一度ビットマップのファイルフォーマッ
トの調べられることをお勧めします。 保存処理に必要な知識になってきますので。。。
”ビットマップ フォーマット”などで検索すればすぐにでてくると思います。

がんばってください。

kool-fox 2008/07/06(日) 12:57:28
まえだ様、ドルドル様、お返事ありがとうございます。

今回載せたソースは、ネットで調べてコピペしただけのものなので、
プログラムのことは何も分かっておりません、申し訳ありません。

GetDIBits()
CBitmapクラス
ビットマップ フォーマット

この点について調べてみたいと思います。
また分からないことがあったらお聞きしますので、
よろしくお願います。ありがとうございました。

kool-fox 2008/07/07(月) 15:07:09
お世話になります。

調べたところ、このようなソースコードを拾ってきました。

void saveBMP(HWND hwnd,LPCTSTR lpszFn) {

    DWORD dwSize,dwFSize,dwWidth,dwHeight,dwLength;
    HANDLE fh;
    LPBITMAPFILEHEADER lpHead;
    LPBITMAPINFOHEADER lpInfo;
    LPBYTE lpBuf,lpPixel;
    RECT rec;
    HDC hdc,hdcMem;
    HBITMAP hBMP,hOld;

    GetClientRect(hwnd,&rec); /* クライアント領域取得 */

    dwWidth=rec.right;
    dwHeight=rec.bottom;

    if ((dwWidth*3) % 4==0) /* バッファの1ラインの長さを計算 */
    dwLength=dwWidth*3;
    else
    dwLength=dwWidth*3+(4-(dwWidth*3) % 4);

    /* 書き込み用バッファのサイズ計算 */
    dwFSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwLength*dwHeight;

    /* バッファ確保とポインタ設定 */
    lpBuf=(LPBYTE)GlobalAlloc(GPTR,dwFSize);
    lpHead=(LPBITMAPFILEHEADER)lpBuf;
    lpInfo=(LPBITMAPINFOHEADER)(lpBuf+sizeof(BITMAPFILEHEADER));
    lpPixel=lpBuf+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

    /* 24ビットBMPファイルのヘッダ作成 */
    lpHead->bfType='M'*256+'B';
    lpHead->bfSize=dwFSize;
    lpHead->bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
    lpInfo->biSize=sizeof(BITMAPINFOHEADER);
    lpInfo->biWidth=dwWidth;
    lpInfo->biHeight=dwHeight;
    lpInfo->biPlanes=1;
    lpInfo->biBitCount=24;

    /* ウインドウのデバイスコンテキスト取得 */
    hdc=GetDC(hwnd);
    /* ウインドウのデバイスコンテキスト互換のBITMAP作成 */
    hBMP=CreateCompatibleBitmap(hdc,dwWidth,dwHeight);

    /* BITMAPにウインドウのクライアント領域をコピー */
    hdcMem=CreateCompatibleDC(hdc);
    hOld=(HBITMAP)SelectObject(hdcMem,hBMP);
    BitBlt(hdcMem,0,0,dwWidth,dwHeight,hdc,0,0,SRCCOPY);
    SelectObject(hdcMem,hOld);
    GetDIBits(hdc,hBMP,0,dwHeight,lpPixel,(LPBITMAPINFO)lpInfo,DIB_RGB_COLORS);

    ReleaseDC(hwnd,hdc);
    DeleteObject(hBMP);
    DeleteObject(hdcMem);

    /* バッファをファイルに書き出す */
    fh=CreateFile(lpszFn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
    WriteFile(fh,lpBuf,dwFSize,&dwSize,NULL);
    CloseHandle(fh);

    GlobalFree(lpBuf);

}

このあとに、

void CPict_line_2Dlg::OnButton4() 
{
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    saveBMP([描画しているウインドウ].GetSafeHWnd(),"test.bmp");
}

とすれば、保存できそうなのですが、[描画しているウィンドウ]には何を書き込めばいい
かわかりません。
どうかご教授お願いします。

古いスレッドには追加発言できません。