グラフィックスを描く
まずは簡単なグラフィックスを表示してみましょう。
線を引くためのソースを表示します
hPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
hOldPen = SelectObject(hdc, hPen);
MoveToEx(hdc, 10, 10, NULL);
LineTo(hdc, 100, 10);
LineTo(hdc, 10, 100);
LineTo(hdc, 100, 100);
SelectObject(hdc, hOldPen);
DeleteObject(hPen);
単に線を引くだけだと言うのに、たくさんの関数が必要になっています。GDIによるグラフィックスでは描画のための手続きがありますのでそれを覚えていかなければなりません。
線の描画手順
1.CreatePen関数で論理ペンを作成します。
2.SelectObject関数でデバイスコンテキストにペンをセットします。
その際、もともとセットされていたペンをhOldPenに保存しておきます。
3.MoveToEx関数で現在の位置(10,10)を指定します。これが開始座標になります。
4.LineTo関数で、開始座標から、終了座標(100,10)へ線を引きます。
開始座標(100,10)から終了座標(10, 100)へ線を引きます。
開始座標(10, 100)から終了座標(100, 100)へ線を引きます。
5.SelectObject関数でペンを元に戻します。
6.不要になったペンはDeleteObject関数で削除します。
ではそれぞれ解説していきます。
1.CreatePen関数で論理ペンを作成します。
hPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
CreatePen関数は指定されたスタイル、幅、色を持つ論理ペンを作成します。
HPEN CreatePen(
int fnPenStyle, // ペンのスタイル
int nWidth, // ペンの幅
COLORREF crColor // ペンの色
);
RGBは色を表すCOLORREF型を取得する為のマクロです。
COLORREF RGB(BYTE bRed , BYTE bGreen , BYTE bBlue);
2.SelectObject関数でデバイスコンテキストにペンをセットします。(ペンを手にもつ。それまで持っていたペンは端においておきましょう。)
その際、もともとセットされていたペンをhOldPenに保存しておきます。
hOldPen = SelectObject(hdc, hPen);
SelectObject関数はGDIオブジェクトを選択する関数でしたね。この関数を使って、デバイスコンテキストにペンをセットしています。
3.MoveToEx関数で開始座標(10,10)へ移動します。
MoveToEx(hdc, 10, 10, NULL);
MoveToEx関数
現在の位置を更新して、指定された点を新しい現在の位置にします。
BOOL MoveToEx(
HDC hdc, // デバイスコンテキストのハンドル
int X, // 新しい現在の位置の x 座標
int Y, // 新しい現在の位置の y 座標
LPPOINT lpPoint // それまでの現在の位置
);
4.LineTo関数で、開始座標から、終了座標(100,10)へ線を引きます。
開始座標(100,10)から終了座標(10, 100)へ線を引きます。
開始座標(10, 100)から終了座標(100, 100)へ線を引きます。
LineTo(hdc, 100, 10);
LineTo(hdc, 10, 100
LineTo(hdc, 100, 100);
LineTo関数
現在の位置と、指定された終点を結ぶ直線を描画します。
BOOL LineTo(
HDC hdc, // デバイスコンテキストのハンドル
int nXEnd, // 終点の x 座標
int nYEnd // 終点の y 座標
);
指定した終点が現在の位置になります。
5.SelectObject関数でペンを元に戻します。
SelectObject(hdc, hOldPen);
6.不要になったペンはDeleteObject関数で削除します。
DeleteObject(hPen);
BOOL DeleteObject(
HGDIOBJ hObject // グラフィックオブジェクトのハンドル
);
フォントのときと同じですね。使わなくなったオブジェクトは削除しましょう。
全ソースは次のとおり。
// gdi001.cpp
//
// 簡単なグラフィックス(線を引く)
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
HWND InitInstance(HINSTANCE, int);
WCHAR szClassName[] = _T("gdi001"); // ウィンドウクラス。UNICODEとしての文字列定数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd)
{
MSG msg;
BOOL bRet;
HWND hWnd;
if (!InitApp(hInstance))
return FALSE;
if (!(hWnd = InitInstance(hInstance,nShowCmd)))
return FALSE;
while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1){
break;
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
// ウィンドウクラスの登録
ATOM InitApp(HINSTANCE hInst)
{
WNDCLASS wc;
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = WndProc; // プロシージャ名
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL; // 未サポート
wc.hCursor = NULL; // 未サポート
wc.hbrBackground= (HBRUSH) COLOR_WINDOW;
wc.lpszMenuName = NULL; // 未サポート
wc.lpszClassName=(LPCTSTR) szClassName;
return (RegisterClass(&wc));
}
// ウィンドウの生成
HWND InitInstance(HINSTANCE hInst, int nShowCmd)
{
HWND hWnd;
hWnd = CreateWindow(szClassName,_T("Window Title"),
WS_CLIPCHILDREN, // ウィンドウの種類
CW_USEDEFAULT, // x座標
CW_USEDEFAULT, // y座標
CW_USEDEFAULT, // 幅
CW_USEDEFAULT, // 高さ
NULL, // 親ウィンドウのハンドル。親を作るのでNULL
NULL, // メニューハンドルまたは子ウィンドウID
hInst, // インスタンスハンドル
NULL);
if (!hWnd)
return FALSE;
&nb
sp;ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
return hWnd;
}
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
PAINTSTRUCT ps;
HDC hdc;
HGDIOBJ hPen,hOldPen;
switch (msg){
case WM_PAINT:
hdc = BeginPaint(hWnd,&ps); // 描画処理を開始します。
hPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
hOldPen = SelectObject(hdc, hPen);
MoveToEx(hdc, 10, 10, NULL);
LineTo(hdc, 100, 10);
LineTo(hdc, 10, 100);
LineTo(hdc, 100, 100);
SelectObject(hdc, hOldPen);
DeleteObject(hPen);
EndPaint(hWnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}
きょうはここまでです。