OnPaint()でビットマップを表示 – プログラミング – Home

OnPaint()でビットマップを表示
 
通知
すべてクリア

[解決済] OnPaint()でビットマップを表示

固定ページ 1 / 2

ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

VC++ 6.0 MFC 
CStaticを派生させたクラスをつくって、そのクラスのOnPaint()
でビットマップを表示させようとしているのですが、
どうも、メモリ上にわざわざ、デバイスコンテキストを作るのが無駄をしているような
気がします。
LoadBitmap()で読んだものをそのまま描画用デバイスコンテキストに出力できないでし
ょうか?
void CStaticBitmapDisp::OnPaint()
{
CPaintDC dc(this); // 描画用のデバイス コンテキスト

CBitmap Bitmap ;
Bitmap.LoadBitmap(m_FileName) ;
// if (!this->SetBitmap(Bitmap)) {
// AfxMessageBox(SetBitmap() Error);
// }

DeleteObject(Bitmap) ;
}
*m_FileName(LPCTSTR)は、ビットマップのファイル名です。


引用未解決
トピックタグ
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

追記 OS XPです。


返信引用
しま
 しま
(@しま)
ゲスト
結合: 18年前
投稿: 123
 

>LoadBitmap()で読んだものをそのまま描画用デバイスコンテキストに出力
>できないでしょうか?

VC++6 の MFC でビットマップを扱うのは SDK を用いるのと大差ありません
なので、DDBとDIBとDIBSection とについて知っておく必要があります
DDBには色々と制約があるのであまりお薦めしません

DDBは DC(Device Context) に選択して使います
DIBは DC に選択することができませんので別の操作 StretchDIBits() で描画します
DIBSection は DDB,DIB 両方の扱いができるものです

CBitmap で LoadBitmap() する以上は ComapatibleDC に選択する必要があるでしょう
ただ、::LoadImage() を用いるのなら DIBSection として読込めるので OK かも
知れません


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

しまさん、レスありがとうございます。

マニュアルには、以下のことしか書いていませんので、DIBについて調べているとこ
ろです。

DDB(device-dependent bitmap:デバイス依存ビットマップ)
  特殊なプリンタ、ディスプレイのときだけに使われるビット配列

DIB(device-independent bitmap:非デバイス依存ビットマップ)
  ビットマップの高さ・幅を指定する、イメージがクリエイトされるデバイスのカラ
ーフォーマット、イメージがクリエイトされるデバイスのレゾリュ-ションの構造体で
構成されるビット配列


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

こんな感じかな?って思うんです。
.bmpは、DBIで、描画用デバイスコンテキストは、DDB。
これを変換して使うためにメモリデバイスコンテキストをつかう?
ってことになるんじゃないかな?と思うんですが・・
描画用デバイスコンテキストは、DBIにはならない?


返信引用
しま
 しま
(@しま)
ゲスト
結合: 18年前
投稿: 123
 

データー構造ではなく、DDB,DIB,DIBSection の使い方の違いについて
知って欲しいと思います

確かに、DDB <->DIB の相互変換ができるようにはなっていますが、単に描画する
場合は相互変換しないでそのまま使うことが多いと思います

>>どうも、メモリ上にわざわざ、デバイスコンテキストを作るのが無駄をしている
>>ような気がします。

ということへの返事を書いているつもりです
文面から、DCにビットマップを選択するのを避けたいとお考えだと判断したので
それなら DIB,DIBSection を用いれば Blit()(or StretchBlit()) ではなく
描画対象のDCに StretchDIBits() で出力できるのではないかと思ったということです


返信引用
ryo
 ryo
(@ryo)
ゲスト
結合: 23年前
投稿: 252
 

ちょいと話はずれますが、

OnPaintのたびに、
ファイルを読み込み・解放と、デバイスコンテキストを作成・解放
をするほうが面倒ではないでしょうか?


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

しまさん、ryoさん、レスありがとうございます。
すいませんが、今、DIB/DDBなど、あれこれ読んでいますので、レスに時間がか
かります。


返信引用
hirocco
 hirocco
(@hirocco)
ゲスト
結合: 14年前
投稿: 138
 

>CBitmap Bitmap ;
>Bitmap.LoadBitmap(m_FileName) ;
LoadBitmapの引数m_FileNameって
ファイルの名称とかパスになってませんか?


返信引用
hirocco
 hirocco
(@hirocco)
ゲスト
結合: 14年前
投稿: 138
 

LoadBitmapでファイルパスは指定できないし、
SetBitmapならWM_PAINTでの処理は無駄だと思います
CStaticの派生クラスのスタイルにはちゃんとSS_BITMAPが指定されていますか?
そしてサブクラス化も不要に思えます

サブクラス化が不要/必要問わず、どのようにしてインスタンスを作りますか?
DDX?SubclassDlgItem?Create?


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

hiroccoさん、レスありがとうございます。

>LoadBitmapの引数m_FileNameって
>ファイルの名称とかパスになってませんか?

なってました。リソースにビットマップファイルを挿入して、リソースIDに変えまし
た。

○ちょっと手がかりを入手
システムが 256 色表示の場合、リソースに登録されている 256 色のビットマップ
(DIB ビットマップ)を LoadBitmap 関数で読み込むと、予約されている 20 色の
システムカラーで描画されてしまいます。これは LoadBitmap 関数が DIB ビットマップ
を DDB ビットマップに変換する際に
カラー情報が失われるためです。

