四角形を描く
線の次は四角をかいてみます。Rectangle関数を使います。
BOOL Rectangle(
HDC hdc, // デバイスコンテキストのハンドル
int nLeftRect, // 長方形の左上隅の x 座標
int nTopRect, // 長方形の左上隅の y 座標
int nRightRect, // 長方形の右下隅の x 座標
int nBottomRect // 長方形の右下隅の y 座標
);
ちょっとわかりにくいでしょうか。要は下の図のように座標を指定するということです。
じゃあ、早速四角を書いてみましょう。方法は、線を引くときとあまり変わりません。
hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
hOldPen = SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(0, 255, 0));
hOldBrush = SelectObject(hdc, hBrush);
Rectangle(hdc, 10, 10, 100, 100);
SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldBrush);
DeleteObject(hPen);
DeleteObject(hBrush);
新しくCreateSolidBrush関数が出てきましたね。これはべた塗り用のブラシを作成する関数です。ブラシとは、システムが図形の内側を描画することです。
CreateSolidBrush関数
指定された色の論理ブラシを作成します。
HBRUSH CreateSolidBrush(
COLORREF crColor // ブラシの色を表す値
);
clrref にはブラシの色を指定します。
// gdi004.cpp
//
// 四角形を描く
#include <windows.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;
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,hBrush,hOldBrush;
static POINT lpPoint[4];
switch (msg){
case WM_PAINT:
hdc = BeginPaint(hWnd,&ps); // 描画処理を開始します。
hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
hOldPen = SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(0, 255, 0));
hOldBrush = SelectObject(hdc, hBrush);
Rectangle(hdc, 10, 10, 100, 100);
SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldBrush);
DeleteObject(hPen);
DeleteObject(hBrush);
EndPaint(hWnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}
実行結果は次のようになります。
今日はここまでです。
テーマ:Windows Mobile - ジャンル:コンピュータ
線を描画する
線を描画する関数にはLineTo関数のほかにPolyline関数があります。
Polyline関数は、点の情報を格納した構造体の配列を渡すと、連続した線分を描画してくれる関数です。
LineTo関数と違い、開始座標を指定する必要はありません。開始座標も含め、配列で渡します。
また、現在の位置の更新も行いません。
BOOL Polyline(
HDC hdc, // デバイスコンテキストのハンドル
CONST POINT *lppt, // 端点からなる配列
int cPoints // 配列内の点の数
);
hdc:デバイスコンテキストのハンドルを指定します。
lppt:複数のPOINT構造体からなる配列へのポインタを指定します。
cPoints:配列内の点の数を指定します。
ソースは次のようになります。
static POINT lpPoint[4];
lpPoint[0].x = 10;
lpPoint[0].y = 10;
lpPoint[1].x = 100;
lpPoint[1].y = 10;
lpPoint[2].x = 10;
lpPoint[2].y = 100;
lpPoint[3].x = 100;
lpPoint[3].y = 100;
Polyline(hdc, lpPoint, 4);
何度もLineTo関数を呼び出すより、スマートになりましたね。
// gdi002.cpp
//
// 簡単なグラフィックス(線を引く)
#include <windows.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;
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;
static POINT lpPoint[4];
switch (msg){
case WM_CREATE:
// 初期化処理など
lpPoint[0].x = 10;
lpPoint[0].y = 10;
lpPoint[1].x = 100;
lpPoint[1].y = 10;
lpPoint[2].x = 10;
lpPoint[2].y = 100;
lpPoint[3].x = 100;
lpPoint[3].y = 100;
break;
case WM_PAINT:
hdc = BeginPaint(hWnd,&ps); // 描画処理を開始します。
hPen = CreatePen(PS_SOLID, 1, RGB(0, 128, 0));
hOldPen = SelectObject(hdc, hPen);
Polyline(hdc, lpPoint, 4);
SelectObject(hdc, hOldPen);
DeleteObject(hPen);
EndPaint(hWnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}
きょうはここまでです。
テーマ:Windows Mobile - ジャンル:コンピュータ
グラフィックスを描く
まずは簡単なグラフィックスを表示してみましょう。
線を引くためのソースを表示します
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;
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;
}
きょうはここまでです。
テーマ:Windows Mobile - ジャンル:コンピュータ
Windowsのグラフィックス表示の仕組みについて説明します。
グラフィックスの表示にはGDI(Graphic Device Interface)を使用します。
GDIはグラフィカルオブジェクトの表示を行うためのWindowsの規格になります。
先にも述べましたが、GDIにより機種や装置による差異を吸収してくれます。
グラフィックスを表示する先として、デバイスコンテキストを指定します。
デバイスコンテキストは、いわば画用紙です。画用紙に絵を描くように、ペンを選び、色を選んで、色々な図形を描いていきます。
画用紙(デバイスコンテキスト)はディスプレイ用、プリンタ用など出力デバイスの数だけあります。ディスプレイ用画用紙に絵を描けば、ディスプレイに表示され、プリンタ用画用紙に絵を描けばプリンタに出力されます。画用紙の種類が違っても、絵の描き方は同じです。ディスプレイもプリンタも、同じ手順で図形を描くことができます。
では、私たちは今からウィン君(Win32API)に、線を引いてもらいましょう。
ウィン君はこの画用紙に、ペン、ブラシ、フォントなどで絵を描いてくれます。でも、何から何まで指示してあげないと、線を引いてくれません。
普通の人に線を引いてもらう場合、たとえば、画用紙に赤い太い線を引いてください。とお願いすれば、もし赤い太いペンがなければ、買ってきて、線を引いてくれるでしょう。しかしウィン君はあまり気が利きません。プログラマが何から何まで指示してあげましょう。
ウィン君は同じ種類のオブジェクトは1つしか持てません。つまり、太いペンと、細いペンを同時に持つことは出来ません(別の種類のオブジェクトであれば同時に持つことができます。たとえば太いペンと、赤いブラシを持つことは出来ます) 。
太いペンで太い線を引いた後は、細いペンに持ち替えて、細い線を描きます。
ウィン君が線を引く手順は次の通り。
どの画用紙に書くのか決める。(画面に書くのか、プリンタに出力するのか等)
ペンの太さや色を指示し、ペンを作ってもらいます。
ペンを持ちます。
ペン先を画用紙のある場所に移動します。
そこからペン先をおろし、スーッと線を引きます。
ペンが要らなくなったら捨てます。(必要になったらまた作ればいいのです)
イメージわきましたか?ウィン君に線を引いてもらうには、上記のようにお願いしなければなりません。
では次にソースを見ていきましょう。
今日はここまでです。
テーマ:Windows Mobile - ジャンル:コンピュータ
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | - | - |