- ベストアンサー
些細な質問ですが、よろしくお願いします。
現在C++のSDKを勉強中の身です。 「猫でも分かるプログラミング」の98章を勉強中に疑問が出てきました。疑問というよりも中身が知りたくて質問させていただきました。 98章 http://www.kumei.ne.jp/c_lang/sdk/sdk_98.htm いままで何気にやってきたことですが、「デバイスコンテキスト」とはどんなものなんでしょうか? 自分ではクライアント領域を描画するためのメモリ空間だと考えていたんですが、次にこんな関数が出てきました。 (HDC)CreateCompatibleDC(hdc) この関数で得られるものは「メモリデバイスコンテキストハンドル」 ・・・? デバイスコンテキストハンドルはメモリ空間じゃなかったの?と疑問を持ってしまいました。 じゃあメモリデバイスコンテキストとはなんぞや?とまたまた新たなる疑問が次々に発生・・・・・ そして例えばビットマップの表示ならば SelectObject関数により、ビットマップハンドルとメモリデバイスコンテキストハンドルを対応図づける?のですが、このSelectObject関数もなにをやっているのかつかみにくいです。「対応づけ」と理解していますが、それがあっているのかどうかも不明です。 よって解決したい問題は (1)「デバイスコンテキストハンドル」および「メモリデバイスコンテキストハンドル」とはなんなのか? (2)SelectObject関数は何をしているのか? すこし図々しい疑問で恐縮ですが、この疑問に答えられる方は返信よろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
回答1:『デバイスコンテキストハンドル』とは ・『デバイスコンテキスト』を大きな絵を描くキャンパスとイメージしてみる。 そのキャンパスは、紙であったり、壁であったり、自分の自動車だったりと様々である。 この紙、壁、自動車などがディスプレイ、プリンタなどのデバイスのことを指します。 ・そして、このキャンパスのことを『デバイスコンテキスト』という言葉で表します。 このように共通したキャンパスを持つことで、プログラマーからはキャンパスが何に 繋がっているか(ディスプレイ、プリンタなどのディバイス)を気にすることが無くなり、 ディスプレイも、プリンタも同じ『デバイスコンテキスト』という概念で扱えるのです。 →これが抽象的って考えかな。 ・また、この共通したキャンパスに関する情報は『デバイスコンテキスト』1つ1つで別々に 内部で管理しています。この管理領域のハンドルこそが『デバイスコンテキストハンドル』です。 ・『キャンパス』=『デバイスコンテキスト』に点、線、円、長方形などの図形を描くには 知ってのとおり GDI というグラフィック描画の機能を提供している関数群を利用します。 この関数群は、デバイスコンテキストの内部にビットマップ構造を保持しているメモリ上に 対していろいろなやり取りを行っています。このやり取りを行うには、そのメモリにアクセス するために『メモリデバイスコンテキストハンドル』を取得する必要があります。 ・『メモリデバイスコンテキストハンドル』とは、『デバイスコンテキスト』に表示するための 図形などを保持しているメモリ領域のことです。GDI 関数群はこのメモリ領域に対して直接 図形を描いたりしています。つまり、メモリデバイスコンテキストとはデバイスコンテキストの ビットマップ構造を持ったメモリ・イメージ領域のことです。 ・通常は、このメモリ・イメージを意識しないでも図形が描けるために GDI 関数群がすでに用意 されている状態にあります。このためプログラマーには隠されているメモリ上ですので普通は 特に気にする必要がありません。が、しかし、GDI 関数群を通すと処理に時間がかかってしまったり、 または、ビットマップ画像を直接メモリ・イメージに描画するときには、そのメモリ領域を取得 する必要があります。このメモリ領域のハンドルこそが『メモリデバイスコンテキストハンドル』です。 ※http://yokohama.cool.ne.jp/chokuto/urawaza/dispcopy.html→『デスクトップ画面を取得してみる』 回答2:『SelectObject()』関数について ・『デバイスコンテキスト』を絵を描くキャンパスと考えると『筆』にあたる部分が必要です。 この『筆』は人間でも同じく右手などに1つしか持てません。イメージできますよね。 ・それでは今、赤色の絵の具のついた筆を持っています。この状態でキャンパスに点、線、円、 長方形の図形を描くと赤い点、赤い線、赤い円、赤い長方形の図形が描けます。 次に緑色のブラシで図形を描くにはどうしますか? 答えは『筆』に新しい緑色の絵の具がついたブラシを手渡せばよいのです。 でも、今まで持っていた赤色の筆はどうしましょうか。絵の具がついていますね。 それでは、赤色の筆を左手に持ち替えてから、新しい緑色のブラシを手渡せばよいのです。 SelectObject() 関数で OldPen などに保存する動作こそ『左手』に持ち替える行為です。 ・キャンパスと筆は常にペアで管理します。 これは『紙』なら『クレヨン』、『壁』なら『ペンキ』、『車』なら『スプレー』とベアで 管理するのと同じです。キャンパスにあったペン(筆)があるのです。これらのそれぞれを キャンパスごとに切り替える動作を SelectObject() 関数が担当しているのです。 ・よって、『デバイスコンテキスト』1つ1つに対して持てる『筆』はたったの1つです。 たくさんの色で描くには切り替える仕組みがどうしても必要になります。この仕組みです。 図解: -------------- アプリケーション -------------- | ↓ |----------- | GDI 関数群 |----------- ↓ ↓ ---------------------- メモリデバイスコンテキスト ---------------------- ↓ ----------------- デバイスコンテキスト ----------------- 解説: ・アプリケーションが GDI 関数群を通さずに直接メモリ・イメージを操作するには、その領域 である『メモリデバイスコンテキスト』のハンドルを取得する必要があります。→CreateCompatibleDC ・一般に『デバイスコンテキスト』は1つの『メモリデバイスコンテキスト』を持っている。 ゲームなどでは『ダブルバッファリング』という技で複数の『メモリデバイスコンテキスト』を 用意してグラフィックにちらつきが起こらない様な仕組みをとる事があります。 ・1つの『デバイスコンテキスト』は1つの『メモリデバイスコンテキスト』を持っているが、 決して『デバイスコンテキスト』=『メモリデバイスコンテキスト』ではない。 つまり『メモリデバイスコンテキスト』とは『デバイスコンテキスト』のビットマップ構造を 格納する画像メモリ領域と考えると良い。→MS-DOS 時代の VRAM(Video RAM) と同じ考え方。 最後に: ・『猫でも分かるプログラミング』サイト以外にも下の『参考URL』もどうぞ。 併用することで SDK の勉強を高められます。 ・以上。参考情報でした。
その他の回答 (2)
プラットフォームSDKのCreateCompatibleDCの解説に >メモリデバイスコンテキストは、メモリ内にのみ存在します。 というくだりがあるのですが、この部分を書いた人は何か混乱していたのではないかと思います。 「GDIにおけるメモリデバイスとはメモリ上のビットマップを意味します」と解説を置き換えれば デバイス=描画対象 デバイスコンテキスト=描画に必要な情報 デバイスコンテキストハンドル=デバイスコンテキスト構造体のアドレス SelectObject=デバイスコンテキストを書き換える手段 このようになって、矛盾もなく非常にすっきりします。
お礼
返信ありがとうございました。 デバイスコンテキストハンドルがデバイスコンテキスト構造体のハンドルだとは知りませんでした。 新しい知識をいただきありがとうございます。 たしかに、上で回答されたように整理すると理解しやすいですね。
- sakusaker7
- ベストアンサー率62% (800/1280)
> (1)「デバイスコンテキストハンドル」および「メモリデバイスコンテキスト > ハンドル」とはなんなのか? デバイスコンテキスト/メモリデバイスコンテキストを操作するための把手 (ハンドル)です。Cでファイルを操作するときにファイルポインタというもの を経由して行いますが、それと同じような性格のものです(さらに低レベルに もぐると「ファイルハンドル」というのがでてきます) デバイスコンテキストとは、ディスプレイだとかプリンタのようなデバイスを 抽象化して扱うためのからくりです。デバイスコンテキストを経由して操作を することにより、 TextOut(hDC, ...); で文字を描画する操作がデバイスの種類によらず共通になります。 また同じ種類のデバイスであっても、違う機種なんかの場合の違いも吸収 することができます(裏でデバイスドライバが頑張ってるんですが)。 このデバイスコンテキストは、たとえば「線を描画せよ」と指示されたときに どんな色の、どんな太さの、etc... の線を描画するかという情報を別に持って いて、それを元に実際の描画を行います。この情報を切り替えるのが SelectObject です。 メモリデバイスコンテキストとは、通常のデバイスコンテキストが実際の デバイスと密接に関わっているのとは違ってデバイス独立です。ただし 先に述べたようにデバイスコンテキストは描画時に使用するペンだとか ブラシなどの情報を保持していますので、メモリデバイスコンテキストも そういう情報を持っています。 何のためにあるのか、といえば、よく使うのは複雑な描画を行うときに 実際に描画を行いたいデバイスコンテキストにちまちま描画していくと ちらつきが出るなどの問題が発生することがあります。そこで、描画 データを裏で組み立てておいて、完成したら一気に転送するということを したりします。そのための作業空間がメモリデバイスコンテキストです。 http://www.char.ne.jp/ppc2002/c104.htm BitmapLoader~第2週~ http://www.geocities.jp/chiakifujimon/makesoft2/proc2.html Windows API Tutorial: Canvas http://www.relisoft.com/win32/canvas.html
お礼
返信ありがとうございました。 わかりやすく、とてもすっきりしました。
お礼
回答ありがとうございました。 以前にOpenGLのプログラムをしたことがあり、そこでダブルバッファリングの描画を勉強したのでつかみやすかったです。 そして、下の方が紹介されたURLで発生した疑問が解決できました。 最後に「参考URL」を紹介いただきありがとうございました。 SDKにてさらに熟読、熟考できそうです。