DOBON.NET DOBON.NETプログラミング掲示板過去ログ

ピクチャーボックスに描画

分類:[(未選択)]

ダイアログにピクチャーボックスをつけそしてボタンもつけました
このボタンを押すとメニューの開くと同じ動きをし画像ファイルを選択させ
そのフルパスを取得するようにしてるのですがこの開くで得たフルパスの
画像をピクチャーボックスに描画させるにはどうすればいいのでしょうか。
■No4620に返信(renさんの記事)
> ダイアログにピクチャーボックスをつけそしてボタンもつけました
> このボタンを押すとメニューの開くと同じ動きをし画像ファイルを選択させ
> そのフルパスを取得するようにしてるのですがこの開くで得たフルパスの
> 画像をピクチャーボックスに描画させるにはどうすればいいのでしょうか。

すいません 書き忘れてました
VC++ 6.0
MFC
OS:windows ME
renさんこんにちは。
BMP限定で、BMP実寸表示でよいのであれば以下のようにすれば表示可能です。

ピクチャBOXのプロパティをビットマップにする。
ClassWizardでピクチャBOXのコントロール変数を追加。(例ではm_pctbox)

m_pctbox.SetBitmap((HBITMAP)::LoadImage(::AfxGetInstanceHandle(),_T("ファイル名.BMP"),IMAGE_BITMAP,0,0,LR_LOADFROMFILE));

BMP以外のファイル表示および拡大縮小等お考えでしたら、GDIPlusを使うか
サードパーティの画像処理ライブラリ等使用したほうが楽ですよ〜
SDIで生成したのですが

ピクチャーボックスの変数をm_picとしダイアログのクラスとしてPICをつくりました
pahtは開くからえたフルパスです。

HBITMAP hbit = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), path,
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);

m_ga.Attach(hbit);

として
OnDrawに
Pic dlg;
dlg.m_pic.SetBitmap(m_ga);
としたのですが

Debug Assertion Failed

とエラーがでました
renさん、こんばんは。

> HBITMAP hbit = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), path,
> IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
>
> m_ga.Attach(hbit);
ここで別のオブジェクトにアタッチする必要はありません。
ここでPictureBoxにSetBitmapしてあげればいいだけです。
上記はダイアログクローズしたタイミングですよね?
であれば、ここで1度画像をセットしてあげればあとは何も
しなくてもPictureBoxが描画、再描画してくれます。

私も昔理解するのに手間取ったのでざっくり概念を書きますね。
OnDraw、OnPaint等で描画をする(いわゆるオーナードロー)場合、
描画するためのエリアさえあれば、それがフォームだろうがCStatic
であろうが、描画先のDCさえあればいいわけです。
描画の必要があるときに常に自分で画像を書くのですから。

でも今回の場合、PictureBoxに対してファイルの画像を表示したいのですよね。
この場合、自分で描画を行う必要はありません。
そのためにPictureBoxというコントロールクラスが用意されているわけですよね。
これを使えばイメージさえセットしてあげれば描画、再描画はPictureBoxが行ってくれます。

もし、オーナードローするのであれば、PictureBoxは単にフレームなどにして
自分で描画するためのキャンパスとして使うことになります。
その場合、OnDrawなどでPictureBoxのDCを使って画像を描画しましょう。
GDIを使用するのであればBitBlt、GDiPlusを使用するのであればDrawImage等調べてみてください。
お返事ありがとうございます

void CNnnView::OnFileOpen()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
CFileDialog dlg(TRUE,"bmp","*bmp");

if(dlg.DoModal()==IDOK){
path = dlg.GetPathName();
}
  hbit = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), path,
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);


Invalidate();

}


oid CNnnView::OnDraw(CDC* pDC)
{
CNnnDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

// TODO: この場所にネイティブ データ用の描画コードを追加します。
Pic dlg;

dlg.m_pic.SetBitmap(hbit);

}


アタッチの部分を書き直したのですがやはりDebug Assertion Failed
となってしまいます。
今SDIで生成していて右クリックでダイアログをだしているのですが
ダイアログのボタンを開くをおし画像選択するとDebug Assertion Failed
となります。
書き方がまちがってるのでしょうか。
renさん、こんにちは
うーん、まずSDIとダイアログベースのアプリの違いを理解するほうがよいかと思います。
単にダイアログを開いてファイルを選択して画像表示するアプリであればダイアログベースのプロジェクトをお勧めします。
何がどう違うのかは、ここでは書ききれません^^;

とにかく、SDIでPictureBoxに絵を描かせるという事で話を絞ります。
まず、OnDrawで描こうという事は忘れてください。PictureBoxに絵を渡せば
いいだけです。

SDIのViewクラスに CStatic *m_st; を追加してください。
ViewクラスのOnCreateハンドラを作成し、
以下のコードを記述してください。

RECT rect = {左位置,上位置,幅,高さ}; //0,0,400,300とか
m_st->Create("ST",WS_CHILD|WS_VISIBLE|SS_BITMAP,rect,this,100);
m_st->SetBitmap((HBITMAP)::LoadImage(AfxGetInstanceHandle(), _T("ファイル名"),IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION));

これだけで絵が表示されます。
あと、Viewクラスのデストラクタでdelete m_st; を忘れずに書いてください。

とにかく、まずはダイアログベースでVCの理解を深めるのがよろしいかと思います。
OnCreateのハンドラをつくり言われたようにコード
を書きましたがOnCreateのところでエラーがでました。
デバックするとエラーメッセージで

「ハンドルされていない例外は(MFC42D.DLL)にあります。0xc0000005:Access Violation」

とでてしまいました

return pWnd->Create(_T("STATIC"), lpszText, dwStyle, rect, pParentWnd, nID);でとまっているみたいなのですが
renさん、こんにちは
すいません、書きもれがありました^^;

m_st= new CStatic(); <-これを追加
m_st->Create("ST",WS_CHILD|WS_VISIBLE|SS_BITMAP,rect,this,100);
確かに描画されたのですがダイアログボックスないではなく
ビューのウインドウに描画されました 
書き方がわるかったのでしょうか^^;
renさん、こんにちは

>SDIで生成したのですが
これを見てSDIに変更したものかと思ってました^^;

ダイアログでいいのであれば、
ダイアログのOnCreateで
m_pctbox.SetBitmap((HBITMAP)::LoadImage(::AfxGetInstanceHandle(),_T("ファイル名.BMP"),IMAGE_BITMAP,0,0,LR_LOADFROMFILE));
これだけです。

ファイル名はダイアログのコンストラクタで渡すなりfriendとしてViewクラスから参照するなり、グローバル変数にしておくなりお好きな方法で。

ちなみにm_pctbox変数はダイアログに貼ってあるピクチャボックスですが、変数を作らないでアクセスするなら以下の方法で。
((CStatic *)this->GetDlgItem(ピクチャボックスのID))->SetBitmap〜〜

DOBON.NET | プログラミング道 | プログラミング掲示板