ビットマップ画像の表示

このQ&Aのポイント
  • 24bitのビットマップ画像を正確に表示するには?
  • ビットマップ画像の表示が動作しない問題の解決方法
  • Visual Studio 2005でのビットマップ画像表示の問題点と解決策
回答を見る
  • ベストアンサー

ビットマップ画像の表示

どうしても正確に動作をしないので、問題点をご指摘していただきたいです。 開発環境は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関数だけではなく、そのほかに設定することがあるのでしょうか?

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

  • ベストアンサー
  • bushclean
  • ベストアンサー率26% (6/23)
回答No.1

BeginPaintまで見て、ふと思ったのですが、hdc = BeginPaint( ... に変えてみては? 私も考えたことなく、hdcは定石の上記方法で無思考に書いてましたが、 http://wisdom.sakura.ne.jp/system/winapi/win32/win16.html >そこで、BeginPaint()関数を用います >この関数は PAINTSTRUCT のポインタを受け取り、それをを初期化し >無効領域を再び描きなおしてクライアントエリアを有効にします と、既にPAINTSTRUCT構造体の中身は(BeginPaintで使用された後に) 破棄されて無意味なものになっているのかもしれません。

seven_star
質問者

お礼

返答ありがとうございました。 bushclean様のアドバイスを受け、返値としてhdcを受け取りSetDIBitsToDeviceの引数に渡してみたのでしたが、描画されませんでした。 自分でも、解決策を考えています。

関連するQ&A

  • CTreeCtrlのCreate関数でエラーになります。

    Visual C++ .NET Win32 プロジェクト で、アプリケーションを作成しようと思っています。 #include<afxwin.h> #include<afxcmn.h> // マルチスレッド CTreeCtrl *m_TreeCtrl; LRESULT CALLBACK int WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_LBUTTONDOWN: m_TreeCtrl=new CTreeCtrl; m_TreeCtrl->Create(WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_BORDER | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_DISABLEDRAGDROP, CRect(10, 10, 300, 100), CWnd::FromHandle(hWnd), 10000); break; case WM_CREATE: break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: HDC hDC; PAINTSTRUCT Paint; hDC=BeginPaint(hWnd,&Paint); EndPaint(hWnd,&Paint); } return DefWindowProc(hWnd,message,wParam,lParam); } ・・・ と記述すると、エラーになります。 解決方法を教えてください。

  • WindowsSDKのCALLBACK内について

    猫でも分かるWindowsSDKを参考にして、とりあえずウィンドウプロシージャの関数内を下のようにしてプログラムを組んでみました。 //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_CREATE: break; case WM_TIMER: break; case WM_PAINT: break; case WM_COMMAND: break; case WM_CLOSE: SendMessage(hWnd, WM_DESTROY, wp, lp); break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; } しかし、これで何もないWindow表示をさせるとCPU使用率が80%くらいまで跳ね上がります。 調べてみたところcase WM_PAINT:を削ったらCPU使用率が下がりました。 普通にクライアント領域に文字を表示したり画像を表示したりするだけだったら、それほどCPU使用率が上がらないのに、上のようにあらかじめ用意しておいたらCPU使用率が跳ね上がるのは何故でしょうか。 まだ勉強したてでレベルの低い質問でしたらすみません。

  • 子ウインドウの作成と破棄について

    CALLBACK のみを書きました。 メインウインドウを破棄したら 子ウインドウも破棄したいのですが、 うまく出来ません。 どうすればよろしいでしょうか? よろしくお願いします。 #include<windows.h> #include"ChildWindow.h" char MainWindowClassName[]="mainwindow"; LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { static HWND childWnd; switch(message) { case WM_ACTIVATEAPP: childWnd=Child_CreateWindow(hWnd,message,wParam,lParam); break; case WM_DESTROY: DestroyWindow(childWnd); PostQuitMessage(0); break; default: return DefWindowProc(hWnd,message,wParam,lParam); } } ///////////////////////////////////////////// #include<windows.h> char ChildWindowClassName[]="childwindow"; LRESULT CALLBACK ChildProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_LBUTTONDOWN: MessageBox(NULL,"","",MB_OK); break; default: return DefWindowProc(hWnd,message,wParam,lParam); } } ATOM Child_RegistWindow(HINSTANCE hInstance){} HWND Child_InitInstance(HWND hParentWnd,HINSTANCE hInst,int CmdShow){} HWND Child_CreateWindow(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { int CmdShow=1; Child_RegistWindow(NULL); HWND ChildWnd=Child_InitInstance(hWnd,NULL,CmdShow); MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return ChildWnd; }

  •    ダイアログのクラス化で仮想関数を用いて派生クラスにしているんです

       ダイアログのクラス化で仮想関数を用いて派生クラスにしているんですが・・・ ダイアログを基本クラスで静的プロシージャと派生クラスでオーバーライドしてプロシージャを使いたい のですが、どうしても自身のポインタが取得できません。 以下にソースを載せておきます。  class CBaseWnd  {  public:    // ポインタの設定    void SetPointer( HWND hWnd );    // ウィンドウプロシージャの呼び出し    static LRESULT CALLBACK CallProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );    // ウィンドウプロシージャの実装    virtual LRESULT MainProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );  }; [クラスの実装]  //===== ポインタの設定 =====//  void CBaseWnd::SetPointer( HWND hWnd )  {    SetWindowLong( hWnd, GWL_USERDATA, (LONG)this );  }  //===== ウィンドウプロシージャの呼び出し =====//  LRESULT CALLBACK CBaseWnd::CallProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )  {    //_プロパティリストからthisポインタを取得 //ここでポインタを取得することができないでいます。値が0です。 //先にSetWindowlongをやっても値が0のままです。    CBaseWnd* thisPtr = (CBaseWnd*)GetWindowLong( hWnd, GWL_USERDATA );    //_thisポインタが取得できなかった場合...    if( ! thisPtr )    {      //_ウィンドウの作成時の場合... //ここでアクセス違反というエラーが起きる      if( message == WM_INITDIALOG )        thisPtr = (CBaseWnd*)((LPCREATESTRUCT)lParam)->lpCreateParams;      //_thisポインタが取得できた場合...      if( thisPtr )      {        //_プロパティリストにオブジェクトハンドル(thisポインタ)を設定する        thisPtr->SetPointer( hWnd );      }    }    //_thisポインタが取得できた場合...    if( thisPtr )    {      LRESULT lResult = thisPtr->MainProc( hWnd, message, wParam, lParam );      return lResult;    }    return DefWindowProc( hWnd, message, wParam, lParam );  }  //===== ウィンドウプロシージャの実装(継承可能) =====//  // ここでの記述はデフォルトの処理  //  LRESULT CBaseWnd::MainProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )  {    switch( message )    {      //_ウィンドウが破棄された場合      case WM_DESTROY:        PostQuitMessage(0);        return 0;        //_デフォルトの場合      default:        return DefWindowProc( hWnd, message, wParam, lParam );    }  } WM_INITDIALOGでダイアログの初期化中にポインタを取得しようとしますが、アクセス違反が起こり失敗します。 どなたか分かる方がいらっしゃったらご指摘お願いします。

  • TextOut( ) が動かない

    LRESULT CALLBACK WndProc( HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam){ PAINTSTRUCT ps; HDC hdc; switch(msg){ case WM_KEYDOWN:  if( wParam == VK_ESCAPE ){   hdc = BeginPaint(hWnd, &ps);   TextOut(hdc,0,0,str,strlen(str));   EndPaint(hWnd, &ps);  }  break; case WM_PAINT:  break; エスケープキーで文字表示をやりたいけど TextOut( ) が動作していないみたいでした。 switch(msg){ case WM_KEYDOWN:  if( wParam == VK_ESCAPE ){   hdc = BeginPaint(hWnd, &ps);   TextOut(hdc,0,0,str,strlen(str));   EndPaint(hWnd, &ps);  }  break; case WM_PAINT:  hdc = BeginPaint(hWnd, &ps);  TextOut(hdc,0,0,str,strlen(str));  EndPaint(hWnd, &ps);  break; とすると、常に文字が表示されたから、やっぱり case WM_KEYDOWN: の中の TextOut( ) が 動作していないんだと思いました。 TextOut( ) は case WM_PAINT: からのつながりが ある場合でないと実行されないんですか? ソースのおかしいところがあったら教えてください。

  • WM_VSCROLL内の実行回数について

    Visual Studio 2010 Express WIN32 ユニコードビルド C言語 でクライアント領域に縦スクロールバーを貼り付け次のようなプログラムを作りました。 スクロールバーの勉強中に適当に作ったプログラムです。 LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { PAINTSTRUCT ps; TCHAR moji[256]; static int countout=0; static int countin=0;       switch(message){       case WM_PAINT: BeginPaint(hwnd,&ps); wsprintf(moji,TEXT("switch文の外=%d回 switch文の中=%d"),countout,countin); TextOut(ps.hdc,0,0,moji,lstrlen(moji)); EndPaint(hwnd,&ps); break; case WM_VSCROLL: countout=countout+1; switch(LOWORD(wParam)){ case SB_LINEDOWN: countin=countin+1; break; } InvalidateRect(hwnd,NULL,TRUE); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,message,wParam,lParam); } return 0; } 私はこのプログラムの実行結果は スクロールバーのどこをクリックしてもcountoutは+1され下の矢印をクリックしたときはcountinが+1 されるという動作になると思ったのですが実行してみると スクロールバーの矢印をクリック countout が+2 スクロールバーのつまみをクリック countout が+3 スクロールバーの下矢印をクリック countout が+2,countinが+1 されるという結果になりました。 この結果から推測するとVSCROLLバーをクリックしたときはWM_VSCROLL:メッセージが複数回送られているということになると思うのですがどうしてこうなるのでしょうか? プログラミングの本などではWM_VSCROLL:の中のswitch文の外に初期化やInvalidateRectがあるのでWM_VSCROLLメッセージが送られるのは1回だけだと思ったのですが・・・・。

  • MessageBoxについて

    次のようなプログラムを作りました。 /*ウィンドウプロシージャ内*/ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){   ・・・  case WM_LBUTTONDOWN:    hantei(hWnd);    break;   ・・・ } /* 判定関数 */ void hantei(HWND hWnd){   MessageBox(hWnd,"テスト","テストです。",MB_OK); } このようになって動かしてみた(左クリックした)ところ、 ウィンドウ自体は非アクティブになったのですが、 BEEP音が鳴るだけで肝心のメッセージボックスが表示されません。 ALTキーを押すと表示されるのですが・・・ 左クリックをするとすぐにメッセージボックスを表示させるにはどうしたらよいのでしょう? 言葉足らずの説明かもしれませんがお願いします。

  • ソースを見てください。お願いします

    始めまして、Missing0001と申します。 ウィンドウズプログラムをしていて、 他のところは正常に動いているのにMoveWindow関数の場所だけ思うように動きません。 どなたかソースの間違っているところを指摘していただけないでしょうか? したいことはButtonのマウスでの移動です。 BtProc・・・サブクラス(Button)のプロシージャ DrawRect・・・Buttonのサイズの四角形を描いたり消したりするもの LRESULT CALLBACK BtProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { static BOOL Btn_Flag = false; static POINTS end,old_end; char Str[512]; switch(uMsg) { case WM_LBUTTONDOWN: Btn_Flag = true; old_end = MAKEPOINTS(lParam); DrawRect(hWnd,old_end); break; case WM_MOUSEMOVE: if(Btn_Flag) { end = MAKEPOINTS(lParam); DrawRect(hWnd,old_end); DrawRect(hWnd,end); old_end = end; } else { return CallWindowProc(fnBtProc,hWnd,uMsg,wParam,lParam); } break; case WM_LBUTTONUP: if(Btn_Flag) { DrawRect(hWnd,end); MoveWindow(hWnd,end.x,end.y,50,30,true); ←ここがうまくいかない Btn_Flag = false; } else { return CallWindowProc(fnBtProc,hWnd,uMsg,wParam,lParam); } } return CallWindowProc(fnBtProc,hWnd,uMsg,wParam,lParam); }

  • ウィンドウが表示されない

    あるサンプルプログラムを改造しようとしているのですが、g_hWnd=CreateWindow( _T(__FILE__),_T("シューティングゲーム"),WINDOW_STYLE, CW_USEDEFAULT,CW_USEDEFAULT,rc.right-rc.left,rc.bottom-rc.top, NULL,NULL,hInst,NULL);のところのWINDOW_STYLEをWS_OVERLAPPEDWINDOWに変えたらウィンドウが表示されません。どうしたら表示されるのでしょうか。わかる方いらいしたらご教授お願いします。多分ここだろうなというところのコードを載せます。 LRESULT CALLBACK MainWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) { switch(msg) { case WM_KEYDOWN: switch(wParam) { case VK_F1: ChangeDisplayMode(); return 0; case VK_ESCAPE: PostMessage(hWnd,WM_CLOSE,0,0); return 0; } return 0; case WM_DISPLAYCHANGE: // IDirect3DDevice9::Reset メソッドから Send される DisplayChange(); return 0; case WM_SIZE: if(g_bWndMode==false || wParam==SIZE_MINIMIZED) return 0; g_D3DPP.BackBufferWidth = LOWORD(lParam); g_D3DPP.BackBufferHeight = HIWORD(lParam); if(wParam==SIZE_MAXIMIZED || wParam==SIZE_RESTORED) ChangeWindowSize(); return 0; case WM_ACTIVATE: g_bActive=(LOWORD(wParam)!=WA_INACTIVE); return 0; case WM_DESTROY: CleanupD3DObject(); CleanupDXGraphics(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd,msg,wParam,lParam); }

  • キィーボードをフックしません、何故ですか???

    パソコンを現在人間が実際に操作中であるか否かを判定しながら進めるアプリを作っています 簡易的にキィーボードを操作していれば操作中と判断します(マウス操作も含めますが話を簡単にするため今はキィーだけとします) グローバルフックでKEY_DOWNをフックする為に以下のDLL(主要部分のみ)を作りました キィーが押されるとMW_KEYDOWN_DLLというメッセージをアプリに送ります EXPORT LRESULT CALLBACK HookProc( int nCode, WPARAM wParam, LPARAM lParam) { if(nCode == HC_ACTION) { CWPSTRUCT *pcwp = (CWPSTRUCT *)lParam; if(pcwp->message == WM_KEYDOWN) { SendMessage(g_hWnd, WM_KEYDOWN_DLL, pcwp->wParam, pcwp->lParam); ←(1) } } return (CallNextHookEx(g_hHook, nCode, wParam, lParam)); } MW_KEYDOWN_DLLメッセージを受けたアプリは操作中フラグを立てます(主要部分のみ) LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_KEYDOWN_DLL: ここで操作中フラグを立てます ←(2)  このフラグは一定時間後にタイマーが倒します break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return (0L); } 実行してみると(1)に来ません、当然(2)のフラグは立ちません WM_KEYDOWNの代わりにWM_CREATE、WM_CLOSEだときちんとフックします WM_CHAR、MW_KEYUPなどのキィーボード系のメッセージだとフックしません なぜでしょうか??? 多分きわめて初歩的な知識の欠如によるものでしょうが分かりません 宜しくご指導願います

専門家に質問してみよう