第23章 簡単なグラフィックス


今回は、簡単なグラフィックスをします。 グラフィックスを作成するにはGDI(Graphics Device Interface) を使います。GDIには、直線、円、長方形などを描画する関数が 用意されています。まず、今回は直線を描いてみましょう。

手順 1.WM_PAINTメッセージの所にプログラムを書く 2.BeginPaintとEndPaint関数で挟まれた間に描画関数を書く 3.ペンを作る 4.始点に移動 5.終点を指定 6.使い終わったペンの削除

これで、直線は描けます。必要な関数について説明します。

BeginPaintとEndPaint関数についてはすでに、第5章で解説しています。 次に直線を描くためのペンを作らなくてはいけません。

HPEN CreatePen( int fnPenStyle, // pen style int nWidth, // pen width COLORREF crColor // pen color );

fnPenStyleとは、実線とか破線とか一点鎖線とかの線の種類を指定します。

fnPenStyle PS_SOLID・・・・・・実線 PS_DASH・・・・・・・破線 PS_DOT・・・・・・・・点線 PS_DASHDOT・・・・・・一点鎖線 PS_DASHDOTDOT・・・・・2点鎖線

上の5つくらいがよく使うものでしょう。 第2引数のnWidthは線の太さです。ただしペンの太さを2以上に した場合上の5つの中では実線以外を選択できません。三番目の引数はすでに 第5章で解説してあります。 さて、CreatePen関数を実行しただけでは、そのペンを使うことになりません。 次に

HGDIOBJ SelectObject( HDC hdc, // デバイスコンテキストハンドル HGDIOBJ hgdiobj // オブジェクトのハンドル );

これによってオブジェクトを選択します。
戻り値は直前のオブジェクトハンドルです。
hOldPen = SelectObject(hdc, hPen);
とすると古いペンを保存できます。

次に直線の始点に移動します。

BOOL MoveToEx( HDC hdc, // デバイスコンテキストハンドル int X, // X座標 int Y, // Y座標 LPPOINT lpPoint // 前回のカレントポイントのポインター );

次にLineTo関数で直線を描きます。

BOOL LineTo( HDC hdc, int nXEnd, int nYEnd );

次に直線を書き終わったらペンの後始末をします。

SelectObject(hdc, hOldPen);

で古いペンに戻してから、

BOOL DeleteObject( HGDIOBJ hObject );

によってhPenを削除します。

ま、ざっとこんなものです。

// グラフィックス描画 int DrawGr(HWND hWnd, HDC hdc) { HPEN hPen, hOldPen; RECT rt; GetClientRect(hWnd, &rt); hPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0)); hOldPen = SelectObject(hdc, hPen); MoveToEx(hdc, 0, 0, NULL); LineTo(hdc, rt.right, rt.bottom); SelectObject(hdc, hOldPen); DeleteObject(hPen); hPen = CreatePen(PS_SOLID, 5, RGB(255, 0, 255)); hOldPen = SelectObject(hdc, hPen); MoveToEx(hdc, rt.right, 0, NULL); LineTo(hdc, 0, rt.bottom); SelectObject(hdc, hOldPen); DeleteObject(hPen); return 0; }

この自作DrawGr関数をウィンドウプロシージャのWM_PAINTメッセージの所で 呼び出せばよいことになります。上の例ではクライアント領域の左上から 右下へ太さ1の緑の実線と、右上から左下に太さ5の実線がひかさる予定です。

あとのプログラム部分はいつもと殆ど変わりません。

// grph01.rcの一部 自前でリソース・スクリプトを作る人は参考にしてください ///////////////////////////////////////////////////////////////////////////// // // Menu // GRPH MENU DISCARDABLE BEGIN MENUITEM "終了(&Q)", IDM_END END

これは、別にどうということもないメニューリソースです。 自前で作る人は、windows.hとIDM_ENDを定義したヘッダーファイルを インクルードしてください。また、次のソースファイルでは resource.hをインクルードするのではなくIDM_ENDを定義した ヘッダファイルをインクルードします。

// grph01.cpp #include <windows.h> #include <windowsx.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE, LPCSTR); BOOL InitInstance(HINSTANCE, LPCSTR, int); int DrawGr(HWND, HDC); int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; char szClassName[] = "grph01"; if (!hPrevInst) { if (!InitApp(hCurInst, szClassName)) return FALSE; } if (!InitInstance(hCurInst, szClassName, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, NULL, NULL)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "GRPH"; wc.lpszClassName = (LPCSTR)szClassName; return (RegisterClass(&wc)); } BOOL InitInstance(HINSTANCE hInst, LPCSTR szClassName, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "GRAPHICS", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; HDC hdc; PAINTSTRUCT ps; switch (msg) { case WM_COMMAND: switch (GET_WM_COMMAND_ID(wp, lp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0L); break; } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); DrawGr(hWnd, hdc); EndPaint(hWnd, &ps); break; case WM_CLOSE: id = MessageBox(hWnd, (LPCTSTR)"終了しますか", (LPCTSTR)"終了確認", MB_OKCANCEL | MB_ICONQUESTION); if (id == IDOK) { DestroyWindow(hWnd); } if (id == IDCANCEL) { return FALSE; } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; } // グラフィックス描画 int DrawGr(HWND hWnd, HDC hdc) { HPEN hPen, hOldPen; RECT rt; GetClientRect(hWnd, &rt); hPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0)); hOldPen = SelectObject(hdc, hPen); MoveToEx(hdc, 0, 0, NULL); LineTo(hdc, rt.right, rt.bottom); SelectObject(hdc, hOldPen); DeleteObject(hPen); hPen = CreatePen(PS_SOLID, 5, RGB(255, 0, 255)); hOldPen = SelectObject(hdc, hPen); MoveToEx(hdc, rt.right, 0, NULL); LineTo(hdc, 0, rt.bottom); SelectObject(hdc, hOldPen); DeleteObject(hPen); return 0; }

さて、これを実行してみましょう。


確かに、予想通りの図形が描画されますね。

ウィンドウの大きさを変えてもクライアント領域の隅から 直線が描画されます。

今回は、簡単でしたね。次回は長方形の描画をします。 尚今回は、リソース・スクリプトを載せていませんがこれは もう、自分で作れますね。


[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]

Update Apr/24/1997 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。