• ベストアンサー

画像表示について。

現在SDKにてBMPやRAWなどの画像表示ソフトを作成している段階です。 そして、一通り作成することができました。 ここで質問に答えてくださった皆様に感謝します。 新たに些細な問題が出てきてしまったので質問します。 作成したソフトはMDI型のソフトであり、その構成はフレーム、クライアント、ドキュメントウィンドウといった構成になっています。 もちろん読み込んだ画像はドキュメントウィンドウに表示をするのですが、このドキュメントウィンドウのサイズをマウスを使って変更した場合、画像にちらつきが生じてしまいます。 原因はプログラム上 WM_PAINT メッセージがきた場合に描画をおこなうことに他ならないのですが、解決する手段はないでしょうか? 例えばダブルバッファリングなどの手段があればよいのですが・・・

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

  • ベストアンサー
noname#30727
noname#30727
回答No.5

ANo.5です。 >・・・・・こんな流れでよいでしょうか。 お礼欄に書かれている流れで、ほぼ完璧だと思います。 >このリージョン1をhdcにクリップする。 「DCのクリッピングリージョンをリージョン1にする」が妥当な解釈だと思います。 何かを描画するときに、ある範囲だけに描画する事を「クリップする」または「クリッピング」と言い、その範囲をクリッピングリージョンと言います。 最終的なクリッピングリージョンは、ウィンドウの重なり方で決定されるシステムクリッピングリージョン、InvalidateRectなどで作成される更新リージョン、SelectClipRgnなどで登録されたユーザー定義クリッピングリージョンが合成されたものだと思います。 >これを行うとSelectClipRgn関数でhdcにクリップしたリージョンがなくなってしまうように思われるのですが・・・・ Platform SDKのドキュメントに書かれているのですが、SelectClipRgn で選択したリージョンは、そのコピーが使用されます。 なので、SelectClipRgn から戻ったら、リージョンは削除してもかまいません。

noconan
質問者

お礼

リージョンの解説までいただありがとうございました。 教えていただいた方法により、納得のいくソフトに近づけそうです。 ありがとうございました。

その他の回答 (4)

noname#30727
noname#30727
回答No.4

ANo.2です。 ビットマップのスタティックコントロールと同じように考えてしまったので、ウィンドウサイズとビットマップサイズが違う事を考慮していませんでした。 チャイルドウィンドウを作成して、ドキュメントウィンドウの上に重ねるのが普通かもしれません。ダイアログの考え方と同じです。 チャイルドウィンドウのクリッピング処理を自前でやる事もできなくはないと思います。メモ程度ですが参考にしてみてください。この場合、hbrBackgroundはNULLのままです。 RECT rect; HRGN hrgn; hdc = BeginPaint(...); GetClientRect(hwnd, &rect); hrgn = CreateRectRgnIndirect(&rect); SelectClipRgn(hdc, hrgn); DeleteObject(hrgn); rectにビットマップの描画領域を設定; hrgn = CreateRectRgnIndirect(&rect); ExtSelectClipRgn(hdc, hrgn, RGN_DIFF); DeleteObject(hrgn); クライアントエリアを背景色で塗りつぶす; SelectClipRgn(hdc, NULL); ビットマップの描画; EndPaint(...);

noconan
質問者

お礼

連続書き込みをお許しください。 調べた結果大体のことは分かりました。 最初にドキュメントウィンドウのクライアントサイズを取得し、その大きさと等しいリージョンを作成する。このリージョンをリージョン1とします。 このリージョン1をhdcにクリップする。 次に描画領域のサイズを取得し、その大きさと等しいリージョンを作成する。 このリージョンをリージョン2とします。 その後ExtSelectClipRgn関数のフラグをRGN_DIFFに設定することでリージョン1とリージョン2との差をとることができ、hdcには描画領域以外の領域をリージョンとすることができる。 その状態で背景を描画した場合、もちろんビットマップの描画領域以外がペイントされ、ビットマップの描画領域を更新しないですむ。 ここまで行われたら、hdcからクリップされたリージョンを削除するためSelectClipRgn関数の第2引数をNULLにする。 そのごビットマップはもちろんそれ自身の表示領域を指定するので、一度の描画更新処理だけですむ。 ・・・・・こんな流れでよいでしょうか。 とても参考になりました。 以前リージョンなんて画像処理ソフトには無意味だろうと思い、疎かにしてしまいましたが、こんなところで顔を出すことになるとは思いもよりませんでしたw ついでに質問してもよろしいでしょうか? SelectClipRgn関数のあとすぐにDeleteObjectによりリージョンハンドルを削除していますが、これを行うとSelectClipRgn関数でhdcにクリップしたリージョンがなくなってしまうように思われるのですが・・・・ 実際うまく動いているのでそんなことはないんでしょうが、動作がはっきり把握できません。 もしよろしければ、自分の考えが正しいか、そして最後の動作の理解も含め解説していただけたら光栄です。

noconan
質問者

補足

返答ありがとうございました。 教えていただいた方法で組んでみた結果、見事ちらつきを消去することに成功しました。 しかし・・・自分はまだ”リージョン”について詳しく勉強したことがないので、例に挙げてくださったプログラムを理解しなければいけません。 申し訳ないですが、例に挙げてくださったプログラムを大雑把でいいので解説してもらえないでしょうか?

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★別の回答を紹介します。 ・回答者 No.1 さんの方法以外にもう一つアイディアを紹介します。  それは『リサイズ』中、WM_PAINT の描画を禁止させて『リサイズ』後に描画処理を  実行させる方法です。 ・仕組みは  (1)リサイズの開始時、WM_ENTERSIZEMOVE をキャッチして描画フラグを OFF に設定  (2)リサイズの終了時、WM_EXITSIZEMOVE をキャッチして描画フラグを ON に設定  (3)リサイズの終了時、安全のために InvalidateRect( hWnd, NULL, TRUE ) を実行しておく  (4)WM_PAINT で描画フラグが ON のときだけ描画処理を行う  これだけです。それではサンプルを載せます。 サンプル: LRESULT CALLBACK DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {  static BOOL bDrawEnable = TRUE; ←描画フラグ(初期値は TRUE にする)    switch ( uMsg ){   case WM_ENTERSIZEMOVE:    bDrawEnable = FALSE; // 描画禁止    break;   case WM_EXITSIZEMOVE:    bDrawEnable = TRUE; // 描画可能    InvalidateRect( hWnd, NULL, TRUE );    break;   case WM_PAINT:    if ( bDrawEnable ){     PAINTSTRUCT ps;     HDC hDC;          hDC = BeginPaint( hWnd, &ps );     /*     描画処理(ダブルバッファリングを BitBlt で転送するなど)     */     EndPaint( hWnd, &ps );    }    break;   default:return DefWindowProc( hWnd, uMsg, wParam, lParam );  }  return 0; } その他: ・この方法だとリサイズ中は一切の描画を行いません。  また、リサイズ終了時とは『マウスドラッグ』をやめたときでマウスボタンが離されたときです。  それまでは一切の描画がないのでちょっと見た目が不自然になるかもしれません。この場合は  タイマーを使って例えば 1 秒間隔で一時的に WM_PAINT させるように工夫すれば良い。  タイマーの間隔は自由です。→下のサンプル2 がタイマー版。 ・回答者 No.1 さんの方法もでちらつき過ぎる場合は、タイマー間隔でちらつく間隔をカスタマイズ  できます。→0.5秒、1.0秒が適当かな。試していないが…。その辺だろう。  そのほかマウスカーソルの移動位置を使って、移動量が 0 の時に一時描画の bDrawTimer=TRUE を  セットする方法などがあります。この方法の方が綺麗かも。動作はご自由にどうぞ。 サンプル2: LRESULT CALLBACK DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {  static BOOL bDrawEnable = TRUE; ←描画フラグ(初期値は TRUE にする)  static BOOL bDrawTimer = FALSE; ←描画フラグ(タイマー用)    switch ( uMsg ){   case WM_ENTERSIZEMOVE:    bDrawEnable = FALSE; // 描画禁止    SetTimer( hWnd, タイマーID, タイマー間隔(ms), NULL );    break;   case WM_EXITSIZEMOVE:    bDrawEnable = TRUE; // 描画可能    KillTimer( hWnd, タイマーID );    InvalidateRect( hWnd, NULL, TRUE );    break;   case WM_TIMER:    bDrawTimer = TRUE; ←一時的に描画させるため    InvalidateRect( hWnd, NULL, TRUE );    break;   case WM_PAINT:    if ( bDrawEnable || bDrawTimer ){     PAINTSTRUCT ps;     HDC hDC;          hDC = BeginPaint( hWnd, &ps );     /*     描画処理(ダブルバッファリングを BitBlt で転送するなど)     */     EndPaint( hWnd, &ps );     bDrawTimer = FALSE; ←リセットしておく    }    break;   default:return DefWindowProc( hWnd, uMsg, wParam, lParam );  }  return 0; }

noconan
質問者

お礼

返答ありがとうございました。 タイマーを使うことは思いつきませんでしたね。 あるいみタイマーの応用範囲は広いですね。 早速実行してみたところ確かに以前に比べちらつきは少なくなりましたが、依然として発生しております。 今作成しているソフトは、ドキュメントウィンドウのサイズが変更されるたびに画像の表示位置を変更して、必ずドキュメントウィンドウの中央に表示されるようにプログラムを組んでいます。 もしサイズが変更されても表示位置は変更しないようなプログラムならおそらくちらつきはなくなるかもしれません。 ちょっと説明不足でしたね。申し訳ないです。 回答者No.2さんの方法とあわせて実行してみましたが、それでも解決できませんでした。 今後色々試行錯誤してみます。

noname#30727
noname#30727
回答No.2

これはWM_PAINTとWM_ERASEBKGNDの関係から起こる事です。 BeginPaintを実行すると内部でWM_ERASEBKGNDがSendMessageされます。 この時点でドキュメントウィンドウは一度クリアされるので、ちらつきが起こります。 何通りかの解決方法が考えられますが、私が良く使うのは、WNDCLASSEX の hbrBackground を NULL にしてウィンドウを作成する方法です。 このままだと、ドキュメントが無い状態ではウィンドウ背景が消去されなくなってしまうので、そのときは、WM_PAINTで空のドキュメントを描画する必要があります。(適当な色で塗りつぶすなど)

noconan
質問者

お礼

回答ありがとうございました。 最初に”適当な色で背景を塗りつぶす”作業を行わずに、hbrBackgroundのみNULLにして実行してみたところ、背景がないため移動軌跡が残ってしまいますが、ちらつきはまったく出ませんでした。 つぎに正常に戻すため、”適当な色で背景を塗りつぶす”作業を含め実行したところ、通常と変わらないちらつきが発生してしまいました。 うまくいくと思ったんですが・・・もう少しがんばってみようと思います。

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.1

MDI は作ったことがありませんが,以前 SDI でやったときは, ウインドウクラススタイルに CS_HREDRAW | CS_VREDRAW を指定するのではなく, WM_SIZE メッセージの処理で InvalidateRect(hwnd, NULL, FALSE) を行う方が かなりちらつきが少なかったと思います. その理由は次のとおり (前半は推測). CS_HREDRAW | CS_VREDRAW だとウインドウをリサイズするたびに WM_PAINT メッセージが (たぶん) send され,非常に頻繁に再描画が行われます.(いまいち確信なし) これに対し,InvalidateRect は WM_PAINT メッセージを post する, つまり後で WM_PAINT がディスパッチされるように「予約」するだけなのに加え, WM_PAINT がディスパッチされる優先度は他のウインドウメッセージに比べて 優先度が低い (他にディスパッチすべきメッセージがなければ WM_PAINT が ディスパッチされる) ので,再描画が行われる回数が激減します. したがって,リサイズが行われている間は WM_SIZE などがディスパッチされ続け, WM_PAINT はほとんどディスパッチされないのに対し,リサイズが (一瞬でも) 停止して 他のメッセージがなくなると WM_PAINT がディスパッチされて再描画が行われます.

noconan
質問者

お礼

返答ありがとうございました。 実行してみたところ、確かにWM_PAINTでInvalidateRectを実行するよりもちらつきは少なくなりました。 しかし完全になくなったとはいえないので、もう少し改良を加えてみようと思います。

関連するQ&A

  • WindowsAPIでの画像表示について

    コード(一部): http://fatalita.sakura.ne.jp/goo/img/APIcode.jpg 本当はこうしたかった実行結果: http://fatalita.sakura.ne.jp/goo/img/Run2.jpg 実際の実行結果: http://fatalita.sakura.ne.jp/goo/img/Run.jpg 現在Windowsプログラミングでウィンドウプロシージャの WM_CREATE 内で仮想画面にtest.bmpを読み込み、 さらにその後に仮想画面に大きな赤い四角形を描画させて WM_PAINT で裏画面をウィンドウに描画させているのですが、 何故かこのコードを実行すると画像ファイル test.bmpの大きさの範囲内でしか赤い四角形が描画されません。 これは何が悪いのでしょうか・・? 開発環境はWinXP / VisualStudio 2005です。 後、WND_SIZE_XとWND_SIZE_Yはそれぞれウィンドウのサイズを表しています。

  • 画像表示について

    画像を表示させたいのですがうまくいきません。 途中まで打ってみたのでご意見お願いします。 (リソースから読み込んで表示させる方法) 環境:MicrosoftVisualC++ SDK ******省略********* case WM_PAINT:   hdc = BeginPaint(hWnd,&ps);   //ビットマップリソースハンドルの取得   hBmp = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP1));   if(hBmp == NULL){     MessageBox(hWnd,"ファイルの読み込みに失敗しました。","エラー",MB_ICONWARNING | MB_OK);     exit(1);   }   //ビットマップの大きさの情報取得   GetObject(hBmp,(int)sizeof(BITMAP),&bmp_info);   w = bmp_info.bmWidth;   h = bmp_info.bmHeight;   hdc_mem = CreateCompatibleDC(hdc);   SelectObject(hdc_mem,hBmp);   BitBlt(hdc,0,0,w,h,hdc_mem,0,0,SRCCOPY);   DeleteDC(hdc_mem);   DeleteObject(hBmp);   EndPaint(hWnd,&ps);   break; ******リソース(img.rc)****** // // Bitmap // IDB_BITMAP1 BITMAP DISCARDABLE "bitmap1.bmp" #ifdef APSTUDIO_INVOKED

  • WinAPIでの画像高速切り替え表示プログラム1

    WinAPIを使用して、ビットマップ画像を8枚読み込み、それを連続高速表示するプログラムを作成しています。 今はSetTimerを使ってWM_TIMERを受け取ったときに画像をInvalidateRect(再描画)しています。 以下のソースで動作はするのですが、WM_TIMERは整数ミリ秒でしか設定できず、精度も悪く優先順位も遅いようなので他の方法を考えています。 画像8枚を6.25msecで切り替えて表示するというのをESCAPEするまで繰り返したいのですが...。 リフレッシュレートは160Hzにあげています。 QueryPerformanceFrequencyというものを使えばいいのかなと思っていますが、どこでどう使えばいいのか、それをどう受け取って再描画すればいいのかわかりません。 どなたかご教授お願いします。ソースファイルを書いていただけたら嬉しいです。 #include<windows.h> #define BMP_SUM8//画像の総数 #define TIMER_ID (100) // 作成するタイマの識別ID #define TIMER_ELAPSE (6) // WM_TIMERの発生間隔 LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){ HDC hdc; PAINTSTRUCT ps; HBITMAP hBitmap; int i; const char *filename[BMP_SUM]={"gazou0.bmp", "gazou1.bmp", "gazou2.bmp", "gazou3.bmp", "gazou4.bmp", "gazou5.bmp", "gazou6.bmp", "gazou7.bmp"}; static HDC hMemDC[BMP_SUM]; static BITMAP bmp; static int bmp_index;//現在の画像番号 LONG lResult; switch(uMsg) { case WM_CREATE: hdc=GetDC(hWnd); for(i=0;i<BMP_SUM;i++){ hBitmap=(HBITMAP)LoadImage(0,filename[i],IMAGE_BITMAP,0,0,LR_LOADFROMFILE); hMemDC[i]=CreateCompatibleDC(hdc); SelectObject(hMemDC[i],hBitmap); } GetObject(hBitmap,sizeof(BITMAP),&bmp); DeleteObject(hBitmap); ReleaseDC(hWnd,hdc); return 0; case WM_TIMER: if( wParam != TIMER_ID ) { break; // 識別IDが一致しないタイマメッセージはDefWindowProc()に任せる } if(++bmp_index >= BMP_SUM) bmp_index=0; for(i = 0; i < BMP_SUM; i++){ InvalidateRect( hWnd, NULL, FALSE ); } return 0; case WM_DESTROY: for(i=0;i<BMP_SUM;i++) DeleteDC(hMemDC[i]); PostQuitMessage(0); return 0; case WM_PAINT: hdc=BeginPaint(hWnd,&ps); BitBlt(hdc,0,0,bmp.bmWidth,bmp.bmHeight,hMemDC[bmp_index],0,0,SRCCOPY); EndPaint(hWnd,&ps); return 0; case WM_KEYDOWN: switch((CHAR)wParam) { case VK_ESCAPE: for(i=0;i<BMP_SUM;i++) DeleteDC(hMemDC[i]); PostQuitMessage(0); //WM_QUITメッセージを出す return 0; } } return DefWindowProc(hWnd,uMsg,wParam,lParam); } 入りきらないので2つに分けます。 続きは「WinAPIでの画像高速切り替え表示プログラム2」を見てください。

  • MDI(自作メモ帳)の子ウィンドウのHWND取得について

    はじめまして、TKOZという者です。 c言語とWINAPIでMDIの自作メモ帳を作っています。 ところで、MDIを使って、複数のドキュメントウィンドウでテキストファイル を保存したいのですが、選択されたドキュメントウィンドウの保存をする 際にそのドキュメントウィンドウのHWND取得をしたいのですが、 どうすればいいでしょうか? ソースコードはこれです。 http://www.kumei.ne.jp/c_lang/sdk/sdk_83.htm http://www.kumei.ne.jp/c_lang/sdk/sdk_84.htm http://www.kumei.ne.jp/c_lang/sdk/sdk_85.htm

  • Win32APIを使って入力されたキーによって表示する画像を変えるプログラムについて

    Win32APIを使って入力されたキーによって表示する画像を変えるプログラムを今、VisualSutudio2005のVC++で作っている最中なのですが、 上手く画像が表示されず困っています。具体的には、キーボードからキーが入力されたらTranslateMessage関数でWM_CHARメッセージを送って、その値(wParam)をWM_CHARメッセージ内でTCHAR型の変数に代入し、InvalidateRect関数を使ってWM_PAINTメッセージを送って、再描画処理を行ってその中で、if(tchar == 'a') { hbitmap = (HBITMAP)LoadImage(NULL,BMP,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); SelectObject(hMemdc,hbitmap); GetObject(hbitmap,sizeof(BITMAP),&bitmap); BitBlt(painthdc,0,0,350,467,hMemdc,0,0,SRCCOPY); } という処理をしてaが入力されたら読み込んだ画像を表示!という形にしたいのですが、実際ウィンドウには表示されなくて悩んでいます。わかりにくくて誠に申し訳ありませんが、どなたかどうかご教授願えないでしょうか。何卒よろしくお願い致します。

  • WINAPI 他のウインドウを重ねると画像やテキストが消える

    C++とWINAPIで、ウインドウを作成し、テキストや画像を表示しています。 このウインドウに他のウインドウを重ねて、再度、このウインドウを表示すると画像やテキストが消えてしまいます。 case WM_PAINT: BitBlt( hbtn0DC, 0, 0, 40, 40, hbtn0bmpDC, 0, 0, SRCCOPY ); return 0; 再描画するタイミングで表示するようにしています。 他のウインドウが被っても消えないようにする方法を教えてください。 もしくは、 他のウインドウが被っても画像が消えないようにする処理を説明しているページをどこかで見たような気がするのですが、見つかりません。 ご存知でしたら教えてください。

  • 画像処理 ビットマップ ダブルバッファリング

    「猫でもわかるWindowsプログラミング」を参考に、ビットマップを表示するプログラムを作っています。 下記ソース(WM_PAINT部分のみ抜粋)のような感じで、 読み込んだビットマップをダブルバッファリングを用いて表示させたいのですが、 何も表示させることができず、困っております。 LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) {   HBITMAP hBmp;   BITMAP bmp_info;   HDC hDC, hDC_mem;   PAINTSTRUCT ps;   int w=0, h=0;   switch (msg) { case WM_PAINT:   hDC = BeginPaint(hwnd,&ps);   hDC_mem = CreateCompatibleDC(hDC);   hBmp=LoadBitmap(hInst, TEXT("MYBMP"));   hBmp = (HBITMAP)LoadImage(hInst, TEXT("MYBMP"), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); GetObject(hBmp, (int)sizeof(BITMAP), &bmp_info); w = bmp_info.bmWidth; h = bmp_info.bmHeight; SelectObject(hDC_mem, hBmp); BitBlt(hDC, 0, 0, w, h, hDC_mem, 0, 0, SRCCOPY); DeleteDC(hDC_mem); DeleteObject( hBmp ); EndPaint( hwnd, &ps ); break; } } リソースですが、下記のように bitmap1.bmpを指定しており、画像はもちろんフォルダ内に入れ、 読み込める状態にはしています。   //   // Bitmap   //   MYBMP BITMAP "bitmap1.bmp"   #endif // 日本語 resources しかし、hBmpの戻り値を調べると NULL の値が入っています。当然画像は表示されません。 当方、Microsoft visual studio 2005を使っておりますが、このプロジェクトは、 Win32コンソールアプリケーション⇒Windowsアプリケーション で作成はせず、 Win32コンソールアプリケーション⇒コンソールアプリケーション で作成していますので、 ここが問題になっているのでしょうか? できれば、コンソールアプリケーションで作成したいですが、LoadImage関数は使えないのでしょうか? それとも他に問題点があるのでしょうか? 以前は動画処理をしており、SetDIBitsToDevice関数を使って配列の中身を指定し、画像をウィンドウ上に表示していました。 しかし、画像のちらつきが気になったため、ダブルバッファリングに改良しようとし、 調べてみたところ、ビットマップを用いるやり方が一般的なようでした。 そこで、まずはビットマップの表示をさせるプログラムをつくってみようと思ったのですが、つまずいている状態です。 環境は、 Microsoft Windows XP Home Edition Version2002 Service Pack 3 Pentium(R) 4 CPU 2.80GHz 1.0GB RAM Microsoft visual studio 2005(有料) です。 何かアドバイスをよろしくお願いします。

  • 復元した画像が表示されない

    「復元、データーリカバリー2」というソフトを使い、画像データー(RAW、PSD、JPEG)を復元しました。各フォルダの中に画像のアイコンがあり、サイズも表示されるのですが、Photosyopに取り込むと、PSD形式で保存したものが「要求された操作を完了できません。有効なPhotoshopドキュメントではありません」とでます。この復元はできないのでしょうか。またできる方法はありませんか。

  • ホームページに画像が表示されません

    Windows XPでホームページを作成中なのですが、画像を1つも表示することができまず困っています。 以下のように作成しました。 ・マイ ドキュメント>Home Page の中にメモ帳で作成したページを .htm で保存しました。(<img src="1/g.JPG">と<body>に書きました) ・画像をマイ ドキュメント>Home Page>1 の中に g.JPG で保存しました。 ・2つともFFFTPでアップロードをしました。 無料ホームページを使用せずにマイ ドキュメントからページを表示すると画像は載っているのですが、FFFTPで開くと×になってしまいます。 なぜホームページ上では表示されないのか分からず困っています。 よろしくお願いします。

  • ビットマップ画像の表示

    どうしても正確に動作をしないので、問題点をご指摘していただきたいです。 開発環境はVisual Studio 2005です 24bitのビットマップ画像を読み込み、新しいwindowを作成して表示するプログラムを作成しています。 しかし、読み込んでから新しいWindowは作成されるのですが、どうしても画像が表示されません。 私が気にしている部分は、画像を読み込んでから新しく作成するWindowのプロシージャにおいて、WM_PAINTメッセージで行うべき処理です。 以下にプロシージャを載せます。 LRESULT CALLBACK WndProc( HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; switch( Message ){ case WM_PAINT: BeginPaint( hWnd, &ps ); SetDIBitsToDevice( ps.hdc, 0, 0, pDib->biWidth, pDib->biHeight, 0, 0, 0, pDib->biHeight, pBitmap, (BITMAPINFO *)pDib, DIB_RGB_COLORS ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, Message, wParam, lParam ); } return 0; } pDibは PBITMAPINFOHEADER のグローバル変数です。 そしてpDibへ情報を格納するとき、 bitmapSize = bmFileHdr.bfSize - sizeof(BITMAPFILEHEADER);   pDib = ( BITMAPINFOHEADER * )malloc( bitmapSize ); と領域を確保し、   fread( pDib, bitmapSize, 1, fp ) というように格納しました。 このときの fp は BITMAPFILEHEADER の分だけ進んでいます。 bmFileHdr は BITMAPFILEHEADERです。 つまりBITMAPFILEHEADER以降の情報を全て格納しました。 また SetDIBitsToDevice での題10引数の pBitmap は    pBitmap = (BYTE *)(pDib) + bmFileHdr.bfOffBits - sizeof(BITMAPFILEHEADER); のように求めました。先ほども記述しましたが pDib には BITMAPFILEHEADER 以降の情報を全て格納したので、pDibからヘッダ部分のみポインタを進めました。 やはり WM_PAINTメッセージの部分で、SetDIBitsToDevice関数だけではなく、そのほかに設定することがあるのでしょうか?

専門家に質問してみよう