• ベストアンサー

画像の転送処理について

前後の処理は省くとして 1.CreateCompatibleDCでメモリデバイスコンテキスト作成 2.SelectObjectでビットマップオブジェクトを選択 3.BitBltで画像を転送 4.SelectObjectで元のオブジェクトを選択 5.DeleteDCでメモリデバイスコンテキストを削除 サンプルを公開されているサイトここのような書き方になっているのですが 5. の段階で削除するのであれば 4. の元に戻す処理の必要性がわかりません。 ※BitBltの直後にSelectObjectで戻し、DeleteDCで削除しており、  間に余計な処理は入っていません。 上記の処理を行う場合、 1.CreateCompatibleDCでメモリデバイスコンテキスト作成 2.SelectObjectでビットマップオブジェクトを選択 3.BitBltで画像を転送 4.DeleteDCでメモリデバイスコンテキストを削除 このようなやり方だと問題ありますでしょうか?

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8520/19368)
回答No.2

1.CreateCompatibleDCでメモリデバイスコンテキスト作成 2.SelectObjectでビットマップオブジェクトを選択 3.BitBltで画像を転送 4.SelectObjectで元のオブジェクトを選択 5.DeleteDCでメモリデバイスコンテキストを削除 2の処理で、選択するビットマップハンドルのユースカウントが1だけインクリメントされます。 4の処理で、選択解除するビットマップハンドルのユースカウントが1だけデクリメントされます。 4の処理が無いと、ビットマップハンドルのユースカウントがインクリメントされたままでデクリメントされません。 そして、ユースカウントが0でないビットマップオブジェクトをDeleteObjectしようとすると、DeleteObjectはエラーを返します。 つまり「ビットマップをDCに割り当てたままだと思い込み、そのビットマップを削除出来なくなる」のです。 この「削除できなかったビットマップ」は、OSを再起動するか、OSをシャットダウンするまでずっと生き残るので、もし「同様の処理が繰り返して行われる」と、最後はシステムリソースが尽きてOS自身がリソース不足で落ちてしまいます。 先ほどの1.~5.の処理の前後には、以下のように「0.」と「6.」の処理がある筈です。普通、別の場所に書いてあるので、見落としがちです。 0.(起動時に1回だけ)CreateBitmap等でビットマップ作成 1.CreateCompatibleDCでメモリデバイスコンテキスト作成 2.SelectObjectでビットマップオブジェクトを選択 3.BitBltで画像を転送 4.SelectObjectで元のオブジェクトを選択 5.DeleteDCでメモリデバイスコンテキストを削除 6.(終了時に1回だけ)DeleteObjectでビットマップ破棄 上記の6.の処理を確実に成功させ、確実にビットマップを破棄するためには、4.の処理でDCとの紐付けを解除する必要があるのです。 上記の仕様は最新のWindowsでも変わっていません。4.の処理は必ず必要です。 しかし、このような「DCとの紐付けの解除忘れ」をする人が多かった為か、最近のWindowsでは紐付けられたDCが削除済みであれば、DeleteObjectがエラーを返さないでオブジェクトを破棄出来るように改良されています(「解除を忘れてる」には違わないので、忘れても動いちゃう事が良い事なのかどうか疑問ですが…)

その他の回答 (1)

  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.1

Windows 3.1/95/98の時代では、そうしないとリソースを食いつぶしOSが不安定になることが多かった気がします。 2000/XPになってからはリソースの管理がうまくなっているようなので滅多に不安定になりませんがね。 おそらくビットマップオブジェクトを選択したままデバイスコンテキストを解放してしまうと、ビットマップオブジェクトが解放できない、ということだと思います。つまりお互い必要とされている、というフラグがたったまま片方が解放されると、もう一つが残されたままになる。。 やっぱちゃんとお行儀良くした方がよいですよ 笑

