Win32API講座8回
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
皆さんお待ちかねの(?)
GDIを使った描画を扱います
GDIとはGraphics Device Interfaceの略で
グラフィカルオブジェクトの表示と、ディスプレイやプリンタ...
今回は
・ペンを使った直線、曲線の描画
・ブラシを使った円、矩形の描画
・ビットマップ画像の描画
・フォント指定した文字列の描画
の基本的な描画を行います
&ref(paint.GIF);
先にことわっておきます
かなりめんどくさいです
まず、Win32APIの描画の概念図から
&ref(hdc.jpg);
真ん中のHDCというのは、デバイスコンテキストのハンドル(ポ...
デバイスコンテキストとは、出力対象を指します
大抵の場合、出力対象とはアプリケーションのクライアント領...
HDCに結ばれているものを描画オブジェクトと呼びます(正式な...
・HPENはペンのハンドルです。
ペンは線を書くのに使います。
・HBITMAPはビットマップのハンドルです。
ビットマップ画像(.bmp)を指します。
ここで、ビットマップ以外は取り扱えないの?って話になるの...
GDI+を使えばそれ以外のフォーマットの画像でも簡単に読み込...
・HBRUSHはブラシのハンドルです。
ブラシは図形の塗りつぶしに使います。
・HFONTはフォントのハンドルです。
フォントは文字を書くときに文字サイズや書式を決めます。
・HRGNはリージョンのハンドルです。
リージョンは、ウィンドウの形の決めることができます
今回は使いません、機会があったら取り上げようと思います。
・HPALETTEはパレットのハンドルです。
ここでは取り扱いません
SIZE(30){ COLOR(#ffaa00){デバイスコンテキストには関連付け...
つまりデバイスコンテキストは
常にペン、ビットマップ、ブラシ、フォント、リージョン、パ...
(イメージ的には、千手観音みたいなもの)
ここで注意してほしいのは、
SIZE(30){ COLOR(#ffaa00){デバイスコンテキストは同時に同じ...
たとえば、ペンを2つ同時に持つことはできません
なので
太い線を書いた後、細い線を書きたいなと思ったら
太いペンで太い線を書いた後、細いペンに持ちかえなければな...
ブラシやフォントに関しても同じです
---------------------------------------------------------...
今回のソースコードです。
//------------------------------------------------------//
// ウィンドウ描画メッセージ処理
//
// 引数: hWnd ウィンドウハンドル
//------------------------------------------------------//
void OnPaint(HWND hWnd){
// 描画開始
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
// ペン作成
HPEN hPen = CreatePen(PS_SOLID,5,RGB(255,0,0));
HPEN hNullPen = CreatePen(PS_NULL,1,RGB(0,0,0));
HPEN hDefPen = (HPEN)SelectObject(hdc,hPen);
// ブラシ作成
HBRUSH hBrush = CreateSolidBrush(RGB(0,255,0));
HBRUSH hDefBrush = (HBRUSH)SelectObject(hdc,hBrush);
// ビットマップ読み込み
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);...
HBITMAP hBmp = (HBITMAP)LoadImage(hInstance,_T("test.bm...
BITMAP Bmp;
GetObject(hBmp,sizeof(BITMAP),&Bmp);
HDC hBmpDC = CreateCompatibleDC(hdc);
HBITMAP hDefBmp = (HBITMAP)SelectObject(hBmpDC, h...
// フォント作成
LOGFONT logfont = {};
logfont.lfHeight = 30; // 文字高さ
logfont.lfWidth = 12; // 文字幅
logfont.lfEscapement = 30; // 文字送りの方向とX軸...
logfont.lfOrientation = logfont.lfEscapement; // ベ...
logfont.lfWeight = FW_BOLD; // フォントの太さ
logfont.lfItalic = TRUE; // イタリック体指定
logfont.lfUnderline = TRUE; // 下線付き指定
logfont.lfStrikeOut = TRUE; // 打ち消し線指定
logfont.lfCharSet = SHIFTJIS_CHARSET; // キャラ...
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; // 出力...
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; // クリ...
logfont.lfQuality = DEFAULT_QUALITY; // 出力品質
logfont.lfPitchAndFamily= FF_DONTCARE|DEFAULT_PITCH;// ...
_tcscpy(logfont.lfFaceName,_T("MS ゴシック")); // フォ...
HFONT hFont = CreateFontIndirect(&logfont);
HFONT hDefFont = (HFONT)SelectObject(hdc,hFont);
// 直線描画
MoveToEx(hdc,10,100,NULL); // 始点をセット
LineTo(hdc,10,200); // 始点から割り当てられたペンで終...
// 曲線描画
POINT pt[4] = {};
pt[0].x = 50;pt[0].y = 50;
pt[1].x = 100;pt[1].y = 150;
pt[2].x = 50;pt[2].y = 250;
pt[3].x = 150;pt[3].y = 250;
// 点情報から割り当てられたペンでベジェ曲線描画、点の数...
PolyBezier(hdc,pt,4);
// 楕円描画
SelectObject(hdc,hNullPen); // 枠がいらない
RECT PointRect;
PointRect.left = -5;
PointRect.top = -5;
PointRect.right = 5;
PointRect.bottom = 5;
for(int i = 0;i < 4;++i)
Ellipse(hdc,pt[i].x + PointRect.left,pt[i].y + PointRe...
// 矩形描画
SelectObject(hdc,hNullPen); // 枠がいらない
RECT rect = {30,130,50,150};
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom...
// 画像表示
BitBlt(hdc,200,0,Bmp.bmWidth,Bmp.bmHeight,hBmpDC,0,0,SR...
int X = 0;
int Y = 0;
// 文字列描画
const TCHAR* szText = _T("Hello World");
SetTextColor(hdc,RGB(0,0,255)); // 文字色を青に変更
TextOut(hdc,X,Y,szText,(int)_tcslen(szText)); // 文字列...
// 使い終わったら元の描画オブジェクトに戻す
SelectObject(hdc,hDefPen);
SelectObject(hdc,hDefBrush);
SelectObject(hBmpDC, hDefBmp);
SelectObject(hdc, hDefFont);
// 使わなくなった描画オブジェクトは破棄
DeleteObject(hPen);
DeleteObject(hNullPen);
DeleteObject(hBrush);
DeleteObject(hBmp);
DeleteObject(hDefFont);
// 使わなくなったデバイスコンテキストを破棄
DeleteDC(hBmpDC);
// 描画終了
EndPaint(hWnd,&ps);
}
//------------------------------------------------------//
// ウィンドウ破棄メッセージ処理
//
// 引数: hWnd ウィンドウハンドル
//------------------------------------------------------//
void OnDestroy(HWND hWnd){
PostQuitMessage(0);
}
//-----------------------------------------------------//
// ウィンドウプロシージャ
// デフォルトの処理はDefWindowProc関数で行う
//
// 引数: hWnd ウィンドウハンドル
// msg メッセージ
// wParam パラメータ
// lParam パラメータ
//
// 戻り値:処理結果
//-----------------------------------------------------//
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wPa...
switch(msg){
HANDLE_MSG(hWnd,WM_PAINT,OnPaint);
HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
描画を行うタイミングというものがあります(好きな時に描画...
それは、WM_PAINTというメッセージが送られてきたときです
このWM_PAINTは、ウィンドウが作成されたときやウィンドウの...
ウィンドウプロシージャに送られてくるメッセージです
メッセージクラッカーで自作のOnPaint関数に処理させます
HANDLE_MSG(hWnd,WM_PAINT,OnPaint);
描画するときは
必ずBeginPaint関数とEndPaint関数の間で描画しなければなり...
// 描画開始
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
// ここに描画処理
// 描画終了
EndPaint(hWnd,&ps);
------------------------------------------------------
ペンを作成するには、
CreatePen関数を使います
// ペン作成
HPEN hPen = CreatePen(PS_SOLID,5,RGB(255,0,0));
HPEN hNullPen = CreatePen(PS_NULL,1,RGB(0,0,0));
CreatePen関数の
第一引数はペンのスタイルです
PS_SOLID 普通の線
PS_DASH 破線
PS_DOT 点線
PS_NULL 空のペン(描画しない)
などがあります
第2引数はペンの太さです
第3引数はペンの色です
引数がCOLORREFとなっていますが
RGBマクロを使うとよいでしょう
各種色成分は0〜255の範囲で指定します
たとえば、RGB(255,0,0)は赤になります
もっと詳しく知りたい人はmsdn公式を見てください
http://msdn.microsoft.com/ja-jp/library/cc428348.aspx
ペンを作っただけでは描画に反映されません
デバイスコンテキストにペンを割り当てなければなりません
SIZE(30){ COLOR(#ffaa00){描画オブジェクトをデバイスコンテ...
HPEN hDefPen = (HPEN)SelectObject(hdc,hPen);
他の描画オブジェクトに関しても割り当てないと反映されません
たとえば、ブラシなどは次のようにキャストして使います
HBRUSH hDefBrush = (HBRUSH)SelectObject(hdc,hBrush);
SelectObject関数の戻り値はHGDIOBJ型となっていますが、
これを割り当てた描画オブジェクト型にキャストします
ここで気を付けてほしいのはデフォルトの描画オブジェクトが...
SIZE(30){ COLOR(#ffaa00){デフォルトの描画オブジェクトは描...
// 使い終わったら元の描画オブジェクトに戻す
SelectObject(hdc,hDefPen);
SelectObject(hdc,hDefBrush);
SelectObject(hBmpDC, hDefBmp);
SelectObject(hdc, hDefFont);
直線を描画するには、MoveTo関数で始点をセットし
LineTo関数で始点から終点までデバイスコンテキストに割り当...
(SelectObjectしなければデフォルトのペンで描画される)
// 直線描画
MoveToEx(hdc,始点x座標,始点y座標,NULL); // 始点をセット
LineTo(hdc,終点y座標,終点y座標); // 始点から割り当てら...
続いて、曲線(ベジェ曲線)を描いてみます
ベジェ曲線とは端点(始点と終点)と制御点
を指定してやるだけで形状が決まる曲線です
3次元ベジェ曲線を描くためには最低4つの点が必要です
(3次元ベジェが最も一般的なベジェ曲線)
&ref(bezier.gif);
緑の枠に囲まれた部分を凸包と呼び、
曲線は必ず凸包の内部に収まるという性質があります
ベジェ曲線を描画するにはPolyBezier関数を使います
(SelectObjectしなければデフォルトのペンで描画される)
// 曲線描画
POINT pt[4] = {};
pt[0].x = 50;pt[0].y = 50;
pt[1].x = 100;pt[1].y = 150;
pt[2].x = 50;pt[2].y = 250;
pt[3].x = 150;pt[3].y = 250;
// 点情報から割り当てられたペンでベジェ曲線描画、点の数...
PolyBezier(hdc,点の配列,点の個数(3の倍数+1));
-----------------------------------------------------
続いてブラシを作ってみます
ブラシは図形の塗りつぶしに使います
単色の塗りつぶし用ブラシ作成にはCreateSolidBrush関数を使...
色を指定して作成します
// ブラシ作成
HBRUSH hBrush = CreateSolidBrush(RGB(0,255,0));
ここでは、説明しませんが
網目模様などのパターン描画にはCreateHatchBrush関数
画像のイメージをタイル状にしたブラシ作成にはCreatePattern...
などが用意されています
ブラシをデバイスコンテキストに割り当てた後
HBRUSH hDefBrush = (HBRUSH)SelectObject(hdc,hBrush);
図形を描画します
円(楕円)を描画するにはEllipse関数を使います
ペンで枠が描かれ
内部はブラシで塗りつぶしされます
(SelectObjectしなければデフォルトのペンとブラシで描画さ...
枠が要らない場合は空のペンをSelectObject関数でデバイスコ...
// 楕円描画
SelectObject(hdc,hNullPen);// 枠がいらない
RECT PointRect;
PointRect.left = -5;
PointRect.top = -5;
PointRect.right = 5;
PointRect.bottom = 5;
for(int i = 0;i < 4;++i)
Ellipse(hdc,pt[i].x + PointRect.left,pt[i].y + PointRec...
矩形を描画するには
Rectangle関数を使います
ペンで枠が描かれ
内部はブラシで塗りつぶしされます
(SelectObjectしなければデフォルトのペンとブラシで描画さ...
枠が要らない場合は空のペンをSelectObject関数でデバイスコ...
// 矩形描画
SelectObject(hdc,hNullPen); // 枠がいらない
RECT rect = {30,130,50,150};
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom)...
---------------------------------------------
ビットマップ画像(.bmp)読み込みです
読み込みにはLoadImage関数を使います
// ビットマップ読み込み
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); ...
HBITMAP hBmp = (HBITMAP)LoadImage(hInstance,_T("test.bmp...
第一引数にはインスタンスハンドルを指定します
第二引数にはビットマップファイル名を指定します
第三引数には読み込みタイプを指定します(ビットマップ画像...
第四、五引数は0で構いません
最後の引数は読み込みフラグです(OR演算子「|」で組み合わせ...
ファイル読み込みなのでLR_LOADFROMFILEは必須です
LR_SHAREDは同じリソースなら、すでに読み込んであるビットマ...
LR_DEFAULTCOLORはカラー画像であることを示します(明示しな...
ビットマップハンドルが取得できたら
ビットマップの情報を取得します
BITMAP Bmp;
GetObject(hBmp,sizeof(BITMAP),&Bmp);
SIZE(30){ COLOR(#ffaa00){ GetObject関数で描画オブジェクト...
ペンやブラシ、フォントに関しても次のように取得できます
// ペン
LOGPEN pen;
GetObject(hPen,sizeof(LOGPEN),&pen);
// ブラシ
LOGBRUSH brush;
GetObject(hPen,sizeof(LOGBRUSH),&brush);
// フォント
LOGFONT font;
GetObject(hFont,sizeof(LOGFONT),&font);
GetObjectしたBITMAP構造体のbmWidth,bmHeightに画像サイズが...
ビットマップの情報を読み取った後
描画画面と互換性を持つ裏画面を作成します
これはあとで画像を描画するために必要です
HDC hBmpDC = CreateCompatibleDC(hdc); // 裏画面を作成し...
HBITMAP hDefBmp = (HBITMAP)SelectObject(hBmpDC, hBmp);
ここで気を付けて欲しいのはSelectObject関数で画像を裏画面...
直接画像を描画することができないので
裏画面から描画画面へ画像を転送します
画像を転送するにはBitBlt関数を使います
// 画像表示
BitBlt(転送先デバイスコンテキスト,転送先X座標,転送先Y座...
BitBlt(hdc,200,0,Bmp.bmWidth,Bmp.bmHeight,hBmpDC,0,0,SRC...
第一引数は描画画面のデバイスコンテキストを指定します
第二、三引数は描画する位置を指定します
第四、五引数は描画サイズを指定します
ここで注意してほしいのは画像を縮小拡大して転送するのでは...
画像サイズより小さいサイズを指定した場合、そのサイズだけ...
そのままコピーしたい場合はそのままの画像サイズを指定して...
第六引数は転送元デバイスコンテキストは裏画面のデバイスコ...
転送元X座標、転送元Y座標は
画像をそのままコピーしたい場合は0を指定してやればいいので...
(というのは裏画面の左上隅に画像はセットされている)
いまひとつわかりにくいと思います
次の図を見てください
&ref(bitblt.GIF);
画像幅、画像高さ、転送元X、転送元Yを
うまく指定してやれば画像の一部を切り取ることができます
アニメーション用の画像などに利用できます
ラスタオペレーションコードはどのように転送するかのフラグ...
----------------------------------------------------------
続いて文字列描画です
フォントを作成するには
CreateFont関数もしくはCreateFontIndirect関数を使います
CreateFont関数は引数があまりにも多いのでやめました
今回はCreateFontIndirect関数を使います
引数の代わりにLOGFONT構造体でフォントの情報を指定しなけれ...
(こちらも変数多いのですが・・・)
// フォント作成
LOGFONT logfont = {};
logfont.lfHeight = 30; // 文字高さ
logfont.lfWidth = 12; // 文字幅
logfont.lfEscapement = 30; // 文字送りの方向とX軸...
logfont.lfOrientation = logfont.lfEscapement; // ベー...
logfont.lfWeight = FW_BOLD; // フォントの太さ
logfont.lfItalic = TRUE; // イタリック体指定
logfont.lfUnderline = TRUE; // 下線付き指定
logfont.lfStrikeOut = TRUE; // 打ち消し線指定
logfont.lfCharSet = SHIFTJIS_CHARSET; // キャラク...
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; // 出力精度
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; // クリ...
logfont.lfQuality = DEFAULT_QUALITY; // 出力品質
logfont.lfPitchAndFamily= FF_DONTCARE|DEFAULT_PITCH; /...
_tcscpy(logfont.lfFaceName,_T("MS ゴシック")); // フォ...
HFONT hFont = CreateFontIndirect(&logfont);
HFONT hDefFont = (HFONT)SelectObject(hdc,hFont);
LOGFONT構造体変数で
とりあえずよく使うやつだけ説明します
それ以外はとりあえずはそのまま使ってください
lfHeight は文字高さを指定します
lfWidth は文字幅を指定します
lfEscapementは文字角度を指定します。(1/10度指定です)傾...
lfOrientationはlfEscapementと同じものを指定してください
lfWeightは文字の太さを決めます
lfItalicはイタリック表示です(使わない場合はFALSE)
lfUnderlineは文字の下に下線を引きます(使わない場合はFALS...
lfStrikeOutは文字に打ち消し線を引きます(使わない場合はFA...
lfFaceNameはフォント名を指定します(MS ゴシック、MS 明朝...
SetTextColor関数で文字の色を変更し
TextOut関数で文字列を描画します
(SelectObjectしなければデフォルトのフォントで描画される)
最後の引数は文字数指定します
_tcslen関数はstrlenと_wstrlenを切り変えるマクロです
// 文字列描画
const TCHAR* szText = _T("Hello World");
SetTextColor(hdc,RGB(0,0,255)); // 文字色を青に変更
TextOut(hdc,X,Y,szText,(int)_tcslen(szText)); // 文字列...
----------------------------------------------------------
最後に、
SIZE(30){ COLOR(#ffaa00){ 新しく作成(Createなんとか)し...
しないとハンドルリークを起こします(メモリリークの一種)
// 使わなくなった描画オブジェクトは破棄
DeleteObject(hPen);
DeleteObject(hNullPen);
DeleteObject(hBrush);
DeleteObject(hBmp);
DeleteObject(hDefFont);
// 使わなくなったデバイスコンテキストを破棄
DeleteDC(hBmpDC);
描画オブジェクトに関してはDeleteObject関数
デバイスコンテキストに関してはDeleteDC関数
を使います
さらに詳しい対応関係はMSDN公式を参照してください
http://msdn.microsoft.com/en-us/library/ms724291%28VS.85%...
-------------------------------------------------------
ふぅ・・・これで基本的な描画の説明は終わりました(^^;...
ここで全てを取り上げるの量的に不可能なので
その他の描画に関しての情報はMSDN公式を見てください
MSDN公式
http://msdn.microsoft.com/ja-jp/library/cc428835.aspx
しかし、冗長なコードですね
やれることが多いのはいいのですが一から描くと
描画オブジェクトの設定が非常にめんどくさいです
GDI+を使えば、純粋に描くよりかなり遅いですが楽に描画でき...
また、ビットマップ以外の画像も簡単に扱うことができます
ただ、裏側で何が行われているか知るためにもこの回は重要です
全ソースコードは下から
&ref(main.cpp);
プログラムで使う画像はこちら
&ref(test.bmp);
画像は作成したプロジェクトと同じ場所においてください
&ref(projectfolder.GIF);
|(^ω^)やったお|3|
|何これwww意味不すぎwww|1|
|。(`ω´#)。あぁん?最近、だらしねぇな|0|
終了行:
皆さんお待ちかねの(?)
GDIを使った描画を扱います
GDIとはGraphics Device Interfaceの略で
グラフィカルオブジェクトの表示と、ディスプレイやプリンタ...
今回は
・ペンを使った直線、曲線の描画
・ブラシを使った円、矩形の描画
・ビットマップ画像の描画
・フォント指定した文字列の描画
の基本的な描画を行います
&ref(paint.GIF);
先にことわっておきます
かなりめんどくさいです
まず、Win32APIの描画の概念図から
&ref(hdc.jpg);
真ん中のHDCというのは、デバイスコンテキストのハンドル(ポ...
デバイスコンテキストとは、出力対象を指します
大抵の場合、出力対象とはアプリケーションのクライアント領...
HDCに結ばれているものを描画オブジェクトと呼びます(正式な...
・HPENはペンのハンドルです。
ペンは線を書くのに使います。
・HBITMAPはビットマップのハンドルです。
ビットマップ画像(.bmp)を指します。
ここで、ビットマップ以外は取り扱えないの?って話になるの...
GDI+を使えばそれ以外のフォーマットの画像でも簡単に読み込...
・HBRUSHはブラシのハンドルです。
ブラシは図形の塗りつぶしに使います。
・HFONTはフォントのハンドルです。
フォントは文字を書くときに文字サイズや書式を決めます。
・HRGNはリージョンのハンドルです。
リージョンは、ウィンドウの形の決めることができます
今回は使いません、機会があったら取り上げようと思います。
・HPALETTEはパレットのハンドルです。
ここでは取り扱いません
SIZE(30){ COLOR(#ffaa00){デバイスコンテキストには関連付け...
つまりデバイスコンテキストは
常にペン、ビットマップ、ブラシ、フォント、リージョン、パ...
(イメージ的には、千手観音みたいなもの)
ここで注意してほしいのは、
SIZE(30){ COLOR(#ffaa00){デバイスコンテキストは同時に同じ...
たとえば、ペンを2つ同時に持つことはできません
なので
太い線を書いた後、細い線を書きたいなと思ったら
太いペンで太い線を書いた後、細いペンに持ちかえなければな...
ブラシやフォントに関しても同じです
---------------------------------------------------------...
今回のソースコードです。
//------------------------------------------------------//
// ウィンドウ描画メッセージ処理
//
// 引数: hWnd ウィンドウハンドル
//------------------------------------------------------//
void OnPaint(HWND hWnd){
// 描画開始
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
// ペン作成
HPEN hPen = CreatePen(PS_SOLID,5,RGB(255,0,0));
HPEN hNullPen = CreatePen(PS_NULL,1,RGB(0,0,0));
HPEN hDefPen = (HPEN)SelectObject(hdc,hPen);
// ブラシ作成
HBRUSH hBrush = CreateSolidBrush(RGB(0,255,0));
HBRUSH hDefBrush = (HBRUSH)SelectObject(hdc,hBrush);
// ビットマップ読み込み
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);...
HBITMAP hBmp = (HBITMAP)LoadImage(hInstance,_T("test.bm...
BITMAP Bmp;
GetObject(hBmp,sizeof(BITMAP),&Bmp);
HDC hBmpDC = CreateCompatibleDC(hdc);
HBITMAP hDefBmp = (HBITMAP)SelectObject(hBmpDC, h...
// フォント作成
LOGFONT logfont = {};
logfont.lfHeight = 30; // 文字高さ
logfont.lfWidth = 12; // 文字幅
logfont.lfEscapement = 30; // 文字送りの方向とX軸...
logfont.lfOrientation = logfont.lfEscapement; // ベ...
logfont.lfWeight = FW_BOLD; // フォントの太さ
logfont.lfItalic = TRUE; // イタリック体指定
logfont.lfUnderline = TRUE; // 下線付き指定
logfont.lfStrikeOut = TRUE; // 打ち消し線指定
logfont.lfCharSet = SHIFTJIS_CHARSET; // キャラ...
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; // 出力...
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; // クリ...
logfont.lfQuality = DEFAULT_QUALITY; // 出力品質
logfont.lfPitchAndFamily= FF_DONTCARE|DEFAULT_PITCH;// ...
_tcscpy(logfont.lfFaceName,_T("MS ゴシック")); // フォ...
HFONT hFont = CreateFontIndirect(&logfont);
HFONT hDefFont = (HFONT)SelectObject(hdc,hFont);
// 直線描画
MoveToEx(hdc,10,100,NULL); // 始点をセット
LineTo(hdc,10,200); // 始点から割り当てられたペンで終...
// 曲線描画
POINT pt[4] = {};
pt[0].x = 50;pt[0].y = 50;
pt[1].x = 100;pt[1].y = 150;
pt[2].x = 50;pt[2].y = 250;
pt[3].x = 150;pt[3].y = 250;
// 点情報から割り当てられたペンでベジェ曲線描画、点の数...
PolyBezier(hdc,pt,4);
// 楕円描画
SelectObject(hdc,hNullPen); // 枠がいらない
RECT PointRect;
PointRect.left = -5;
PointRect.top = -5;
PointRect.right = 5;
PointRect.bottom = 5;
for(int i = 0;i < 4;++i)
Ellipse(hdc,pt[i].x + PointRect.left,pt[i].y + PointRe...
// 矩形描画
SelectObject(hdc,hNullPen); // 枠がいらない
RECT rect = {30,130,50,150};
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom...
// 画像表示
BitBlt(hdc,200,0,Bmp.bmWidth,Bmp.bmHeight,hBmpDC,0,0,SR...
int X = 0;
int Y = 0;
// 文字列描画
const TCHAR* szText = _T("Hello World");
SetTextColor(hdc,RGB(0,0,255)); // 文字色を青に変更
TextOut(hdc,X,Y,szText,(int)_tcslen(szText)); // 文字列...
// 使い終わったら元の描画オブジェクトに戻す
SelectObject(hdc,hDefPen);
SelectObject(hdc,hDefBrush);
SelectObject(hBmpDC, hDefBmp);
SelectObject(hdc, hDefFont);
// 使わなくなった描画オブジェクトは破棄
DeleteObject(hPen);
DeleteObject(hNullPen);
DeleteObject(hBrush);
DeleteObject(hBmp);
DeleteObject(hDefFont);
// 使わなくなったデバイスコンテキストを破棄
DeleteDC(hBmpDC);
// 描画終了
EndPaint(hWnd,&ps);
}
//------------------------------------------------------//
// ウィンドウ破棄メッセージ処理
//
// 引数: hWnd ウィンドウハンドル
//------------------------------------------------------//
void OnDestroy(HWND hWnd){
PostQuitMessage(0);
}
//-----------------------------------------------------//
// ウィンドウプロシージャ
// デフォルトの処理はDefWindowProc関数で行う
//
// 引数: hWnd ウィンドウハンドル
// msg メッセージ
// wParam パラメータ
// lParam パラメータ
//
// 戻り値:処理結果
//-----------------------------------------------------//
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wPa...
switch(msg){
HANDLE_MSG(hWnd,WM_PAINT,OnPaint);
HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
描画を行うタイミングというものがあります(好きな時に描画...
それは、WM_PAINTというメッセージが送られてきたときです
このWM_PAINTは、ウィンドウが作成されたときやウィンドウの...
ウィンドウプロシージャに送られてくるメッセージです
メッセージクラッカーで自作のOnPaint関数に処理させます
HANDLE_MSG(hWnd,WM_PAINT,OnPaint);
描画するときは
必ずBeginPaint関数とEndPaint関数の間で描画しなければなり...
// 描画開始
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
// ここに描画処理
// 描画終了
EndPaint(hWnd,&ps);
------------------------------------------------------
ペンを作成するには、
CreatePen関数を使います
// ペン作成
HPEN hPen = CreatePen(PS_SOLID,5,RGB(255,0,0));
HPEN hNullPen = CreatePen(PS_NULL,1,RGB(0,0,0));
CreatePen関数の
第一引数はペンのスタイルです
PS_SOLID 普通の線
PS_DASH 破線
PS_DOT 点線
PS_NULL 空のペン(描画しない)
などがあります
第2引数はペンの太さです
第3引数はペンの色です
引数がCOLORREFとなっていますが
RGBマクロを使うとよいでしょう
各種色成分は0〜255の範囲で指定します
たとえば、RGB(255,0,0)は赤になります
もっと詳しく知りたい人はmsdn公式を見てください
http://msdn.microsoft.com/ja-jp/library/cc428348.aspx
ペンを作っただけでは描画に反映されません
デバイスコンテキストにペンを割り当てなければなりません
SIZE(30){ COLOR(#ffaa00){描画オブジェクトをデバイスコンテ...
HPEN hDefPen = (HPEN)SelectObject(hdc,hPen);
他の描画オブジェクトに関しても割り当てないと反映されません
たとえば、ブラシなどは次のようにキャストして使います
HBRUSH hDefBrush = (HBRUSH)SelectObject(hdc,hBrush);
SelectObject関数の戻り値はHGDIOBJ型となっていますが、
これを割り当てた描画オブジェクト型にキャストします
ここで気を付けてほしいのはデフォルトの描画オブジェクトが...
SIZE(30){ COLOR(#ffaa00){デフォルトの描画オブジェクトは描...
// 使い終わったら元の描画オブジェクトに戻す
SelectObject(hdc,hDefPen);
SelectObject(hdc,hDefBrush);
SelectObject(hBmpDC, hDefBmp);
SelectObject(hdc, hDefFont);
直線を描画するには、MoveTo関数で始点をセットし
LineTo関数で始点から終点までデバイスコンテキストに割り当...
(SelectObjectしなければデフォルトのペンで描画される)
// 直線描画
MoveToEx(hdc,始点x座標,始点y座標,NULL); // 始点をセット
LineTo(hdc,終点y座標,終点y座標); // 始点から割り当てら...
続いて、曲線(ベジェ曲線)を描いてみます
ベジェ曲線とは端点(始点と終点)と制御点
を指定してやるだけで形状が決まる曲線です
3次元ベジェ曲線を描くためには最低4つの点が必要です
(3次元ベジェが最も一般的なベジェ曲線)
&ref(bezier.gif);
緑の枠に囲まれた部分を凸包と呼び、
曲線は必ず凸包の内部に収まるという性質があります
ベジェ曲線を描画するにはPolyBezier関数を使います
(SelectObjectしなければデフォルトのペンで描画される)
// 曲線描画
POINT pt[4] = {};
pt[0].x = 50;pt[0].y = 50;
pt[1].x = 100;pt[1].y = 150;
pt[2].x = 50;pt[2].y = 250;
pt[3].x = 150;pt[3].y = 250;
// 点情報から割り当てられたペンでベジェ曲線描画、点の数...
PolyBezier(hdc,点の配列,点の個数(3の倍数+1));
-----------------------------------------------------
続いてブラシを作ってみます
ブラシは図形の塗りつぶしに使います
単色の塗りつぶし用ブラシ作成にはCreateSolidBrush関数を使...
色を指定して作成します
// ブラシ作成
HBRUSH hBrush = CreateSolidBrush(RGB(0,255,0));
ここでは、説明しませんが
網目模様などのパターン描画にはCreateHatchBrush関数
画像のイメージをタイル状にしたブラシ作成にはCreatePattern...
などが用意されています
ブラシをデバイスコンテキストに割り当てた後
HBRUSH hDefBrush = (HBRUSH)SelectObject(hdc,hBrush);
図形を描画します
円(楕円)を描画するにはEllipse関数を使います
ペンで枠が描かれ
内部はブラシで塗りつぶしされます
(SelectObjectしなければデフォルトのペンとブラシで描画さ...
枠が要らない場合は空のペンをSelectObject関数でデバイスコ...
// 楕円描画
SelectObject(hdc,hNullPen);// 枠がいらない
RECT PointRect;
PointRect.left = -5;
PointRect.top = -5;
PointRect.right = 5;
PointRect.bottom = 5;
for(int i = 0;i < 4;++i)
Ellipse(hdc,pt[i].x + PointRect.left,pt[i].y + PointRec...
矩形を描画するには
Rectangle関数を使います
ペンで枠が描かれ
内部はブラシで塗りつぶしされます
(SelectObjectしなければデフォルトのペンとブラシで描画さ...
枠が要らない場合は空のペンをSelectObject関数でデバイスコ...
// 矩形描画
SelectObject(hdc,hNullPen); // 枠がいらない
RECT rect = {30,130,50,150};
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom)...
---------------------------------------------
ビットマップ画像(.bmp)読み込みです
読み込みにはLoadImage関数を使います
// ビットマップ読み込み
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); ...
HBITMAP hBmp = (HBITMAP)LoadImage(hInstance,_T("test.bmp...
第一引数にはインスタンスハンドルを指定します
第二引数にはビットマップファイル名を指定します
第三引数には読み込みタイプを指定します(ビットマップ画像...
第四、五引数は0で構いません
最後の引数は読み込みフラグです(OR演算子「|」で組み合わせ...
ファイル読み込みなのでLR_LOADFROMFILEは必須です
LR_SHAREDは同じリソースなら、すでに読み込んであるビットマ...
LR_DEFAULTCOLORはカラー画像であることを示します(明示しな...
ビットマップハンドルが取得できたら
ビットマップの情報を取得します
BITMAP Bmp;
GetObject(hBmp,sizeof(BITMAP),&Bmp);
SIZE(30){ COLOR(#ffaa00){ GetObject関数で描画オブジェクト...
ペンやブラシ、フォントに関しても次のように取得できます
// ペン
LOGPEN pen;
GetObject(hPen,sizeof(LOGPEN),&pen);
// ブラシ
LOGBRUSH brush;
GetObject(hPen,sizeof(LOGBRUSH),&brush);
// フォント
LOGFONT font;
GetObject(hFont,sizeof(LOGFONT),&font);
GetObjectしたBITMAP構造体のbmWidth,bmHeightに画像サイズが...
ビットマップの情報を読み取った後
描画画面と互換性を持つ裏画面を作成します
これはあとで画像を描画するために必要です
HDC hBmpDC = CreateCompatibleDC(hdc); // 裏画面を作成し...
HBITMAP hDefBmp = (HBITMAP)SelectObject(hBmpDC, hBmp);
ここで気を付けて欲しいのはSelectObject関数で画像を裏画面...
直接画像を描画することができないので
裏画面から描画画面へ画像を転送します
画像を転送するにはBitBlt関数を使います
// 画像表示
BitBlt(転送先デバイスコンテキスト,転送先X座標,転送先Y座...
BitBlt(hdc,200,0,Bmp.bmWidth,Bmp.bmHeight,hBmpDC,0,0,SRC...
第一引数は描画画面のデバイスコンテキストを指定します
第二、三引数は描画する位置を指定します
第四、五引数は描画サイズを指定します
ここで注意してほしいのは画像を縮小拡大して転送するのでは...
画像サイズより小さいサイズを指定した場合、そのサイズだけ...
そのままコピーしたい場合はそのままの画像サイズを指定して...
第六引数は転送元デバイスコンテキストは裏画面のデバイスコ...
転送元X座標、転送元Y座標は
画像をそのままコピーしたい場合は0を指定してやればいいので...
(というのは裏画面の左上隅に画像はセットされている)
いまひとつわかりにくいと思います
次の図を見てください
&ref(bitblt.GIF);
画像幅、画像高さ、転送元X、転送元Yを
うまく指定してやれば画像の一部を切り取ることができます
アニメーション用の画像などに利用できます
ラスタオペレーションコードはどのように転送するかのフラグ...
----------------------------------------------------------
続いて文字列描画です
フォントを作成するには
CreateFont関数もしくはCreateFontIndirect関数を使います
CreateFont関数は引数があまりにも多いのでやめました
今回はCreateFontIndirect関数を使います
引数の代わりにLOGFONT構造体でフォントの情報を指定しなけれ...
(こちらも変数多いのですが・・・)
// フォント作成
LOGFONT logfont = {};
logfont.lfHeight = 30; // 文字高さ
logfont.lfWidth = 12; // 文字幅
logfont.lfEscapement = 30; // 文字送りの方向とX軸...
logfont.lfOrientation = logfont.lfEscapement; // ベー...
logfont.lfWeight = FW_BOLD; // フォントの太さ
logfont.lfItalic = TRUE; // イタリック体指定
logfont.lfUnderline = TRUE; // 下線付き指定
logfont.lfStrikeOut = TRUE; // 打ち消し線指定
logfont.lfCharSet = SHIFTJIS_CHARSET; // キャラク...
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; // 出力精度
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; // クリ...
logfont.lfQuality = DEFAULT_QUALITY; // 出力品質
logfont.lfPitchAndFamily= FF_DONTCARE|DEFAULT_PITCH; /...
_tcscpy(logfont.lfFaceName,_T("MS ゴシック")); // フォ...
HFONT hFont = CreateFontIndirect(&logfont);
HFONT hDefFont = (HFONT)SelectObject(hdc,hFont);
LOGFONT構造体変数で
とりあえずよく使うやつだけ説明します
それ以外はとりあえずはそのまま使ってください
lfHeight は文字高さを指定します
lfWidth は文字幅を指定します
lfEscapementは文字角度を指定します。(1/10度指定です)傾...
lfOrientationはlfEscapementと同じものを指定してください
lfWeightは文字の太さを決めます
lfItalicはイタリック表示です(使わない場合はFALSE)
lfUnderlineは文字の下に下線を引きます(使わない場合はFALS...
lfStrikeOutは文字に打ち消し線を引きます(使わない場合はFA...
lfFaceNameはフォント名を指定します(MS ゴシック、MS 明朝...
SetTextColor関数で文字の色を変更し
TextOut関数で文字列を描画します
(SelectObjectしなければデフォルトのフォントで描画される)
最後の引数は文字数指定します
_tcslen関数はstrlenと_wstrlenを切り変えるマクロです
// 文字列描画
const TCHAR* szText = _T("Hello World");
SetTextColor(hdc,RGB(0,0,255)); // 文字色を青に変更
TextOut(hdc,X,Y,szText,(int)_tcslen(szText)); // 文字列...
----------------------------------------------------------
最後に、
SIZE(30){ COLOR(#ffaa00){ 新しく作成(Createなんとか)し...
しないとハンドルリークを起こします(メモリリークの一種)
// 使わなくなった描画オブジェクトは破棄
DeleteObject(hPen);
DeleteObject(hNullPen);
DeleteObject(hBrush);
DeleteObject(hBmp);
DeleteObject(hDefFont);
// 使わなくなったデバイスコンテキストを破棄
DeleteDC(hBmpDC);
描画オブジェクトに関してはDeleteObject関数
デバイスコンテキストに関してはDeleteDC関数
を使います
さらに詳しい対応関係はMSDN公式を参照してください
http://msdn.microsoft.com/en-us/library/ms724291%28VS.85%...
-------------------------------------------------------
ふぅ・・・これで基本的な描画の説明は終わりました(^^;...
ここで全てを取り上げるの量的に不可能なので
その他の描画に関しての情報はMSDN公式を見てください
MSDN公式
http://msdn.microsoft.com/ja-jp/library/cc428835.aspx
しかし、冗長なコードですね
やれることが多いのはいいのですが一から描くと
描画オブジェクトの設定が非常にめんどくさいです
GDI+を使えば、純粋に描くよりかなり遅いですが楽に描画でき...
また、ビットマップ以外の画像も簡単に扱うことができます
ただ、裏側で何が行われているか知るためにもこの回は重要です
全ソースコードは下から
&ref(main.cpp);
プログラムで使う画像はこちら
&ref(test.bmp);
画像は作成したプロジェクトと同じ場所においてください
&ref(projectfolder.GIF);
|(^ω^)やったお|3|
|何これwww意味不すぎwww|1|
|。(`ω´#)。あぁん?最近、だらしねぇな|0|
ページ名: