• ベストアンサー

デバイスコンテキストについて詳しく教えてください

C言語でwin32APIを勉強しているのですが、デバイスコンテキストとは具体的にどのようなものでしょうか?Windowsが管理しているGDIで描画をするための構造体らしいですが・・・。 それともう1つ質問です。解説サイトに「デバイスコンテキストは使ったらすぐ解放しなければならない」と書かれているのですが、なぜすぐに解放しなければならないのですか?サンプルプログラムを見ていると、まだ使えそうなデバイスコンテキストもすぐ解放し、次に必要になれば新たにデバイスコンテキストを確保していますが、そのまま取って置くのは駄目なのでしょうか。そのようなプログラム(汎用的なデバイスコンテキストをWinMainの最初に確保し、完全に使わなくなった時点で解放する)を作って動作させてみても、ぱっと見では問題が見つかりません。ですがこれではやはり問題があるのでしょうか? 質問は以上の2点です。回答よろしくお願いします。

noname#113783
noname#113783

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

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

>そのまま取って置くのは駄目なのでしょうか。 駄目です。 「同時に存在できるDCの個数」と「DCの生存期間」を考えて下さい。 Windowsでは「同時に存在できるDCの個数」は「256個くらい」です。 >汎用的なデバイスコンテキストをWinMainの最初に確保し、完全に使わなくなった時点で解放する このプログラムを複数起動すると、たぶん、220個目辺りで「DCが確保出来ない」というエラーが起きます。 「同時に存在できるDCの個数が256個」では「何が問題なのか、よく判らない」と思うので「同時に存在できるDCの個数が4個」で考えて見ましょう。 「起動直後にDCを確保して、終了直前に開放するプログラム」は、4つしか同時に起動する事は出来ません。5つ目を起動すると「DCの確保に失敗」してしまいます。 しかし「使う瞬間のみDCを確保して、すぐに開放するプログラム」は、4つでも5つでも6つでも、メモリが許す限り起動出来ます。 何故なら「使う瞬間のみDCを確保してすぐに開放する、という処理が、5つ以上同時に完全に同じタイミングで起きる事は、滅多にない」からです。 同時に起きたとしても、せいぜい3つくらいでしょう。4つ同時に起きるとは思えませんし、5つ同時発生するとすれば「ユーザーが、故意にそうなる操作をした」くらいでしょう。 _を「まだ起動してない期間」、□を「DCを確保してない期間」、■を「DCを確保している期間」、×を「DCを確保しようとして失敗した時」として、グラフにしてみると良く判るでしょう。 ・最初に確保して保持しっ放しのプログラム プロセス1:□■■■■■■■■■■■■■■■■■■■■■■■■■ プロセス2:__□■■■■■■■■■■■■■■■■■■■■■■■ プロセス3:___□■■■■■■■■■■■■■■■■■■■■■■ プロセス4:_____□■■■■■■■■■■■■■■■■■■■■ プロセス5:_______□× プロセス6:________□× プロセス7:__________□× プロセス8:_____________□× (以下略) ・必要な時だけ確保してすぐ開放するプログラム プロセス1:□■□□□□□□■□□□■□□■□□□□■□□□□□ プロセス2:__□■□□□□□□■□□□■□□■□□□□■□□□ プロセス3:___□■□□□□□□■□□□■□□■□□□□■□□ プロセス4:_____□■□□□□□□■□□□■□□■□□□□■ プロセス5:_______□■□□□□□□■□□□■□□■□□□ プロセス6:________□■□□□□□□■□□□■□□■□□ プロセス7:__________□■□□□□□□■□□□■□□■ プロセス8:_____________□■□□□□□□■□□□■ (以下略) 「DCの確保しっ放し」が「問題あり過ぎ」なのは、これで理解出来たでしょうか?

noname#113783
質問者

お礼

なるほど!デバイスコンテキストには確保の上限があるんですか。だから使い終わったら解放しなければいけないんですね。 回答ありがとうございました!

その他の回答 (2)

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

追記。 簡単に説明すると「DCを確保したまま開放せずに持ちっ放しする」のは「カラオケに行って自分が歌う順番じゃないのにマイクを手放さないで独占する」のと同じです。 マイクが1本しか無ければ「他の人が歌えなくなってしまう」でしょう。自分が歌い終わったら、マイクをテーブルに置いて次の人が歌えるようにするのがマナーです。 Windowsでは「マイクが256本ある」ので「1本くらい占有しても、問題がないように見える」のです。でも「1本占有する人が256人居れば、他の人が歌えなくなる」のは同じなので、やはり「問題あり」です。

noname#113783
質問者

お礼

自分のプログラムでは持ちっぱなしにしたいですけど、確かに他のプログラムにそれをやられたら困りますね。しっかり知れてよかったです。

回答No.1

えーと、いろんなものを操作するためのハンドルといえばよいでしょうか? 車を運転するのにはハンドルが必要ですよね? そういう感じです windowsで動くアプリケーションは 必要な時にハンドルを取得して、使用し、使い終わったら解放するのが習わしです 1台の車をみんなでシェアリングしているようなイメージです

