お世話になります。
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);
}
///////////////////////////////////////////////////////
よろしくお願いします。
OnButton4()
が分からないってこと?
kool-fox さん。
2点ほど述べさせていただきます。
1 GetDIBits()を調べてみてください。あとMFCを使われているので CBitmapクラスな
どで検索すればサンプルとか見つかると思います。
2 ソースみて思ったのですが、ビットマップのファイルフォーマットはご存じです
か?? 例えば下記のdefine定義が意味していること、BITMAPINFOHEADERが表すことなど
です
> #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
もし、そのあたりがご存じないようでしたら、一度ビットマップのファイルフォーマッ
トの調べられることをお勧めします。 保存処理に必要な知識になってきますので。。。
”ビットマップ フォーマット”などで検索すればすぐにでてくると思います。
がんばってください。
まえだ様、ドルドル様、お返事ありがとうございます。
今回載せたソースは、ネットで調べてコピペしただけのものなので、
プログラムのことは何も分かっておりません、申し訳ありません。
GetDIBits()
CBitmapクラス
ビットマップ フォーマット
この点について調べてみたいと思います。
また分からないことがあったらお聞きしますので、
よろしくお願います。ありがとうございました。
お世話になります。
調べたところ、このようなソースコードを拾ってきました。
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);
}
とすれば、保存できそうなのですが、[描画しているウィンドウ]には何を書き込めばいい
かわかりません。
どうかご教授お願いします。