Graphic(GDI)


POINT current state の影響をうける( GL 同様 ) デバイスコンテキストは 描画ステートの集合。 各描画 API ( TextOut, )は関数をコールした時点のステートを使って描画される。 SAMPLE https://www.dropbox.com/s/6z8a8o87erutm03/pen.exe( ペンで描画 右クリック : 色を取得 ) DESC LineXXX : 現在のペンの影響をうける window を隠して再描画すると, 影響がわかる GDI を使うには DC への Handle を取得する必要がある Programmer は 描画対象 の違いを意識しなくてもよくなる 描画対象であるDeviceContextの Handle をとるには GetDC(), BeginPaint() をつかう GetDC(); BeginPaint(); BeginPaint Window で設定されている BgColor で塗られ, Control が再描画される GetDC ClientArea すべてが描画される Window 前面に上書きされる POINT 次の使い分けをする WM_PAINT BeginPaint() その他 GetDC() int ReleaseDC();


描画処理の流れ


POINT 描画処理は ひとつの関数にまとめてバックバッファ(にしておき) WM_PAINT イベントをキッカケにして画面にコピーするだけにしておく。 WM_PAINT がくるのは system から 無効領域 が発生したという Message WARNING InvalidateRect() を WM_PAINT でコールしてはダメ
draw() { // 見えない画面にかく } wndProc() { case WM_PAINT: BitBlt(); }



文字を表示する


SYNTAX bool TextOut( HDC hdc, // 描画対象の DeviceContext int x, y, // 位置 LPCTSTR str, // 文字 ( \0 terminate してなくてもいい ) int nrStr // 文字数 ); DESC window の クライアント領域に文字を表示する フォント、背景色、文字色のステートの影響をうける windows の text は console に文字を表示することは異なる 文字も [ 画像 ]として扱う GDI とは Graphic 専門の sub system ( win32 API の描画担当 ) これらは window に関連つけられる HDC GetDC( HWND ); 解放も必要 void ReleaseDC( HDC, HWND );
HDC hdc = GetDC( hwnd ); TextOut( hdc, 10, 10, str, lstrlen( str ) ); ReleaseDC(hwnd , hdc);
POINT 自前でするならば, font を記述することになる GDI の座標系は左上原点
WndProc () { // System から再描画要求があったら描画する if ( msg == WM_PAINT ) { HDC hDC = GetDC( hWnd ); TextOut( hDC, 100, 0, "aiueo", strlen( "aiueo" ) ); } }



DrawText


SYNTAX int DrawText( HDC hDC, LPCTSTR str, int nr, // 文字数 ( -1 : NULL 終端文字とみなす ) RECT rc, // テキストを描画する長方形領域 UINT fmt // DT_XXX ( DT_WORDBREAK ) );
typedef struct tagRECT { LONG left; LONG top; LONG right; LONG bottom; } RECT
if ( msg == WM_PAINT ) { RECT rc; GetClientRect( hWnd, &rc ); // 画面中央に表示 // VCENTER を利用する場合は DT_SINGLELINE のみ有効 DrawText( hDC, "test", -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER); }



文字色


SYNTAX COLORREF SetTextColor( HDC hdc, COLORREF col, // == u32 RGB(255 255 255) ) COLORREF SetTextColor( HDC hdc, COLORREF col, // == u32 RGB(255 255 255) ) DESC TextOut() では色を設定できない -> 使いまわしがききそうな値は, GDI は DC へのハンドルを利用する ( 現在の state を参照する ) current state を保持できない ? // MACRO COLORREF RGB(BYTE bRed , BYTE bGreen , BYTE bBlue);
// 赤に変更 SetTextColor( hDC, RGB(0xff, 0x0, 0x0) ); SetTextColor( hDC, RGB(255, 0, 0) ); // Brush の設定に使う SetBkMode ( HDC, int bkMode );
DESC win32 API は文字を描画する前に 背景色で塗りつぶしてから描画している( clear color ) COLORREF SetBkColor( HDC hDC, COLORREF color // 塗りつぶしに使用される背景色 ); int SetBkMode( HDC hDC, int mode // 背景モード ); TIP 文字を描画すると, default の白で描画される 白い□ と黒い文字になる
// 背景は塗りつぶされなくなる // glBlendMode() と同じ SetBkMode(hDC , TRANSPARENT); TextOut( hDC, x, y+30, str, lstrlen(str) );



SetBkMode


SYNTAX int SetBkMode( HDC hDC, // デバイスコンテキストのハンドル int iBkMode // 背景モード ); DESC デバイスコンテキストの背景モードを設定する 背景モードは テキスト( TextOut() ) ハッチブラシ、(点線や鎖線など)実線ではないペンで使う
// 背景をそのまま残す SetBkMode( hDC, TRANSPARENT );



GDI.Object


POINT 作成( Create ) したら 破棄( Delete ) すること DeviceContext は描画のステートをもつ。 各GDIオブジェクト ( Pen, brush )を作成したら、 DeviceContext に SetObject() で関連づけることで描画APIで反映される。 Bitmap 画像を 画面に表示するには MemoryDC に関連づけてから Copy することで対応する


Brush


DESC Rectangle(), Ellipse(), 背景塗りつぶしに使用される属性 WHITE_BRUSH | BLACK_BRUSH | GRAY_BRUSH // Brush を作成する -> 破棄忘れずに HBRUSH CreateSolidBrush(COLORREF crColor); HBRUSH CreateHatchBrush(int fnStyle , COLORREF clrref); HBRUSH CreateBrushIndirect(CONST LOGBRUSH *lplb); HS_CROSS | typedef struct tagLOGBRUSH { UINT lbStyle; // BS_SOLID | BS_HATCHED COLORREF lbColor; LONG lbHatch; } LOGBRUSH;


Pen


SYNTAX HPEN CreatePen( int style, // 線の種類 ( 実線 | 点線 ) int width, // 太さ COLORREF color // 色 ); RET 0 : 失敗 N : 前に指定されていたペンのハンドル DESC ペンオブジェクトを作成する。 作成したペンをデバイスコンテキストに指定することで 直線( LineTo ), 曲線を描くときに利用できる。 POINT default obj ( BLACK_PEN | WHITE_PEN | NULL_PEN ) 取得可能 HGDIOBJ GetStockObject(); // GDIOBJ( 画材 )を選択 HGDIOBJ SelectObject(HDC hdc , HGDIOBJ hgdiobj);
hPen = CreatePen(PS_SOLID , 5 , RGB(255, 0, 0 ) );



Font


SYNTAX HGDIOBJ GetStockObject( int IDObj // ストックオブジェクトのタイプ ); DESC 用意された(ストック)のペン、ブラシ、フォント、パレットのハンドルを取得 HGDIOBJ を返すので適当な型に cast すること. DeleteObject() を呼び出してストックオブジェクトを削除しなくてもいい
// 組み込み font を利用 GetStockObject( ANSI_FIXED_FONT );
DKGRAY_BRUSH GRAY_BRUSH LTGRAY_BRUSH の各ストックオブジェクトは CS_HREDRAW, CS_VREDRAW スタイルを指定しているウィンドウでのみ使える 他のスタイルを指定しているウィンドウで灰色のストックブラシを使うと ウィンドウの移動やサイズ変更をした後で ブラシのパターンがずれることがあります これらのストックブラシの原点は調整できません HOLLOW_BRUSH と NULL_BRUSH ストックオブジェクトは同じ DEFAULT_GUI_FONT のストックオブジェクトで使われているフォントは 他のフォントへ変更できる メニュー ダイアログボックス 他のユーザーインターフェイスオブジェクトの表示に特定のフォントを使いたいときは このストックオブジェクトを利用して指定をする HGDIOBJ SelectObject( HDC hdc, HGDIOBJ hgdiobj ); bool DeleteObject( HGDIOBJ hObj ); // カスタムの際は必要.


CreateFont


SYNTAX HFONT CreateFont( int h, // フォントの高さ int w, // 平均文字幅 int nEscapement, // 文字送り方向の角度 int nOrientation, // ベースラインの角度 int fnWeight, // フォントの太さ DWORD fdwItalic, // 斜体にするかどうか DWORD fdwUnderline, // 下線を付けるかどうか DWORD fdwStrikeOut, // 取り消し線を付けるかどうか DWORD fdwCharSet, // 文字セットの識別子 DWORD fdwOutputPrecision, // 出力精度 DWORD fdwClipPrecision, // クリッピング精度 DWORD fdwQuality, // 出力品質 DWORD fdwPitchAndFamily, // ピッチとファミリ LPCTSTR lpszFace // フォント名 );
if ( msg == WM_CREATE ) { hDC = GetDC( hWnd ); // Font Object の作成 HFONT hFont = CreateFont( 30, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FIXED_PITCH | FF_MODERN, "MS ゴシック" ); // Font を選択 SelectObject( hDC, hFont ); return 0; }



図形(Primitive)の描画


DESC PEN , BRUSH 属性で描画( pen : 外側, brush 内側 )


点.線


SYNTAX COLORREF SetPixel( HDC hDC, int X, int Y, COLORREF col ); BOOL MoveToEx( HDC hdc, int x, int y, LPPOINT point ); BOOL LineTo( HDC hdc , int x , int y ); DESC 指定した位置に点を描画する。 ペンの属性の影響をうける。 GetPixel(HDC hdc , int XPos , int nYPos);
for( u32 i=0; i<100; i++ ){ SetPixel( hdc, i, 150, COL_GRN ); }
POINT 大きな点をうつには PEN を利用する。 SetPixel() では 1 pixel の点だけが描画できる。
HDC hDC = GetDC( hWnd ); // 毎回ペンの設定をしないと描画に反映されないらしい HANDLE hPen = CreatePen( PS_SOLID , 50 , RGB(255, 0, 0 ) ); // 位置を移動( lpPoint : 前の位置 ) BOOL MoveToEx( hDC , x, y, NULL ); // 指定位置まで線をひく。( 現在地も移動 ) BOOL LineTo( hDC, x , y ); DeleteObject( hPen ); ReleaseDC( hWnd, hDC );
// カレント位置から N line 描画 BOOL PolylineTo(HDC hdc , CONST POINT *lppt , DWORD cCount); // 複数のラインを描画 ( index で指定できないので不便 ) BOOL PolyPolyline( HDC hdc, CONST POINT *lppt, CONST DWORD *lpdwPolyPoints, DWORD cCount);


GetPixel . ピクセルの色を取得


COLORREF GetPixel( HDC hDC, int x, int y, ); DESC 指定した座標のピクセルを取得する。


多角形(Polygon)


SYNTAX BOOL Polygon(HDC hdc , CONST POINT *lpPoints , int nCount); DESC 内部を brush で塗って描画 int SetPolyFillMode(HDC hdc , int iPolyFillMode); ALTERNATE : 交互に塗る WINDING : 全域を塗る


Rectangle


SYNTAX BOOL Rectangle( HDC hdc, int nLeftRect, int nTopRect, // 左上 int nRightRect , int nBottomRect // 右下 ); DESC 現在の Brush Object で矩形領域を塗りつぶす BOOL Ellipse( HDC hdc , int nLeftRect , int nTopRect , int nRightRect , int nBottomRect); BOOL RoundRect( HDC hdc, int nLeftRect, int nTopRect, int nRightRect , int nBottomRect, int nWidth , int nHeight ); // API がメンドイので省略 BOOL Arc( HDC hdc, int nLeftRect , int nTopRect , int nRightRect , int nBottomRect , int nXStartArc , int nYStartArc , int nXEndArc , int nYEndArc ); WARNING Button などの子供 Window があると消えるかも POINT カレント位置の影響はなし 右下の 1 pixel は描画されない


CreateCompatibleDC


DESC 指定したデバイスと互換性のあるメモリデバイスコンテキストをつくる Application は Bitmap を画面に表示するには MemoryDC に選択すること SYNTAX HDC CreateCompatibleDC( HDC hdc // 互換性をもたせる DC Handle );
// NULL を指定するとアプリケーションの現在の画面と互換性のあるものが作成される HDC CreateCompatibleDC( NULL );
hDCMem = CreateCompatibleDC( hDC ); //hBMP = CreateCompatibleBitmap( hDC, 300, 300 ); //SelectObject( hDCMem, hBMP ); SelectObject( hDCMem , hBmp ); で bitmap の大きさにあった Backbuffer にする. // 転送元の bitmap を拡縮して転送. // HDC 間ならば, FrontBuffer でなくても OK


BitBlt


SYNTAX BOOL BitBlt( HDC hdcDest, // コピー先デバイスコンテキストのハンドル int xDest, yDest // コピー先長方形の左上隅の x, y 座標と int w, y // 幅, 高さ HDC hdcSrc, // コピー元デバイスコンテキストのハンドル int x, y, // コピー元の左上の x , y 座標 DWORD dwRop // ラスタオペレーションコード ); DESC ビットブロック転送をする コピー元からコピー先のデバイスコンテキストへ 指定された長方形内の各ピクセルデータをコピーする
SRCCOPY : コピー元の色をそのままコピー先へ上書き ( 通常はこれ ) NOTSRCCOPY : コピー元の反転色をコピー先へ上書き SRCAND : 論理 AND 演算子を使って、src, dst 色を混ぜる。 SRCPAINT : 論理 OR 演算子を使って、src, dst 色を混ぜる。



StretchBlt


SYNTAX StretchBlt( HDC dst, x, y, w, h, HDC src, x, y, w, h, DWORD dwRop // ラスタオペレーションコード ); DESC コピー元の長方形からコピー先へビットマップを拡縮コピー システムは コピー先のデバイスコンテキストで設定されている伸縮モードを使う


TransparentBlt


DEP msimg32.lib # pragma comment(lib,"msimg32.lib") SYNTAX TransparentBlt( HDC dst, x, y, w, h, HDC src, x, y, w, h, UINT crTransparent // 透明扱いにする色 ); DESC 4 bpp , 8 bpp (ビット/ピクセル) の送信元ビットマップに関してサポート
// RGB マクロで指定する // 透明色の指定以外は , BitBlt と同じ TransparentBlt( ... , RGB(255, 0, 0) );



PatBlt


SYNTAX PatBlt( HDC hDCMem, x, y, w, h, UINT ); DESC 矩形を描画 PatBlt( hDCMem, 0, 0, 300, 300, WHITENESS );


BeginPaint


SYNTAX BeginPaint( HWND, PAINTSTRUCT *ps ); DESC GDI は Window 全体に対してではなく, 無効領域にのみ描画される PAINTSTRUCT に描画の情報をいれる


SelectObject


SYNTAX HGDIOBJ SelectObject( HDC hdc, // デバイスコンテキストのハンドル HGDIOBJ hgdiobj // オブジェクトのハンドル ); DESC 指定されたデバイスコンテキストで 指定された 1 個のオブジェクトを選択します 新しいオブジェクトは、同じタイプの以前のオブジェクトを置き換える 指定されたのと同じタイプで それまで選択されていたオブジェクトを返す アプリケーションは新しいオブジェクトを使い終えたら 必ず元の(既定)オブジェクトに置き換えるべき アプリケーションは 1 つのビットマップを一度に複数のデバイスコンテキストで選択することはできない


GetObject


SYNTAX int GetObject( HGDIOBJ hgdiobj, // グラフィックオブジェクトのハンドル int cbBuffer, // オブジェクト情報を格納するバッファのサイズ LPVOID lpvObject // オブジェクト情報を格納するバッファ ); DESC GDIオブジェクトの情報を取得する。 BITMAP のハンドルを指定すれば、画面のサイズなどを取得できる。
BITMAP bitmap; GetObject( hBitmap, sizeof(BITMAP), &bitmap);



InvalidateRect


SYNTAX BOOL InvalidateRect( HWND hWnd, // 対象となる Window ( NULL ならばすべて ) CONST RECT *lpRect, // NULL ならば クライアント領域すべて BOOL bErase // true : BeginPaint() 時に clearColor() // false : 背景はそのまま残る );
// WM_PAINT を POST して Window の Client 領域をすべて再描画する InvalidateRect( hWnd, NULL, false ); // これでも同じ。 PostMessage( hWnd, WM_PAINT, 0, 0 );