ただいま、256色のビットマップを表示しようとしていますが、 LoadBitmap()ならD
IBのリソースをDDBに変換してしまう。ということですね。
DDBを使うとGDI関数が使えないということですが・・・そのへんがどうもわから
ないところです。


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

>スタイルにはちゃんとSS_BITMAPが指定されていますか?
スタイル指定は、していません。デフォルトのままです。

>サブクラス化が不要/必要問わず、どのようにしてインスタンスを作りますか?
メンバの一つとして、インスタンスを作ります。
SubclassDlgItemということになるとおもいます。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

>どうも、メモリ上にわざわざ、デバイスコンテキストを作るのが無駄をしているような
>気がします。
>LoadBitmap()で読んだものをそのまま描画用デバイスコンテキストに出力できないでし
>ょうか?

できません。

デバイスコンテキスト(HDC)は作成時のデフォルト状態で1×1のモノクロ
ビットマップ(BMP)を選択しています。ただし、BeginPaint()又はGetDC()
で取得したHDC(CPaintDCも同じ)は画面上の当該HWNDのクライアント領域全体を指
し示すBMPを選択しています。つまりHDCとBMPは一蓮托生なのです。
たとえばBitBlt()関数は対象HDC同士の転送を意味しますが、実態はそれぞれの
HDCが選択しているBMP同士のBitの転送を行います。HDCに直接BMPを表示させる
ことはできません。当然、システムが割り当てたHDC(=PaintDC、ClientDC等)が
選択しているBMPを別のBMPに選択しなおすことも危なくてできません。

次に、VC6で作成するリソース内のBMPは全て16(ないしシステム20色)色の
BMPに変換されて保持されてしまいます。これは、リソースをコンパイルする
ときに変換されるため、元となったBMPが256色以上の場合、いかなる方法を
もってしても、元の色に戻すことはできません。リソース内に元の状態で
ビットマップファイル全体を保持するにはカスタムリソースという手法を
使う方法もありますが、一般には、リソースではなく、外部ファイルとして
別にロードする方法を使用します。

最後に、単に表示するだけならば、デバイス依存のビットマップ(=BMP)と
デバイス独立系ビットマップ(=DIB、DIBセクション)の違いは、ほとんど
ありません。大きな違いは、BMPの場合、画像データ部分を分離して単なる
データ配列として扱えない点です。BMPの画像部分に対して、このようなことを
行いたい場合は、一旦DIB又はDIBセクションに変換する必要があります。

上記の様に、また、しまさんの発言どおり、BMP、DIB、DIBセクションの
性質の違い、および、それに依存するそれぞれの取り扱い方法の違いを
理解していたほうが、より適切に利用できると考えられます。
できれば、HDCとの関係についても知っておくとベターです。


返信引用
いしだ
 いしだ
(@いしだ)
ゲスト
結合: 17年前
投稿: 53
 

CImageを使えば、メモリビットマップを作らずに
DCに直接描画できますが、これってVC6には無かったでしたっけ?

CImage m_image;
m_image.LoadFromResource(AfxGetInstanceHandle(), IDB_BITMAP1);

CPaintDC dc(this);
m_image.Draw(dc, 0, 0);


返信引用
hirocco
 hirocco
(@hirocco)
ゲスト
結合: 14年前
投稿: 138
 

>CStaticを派生させたクラスをつくって、そのクラスのOnPaint()
>でビットマップを表示させようとしているのですが、
>どうも、メモリ上にわざわざ、デバイスコンテキストを作るのが
>無駄をしているような気がします。
>LoadBitmap()で読んだものをそのまま描画用デバイスコンテキストに
>出力できないでしょうか?
知識ばかり先行しているようにお見受けします
 派生させる意味
 デバイスコンテキストの意味
 LoadBitmapの振る舞い
 DIBやDDBの差異

>SubclassDlgItemということになるとおもいます
おもいます?

えっと, でも, 要するにBitmapをファイルで読み込んでSTATICの背景に設定したいっ
ていうことであって,
そこにWM_PAINTやデバイスコンテキスト/DIB/DDB, ましてやLoadBitmapまでも関係なく
最終的にファイルと同じビットマップを表示したいって事じゃないかなぁと…
どうでしょう?

それだと仮定すると
表示させたいSTATICのスタイルはSS_BITMAPが指定されているべき
LoadBitmapではなくLoadImageであるべき
初期化時に背景を設定するためにSetBitmapを使用するべき
以上です

生成済みのSTATICコントロールに
ModifyStyle( 0x000F,SS_BITMAP );
を実行させて,
(HBITMAP)LoadImage( NULL,ファイルのフルパ
ス,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_CREATEDIBSECTION|LR_LOADFROMFILE );

LoadImageで作られたHBITMAPをSetBitmapです
あとは何も要りませんし, 考える必要も無し, インスタンスも気にしないで大丈夫でし
ょう
ただ, LoadImageで作られたHBITMAPはメンバ変数として取っておいて, 終了時に解放し
ます

VC6.0ってよく知りませんけど, LoadImageが無いとか, そういうことあります?

どかな?

あ, どうしてもリソースからしかもVC6.0から元々のビット深さのビットマップを操作し
たいとか
そういうことだったのかな?
VC.NETからしかしりませんのでお役に立てません...
ゴメンナサイ


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました