POINT
current state の影響をうける( GL 同様 )
デバイスコンテキストは 描画ステートの集合。
各描画 API ( TextOut, )は関数をコールした時点のステートを使って描画される。
SAMPLE
ペンで描画 右クリック : 色を取得
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, // == unsigned int RGB(255 255 255)
)
COLORREF SetTextColor(
HDC hdc,
COLORREF col, // == unsigned int 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( unsigned int 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 );