noname#113783
質問者

お礼

シェアリングですか!ではあまり多くのハンドルを持っておくということはないんですね。 回答ありがとうございました。

関連するQ&A

  • MFC デバイスコンテキストについて

    MFCのデバイスコンテキストを取得して、DirectXなどで描画を行っています。 環境は、 VS2008 DirextX 9.0 MDIなんですがOnInitDialogでDirectXのデバイスを取得しています。 次にOnDrawで描画を行っています。 GetDcでコンテキストを取得し、円の描画を行っています。 MDIですので、5以上のファイルを作成すると、描画が行われなくなります。 共通デバイスコンテキストは、5以上持てないということは検索して分かったのですが、5以上のファイルに描画を成功させるためには、どうすればいいのでしょうか? ・単純に新規ファイルを作ったときに、以前に作ったファイルのデバイスコンテキストを開放また、Directxのデバイスを開放すればいい? ・DirectXのデバイスをファイルごとに作成するのではなく、共通してもてば解決できる?? ・そもそも解放したりしても無理?? と考えているのですが、どうでしょうか? 助言をお願いします。

  • GDI+について

    いつもお世話になっております。 今回教えていただきたいことは、GDI+についてです。 今まで GDI と OpenGL を組み合わせてプログラミングをしていましたが、GDIでは自前でアンチエリアス処理をしなければならないなど面倒な部分が多く困っていました。 そこで GDI+ を使用して楽にプログラミングしようと考えて色々とプログラムをしてみたのですが、ここにきて壁にぶち当たりましたので、先人の方にご教授していただきたいのです。 《 GDI でプログラムしていた時 》 (1)画像バッファを作成しておく  //ディスクトップのDCを取得  HDC hdcTmp = GetDC( GetDesktopWindow() );  //ビットマップのハンドルと、作成したバッファの先頭アドレスを取得  hBitmap = CreateDIBSection( hdcTmp, &bmi, DIB_RGB_COLORS, (void**)&buffer, 0, 0 );  //HBITMAPにHDCを結び付ける  hdc = CreateCompatibleDC( hdcTmp );     //DIBSection用メモリデバイスコンテキスト作成  hOldHandle = SelectObject( hdc, hBitmap );       //画像バッファ(m_hBitmap)をメモリデバイスコンテキストに選択 (GDIでも描画出来るようにするため) (2)画像バッファ上にGDIで描画する  hdcに対してGDIの関数を使用して描画 (3)BitBlt()でウィンドウに転送する  WM_PAINTのメッセージのときだけウィンドウに対して転送 上記(1)(2)(3)のようにして描画を行っていました。 ■したいこと(1)■ 今したい事は 上記(1)で作成したGDI の画像バッファのhdcを使ってGDI+関数で描画したいのです。 そうするといままで使っていたGDIの知識を生かして両方使えます。 ■したいこと(2)■ したいこと(1)がもし出来ないのであればGDI+での画像バッファがつくれるかどうか、その画像バッファのデバイスコンテキスト は取得できるのかどうか教えていただきたいと思います 情報不足かもしれませんが、ご教授よろしくお願いいたします。

  • デバイスコンテキストに関して2つの質問

    閲覧ありがとうございます。デバイスコンテキストに関して2つの 質問があります。 1)矩形描画の際に背景色の反転色を設定したければSetROP2で  R2_NOTを指定します。このような「背景色の反転色を設定する」と  いう処理をTextOutで出力される文字に対して行いたいのですが  何か方法はあるでしょうか。 2)同一の領域に、それぞれ独立した2つの矩形が描けるように実装  しています。それぞれに対してR2_NOTを設定しており、そのため、  2つの矩形が重なると線が消えてしまいます。(反転の反転、のため)  これを回避し、重なった部分は一方のR2_NOTだけが作用するように  したいのですが、なにか方法はありますでしょうか。  よろしくお願いいたします。 環境はWindowsXP, VC2005++ &MFC です。

  • 文字の行間

    テキストをDIBビットマップに、 DrawTextで、描画しているのですが、 複数行の時に、行間を変えたいと思っています。 字間は、APIで、デバイスコンテキスト に設定できるのですが、 行間のやり方がわかりません。 知っている方がいたら、教えてください!

  • ダイアログボックス・・・・・ bySDK

    現在SDKにて画像処理ソフトを作成しています。もちろん個人にて。 そこで確実にほしい機能”ヒストグラム”の表示を行おうと思ったのですが、問題が起こりました。 目的は”2値化"という処理に伴い、ダイアログボックスに入力した画像のヒストグラムを表示させたいということです。 もちろんヒストグラムは単に白黒だけで表示させたいと思っています。 問題というのはダイアログボックスに任意の図形をどのように描画するかです。ビットマップの描画は以前行ったことがあるのですが、任意の図形は行ったことがありませんでした。 試しに、ダイアログボックスにPicture Controlを貼り付け、そのPicture ControlのデバイスコンテキストをGetDCにより無理やり取得し、そのデバイスコンテキストに直線などの描画を行ってみましたが、表示はされませんでした。(あたりまえかも・・・・) そこでまず、ダイアログボックスに使用するコントロール類は何を設定したらよいか? そして、そのコントロールから取得したデバイスコンテキストに直接描画は可能か? これらの質問に答えられる方はアドバイスをお願いしたいと思います。 よろしくお願いします。

  • 設定したGDIオブジェクトを必ず削除しなければいけない理由

    今参考にしている本や、いろいろなサイトで >そしてこのようにしてつくったGDIオブジェクトを使用後に削除する必要があることを肝に銘じてほしい >デバイスコンテキストに設定されているGDIオブジェクトを削除してはいけません というようなことが書いてありました。 GDIオブジェクトをどのように使えばいいのかはわかるのですが、なぜ、こんなことを肝に銘じなくてはいけないんでしょうか。 間違えると、何か取り返しのつかないことになってしまうんでしょうか? 怖いので、試してみることができません。 この理由が、おそらくですが、どこのサイトにもないようなので、この質問をさせてもらいます。 もし書いてあるサイトなんかがあったら、そこも教えてください。。

  • 「プラグイン」の使い方

    ソフトウェアの機能拡張プログラムを意味する「プラグイン」について質問があります。 例えば 『Sample』と言うプログラムがあり、これの開発元は『Sample-API』を別途で提供しており、この『Sample-API』を使って『Sample』用のプラグインを作れるとします。 『Sample-API』にはクラスやメソッドのみ用意されているだけで、このAPIのみでは意味はありません。 これで作られたプラグイン全般に対してどう呼ぶのか?を友人と話したところ、 友人は「『Sample-API』を使ったプラグインだから、『Sample-APIプラグイン』でしょ」とのこと。 しかし、私は「『Sample』用のプラグインだから、『Sampleプラグイン』では」と考えています。 どちらで呼ぶのがよいのでしょうか?

  • マウスカーソルのデスクトップ描画について

    vb2008で現在のマウスカーソルのハンドルを取得し、デスクトップに描画するというプログラムを組んでいます。しかし、以下の部分を実行してもマウスカーソルは描画されません。どこがおかしいのでしょうか? Dim hcur As Long Dim hdc As Long 'マウスカーソルのハンドル取得 hcur = GetCursor() 'デスクトップのデバイスコンテキスト取得 hdc = GetDC(GetDesktopWindow()) 'カーソル描画 DrawIcon(hdc,0,0,hcur) ちなみに同名のAPIの宣言はしてあります。 後,このソースの用途ですが,複数マウスに対応した複数カーソルの表示です。もしそれにあたって別の方法でカーソルを表示すべきなどのご指摘がありましたら,それもよろしくお願いします。

  • API関係の用語で質問です

    'デバイスコンテキストにオブジェクトを選択する Private Declare Function SelectObject Lib "gdi32" _ (ByVal hDC As Long, ByVal hObject As Long) As Long 'グラフィックスオブジェクトを削除しシステムリソースを開放する Private Declare Function DeleteObject Lib "gdi32" _ (ByVal hObject As Long) As Long ―――――――――――――――――――――――――――――――― VBの初心者です 使うAPIとは別に上のようなSelectObjectや DeleteObjectという関数を 使わなければならないようなのですが これはどういう意味なのでしょうか? またこれはどういうことをしているのでしょうか? ほかの例ではDeleteObjectという関数だけを 使ってSelectObjectを使っていないのも見かけました。

  • メモリデバイスコンテキストを用いた描画処理

    お世話になります。 Borland C++ 5.5.1 for Win32で簡易な画像ビュアーを開発しています。 基本的な動作は完成したのですが、ある条件下で発生する問題を回避するために、メモリデバイスコンテキストを用いようと考えています。 ところが、後述のように変更したところ、画像がまったく表示されなくなりました。(ウィンドウ背景色で塗りつぶされたままです。一瞬たりとも表示されません。) Windowsプログラムに慣れていないため解決に難儀しています。 どなたか原因と対策をご教示くださいますようよろしくお願いします。 ////////////////////////// //変更前 画像表示される// ////////////////////////// case WM_PAINT: hdc = BeginPaint(hWnd, &ps); /* ~省略(画像処理)~ */ StretchDIBits(hdc,~,SRCCOPY);//処理した画像をウィンドウへ EndPaint(hWnd, &ps); break; //////////////////////////// //変更後 画像表示されない// //////////////////////////// case WM_PAINT: hdc = BeginPaint(hWnd, &ps); hmemdc = CreateCompatibleDC(hdc); /* ~省略(画像処理)~ */ StretchDIBits(hdc,~,SRCCOPY);//処理した画像をMemoryDCへ BitBlt(hdc, 0, 0, rc.right, rc.bottom, hmemdc, 0, 0, SRCCOPY);//MemoryDCからウィンドウへ(rcはクライアント領域) DeleteDC(hmemdc); EndPaint(hWnd, &ps); break;

専門家に質問してみよう