• ベストアンサー

ダイアログの表示と同時に、ピクチャーボックスを塗る方法

あるサイトの過去ログで以下を見つけました。 エラーは出ませんが、何も起こりません。 このコードは何をしようとしているのでしょうか? ************************* ダイアログ上にピクチャーボックスを配置して、ダイアログの表示と同時に、ピクチャーボックスを塗る方法。 まず、ピクチャコントロールをClassWizardのメンバ変数タブによりm_pictureとして実態を作成します。 その後、 class CPictureDlg { private: CBitmap m_bitmap; // ... }; BOOL CPictureDlg::OnInitDialog() { CDialog::OnInitDialog(); // ... CDC desktopDC; desktopDC.Attach ( ::GetDC ( NULL ) ); CDC memDC; memDC.CreateCompatibleDC ( &desktopDC ); m_bitmap.CreateCompatibleBitmap ( &desktopDC, 100, 100 ); CBitmap *pOldBitmap = memDC.SelectObject ( &m_bitmap ); CRect rcPicture ( 0, 0, 100, 100 ); CBrush brush; brush.CreateStockObject ( WHITE_BRUSH ); memDC.FillRect ( &rcPicture, &brush ); memDC.SelectObject ( pOldBitmap ); m_picture.SetBitmap ( ( HBITMAP ) m_bitmap.GetSafeHandle () ); ReleaseDC ( &desktopDC ); memDC.DeleteDC (); }

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

  • ベストアンサー
noname#5537
noname#5537
回答No.2

ピクチャボックスのタイプが「ビットマップ」になってますか? ダイアログエディタで,ピクチャボックスの「プロパティ」を見てください。 # ウィンドウスタイルで言えば SS_BITMAP です。 そのコードは直接ピクチャボックスを塗っているわけではありません。 まずビットマップを作成し, 作成したビットマップをピクチャボックスにセットする(m_picture.SetBitmap のところ)コードです。 ピクチャボックスのタイプが「ビットマップ」になっていれば, セットしたビットマップを表示してくれます。 タイプが「ビットマップ」でなければ何もおこりません。

参考URL:
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vclib/html/_mfc_cstatic.3a3a.setbitma
VitaminBB
質問者

お礼

回答ありがとうございます。 プロパティをビットマップにすることで、ちゃんと白色でピクチャーボックスが塗りつぶされました。 今一つこのコードがなにをしているのか分かりません。 (結果は分かりましたが。) 申し訳ありませんが、各行が何をしているのが、ざっくりの殴り書きで良いので教えていただけないでしょうか?

その他の回答 (4)

noname#5537
noname#5537
回答No.5

#4 の訂正です。最後のほうが意味不明になってますね。 > CDC のデストラクタでは DeleteObject が呼ばれるようになっているので, > 結局,GetDC(NULL) で取得した DC に対して,DeleteObject を呼ぶことになってしまいます。 DeleteObject ではなくて,DeleteDC の間違いでした。

noname#5537
noname#5537
回答No.4

まず #3 で書いたコードについてですが, CreateCompatibleBitmap にメモリ DC を渡したのがいけなかったようです。 # MSDN によると,メモリ DC を渡した場合,モノクロのビットマップが作成されます。 冒頭部分を以下のように変更してください。 CClientDC dc(this); CDC memDC; memDC.CreateCompatibleDC(&dc); m_bitmap.CreateCompatibleBitmap(&dc, 100, 100); > Attachは何をしているのでしょうか? CDC::Attach はデバイスコンテキストのハンドル(HDC 型)を, CDC のオブジェクトに結び付けます。 ::GetDC(NULL) で画面全体を表す DC を取得していますが,戻り値はハンドル(HDC 型)です。 しかしながら,CreateCompatibleDC や CreateCompatibleBitmap には CDC* を渡さなければならないので, desktopDC.Attach で,desktopDC(CDC 型)にハンドル(HDC 型)を結び付けているのでしょう。 ただ,元のコードには少し問題があります。 CDC のデストラクタでは DeleteObject が呼ばれるようになっているので, 結局,GetDC(NULL) で取得した DC に対して,DeleteObject を呼ぶことになってしまいます。 # 実際には DeleteDC が失敗するだけなので実害はないようですが。

VitaminBB
質問者

お礼

いろいろ親切にありがとうございました。 PGはコードの変更にて問題無く動きました。 Attachについては相変わらず良く分かりません。 yoppiiさんはオブジェクトに結びつけると説明されています。 その他本で調べても、Attach関数でアタッチする。と書いてあり結局Attachそのものの意味は分かりませんでした。 前後のコードなどから分かるべきなのでしょうが、今回はまだ実力不足ということで諦めます。

noname#5537
noname#5537
回答No.3

元のコードと若干変えてあります。 // メモリ DC (デバイスコンテキスト)を作成する CDC memDC; memDC.CreateCompatibleDC(NULL); // ビットマップを作成する m_bitmap.CreateCompatibleBitmap(&memDC, 100, 100); // 作成したビットマップをメモリ DC で選択 // 以後 memDC に描画した結果が m_bitmap に反映されるようになる CBitmap *pOldBitmap = memDC.SelectObject(&m_bitmap); // ここで,memDC のメンバ関数を用いて描画する。例えば, memDC.FillSolidRect(0, 0, 100, 100, RGB(255,255,0)); // 黄色一色に塗る // ビットマップの選択を元に戻す(m_bitmap は選択から外れる) memDC.SelectObject(pOldBitmap); // 作成したビットマップをピクチャボックスにセットする m_picture.SetBitmap((HBITMAP)m_bitmap.GetSafeHandle());

VitaminBB
質問者

お礼

回答ありがとうございます。 yoppiiさんの若干変えられたコードでは、エラーは出ませんが、何も描かれませんでした。 また、自分でも色々調べているのですが、一番分からないコードが desktopDC.Attach ( ::GetDC ( NULL ) ); です。 Attachは何をしているのでしょうか? 何度も済みませんが、お分かりでしたらお教えください。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

Windowsのメッセージについて勉強しなおしましょう。 WM_CREATEや、WM_INITDIALOGのタイミングでは、ウィンドウはまだ表示されていません。 この状態で描画を行っても表示されていないので意味がありません。 Windowsから、描画を行うタイミングで送られるメッセージがWM_PAINTです。 もちろん、ウィンドウが表示されようとしているときにも送られてくるので描画処理はここで問題ありません。 OnDrawやOnPaintがWM_PAINTに対応するメッセージハンドラになります。 描画した絵がちらつくとかいう話であれば、別ですが。

VitaminBB
質問者

お礼

回答ありがとうございます。 OnPaintでもやってみましたが、何も起こりませんでした。

関連するQ&A

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

    ビットマップに描画をしてピクチャーコントロールに貼り付けるためには どうすればよいでしょうか? ネットで検索しましたそして、 下のようなコードを書きましたがうまくゆきません。 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で、ボタンをクリックした イベントで描画する場合です、 直線とかは、問題なく描画できました。 ビットマップに描画して貼り付けたいのです、 よろしくお願いします

  • ビューにビットマップファイルを描画する方法

    MFCのプログラムで(マルチウィンドウ)ビュー上に指定したビットマップファイルをオープンして描画したいと思ってます。 Bitmapリソースを指定して描画する方法はわかりましたが、ビットマップファイル名を指定して、そのファイルをオープンしてビュー上に描画する方法はどのようすればよいのでしょうか? 今は以下のようにOnDraw()内で以下のように実装しています。 -------------------------------------------------------- CBitmap kaitaGazou; kaitaGazou.LoadBitmap(IDB_BITMAP1); CDC MemDC; MemDC.CreateCompatibleDC(pDC); CBitmap *pTmpBitmap; pTmpBitmap = MemDC.GetCurrentBitmap(); MemDC.SelectObject(&kaitaGazou); pDC->BitBlt(0, 0, 100, 100, &MemDC, 10, 10, SRCCOPY); MemDC.SelectObject(pTmpBitmap); kaitaGazou.DeleteObject(); --------------------------------------------------------

  • VisualC++6.0にてボタンにビットマップを表示させる方法

    VisualC++6.0のダイアログベースのアプリにおいて、 フォーム上に配置したボタン上にビットマップを表示 させたいと思ってます。OnPaint()の中で、以下のコード を書いたのですが、うまくいきません。  CWnd* myWnd = GetDlgItem(IDC_BUTTON1);  CDC* pDC = myWnd->GetDC();  CDC myDC;  CBitmap myBMP;  myBMP.LoadBitmap(IDB_BITMAP);  myDC.CreateCompatibleDC(pDC);  CBitmap* oldBMP = myDC.SelectObject(&myBMP);  pDC->BitBlt(0,0,100,100,&myDC,0,0,SRCCOPY);  myDC.SelectObject(oldBMP); ビットマップはちゃんと書かれてはいますが、その上にボタンが 描かれてしまうので、ビットマップが隠されてしまいます。 解決方法を教えてくださいますでしょうか。 よろしくお願いします。 % 絵をクリックするとアクションを起こすようにしたいので、 % ピクチャーボックスでも試してみました。これだとビット % マップはちゃんと表示されますが、BN_CLICKEDを書いて % ピクチャーボックスをクリックしてもOnPict()に処理が % 移りません。

  • Visual C++のStretchBltについて

    こんにちは VC++で壁紙チェンジャーのプログラムを作成していたのですが、壁紙画像をStretchBltをつかってプログラムの中に表示させたいのですが、pDCをつかって呼び出すさいpDC->StretchBlt();の括弧ないは何を記述すればよいのですか?わかるかたいたらご指導ください。参考までに前後の文 OnPaint 省略 else { CRect ClientRect; GetClientRect(ClientRect); BITMAP BMP; HBITMAP h_BMP=(HBITMAP)LoadImage(AfxGetApp()->m_hInstance,_T(m_filename), IMAGE_BITMAP,0,0,LR_LOADFROMFILE); CDC* pDC=this->GetDC(); CDC MemDC; MemDC.CreateCompatibleDC(pDC); HBITMAP h_OLD_BMP=(HBITMAP)::SelectObject(MemDC.m_hDC,h_BMP); ::GetObject(h_BMP,sizeof(BITMAP),&BMP); //////////////////////////////        ここ→pDC->StretchBlt(); ////////////////////////////// ::SelectObject(MemDC.m_hDC,h_OLD_BMP); MemDC.DeleteDC();

  • ダイアログにビットマップを貼り付けた時にフリーズしてしまう

    お世話になります、fujicafeです。 現在、MFCにてダイアログベースのアプリケーションを作成中なのですが、ダイアログにビットマップを貼り付けてOnPaint()で表示するようにプログラムを作成したのですが、何度かダイアログの表示を繰り返すとOnPaintでのビットマップの読み込みが途中まででフリーズしてしまう現象が起きてしまいました。 プログラムは以下のように作成しています void C****Dlg::OnPaint() {  CDC* pDC = this->GetDC(); CDC myDC; CBitmap newbitmap; CBitmap* oldbitmap; CRect rc; GetClientRect(rc); newbitmap.LoadBitmap(IDB_BITMAP); myDC.CreateCompatibleDC( pDC ); oldbitmap=myDC.SelectObject( &newbitmap ); pDC->BitBlt( 0, 0, rc.Width(), rc.Height(), &myDC, 0, 0, SRCCOPY ); myDC.SelectObject(oldbitmap); } としています。 初めにこのダイアログを表示時は、ちゃんとビットマップが表示されるのですが、他のダイアログでこのダイアログを表示させた時にビットマップが上半分まで表示されて、動作がフリーズしてしまう現状です。 なにかよい打開策がありましたら、教えていただけたらと思っています。宜しくお願いいたします。

  • ちらつきについて

    ゲームをつくっているのですが、画面がちらつくのが気になり、直そうと、ネットで調べたのですが、裏画面に一度、ビットマップを表示させて、それをデバイスコンテキストに転送する?ってやりかたがよくわかりません。 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++始めたばっかりでデバイスコンテキストとかもよくわかってないんでわかりやすい説明お願いします。

  • VC++ダイアログボックスの表示更新がわかりません

    現在ダイアログボックスにスタティックコントロールを配置し、表示更新する際不明な点があります。VC6.0 MFCです。 1、ダイアログボックス上のコントロールに、作成したビットマップを表示させる際、OnInitDialog関数内で、Bitbiltしていますが、表示されません。 ボタンクリックイベント等で、同様の手順でBitbiltすると表示されます。 これはなぜなのでしょうか? また、ダイアログボックスが表示された際にBitmapを表示するにはどうすればよいでしょうか? 2、また、表示されたBitmapはダイアログボックスを動かしたり、隠れたりすると消えてしまいます。 再表示を自動的にさせるにはどうすればよいでしょうか?(OnDraw関数のようなものがあるのでしょうか?) 初歩的な質問で申し訳ありませんが、よろしくお願いいたします。

  • CImage::ReleaseDC()のエラーで困っています。

    CImage::ReleaseDC()のエラーで困っています。 ウインドウ上に複数の画像を表示し、それぞれ配置や大きさを マウスのD&Dで変えられるようなアプリを作っています。 Visual Studio 2005 C++, MFC 画像はCImageクラスのm_ImageへLoadしてあります。 GetDCでハンドルを取得しているので、ReleaseDCにて開放を 行っていますが、そこで下のエラーになります。 [Second Chance Assertion Failed: File c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlimage.h, Line 1217] 何か解決のヒントになる事がありましたら教えてください。 void CImageButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { (前略) //ウィンドウDC互換Bitmap作成 CBitmap Bmp; Bmp.CreateCompatibleBitmap(pDC, nWidth, nHeight); //メモリDC作成 CDC MemDC; MemDC.CreateCompatibleDC(pDC); //メモリDCにBitmap選択 MemDC.SelectObject(&Bmp); //メモリDCにストレッチ描画 MemDC.SetStretchBltMode(HALFTONE); CDC* pImgDC = CDC::FromHandle(pBtnInfo->m_Image.GetDC()); HDC hImgDC = pImgDC->m_hDC; pBtnInfo->m_Image.StretchBlt(MemDC.m_hDC, 0, 0, nWidth, nHeight, SRCCOPY); pBtnInfo->m_Image.ReleaseDC(); (中略) //四角形を描画 CPen focusPen(PS_DOT, nPenWidth, RGB(nR, nG, nB)); CPen* OldPen = MemDC.SelectObject(&focusPen); MemDC.MoveTo(btnRect.left, btnRect.top); MemDC.LineTo(btnRect.left, btnRect.bottom); MemDC.LineTo(btnRect.right, btnRect.bottom); MemDC.LineTo(btnRect.right, btnRect.top); MemDC.LineTo(btnRect.left, btnRect.top); MemDC.SelectObject(OldPen); //メモリDCからウィンドウDCにビット転送 pDC->BitBlt(0, 0, nWidth, nHeight, &MemDC, 0 ,0, SRCCOPY); (後略)

  • ピクチャとHBITMAP

    はじめまして。 VC.net winXPでプログラムの勉強をしてるんですが、 裏画面(メモリDC?)の処理がうまくできません。 ピクチャのプロパティをビットマップにしてOnInitDialogで HBITMAPにLoadimageで読み込み 関連しているCstaticにsetbitmapをしてビットマップの表示をしています。 さらにその上にMoveToやらLineToやらで線を引いているんですが、 ウィンドウが隠れた後等の再描画時に引いた線が消えてしまいます。 それを回避する為に裏画面のHBITMAPに描画し、 それをBitBlt等を使ってピクチャに転送すれば良いような事はわかったのですが、 うまくそれを実現する事ができません。 ソースの一部は以下の通りです。 void CtestpictDlg::OnBnClickedDraw()//コマンドボタンを押した時に処理 { //m_StaticPictureにはOnInitDialogでSetBitmap(m_hBmp)として //ビットマップのセットがしてあり、ダイアログを見るとちゃんと表示されている。 CDC dc; CString str; CWnd *h = GetDlgItem(IDC_STATICPICTURE); CDC *hdc = h->GetDC();//ピクチャのDCを取得 dc.CreateCompatibleDC(hdc); HBITMAP test=CreateCompatibleBitmap(hdc->m_hDC,256,256); //ピクチャからビットマップを初期化 HBITMAP* oldbmp = (HBITMAP*)dc.SelectObject(&test); //dcにビットマップを割り当て CPen p(PS_SOLID,1,RGB(0,255,0)); CPen* oldp = (CPen*)dc.SelectObject(&p); dc.MoveTo(10,10); dc.LineTo(100,100);//とりあえず斜めに線を引けるように。 //m_StaticPicture.SetBitmap(test);//ここでtestを見てみると真っ黒な256*256の画像 BitBlt(hdc->m_hDC,0,0,256,256,dc.m_hDC,0,0,SRCCOPY); //UpdateData(FALSE);必要かどうかわからない… //以下に開放処理等 } まだ勉強し始めて日が浅いので、 ちぐはぐな事をしているかもしれませんがよろしくお願いします。

  • オブジェクトの削除について

    環境 WIN98 VC++6.0 MFC にて オブジェクトを使い終わってから削除している場合としていない場合が有るのですが、どうしてなのですか? 作ったオブジェクトはなんでもかんでも削除したほうが無難な気がしますが、本にのっているコードで削除してない場合も良く見かけます。 <削除していない>//著名な本のコード void Cxxx::OnDraw(CDC* pDC) {  CBitmap bmp;  bmp.LoadBitmap(nID);  略  //bmp.DeleteObject(); //■この記述が無い } <削除している>//ネット上でみかけたコード void CMainFrame::_SetBmp(CWnd* pBox,int nID,int  width,int height) // 単品 {  CDC* pDC=pBox->GetDC();  CDC memDC;  CBitmap bmp;  bmp.LoadBitmap(nID);  memDC.CreateCompatibleDC(pDC);  CBitmap* pOldBmp=memDC.SelectObject(&bmp);  pDC->BitBlt(0,0,width,height,&memDC,0,0,SRCCOPY);  memDC.SelectObject(pOldBmp);  bmp.DeleteObject();  memDC.DeleteDC(); }

専門家に質問してみよう