• ベストアンサー

BitBlt関数について教えてください

よろしくお願いします。 画像を読み込むための、BitBlt関数について、色々調べてみたのですが、どうしても分からない記述が2つあります。ご指導、アドバイスをお願いします。 1、サンプルのソースを参考にしているのですが、BitBlt関数の第2、第3の記述の意味として、 『PAINTSTRUCT構造体のポインタpsが、左隅上、を参照している』と解釈したのですが、第4、第5引数の、-(引く)の意味が理解できません。 2、画像を2種類表示するためメニューに、『オプション1とオプション2』を作り、オプション1はコピー元と同じ画像を表示、 オプション2は、ラスタオペレーションを選択可能にして、選択した画像を表示すると言うものですが、DWORD dwRop; を宣言し『第9引数をNOTSRCCOPY』として、二つ目の画像を表示する case文に dwRop = NOTSRCCOPY; を追加したのですがうまく行きません。多分 『dwRop』の使い方に問題があるのかと思うのですが、うまく表示されません。 因みに、 BitBlt関数の第9引数が『SRCCOPY』の時は、正常に2種類の画像が表示されます。 /*ウィンドウプロシージャ*/  LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)  { HDC hdc;  DWORD dwRop; //追加した  PAINTSTRUCT ps;  HBITMAP hBmp;  HDC hdc_memx;  switch(msg){  case WM_CREATE:  hdc = GetDC(hWnd);  hBmp = LoadBitmap(hInst, "MYBMP1");  if(hBmp == NULL){  MessageBox(hWnd, "画像1のロードに失敗しました", "エラー",  MB_OK | MB_ICONWARNING);  return 0;  }  hdc_mem1 = CreateCompatibleDC(hdc);  SelectObject(hdc_mem1, hBmp);  DeleteObject(hBmp);  hBmp = LoadBitmap(hInst, "MYBMP2");  if(hBmp == NULL){   MessageBox(hWnd, "画像2のロードに失敗しました", "エラー",   MB_OK | MB_ICONWARNING);  return 0;  } hdc_mem2 = CreateCompatibleDC(hdc);  SelectObject(hdc_mem2, hBmp);  DeleteObject(hBmp);  ReleaseDC(hWnd, hdc);  break;  case WM_PAINT:  BeginPaint(hWnd, &ps);  if(show_no == 1) hdc_memx = hdc_mem1;  if(show_no == 2) hdc_memx = hdc_mem2;  BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdc_memx, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);  // PATCOPYにして,IDM_ANIME2に、dwRop=NOTSRCCOPY //を追加しても変更されないし、画像の表示が出来ない EndPaint(hWnd, &ps);  break; case WM_COMMAND: switch (LOWORD(wp)){ case IDM_ANIME1: show_no = 1;      //dwRop = SRCCOPY //追加したが変化なし InvalidateRect(hWnd, NULL, TRUE); break;  case IDM_ANIME2: show_no = 2; //dwRop = NOTSRCCOPY; //追加したが変化なし InvalidateRect(hWnd, NULL, TRUE); break;  case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; } break;  case WM_DESTROY: DeleteDC(hdc_mem1); DeleteDC(hdc_mem2); PostQuitMessage(0); break;  default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

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

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, は 書き換えが必要な部分つまり 無効になっている部分を算出しています BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdc_memx, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); の SRCCOPYを dwRopに変更します つまり BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdc_memx, ps.rcPaint.left, ps.rcPaint.top, dwRop); dwRopを設定する部分を実装します ... メニューイベントの対応とかです dwRopが大域変数ならいいのですが WndProcのローカル変数ならstatic属性を指示しましょう PATCOPYはデバイスコンテキストに指定されたブラシをコピーするのに用います BitBltで指定する場合 第一引数のデバイスコンテキストで選択されているブラシが対象です 普通は PatBltで使います

noname#220054
質問者

お礼

アドバイス有難うございます。 早速 『BitBlt()の、第9引数』をdwRopに 変更し、メニューリソースも変更しました。 ファイルとオプションを作り、ファイルからは画像1、画像2の選択肢 オプションには、ラスタオペレーションの選択肢を作りました。 結果、ぶじにコンパイルできました。 ただ、一つ気になることがあるのですが、ファイルをクリックした時に、クライアント領域が真っ黒く表示されます。 その後に画像を選択すると、クライアント領域が白く変わり、そこに画像が表示されます。 この真っ黒になる原因が理解できません。これから白いクライアント領域に修正したいと思っっています。 何かお気づきでしたら、アドバイスをお願いします。

noname#220054
質問者

補足

アドバイス、有難うございます。 ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, については、VTClientさんのアドバイスで、少し意味が分かりかけていたのですが、『画像を算出しているのではなく、無効領域を算出していたのですね』 すっきりしました。 また、 BitBlt()の、第9引数の、『SRCCOPY』を 『変数のdwRop』に変えるのは 『もしかしたら』 と思ったのですが、これで確信が持てました。 変更すると、ソースの記述や、メニューリソースも変更ですね。 それと、PATCOPYの使い方が間違ってました。ご指摘有難うございます。 ラスタオペレーションの使い方も、もう少し調べてみます。 これから早速ソースを変更して試してみます。 結果は、お礼のほうに報告したいと思います。

すると、全ての回答が全文表示されます。

その他の回答 (2)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

show_noの値が初期化されていない場合または 1or2以外の場合 hdc_memxが不定になってしまっていませんか show_noが 1or2以外だったら BitBltを実行しないようにするとか WM_CREATEで LoadBitmap(hInst,"MYBMP1")が成功したら show_noを1に初期化するとか デバイスコンテキストに選択したグラフィックオブジェクトを選択をはずす前に DeleteObjectで削除するのはお勧めしません MSDNなどで DeleteObjectなどを検索してみてください

noname#220054
質問者

お礼

再度のアドバイス、有難うございます。 ご指摘のとおり 『show_no1,show_no2 』以外のときの処理が出来ていませんでした。 WM_CREATEで、ウィンドウが作られたら画像を表示する様にしたら、改善されました。 後は、いろいろの記述を試して見ます。 貴重なアドバイスを有難うございました。

すると、全ての回答が全文表示されます。
noname#50176
noname#50176
回答No.1

<1> BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdc_memx, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); の ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, は幅、高さを指定します。つまり座標が (10,10) - (100,80) であるとき、幅は、100 - 10 = 90 / 高さは 80 - 10 = 70 ですから差分で算出するわけです。 でもクライアント座標は (0,0) - になるので引く必要はないの ですがスクリーン座標を想定して引くべきですね。 <2> DWORD dwRop; //追加した を static DWORD dwRop; に変更してはだめですか?

noname#220054
質問者

補足

早いアドバイス有難うございます。 ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, の記述を分かりやすく説明していただき、有難うございます。 rcPaintメンバ(無効領域)から、無効でない部分(画像)を算出しているのですね。 また、『DWORD dwRop』を、『static DWORD dwRop』 に変更して試してみたのですが、 画像2は、反転表示されませんでした(普通の画像)。 この時、BitBlt()の、第9引数は、『SRCCOPY』ですが、ここを『PATCOPY』に変更すると、画像1、画像2、どちらも表示されません。 第9引数の設定が悪いのでしょうか? 色々調べてみますが、何かお気づきの所がありましたら、アドバイスをお願いします。

すると、全ての回答が全文表示されます。

関連するQ&A