MFCでJPEG画像を表示するプログラムの初期化方法について

このQ&Aのポイント
  • MFCでJPEG画像を表示するプログラムの初期化方法について教えてください。
  • 現在はOnPaint()関数内でCreateCompatibleDC関数を使用して初期化を行っていますが、PreCreateWindow関数などの初期化関数内に移したいと考えています。
  • また、CreateCompatibleDC関数を再描画のたびに呼び出すことも試しましたが、異常終了してしまいます。スマートな初期化方法をご教示いただけないでしょうか?
回答を見る
  • ベストアンサー

CreateCompatibleDCを初期化時にしたい(MFC)

MFCでJPEG画像を表示するプログラムを OnPaint() の中に書いていたのですが・・・  : bool m_bImageMemDCInit; CImage m_Image; CBitmap *m_pImageBitmap; CDC m_ImageMemDC;  :  : void CChildView::OnPaint() {  CPaintDC dc(this);  if(!m_bImageMemDCInit){   m_bImageMemDCInit = true;   // イメージをロード   m_Image.Load("test.jpg");   m_pImageBitmap = CBitmap::FromHandle(m_Image);   m_ImageMemDC.CreateCompatibleDC(&dc);   m_ImageMemDC.SelectObject(m_pImageBitmap);  }  // 描画  dc.BitBlt(0, 0, 256, 256, &m_ImageMemDC, 0, 0, SRCCOPY); } このように、Load や CreateCompatibleDC などの初期化にあたる処理を、起動時に1度しか処理しないように書いています。 しかし、このプログラムではあまりに汚い。どうにかして PreCreateWindow などの初期化関数内に書きたいのですが、CreateCompatibleDC 関数で CPaintDC* を渡す必要があるので、OnPaint 関数内に書かざるを得ないのです。 (Loadだけなら初期化関数内に移せるのですが・・・) いっそ CreateCompatibleDC を再描画のたびに呼んでもいいのでは? と思い、やってみると異常終了してしまいました。 また、CPaintDC dc(this); を PreCreateWindow 関数内に書いても異常終了しました。 どなたかスマートな方法をご存知でしたら、ご指導願います m(_ _)m

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

PreCreateWindowで CPaintDC(this)としてもエラーになるのは当然です CPaintDCはウィンドウハンドルを必要とします しかし PreCreateWindowではまだウィンドウハンドルは作成されていません # ウィンドウ作成の前処理なので当然ですが ・・・ WM_CREATEメッセージに対するイベントハンドラOnCreateかCreateで処理します OnCreateでやるなら int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) {   if (CView::OnCreate(lpCreateStruct) == -1)     return -1;   // TODO: ここに特定な作成コードを追加してください。   return 0; } といったスケルトンを VC++が作成してくれるので TODOコメントの部分で DCの初期化処理を行いましょう int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) {   if (CView::OnCreate(lpCreateStruct) == -1)     return -1;   // TODO: ここに特定な作成コードを追加してください。   m_Image.Load("test.jpg");   m_pImageBitmap = CBitmap::FromHandle( m_Image );   CClientDC dc(this);   m_ImageMemDC.CrateCompatibleDC( &dc );   m_ImageMemDC.SelectObject( m_pImageBitmap );   return 0; } といった具合です 本来は m_ImageMemDC.SelectObject( m_pImageBitmap ) の戻り値も記憶しておいて m_ImageMemDCを破棄する際に選択を元に戻すのがセオリーです

jeddom
質問者

お礼

うまくいきました、ありがとうございます!

関連するQ&A

  • クライアント領域をCBitmapに取り込みたい

    VC6.0MFCで クライアント領域(みたまま)を CBitmapに取り込みたいのですがどうすればよいのでしょうか? ためしにダイアログの領域をクリップボードに取り込むコード OnPaint書いたのですが真っ黒の画像しか取り込めていませんでした。 根本的に使うAPIが違うのでしょうか? void CCaptureDlg::OnPaint() {  CPaintDC dc(this); // 描画用のデバイス コンテキスト  CRect cr;  GetClientRect(&cr);  dc.TextOut(0,0,"テスト");  CDC* pDC = new CDC();  pDC->CreateCompatibleDC(&dc);  CBitmap img;  img.CreateCompatibleBitmap(pDC, cr.Width(), cr.Height());  OpenClipboard();  ::EmptyClipboard();  ::SetClipboardData(CF_BITMAP, img.GetSafeHandle());  ::CloseClipboard();  pDC->DeleteDC();  delete pDC;  CDialog::OnPaint(); }

  • 非クライアント領域への描画について

    非クライアント領域に文字を書こうとしました。 以下の(2)では書けますが、(1)では書いてくれません。 CPaintDCはクライアント領域でないとダメなのですか? void CMainFrame::OnPaint() { CPaintDC dc(this); // 描画用のデバイス コンテキスト dc.TextOut(0,0,"こんにちは"); ・・・(1) CDC* pDC = GetWindowDC(); pDC->TextOut(100,0,"こんにちは"); ・・・(2) 環境 WIN98 VC++6.0 MFC

  • CStaticコントロールの静的イメージ描画

    はじめまして、質問させてください。 VC++ 2005 MFC で開発しております。 Picture Control(DDX CStasic型)に イメージ(外部ファイル JPG)を静的に描画させたいのですが 方法がわかりません。 お詳しい方がおられましたら、ご教授お願いいたします。 ちなみに CImageを使用して描画はできるのですが その場合、OnPaintをオーバーライドして 描画更新処理を書かないと一度だけ描画されて終わって しまうと思います。 CStaic変数にロードしたら 再度ロードされるまで ずっと描画させていたいです。 以上になります。 宜しくお願いいたします。

  • MFC XPでのTextOutのボヤケについて

    はじめまして。 質問させてください。 CImageを使用して OnPaint( )でBMP画像を描画するアプリを作成しております。 仕様といたしまして ダイアログのDC部にBMPを全体に描画して RGB( 255, 255, 255 )を透明化(背景が完全に見える)する ようにしております。 OnInitDialog( )で透過、透明処理をしています。 OnPaint( )で PaintDC PDC; //背景を透過 PDC.SetBkMode( TRANSPARENT ); PDC.SetTextColor( RGB( 255, 0, 0 ) ); PDC.SetBkColor( RGB( 255, 255, 255 ) ); PDC.TextOutW( 100, 100, _T( "TEST" ) ); 上記のように実装して、EXEで実行して確認しますと Windows2000の場合、正常に文字(TEST)が赤字で描画されるのですが WindowsXPの場合、赤字で描画されるのですが文字の周りがぼやけてしまいます。 イメージとしては文字描画部分が 2000の場合、BMP表示 XPの場合、JPG表示 のようになります。 これは仕様なのでしょうか? それとも何かコードレベルで解決できるのでしょうか? お詳しい方がおりましたらご教授お願いいたします。 よろしくお願いいたします。

  • MFC C++

    MFCでソリューションを新規作成した時に作られるプログラムにちょこちょこと手を加えています。 以下のプログラムは、画面の中心に黒い円を描くプログラムの一部です。 void CChildView::OnPaint() { CPaintDC dc(this); // 描画のデバイス コンテキスト CRect rect; GetClientRect(&rect); CPoint center = rect.CenterPoint(); const int sizeCircle = 60; CSize offset(sizeCircle / 2, sizeCircle / 2); CSize size(sizeCircle, sizeCircle); CRect rectCircle(center - offset, size); CBrush brush(RGB(0, 0, 0)); CBrush* pBrushOrg = dc.SelectObject(&brush); dc.Ellipse(rectCircle); dc.SelectObject(pBrushOrg); } どなたか以下のことを教もらえないでしょうか。 (1)CSize size(sizeCircle, sizeCircle);の部分ですが、size()はCSizeのメンバ変数ではないと思うのですが、size()の型がCSizeになっているのはどうしてでしょうか? (2)上の続きで、size()関数は見る限りどこにも定義されていなかったのですが、どこかに元々定義があるのでしょうか?(元々というのは、Microsoft側で定義してくれているということです。) (3)dc.Ellipse(rectCircle);の部分で、dc.とはどういう意味でしょうか? どなたかお願いします。

  • MFCでネガポジ変換

    以下のプログラムはネガポジ変換をするプログラムです。MFCで最初に作られるプロジェクトのCChildView.cppのOnPaint関数に実装しました。デバッグするとウィンドウ全体が真っ黒になるはずです。が、なぜか添付のファイルのように白黒の縞模様になってしまします。ちなみに私はVC++2008を使っています。知人にも相談して、VC++2005で全く同じプログラムで試してもらいましたが、そちらではウィンドウが真っ黒になって成功しました。違いはおそらく2008か2005かということだけ何のです。 何か原因をご存知の方がいらしたら教えてもらえないでしょうか。 void CChildView::OnPaint() { CPaintDC dc(this); // 描画のデバイス コンテキスト int w = dc.GetDeviceCaps(HORZRES); //DCの幅を得る int h = dc.GetDeviceCaps(VERTRES); //DCの高さを得る int i, j; for(j=0; j<h; j++) { for(i=0; i<w; i++) { //DCの(i,j)位置から色を得る COLORREF c = dc.GetPixel(i, j); //色を取得 if(c!=CLR_INVALID) { //反転したr,g,b値を取得 int r = 255- GetRValue(c); int g = 255- GetGValue(c); int b = 255- GetBValue(c); c = RGB(r, g, b); //その画素を置く dc.SetPixel(i, j, 0); } } } }

  • ちらつきについて

    ゲームをつくっているのですが、画面がちらつくのが気になり、直そうと、ネットで調べたのですが、裏画面に一度、ビットマップを表示させて、それをデバイスコンテキストに転送する?ってやりかたがよくわかりません。 CMyFrameWnd::OnPaint(){ CPaintDC dc(this); CDC MemDC; CBitmap bitmap1; bitmap1.LoadBitmap("IDB_BITMAP1"); ...略 for(j=0;j<30;j++){ for(k=0;k<30;k++){ MemDC.SelectObject(&bitmap1); dc.Blt(j*32,k*32,32,32,&MemDC,0,0,SRCCOPY); } } } 見たいな感じです。なにぶんc,c++始めたばっかりでデバイスコンテキストとかもよくわかってないんでわかりやすい説明お願いします。

  • ビットマップに描画をしてピクチャーコントロールに貼り付けるためには?

    ビットマップに描画をしてピクチャーコントロールに貼り付けるためには どうすればよいでしょうか? ネットで検索しましたそして、 下のようなコードを書きましたがうまくゆきません。 void CXXXView::OnButton() { CStatic m_ctlImage; // ピクチャーボックスに関連付けした変数 CBitmap m_bmpImage; // ピクチャーボックスに貼り付けるイメージ CDC m_dcImage; // Bitmap描画用のDC CDC* pDC = m_ctlImage.GetDC(); m_dcImage.CreateCompatibleDC(pDC); CRect Cltsz; picture1.GetClientRect(&Cltsz); m_bmpImage.CreateCompatibleBitmap(pDC,Cltsz.Width(),Cltsz.Height()); CBitmap* pOld=m_dcImage.SelectObject(&m_bmpImage); CPen myPEN(PS_SOLID,5,RGB(0,0,255)); CPen* oldPEN=m_dcImage.SelectObject(&myPEN); m_dcImage.MoveTo(10,10); m_dcImage.LineTo(100,100); m_dcImage.SelectObject(oldPEN); m_dcImage.SelectObject(pOld); m_ctlImage.SetBitmap(m_bmpImage); } この様にしましたが、ピクチャーコントロールには 何も描画されません、 何故でしょうか? VS2005で、ボタンをクリックした イベントで描画する場合です、 直線とかは、問題なく描画できました。 ビットマップに描画して貼り付けたいのです、 よろしくお願いします

  • 地図の上にL字スケールを描画

    MDIフレーム上に、複数のチャイルドスタイルのダイアログが存在するプログラムを改造しました。(元は別の人間が作成) その中にMapDKIVの地図を描画しているダイアログがあり、その地図上に別のダイアログをおき、そこに縮尺L字スケールのビットマップを描画しました。(MapDKIVには、その機能がまだ無い為) 色々と試行錯誤した結果、この方法を取ったのですが、納品した矢先、お客様から、地図をマウスでドラッグして動かそうとすると、スムーズに動いたり、カクカクとしか動かなかったり、時には全く動かない事があるとのクレームがありました。(その操作以外は正常に動作している模様) 以前はこの症状はなかったとの事から、今回のL字スケール描画に原因があるのではと調べていますが、原因が見付かりません。 以下に、ソースの一部分を記載しますので、どなたか助言をお願いします。 ******** ビットマップデータ管理クラス ******** ビットマップは、スケール毎に準備 <BitmapData.h> private: CBitmap m_bmpLScale0; CBitmap m_bmpLScale2; <BitmapData.cpp> //-------- 機能 ビットマップ情報の読込 -------- void CBitmapData::Load(void) { m_bmpLScale0.LoadBitmap(IDB_BITMAP_SCALE0); // 全国図 m_bmpLScale2.LoadBitmap(IDB_BITMAP_SCALE2); // 1/160万 //-------- 機能 ビットマップ情報の取得 -------- CBitmap& CBitmapData::GetScaleBitmap(void) { UINT unIndex = GetScaleNumber();// 現在選択されているスケールレベル switch(unIndex) { case 0:  return m_bmpLScale0; break; // 全国図 case 2:  return m_bmpLScale2; break; // 1/160万 ******** 地図描画ダイアログ ******** L字スケール描画用ダイアログの生成 <MainMap.cpp> // 地図描画フレームサイズを取得 m_ctrlMapFrame.GetWindowRect(LPRECT(rect)); // スケールレベルをセット g_BitmapData.SetScaleNumber(m_ctrlMapZoom.GetPos()); // スケール描画用ダイアログの生成(地図フレームの左下位置を渡す) m_pMapScaleDlg = new CMapScaleDlg(); m_pMapScaleDlg->Create(m_hWnd, IDD_MAP_SCALE_DIALOG, ・・・ ******** L字スケール描画ダイアログ ******** //-------- 機能 OnInitDialog() -------- // ウインドウ拡張スタイルをレイヤード設定 lStyle = GetWindowLong( this->m_hWnd, GWL_EXSTYLE ); lStyle |= 0x00080000; SetWindowLong( this->m_hWnd, GWL_EXSTYLE, lStyle ); // レイヤードウィンドウの不透明度と透明のカラーキーを設定(青色部分を透明化する) SetLayeredWindowAttributes( this->m_hWnd, RGB(0,0,255), 100, 0x00001/*LWA_COLORKEY*/ ); //-------- 機能 OnPaint() -------- BITMAP bitmap; CBitmap& mBitmap = g_BitmapData.GetScaleBitmap(); mBitmap.GetBitmap(&bitmap); CSize sz(bitmap.bmWidth, bitmap.bmHeight); CDC dc; dc.CreateCompatibleDC(&PaintDC); CBitmap *pOld = dc.SelectObject(&mBitmap); // もともとのディバイスコンテキストにビットマップを透過で転送(青色部分を透明化する) if( ::TransparentBlt(PaintDC, 0, 0, sz.cx, sz.cy, dc, 0, 0, sz.cx, sz.cy, (UINT)RGB(0,0,255)) == FALSE ){ } // ビットマップ選択解除 dc.SelectObject( pOld); } //-------- 機能 スケール(ビットマップ)変更メッセージを受信 -------- // 現在選択されているスケール用のビットマップを取得(ポインタ) CBitmap& mBitmap = g_BitmapData.GetScaleBitmap(); mBitmap.GetBitmap(&bitmap); CSize sz(bitmap.bmWidth, bitmap.bmHeight); // メインマップダイアログの地図フレームの左下になるよう変更 this->MoveWindow(m_nMapFrameLeft, (m_nMapFrameBottom - sz.cy), sz.cx, sz.cy); // ウインドウの再描画 this->Invalidate(); 1.L字スケール描画用のダイアログを、背景青色で準備 2.L字スケール描画用のダイアログの青色部分を透明化に設定 3.L字スケール描画用のダイアログのウインドウサイズを、選択されているスケール用のビットマップと同じサイズに、且つ、地図フレームの左下に位置を設定 4.地図ダイアログからスケール変更メッセージを受信  (1) その時に選択されているスケール用のビットマップと同じサイズに、且つ、地図フレームの左下に位置を設定  (2) ウインドウの再描画 this->Invalidate() 5.OnPaint()  (1) 現在選択されているスケールのビットマップ情報を取得  (2) ビットマップを透過で転送(青色部分を透明化)    ビットマップのL字以外の部分は青色 以上、文字数制限の為、かなり省略していますが、大変困っています。 とにかく助言を頂きたく、よろしくお願いします。

  • dc.TextOut(0 ,0 , *str) ;について

    環境 WIN98 VC++6.0 MFC にて パターンBはOKですが、パターンAだと不正な処理で落ちてしまいます。 どうしてなのかお教えください。 void CFffView::OnPaint() { CPaintDC dc(this); //パターンA CString* str ; str = (CString*)("999"); dc.TextOut(0 ,0 , *str) ; //パターンB CString aaa ; aaa = (CString)("999"); dc.TextOut(0 ,0 , aaa) ; }