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)は、ビットマップのファイル名です。
追記 OS XPです。
>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 かも
知れません
しまさん、レスありがとうございます。
マニュアルには、以下のことしか書いていませんので、DIBについて調べているとこ
ろです。
DDB(device-dependent bitmap:デバイス依存ビットマップ)
特殊なプリンタ、ディスプレイのときだけに使われるビット配列
DIB(device-independent bitmap:非デバイス依存ビットマップ)
ビットマップの高さ・幅を指定する、イメージがクリエイトされるデバイスのカラ
ーフォーマット、イメージがクリエイトされるデバイスのレゾリュ-ションの構造体で
構成されるビット配列
こんな感じかな?って思うんです。
.bmpは、DBIで、描画用デバイスコンテキストは、DDB。
これを変換して使うためにメモリデバイスコンテキストをつかう?
ってことになるんじゃないかな?と思うんですが・・
描画用デバイスコンテキストは、DBIにはならない?
データー構造ではなく、DDB,DIB,DIBSection の使い方の違いについて
知って欲しいと思います
確かに、DDB <->DIB の相互変換ができるようにはなっていますが、単に描画する
場合は相互変換しないでそのまま使うことが多いと思います
>>どうも、メモリ上にわざわざ、デバイスコンテキストを作るのが無駄をしている
>>ような気がします。
ということへの返事を書いているつもりです
文面から、DCにビットマップを選択するのを避けたいとお考えだと判断したので
それなら DIB,DIBSection を用いれば Blit()(or StretchBlit()) ではなく
描画対象のDCに StretchDIBits() で出力できるのではないかと思ったということです
ちょいと話はずれますが、
OnPaintのたびに、
ファイルを読み込み・解放と、デバイスコンテキストを作成・解放
をするほうが面倒ではないでしょうか?
しまさん、ryoさん、レスありがとうございます。
すいませんが、今、DIB/DDBなど、あれこれ読んでいますので、レスに時間がか
かります。
>CBitmap Bitmap ;
>Bitmap.LoadBitmap(m_FileName) ;
LoadBitmapの引数m_FileNameって
ファイルの名称とかパスになってませんか?
LoadBitmapでファイルパスは指定できないし、
SetBitmapならWM_PAINTでの処理は無駄だと思います
CStaticの派生クラスのスタイルにはちゃんとSS_BITMAPが指定されていますか?
そしてサブクラス化も不要に思えます
サブクラス化が不要/必要問わず、どのようにしてインスタンスを作りますか?
DDX?SubclassDlgItem?Create?
hiroccoさん、レスありがとうございます。
>LoadBitmapの引数m_FileNameって
>ファイルの名称とかパスになってませんか?
なってました。リソースにビットマップファイルを挿入して、リソースIDに変えまし
た。
○ちょっと手がかりを入手
システムが 256 色表示の場合、リソースに登録されている 256 色のビットマップ
(DIB ビットマップ)を LoadBitmap 関数で読み込むと、予約されている 20 色の
システムカラーで描画されてしまいます。これは LoadBitmap 関数が DIB ビットマップ
を DDB ビットマップに変換する際に
カラー情報が失われるためです。
ただいま、256色のビットマップを表示しようとしていますが、 LoadBitmap()ならD
IBのリソースをDDBに変換してしまう。ということですね。
DDBを使うとGDI関数が使えないということですが・・・そのへんがどうもわから
ないところです。
>スタイルにはちゃんとSS_BITMAPが指定されていますか?
スタイル指定は、していません。デフォルトのままです。
>サブクラス化が不要/必要問わず、どのようにしてインスタンスを作りますか?
メンバの一つとして、インスタンスを作ります。
SubclassDlgItemということになるとおもいます。
>どうも、メモリ上にわざわざ、デバイスコンテキストを作るのが無駄をしているような
>気がします。
>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との関係についても知っておくとベターです。
CImageを使えば、メモリビットマップを作らずに
DCに直接描画できますが、これってVC6には無かったでしたっけ?
CImage m_image;
m_image.LoadFromResource(AfxGetInstanceHandle(), IDB_BITMAP1);
CPaintDC dc(this);
m_image.Draw(dc, 0, 0);
>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からしかしりませんのでお役に立てません...
ゴメンナサイ