関連するQ&A

  • Active Basic 画像の透過処理

    AB4.23.00を使っています。 簡単なゲームを作ろうと思って作成を進めているのですが、 画像を透過する処理でつまずいてしまいました。 Sub ShowPictures() /*ピクチャを描写する*/ Dim n As Long Dim hDC As HDC Dim hMyMaskDC As HDC '自機マスク用 Dim hMyMaskBmp As HBITMAP '自機マスク用 Dim hMyTempDC As DWord Dim hMyTempBmp As DWord hDC=GetDC(hMainWnd) '背景 BitBlt(hMemDC,0,0,640,480,hBackDC,0,0,SRCCOPY) '敵画像 For n=0 to 100 Step 1 BitBlt(hMemDC,ex[n],ey[n],30,30,hEneDC[n],0,0,SRCCOPY) Next '自機描写 hMyMaskDC=CreateCompatibleDC(hDC) hMyMaskBmp=CreateBitmap(40,50,1,1,0) SelectObject(hMyMaskDC,hMyMaskBmp) BitBlt(hMyMaskDC,0,0,x,y,hMyDC,0,0,SRCCOPY) hMyTempDC=CreateCompatibleDC(hDC) hMyTempBmp=CreateCompatibleBitmap(hDC,40,50) SelectObject(hMyTempDC,hMyTempBmp) BitBlt(hMyTempDC,0,0,x,y,hMyMaskDC,0,0,NOTSRCCOPY) 'BitBlt(hMyTempDC,0,0,x,y,hMyDC,x,y,SRCAND) 'キャラクタ画像をOR転送 BitBlt(hMemDC,0,0,x,y,hMyTempDC,0,0,SRCPAINT) 'マスク画像をAND転送 BitBlt(hMemDC,0,0,x,y,hMyMaskDC,0,0,SRCAND) 'マスク用画像をメモリから解放 DeleteDC(hMyMaskDC) DeleteObject(hMyMaskBmp) 'キャラクタの一時画像をメモリから解放 DeleteDC(hMyTempDC) DeleteObject(hMyTempBmp) InvalidateRect(hMainWnd,ByVal 0,FALSE) DeleteObject(hMyMaskBmp) DeleteDC(hMyMaskDC) End Sub 描写処理のルーチンです。 これを実行すると、黒い塊になってしまいます。 どのように書けば、ちゃんと表示できるようになるのでしょうか。 すみませんが、ご教授をお願いします。

  • Active Basic 自動でマスク画像を制作して、画像を透過する方法

    ABの4.23.00を使用しています 今回、マスク画像を自動的に作成して、ビットマップ画像を透過して表示させる方法を考えているのですが、なかなかうまくいきません。 皆さんの知識をお貸しください。 とりあえず、グローバルで変数を用意しました。 Dim hMemDC As HDC Dim hMemBmp As HBITMAP Dim hIconDC As HDC Dim hIconBmp As HBITMAP BITMAPリソースに適当な画像を入れて、クリエイトイベントで変数に読み込みました。 ※ビットマップの大きさは、32*32の物を使用してみました。 Dim hDC As HDC hDC=GetDC(hMainWnd) hIconDC=CreateCompatibleDC(hDC) hMemDC=CreateCompatibleDC(hDC) hIconBmp=LoadBitmap(GetModuleHandle(0),IDB_BITMAP1) hMemBmp=CreateCompatibleBitmap(hDC,300,300) SelectObject(hIconDC,hIconBmp) SelectObject(hMemDC,hMemBmp) 背景の色を指定しました SetBkColor(hIconDC,GetPixel(hIconDC,0,0)) とりあえず、hMemDCに画像をコピーしました。 BitBlt(hMemDC,0,0,32,32,hIconDC,0,0,SRCCOPY) ReleaseDC(hMainWnd,hDC) 次に、再描写の処理のときに、マスク画像を用意する処理を入れてみたのですが、うまくいきません。 Dim hMaskDC As HDC Dim hMaskBmp As HBITMAP Dim hTempDC As HDC Dim hTempBmp As HBITMAP hMaskDC=CreateCompatibleDC(hMemDC) hMaskBmp=CreateBitmap(32,32,1,1,0) SelectObject(hMaskDC,hMaskBmp) BitBlt(hMaskDC,0,0,32,32,hIconDC,0,0,SRCCOPY) hTempDC=CreateCompatibleDC(hDC) hTempBmp=CreateCompatibleBitmap(hMemBmp,32,32) SelectObject(hTempDC,hTempBmp) BitBlt(hTempDC,0,0,32,32,hMaskDC,0,0,NOTSRCCOPY) BitBlt(hTempDC,0,0,32,32,hIconDC,0,0,SRCAND) BitBlt(hMemDC,0,0,32,32,hMaskDC,0,0,SRCAND) BitBlt(hMemDC,0,0,32,32,hTempDC,0,0,SRCPAINT) DeleteDC(hMaskDC) DeleteObject(hMaskBmp) DeleteDC(hTempDC) DeleteObject(hTempBmp) BitBlt(hDC,0,0,32,32,hMemDC,0,0,SRCCOPY) このような感じで書いてみました すみませんが、添削をお願いします

  • GetPixelに使うHDCの作り方

    ビットマップハンドルhBitmap の(x,y)の画素の色を読み取るプログラムに使うデバイスコンテキストとして、  hDC = CreateCompatibleDC(NULL);  SelectObject(hDC, hBitmap);  rgb = GetPixel(hDC, x,y);  DeleteDC(hDC); のように、NULL を指定して、画面と互換性のあるメモリデバイスコンテキストを指定したのですが、正しい色が読み出せません。hDC = GetDC(NULL);でも同じく駄目でした。hDCはどのように作ったらよいのでしょう。 なお、関数の中でGetPixel()を使いたいので、hWnd などは使えません。

  • 透過済み画像を作りたい

    プログラムを始めたところの初心者です。 画像を透過し、ウインドウに表示させたいので、いろいろ探してみたところ、 マスクを自動で作成すると言う物があったので、参考にさせてもらいました。 さらに、その中に、『同じように透過済み画像を作れる』とあったので、いろいろ試したのですが、ダメでした・・・ よろしければ、やり方を教えていただけないでしょうか。 http://oshiete1.goo.ne.jp/qa5254128.html 上を参考にさせていただきました Dim hDC as HDC, hTemp As HDC, hDest as HDC,hOriDC As HDC Dim hBmpTemp as HBITMAP, dummy(3) as HBITMAP,hOriBmp As HBITMAP Dim bmp as BITMAP Dim hMemDC As HDC,hMemBmp As HBITMAP hDC=GetDC(NULL) hTemp=CreateCompatibleDC(hDC) hDest=CreateCompatibleDC(hDC) hOriDC=CreateCompatibleDC(hDC) hMemDC=CreateCompatibleDC(hDC) ReleaseDC(NULL,hDC) ' 元画像の情報の取得 GetObject(hBmp,Len(bmp),bmp) ' モノクロBITMAPの生成 hBmpTemp=CreateCompatibleBitmap(hDest,bmp.bmWidth,bmp.bmHeight) hOriBmp=CreateCompatibleBitmap(hOriDC,bmp.bmWidth,bmp.bmHeight) hMemBmp=hBmp dummy(0)=SelectObject(hTemp,hBmp) dummy(1)=SelectObject(hDest,hBmpTemp) dummy(2)=SelectObject(hOriDC,hOriBmp) dummy(3)=SelectObject(hMemDC,hMemBmp) SetBkColor(hTemp,GetPixel(hTemp,0,0)) ' 背景マスクの生成 BitBlt(hDest,0,0,bmp.bmWidth,bmp.bmHeight,hTemp,0,0,SRCCOPY) 'スプライト BitBlt(hOriDC,0,0,bmp.bmWidth,bmp.bmHeight,hDest,0,0,NOTSRCCOPY) BitBlt(hOriDC,0,0,bmp.bmWidth,bmp.bmHeight,hTemp,0,0,SRCAND) '透過 BitBlt(hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,hDest,0,0,SRCAND) BitBlt(hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,hOriDC,0,0,SRCPAINT) ' HBITMAPの切り離し SelectObject(hTemp,dummy(0)) SelectObject(hDest,dummy(1)) SelectObject(hOriDC,dummy(2)) SelectObject(hMemDC,dummy(2)) ' HDCの後始末 DeleteDC(hTemp) DeleteDC(hDest) DeleteDC(hOriDC) DeleteDC(hMemDC) ' 呼び出し元への返り値 MakeMaskWith=hMemBmp

  • [Active Basic]BitBltで画像を表示

    ActiveBasicでプログラムを書いています。 少しずつデバイスコンテキストが使えるようになってきて、簡単なブロック崩しを作ってみようと思い、作り始めました。 以前、デバイスコンテキストを使えるようになろうと、上から物体が降ってきて、それを避けるというゲームを書いてみたのですが、画像(ビットマップ)の表示方法が分からず、すべて MainWnd_Paint(hDC As HDC) に中に書きました。 すると、処理ごとにいらないものまで描写されるので画面がかなりちらついてしまいました。 ActiveBasicのヘルプ(http://www.activebasic.com/help_center/articles/win32/step16/index.html)を参考にして、プログラムを書いてみたのですが、背景が描写されません。 コードを下に書きますので、すみませんが添削の方をお願いします。 まだ、プログラムを始めたばかりのほやほやですので、なるべくやさしくお願いします。 '------------グローバル------------ Dim ImgBack As HBITMAP '背景画像 Dim hBackDC As HDC '背景画像用デバイスコンテキスト Dim hMemDC As HDC 'BitBlt用のデバイスコンテキスト '------------グローバル------------ Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT) Dim hDC As HDC 'イメージを読み込んでいく ImgBack = LoadImage(0,".\pic\back.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE) 'デバイスコンテキストをそれぞれ作成 hDC = GetDC(hMainWnd) hBackDC = CreateCompatibleDC(hDC)'背景用DC hMemDC = CreateCompatibleDC(hDC)'BitBlt用DC '背景を描写 SelectObject(hBackDC,ImgBack) BitBlt(hMemDC,0,0,640,480,hBackDC,0,0,SRCCOPY) '最後にhDCだけ開放 ReleaseDC(hMainWnd,hDC) End Sub Sub MainWnd_Paint(hDC As HDC) End Sub 後、BitBltを MainWnd_Paint(hDC As HDC) の中に表記すると、画像が表示されます。 何故か、いまいち分かっていません・・・ すみませんが、ご教授ください。

  • ActiveBasic 透過画像の作り方

    ゲームを作っています。 そのときに、背景を透過した画像を作る関数を書いたのですが、どうしてもうまく処理が出来ません。 Function CreateMask(hBmp As HBITMAP) As HBITMAP Dim hDC As HDC Dim hBaseDC As HDC,hBaseBmp As HBITMAP Dim hMaskDC As HDC,hMaskBmp As HBITMAP Dim hTempDC As HDC,hTempBmp As HBITMAP Dim hCompDC As HDC,hCompBmp As HBITMAP Dim bmp As BITMAP Dim dummy[5] As HBITMAP hDC=GetDC(hMainWnd) hBaseDC=CreateCompatibleDC(hDC) hMaskDC=CreateCompatibleDC(hDC) hTempDC=CreateCompatibleDC(hDC) hCompDC=CreateCompatibleDC(hDC) GetObject(hBmp,len(bmp),bmp) hMaskBmp=CreateCompatibleBitmap(hMaskDC,bmp.bmWidth,bmp.bmHeight) hBaseBmp=CreateCompatibleBitmap(hDC,bmp.bmWidth,bmp.bmHeight) hCompBmp=CreateCompatibleBitmap(hDC,bmp.bmWidth,bmp.bmHeight) dummy[0]=SelectObject(hTempDC,hBmp) dummy[1]=SelectObject(hMaskDC,hMaskBmp) dummy[2]=SelectObject(hBaseDC,hBaseBmp) dummy[3]=SelectObject(hCompDC,hCompBmp) SetBkColor(hTempDC,GetPixel(hTempDC,0,0)) BitBlt(hMaskDC,0,0,bmp.bmWidth,bmp.bmHeight,hTempDC,0,0,NOTSRCCOPY) BitBlt(hBaseDC,0,0,bmp.bmWidth,bmp.bmHeight,hTempDC,0,0,SRCCOPY) BitBlt(hBaseDC,0,0,bmp.bmWidth,bmp.bmHeight,hMaskDC,0,0,SRCAND) BitBlt(hMaskDC,0,0,bmp.bmWidth,bmp.bmHeight,hMaskDC,0,0,NOTSRCCOPY) BitBlt(hCompDC,0,0,bmp.bmWidth,bmp.bmHeight,hMaskDC,0,0,SRCAND) BitBlt(hCompDC,0,0,bmp.bmWidth,bmp.bmHeight,hBaseDC,0,0,SRCPAINT) SelectObject(hTempDC,dummy[0]) SelectObject(hMaskDC,dummy[1]) SelectObject(hBaseDC,dummy[2]) SelectObject(hCompDC,dummy[3]) DeleteDC(hTempDC) DeleteDC(hMaskDC) DeleteDC(hBaseDC) DeleteDC(hCompDC) CreateMask=hCompBmp End Function とりあえず、いろいろと実験したところ、 背景を黒くしたもの(hBaseDC)とマスク画像(hMaskDC)はちゃんと出来ています。 おそらく問題なのは、 BitBlt(hCompDC,0,0,bmp.bmWidth,bmp.bmHeight,hMaskDC,0,0,SRCAND) BitBlt(hCompDC,0,0,bmp.bmWidth,bmp.bmHeight,hBaseDC,0,0,SRCPAINT) ここではないかと思っています。 これを処理すると、背景を黒くしたもの(hBaseDC)と同じものが出てきます。 これを透過するにはどうしたらいいのでしょうか? ご教授お願いします。 Win.XP AB 4.23.00

  • CreateCompatibleDCが返した値の開放

    hdc = CreateCompatibleDC( GetDC(hWnd) ); //色々な条件による処理 SelectObject( hdc, hbitmap ); //hdcを使った処理 DeleteDC( hdc ); というソースで、「色々な条件による処理」によって処理を中止する場合 つまり、SelectObject()は実行していないけど、CreateCompatibleDC()は 実行済みの場合、DeleteDC(hdc);は必要ですか? もし必要でない場合、DeleteDC(hdc);を実行してはいけないですか?

  • 些細な質問ですが、よろしくお願いします。

    現在C++のSDKを勉強中の身です。 「猫でも分かるプログラミング」の98章を勉強中に疑問が出てきました。疑問というよりも中身が知りたくて質問させていただきました。 98章 http://www.kumei.ne.jp/c_lang/sdk/sdk_98.htm いままで何気にやってきたことですが、「デバイスコンテキスト」とはどんなものなんでしょうか? 自分ではクライアント領域を描画するためのメモリ空間だと考えていたんですが、次にこんな関数が出てきました。 (HDC)CreateCompatibleDC(hdc) この関数で得られるものは「メモリデバイスコンテキストハンドル」 ・・・? デバイスコンテキストハンドルはメモリ空間じゃなかったの?と疑問を持ってしまいました。 じゃあメモリデバイスコンテキストとはなんぞや?とまたまた新たなる疑問が次々に発生・・・・・ そして例えばビットマップの表示ならば SelectObject関数により、ビットマップハンドルとメモリデバイスコンテキストハンドルを対応図づける?のですが、このSelectObject関数もなにをやっているのかつかみにくいです。「対応づけ」と理解していますが、それがあっているのかどうかも不明です。 よって解決したい問題は (1)「デバイスコンテキストハンドル」および「メモリデバイスコンテキストハンドル」とはなんなのか? (2)SelectObject関数は何をしているのか? すこし図々しい疑問で恐縮ですが、この疑問に答えられる方は返信よろしくお願いします。

  • メモリデバイスコンテキスト&ビットマップハンドル

    static VOID _SetSize(pLayer object, LONG w, LONG h) { LayerEx * obj; obj = (LayerEx *)object; obj->size.x = w; obj->size.y = h; if(obj->hBitmap){ HDC hdc , hNewDC; HBITMAP hNewBitmap; hdc = object->GetDC(object); hNewDC = CreateCompatibleDC(hdc); hNewBitmap = CreateCompatibleBitmap(hdc , w , h); SelectObject(hNewDC , hNewBitmap); BitBlt(hNewDC , 0 , 0 , w , h , hdc , 0 , 0 , SRCCOPY); DeleteObject(hNewDC); object->DeleteDC(object , hdc); DeleteObject(obj->hBitmap); obj->hBitmap = hNewBitmap; } 一度生成したビットマップのサイズを変更してもう一度ビットマップを生成するプログラムらしいのですが、 BitBlt(hNewDC , 0 , 0 , w , h , hdc , 0 , 0 , SRCCOPY); ↑なぜBitBltで転送しているのかわかりません。 新しく生成したビットマップをSelectObjectで登録したらいいような感じがするんですが・・・ DeleteObject(hNewDC); ↑あとこれはDeleteDC(hNewDC)の間違いなのでしょうか?ここも何しているか分かりません。 分かる人いたら教えてください。説明足りなかったらごめんなさい^^; ↓一応object->GetDC(object)のソースです。 static HDC _GetDC(pLayer layer) { LayerEx * obj; HDC hResult; obj = (LayerEx *)layer; if(obj->hBitmap == NULL){ HDC hdc; hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); obj->hBitmap = CreateCompatibleBitmap(hdc, obj->size.x, obj->size.y); hResult = CreateCompatibleDC(hdc); SelectObject(hResult, obj->hBitmap); DeleteDC(hdc); } else{ hResult = CreateCompatibleDC(NULL); SelectObject(hResult, obj->hBitmap); } return hResult; }

  • GetDC()とCreateCompatibleDC()

    お世話になっています。 GetDC(NULL)とCreateCompatibleDC(NULL)で得られるhdcの違いがよくわかりません。 以下のプログラムA,Bで得られるのhDCw1,hDCw2に違いはありますか? A: hDCw1 = CreateCompatibleDC(NULL); //現在の画面と互換性のあるメモリデバイスコンテキスト hDCw2 = CreateCompatibleDC(NULL); <<hDCw1,hDCw2を使用>> DeleteDC(hDCw1); DeleteDC(hDCw2); B: hdc = GetDC( NULL ); // 画面全体を表すデバイスコンテキスト hDCw1 = CreateCompatibleDC(hdc); hDCw2 = CreateCompatibleDC(hdc); <<hDCw1,hDCw2を使用>> ReleaseDC( NULL, hdc ); // 取得した HDCの開放 DeleteDC(hDCw1); DeleteDC(hDCw2);

専門家に質問してみよう