ディスク上のビットマップをピクチャーボックスへ表示
【ピクチャーボックスのバンドル取得】
リソース管理された画像を標準の手順でピクチャーボックスへ出力するためには、
CDC* pDC = m_pict.GetDC();
CDC myDC;
CBitmap myBMP;
myBMP.LoadBitmap(IDB_BITMAP_MORI);
myDC.CreateCompatibleDC(pDC);
CBitmap* oldBMP = myDC.SelectObject(&myBMP);
pDC->BitBlt(0,0,256,256,&myDC,0,0,SRCCOPY);
といった記述を使います。GetDC()で取得したCDC型のデバイスコンテキストを出発先
指定に使います。とこらが今、記述しようとしている方法ではAPI関数を使うので、
HBITMAP myDIB; //ビットマップのハンドル
HDC hDC; //デバイスコンテキストのハンドル
HDC hCompatiDC; //メモリデバイスコンテキスト
PAINTSTRUCT ps; //クライアント領域の描画に使う情報を保持
hDC = ::GetDC(m_hWnd);
::BeginPaint(m_hWnd, &ps);
hCompatiDC = ::CreateCompatibleDC(hDC);
myDIB = ::CreateDIBitmap(hDC, &m_BmpInfo->bmiHeader,
CBM_INIT, m_BmpImage, m_BmpInfo, DIB_RGB_COLORS);
::SelectObject(hCompatiDC, myDIB);
BitBlt(hDC, 5, 30, m_BmpInfo->bmiHeader.biWidth,
m_BmpInfo->bmiHeader.biHeight, hCompatiDC, 0, 0, SRCCOPY);
::EndPaint(m_hWnd, &ps);
のように、HDC型のハンドルであるhDCを使います。ここで2GetDC関数を比較する
と次のようになります。
MFC : CDC* GetDC(); //CWnd::GetDCの書式
API : HDC GetDC(HWND hWnd); //API関数であるGetDCの書式
このように、戻り値に違いがあります。そこで、MFCを使って
CDC* pDC = m_pict.GetDC();
で求めたpDCは使用できません。正しい処理をするためには、
CDC*型のpDCからHDC型のハンドルを取り出す
という作業が必要です。従って、以下のように記述することでHDC型のハンドルを
取得できます。
HDC hDC;
hDC = m_pict.GetDC()->GetSafeHdc();
(備考)
GetSafeHdc関数 : デバイスコンテキストからハンドルを取得
【サンプル・ソース】
//-----------------------------------------
public:
char* m_BmpImage;
LPBITMAPINFO m_BmpInfo;
BITMAPFILEHEADER m_BmpFileHdr;
COpenviewsapDlg::COpenviewsapDlg(CWnd* pParent /*=NULL*/)
: CDialog(COpenviewsapDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(COpenviewsapDlg)
// メモ: この位置に ClassWizard によってメンバの初期化が追加されます。
//}}AFX_DATA_INIT
// メモ: LoadIcon は Win32 の DestroyIcon のサブシーケンスを要求しません。
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
//---------------------------------------------
m_BmpInfo = NULL;
m_BmpImage = NULL;
}
void COpenviewsapDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 描画用のデバイス コンテキスト
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// クライアントの矩形領域内の中央
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// アイコンを描画します。
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
//--------------------------------------------------------
HBITMAP myDIB; //ビットマップのハンドル
HDC hDC; //デバイスコンテキストのハンドル
HDC hCompatiDC; //メモリデバイスコンテキスト
PAINTSTRUCT ps; //クライアント領域描画用
//-------------------------------
//画像の準備ができれいるかの判定
if(!m_BmpInfo)return;
//--------------------------------------------------------------------------
//ピクチャーボックスへの出力(ID = IDC_PICT としメソッド変数を m_pict と設定)
hDC = m_pict.GetDC()->GetSafeHdc();
//--------------------------------------------------
//画像の描画準備
//描画が終了したら必ずEndPaintを実行する必要がある
::BeginPaint(m_hWnd,&ps);
//---------------------------------------------------
//hDCと互換性のあるメモリデバイスコンテキストを作成
hCompatiDC = ::CreateCompatibleDC(hDC);
//-------------------------------------------------------------
//DIB形式ビットマップからDDB(デバイス依存)形式ビットマップ作成
myDIB = ::CreateDIBitmap(hDC,&m_BmpInfo->bmiHeader,
CBM_INIT,m_BmpImage,m_BmpInfo,DIB_RGB_COLORS);
//--------------------------------------------------
//hCompatiDCでmyDIBの示すオプションを使用可能にする
::SelectObject(hCompatiDC, myDIB);
//-------------------------------------------------
//hCompatiDCにある画像をhDCに表示する
BitBlt(hDC,0,0,m_BmpInfo->bmiHeader.biWidth,
m_BmpInfo->bmiHeader.biHeight,hCompatiDC,0,0,SRCCOPY);
//------------------------------------------------
//BeginPaint対応処理(描画の後はEndPaintが必要)
::EndPaint(m_hWnd,&ps);
//----------------------------------
//オブジェクトの解放
::DeleteObject(myDIB);
::DeleteObject(hCompatiDC);
::ReleaseDC(m_hWnd,hDC);
}
}
void COpenviewsapDlg::OnButton1()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
CString filename;
CFile file;
BITMAPINFOHEADER myBmpInfoHdr;
//ファイルダイアログを表示してファイル指定する
CFileDialog myDLG(TRUE,NULL,NULL,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
"ビットマップ(*.BMP)|*.BMP||");
if(myDLG.DoModal() != IDOK)return;
//取得したファイルをオープンする
filename = myDLG.GetPathName();
if(!file.Open(filename,CFile::modeRead|CFile::typeBinary)){
return;
}
//タイトルバーにファイル名を表示する
SetWindowText(filename);
//ファイルヘッダ部とインフォヘッダ部を読み込みます
file.Read(&m_BmpFileHdr,sizeof(BITMAPFILEHEADER));
file.Read(&myBmpInfoHdr,sizeof(BITMAPINFOHEADER));
//前回を使用していれば、一旦メモリを解放する
if(m_BmpInfo) delete[] m_BmpInfo;
//色情報を取得する
//biBitCountは1ビクセルあたりのカラー表現ビット数
//1,4,8,16,24,32がある。数字が大きいほど情報表現が可能
//16ビット以上と未満でカラーデータ格納が異なる
if(myBmpInfoHdr.biBitCount >= 16){
m_BmpInfo = (LPBITMAPINFO)new char[sizeof(BITMAPINFO)];
}
else{
m_BmpInfo = (LPBITMAPINFO)new char[sizeof(BITMAPINFOHEADER) +
(1 << myBmpInfoHdr.biBitCount) * sizeof(RGBQUAD)];
file.Read(m_BmpInfo->bmiColors,
(1 << myBmpInfoHdr.biBitCount) * sizeof(RGBQUAD));
}
//m_BmpInfo(LPBITMAPINFO型)のmyBmpInfoHdrメンバに設定
m_BmpInfo->bmiHeader = myBmpInfoHdr;
//ファイル内のビットマップ実データ言いに合わせる
file.Seek(m_BmpFileHdr.bfOffBits,CFile::begin);
//前回の画像イメージを一旦解放
if(m_BmpImage) delete[] m_BmpImage;
//実画像データ分のバイト数を確保
//bfsizeビットマップ・ファイル全サイズ
//bfOffBits先頭にあるヘッダ情報サイズ
m_BmpImage = new char[m_BmpFileHdr.bfSize - m_BmpFileHdr.bfOffBits];
//ビットマップ実データを読み込み格納
file.Read(m_BmpImage,m_BmpFileHdr.bfSize - m_BmpFileHdr.bfOffBits);
file.Close();
//再描画表示
Invalidate();
}