#pragma twice

KAB-studio > プログラミング > #pragma twice > 130 Version 7.10 いろんな描画モード

#pragma twice 130 Version 7.10 いろんな描画モード

前のページへ 表紙・目次へ 次のページへ

 Version 7.10
いろんな描画モード

前回、前々回と C++ の方中心だったけど、今回はデバイスコンテキスト
の話に戻ります
難しい? 簡単?
簡単な方だと思うよ。まずこれ

void CAnimeDlg::OnBDraw() 
{
    HDC hCanvasDC = ::GetDC( m_cCanvasStatic.GetSafeHwnd() );
    HBRUSH hBrush = CreateHatchBrush( HS_CROSS, RGB( 0, 0, 255 ) );
    HBRUSH hOldBrush = (HBRUSH)::SelectObject( hCanvasDC, hBrush );

    ::Ellipse( hCanvasDC, 10, 10, 80, 50 );
    // 右下に 10 ずらしてもう一度描きます。
    ::Ellipse( hCanvasDC, 20, 20, 90, 60 );

    ::SelectObject( hCanvasDC, hOldBrush );
    ::DeleteObject( hBrush );
}

ん? 前に似たのやったよね
ブラシを用意して楕円描くっていうの。今回はペンは特に重要じゃないか
ら使ってないけどね
あ、 CreateHatchBrush() 使ってる。編み目のだよね
そう、これは〈編み目ブラシ〉を作るためのもの。第1引数で HS_CROSS 
を渡してるから、これは縦横の編み目
リファレンス見ると斜めなんかもあるみたいだね。でもそれだけ……
ま、こういうのはちょっとした作図用だからね。で、この楕円を、ひとつ
めの10ドット右下にもうひとつ描いてます
楕円ふたつ重ねて描いてるわけね。でもこれが?
試してみて
ほい実行。うん、ふたつ楕円が重なってるね。……あれ? でもさ、編み
目の隙間って下が透けて見えないんだね
そう、そこがポイント。実は、今は〈背景モード〉が〈透けて見えない
モード〉になってるんです
ってことは透けて見えるモードにもなる?
そゆこと。それを変える API が SetBkMode() 

void CAnimeDlg::OnBDraw() 
{
    HDC hCanvasDC = ::GetDC( m_cCanvasStatic.GetSafeHwnd() );
    HBRUSH hBrush = CreateHatchBrush( HS_CROSS, RGB( 0, 0, 255 ) );
    HBRUSH hOldBrush = (HBRUSH)::SelectObject( hCanvasDC, hBrush );

    // ここで背景モード変更。
    ::SetBkMode( hCanvasDC, TRANSPARENT );

    ::Ellipse( hCanvasDC, 10, 10, 80, 50 );
    ::Ellipse( hCanvasDC, 20, 20, 90, 60 );
    ::SelectObject( hCanvasDC, hOldBrush );
    ::DeleteObject( hBrush );
}

お、下が透ける!
 transparent は英語で〈透明〉って意味。ちなみにデフォルトの塗り潰し
モードにする時は OPAQUE 。 opaque は不透明って意味

ボケ不可
うっ。あれ……? でもこれ、よく見るとなんか変
どの辺が?
んー……あ、縞模様が透けてない! っつーか下のと一緒に並んでるみた

そうなんだよねー。これはデバイスコンテキストの仕様で、描画場所を変
えても、ブラシの模様はずれないんだよね。だから

    ::Ellipse( hCanvasDC, 13, 13, 83, 53 );

ってふたつめの楕円をちょっとだけずらしても
編み目がずれない……
ま、やっぱりちゃんとした模様を描くなら、こういうの使わない方がい
いってことかも
ふーん。あ、あともうひとつ質問。 OPAQUE は透明じゃないんだよね。
ってことは編み目の隙間の色ってどうなってるの? ペンとブラシ以外で指
定するの?
そう、これはまた別に SetBkColor() って API で指定します

void CAnimeDlg::OnBDraw() 
{
    HDC hCanvasDC = ::GetDC( m_cCanvasStatic.GetSafeHwnd() );
    HBRUSH hBrush = CreateHatchBrush( HS_CROSS, RGB( 0, 0, 255 ) );
    HBRUSH hOldBrush = (HBRUSH)::SelectObject( hCanvasDC, hBrush );

    // ここで背景色変更。
    ::SetBkColor( hCanvasDC, RGB( 255, 0, 0 ) );

    ::Ellipse( hCanvasDC, 10, 10, 80, 50 );
    ::Ellipse( hCanvasDC, 20, 20, 90, 60 );
    ::SelectObject( hCanvasDC, hOldBrush );
    ::DeleteObject( hBrush );
}

うわ、編み目の隙間が真っ赤!
この SetBkColor() は〈背景色〉を変えるもの。単純に楕円だけでも、ペ
ンとブラシとこの背景色の3色を決める必要があるってことかな
もしくは透明か、ね
そゆこと
……んでもさ、 API の名前、なんか混乱しそう
ん? どういうこと?
だってさ、 SetBkColor() なんて言ったら、普通、キャンバスそのものの
色を変えるって思わない?
それはそうかも。 SetBkMode() もキャンバスそのものを透明にしそうだ
よね
そうそう。でも、この〈背景〉って、ようするにこれから塗る楕円とかそ
ういうのの背景、ってわけなのね
そういうことだね。この辺も、デバイスコンテキストのクセかも
こういうの、ひとつひとつ憶えていかなきゃいけないわけね……
じゃ、さらに憶えてもらいましょう
げげ
というわけで、今度は【ラスタオペレーション】ってゆーの

void CAnimeDlg::OnBDraw() 
{
    HDC hCanvasDC = ::GetDC( m_cCanvasStatic.GetSafeHwnd() );
    HBRUSH hBrush = CreateHatchBrush( HS_CROSS, RGB( 0, 0, 255 ) );
    HBRUSH hOldBrush = (HBRUSH)::SelectObject( hCanvasDC, hBrush );
    ::Ellipse( hCanvasDC, 10, 10, 80, 50 );

    // ここでラスタオペレーションを設定します。
    ::SetROP2( hCanvasDC, R2_BLACK );

    ::Ellipse( hCanvasDC, 20, 20, 90, 60 );
    ::SelectObject( hCanvasDC, hOldBrush );
    ::DeleteObject( hBrush );
}

げ、ふたつめの楕円が真っ黒!
 SetROP2() の第2引数で R2_BLACK を渡すと、何色のペンやブラシを
持っていても真っ黒になっちゃうんです
げげ。で、そのラスタオペレーションってなんなの?
英語で書くと raster operation 。 raster は〈画面の格子〉って意味。
縦横にドットが並んでるものそのものって事かな
つまりドット絵ってことね……
 operation は操作。つまりラスタオペレーションは〈ピクセルの操作〉
って意味
たいそうな名前の割りには……
略して ROP 。で、この ROP には簡単なのから複雑なのまであるんだけ
ど、ここで使ってるのは一番簡単な ROP2 ってグループ
簡単だから、真っ黒だけ?
いや、そういうわけじゃないけど、でもシンプルなのが多いよ。真っ白に
塗り潰す R2_WHITE とか、あとデフォルトの普通に塗り潰す R2_COPYPEN と

 SetROP2() 見ると他にも結構あるけど、はっきり言って意味分かんな
いの多いかも。どういうのなの? たとえば R2_NOT とか。否定??
 R2_NOT は、背景色を〈逆の色〉にするもの。たとえば白は黒、青は黄

白は黒、は分かるけど、青は黄色って……そうなの?
逆の色っていうのは、 RGB 各色で、 0 は 255 、 100 は 155 みたく、
256 の真ん中で逆転させた色って事。青は RGB( 0, 0, 255 ) で、黄色は
RGB( 255, 255, 0 ) 
そういうもんなのね
ま、こういうのはどっちかっていうと美術の話かも。他には……

void CAnimeDlg::OnBDraw() 
{
    HDC hCanvasDC = ::GetDC( m_cCanvasStatic.GetSafeHwnd() );
    HBRUSH hBrush = CreateHatchBrush( HS_CROSS, RGB( 0, 0, 255 ) );
    HBRUSH hOldBrush = (HBRUSH)::SelectObject( hCanvasDC, hBrush );

    ::SetBkColor( hCanvasDC, RGB( 0, 255, 0 ) );
    ::Ellipse( hCanvasDC, 10, 10, 80, 50 );

    ::SetROP2( hCanvasDC, R2_MASKPEN );
    ::SetBkColor( hCanvasDC, RGB( 255, 0, 255 ) );

    ::Ellipse( hCanvasDC, 20, 20, 90, 60 );
    ::SelectObject( hCanvasDC, hOldBrush );
    ::DeleteObject( hBrush );
}

重なってるとこが黒く!
 R2_MASKPEN は、色を塗り重ねてさらに濃くします。逆に R2_MERGEPEN 
は、塗り重ねるとさらに薄くします

void CAnimeDlg::OnBDraw() 
{
    HDC hCanvasDC = ::GetDC( m_cCanvasStatic.GetSafeHwnd() );
    HBRUSH hBrush = CreateHatchBrush( HS_CROSS, RGB( 0, 0, 255 ) );
    HBRUSH hOldBrush = (HBRUSH)::SelectObject( hCanvasDC, hBrush );

    ::SetBkColor( hCanvasDC, RGB( 0, 0, 0 ) );
    ::Ellipse( hCanvasDC, 10, 10, 80, 50 );

    ::SetROP2( hCanvasDC, R2_MERGEPEN );
    ::SetBkColor( hCanvasDC, RGB( 0, 0, 255 ) );

    ::Ellipse( hCanvasDC, 20, 20, 90, 60 );
    ::SelectObject( hCanvasDC, hOldBrush );
    ::DeleteObject( hBrush );
}

ホントだ、黒が薄くなった
あと R2_XORPEN かな
試すとなんか R2_NOT に似てる……けどちょっと違うね
簡単に言うと、 R2_XORPEN は、塗る色と背景の色が離れてれば白に近づ
いて薄くなって、逆に色が近いと黒に近づいて濃くなります
ややこしい……
ま、これはあんまり使わないでしょ。で、あとはこれらの組み合わせ
って簡単に言うけど、はっきり言ってよく分かんないよ?
ってゆーか実際にはあまり使わないと思うよ。ちゃんとした CG ソフトは
GetPixel() で色拾って合成して SetPixel() する、みたいなことしてると
思うし
むしろその方が分かりやすそう……
デバイスコンテキストの機能って色々あるけど、こういった複雑な機能を
憶えるよりは、基本的なことの応用の方がいいかもね

/*
    Preview Next Story!
*/
ってゆーか、もしかしてデバイスコンテキストって使いにくくない?
それは言えるかも。ペンの付け替えとか大変だよね
今回の ROP も複雑だし
でも、そういう細かいとこを自分でやるか任せるかっていうのは
難しいとこよねー。だって、 CG の勉強もしなきゃいけないでしょ?
そういうことになるね
というわけで次回
< Version 7.11 クリッピングではみ出さない! >
につづく!
どうしても左向いてる顔って描けないのよねー
いや、そういう勉強は必要ないから
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。