レガシー Windows API(概要)について

ここで紹介しているAPIは、Windows95、Windows NT3.5時代のAPI群であり、最新のAPIは含まれていないことに注しして欲しい。なお、当時の解説書は現在よりもより詳細に解説しているため、参考になるはずである。

  • レイアウトを変換する際、崩れているページがあります。
  • 概要およびSampleコードはありますが、APIの解説はありません。

ご要望があれば旧版のWin32 API(HELP形式)をお譲りします。問い合わせフォームより申し込みください。

Windows API 直線と曲線の概要

Microsoft(R) Windows(R) 用に作成されているさまざまなアプリケーションは、 直線や曲線を使って、 ラスタ デバイスにグラフィックを描画します。CADアプリケーションや描画アプリケーションは、 オブジェクトのアウトラインの描画やオブジェクトの中心の指示、 オブジェクトの寸法の表示などに直線と曲線を使います。表計算アプリケーションは、 直線と曲線を使って、 表の罫線やグラフ、 図を描画します。また、 ワード プロセッサ アプリケーションは、 直線を使って、 ページの枠や罫線を作成します。

次に示すトピックでは、 直線と曲線について説明しています。

直線

曲線

直線と曲線の組み合わせ

直線と曲線の属性

直線と曲線の使用

直線関数によるマーカーの描画

直線と曲線による円グラフの描画

直線と曲線の関数

 

 

直線

「直線」とは、 画面 (またはプリンタの用紙) の始点と終点の2点で識別される、 強調表示されたピクセル (またはドット) の集合です。Windowsでは、 始点のピクセルは常に直線に含まれ、 終点のピクセルは常に直線には含まれません (このような直線は、 包含-除外型とも呼ばれます)。

アプリケーションがWindowsの直線描画関数を呼び出すと、 グラフィック デバイス インターフェイス (GDI) やデバイス ドライバが、 どのピクセルを強調表示するかを判断します。「GDI」は、 Windows用アプリケーションのグラフィック関数呼び出しを処理して、 デバイス ドライバに渡します。「デバイス ドライバ」とは、 GDIから入力を受け取ってデバイス コマンドに変換し、 そのコマンドを適切なデバイスに渡すダイナミック リンク ライブラリです。GDIは、 デジタル差分解析 (DDA; Digital Differential Analyzer) を使って、 直線を定義するピクセルの集合を決定します。「DDA」とは、 直線上の各点を調べて、 その点に対応する表示面のピクセルや印刷ページのドットを判断する方法です。次の図は、 直線とその始点と終点、 簡単なDDAで強調表示したピクセルを示しています。

最も簡単でよく使われるDDAは、 Bresenhamによる増分DDAです。Windowsバージョン3.xでは、 このアルゴリズムを改良したものを使って、 直線を描画しています。増分DDAの特徴は簡単さですが、 不正確であるという欠点もあります。このアルゴリズムでは最も近い整数値に丸めるため、 アプリケーションが必要とする元の直線を表現できない場合があります。新しいGDIで使われているDDAでは、 最も近い整数に丸めません。このため、 アプリケーションが要求した元の直線により近い出力が得られます。

注: 新しいWin32 DDAで実現できない直線出力が必要ならば、 LineDDA関数と自分のDDAを使って直線を描画してください。しかし、 LineDDA関数による直線の描画は、 Windowsの直線描画関数よりも非常に低速です。速度が問題となる場合は、 この関数は使わないでください。

アプリケーションは、 新しいWin32 DDAを使って、 直線や連結した線分を描画できます。直線を1つ描画するには、 LineTo関数を使います。この関数は、 デバイス コンテキストの現在位置から、 指定された終点までの直線を描画します。一連の連結した線分を描画するには、 各線分の終点を指定した配列を指定して、 Polyline関数を呼び出します。連結した線分の集合をいくつか描画するには、 必要な終点を指定して、 PolyPolyline関数を呼び出します。

次の図は、 LineTo関数、 Polyline関数、 PolyPolyline関数で作成した直線出力を示しています。

 

 

曲線

「正規曲線」とは、 円錐曲線 (またはその一部) を定義する、 強調表示されたラスタ ディスプレイのピクセル (または印刷ページのドット) の集合です。「非正規曲線」とは、 円錐曲線にそわない曲線を定義するピクセルの集合です。Windowsでは、 直線と同様に、 終点は曲線から除外されます。

Windowsの曲線描画関数をアプリケーションが呼び出すと、 GDIは、 曲線を非常に小さな多数の線分に分割します。GDIは、 その各線分の終点を決定したら、 DDAを使って、 各直線を定義するピクセル (またはドット) を判断します。

だ円またはその一部を描画するには、 Arc関数を呼び出します。この関数は、 境界長方形と呼ばれる仮想の長方形の内側に曲線を描画します。だ円のサイズは、 長方形の中心から長方形の辺までの仮想的な2つの半径で指定します。Arc関数で描画した円弧 (だ円の一部) を次の図に示します。

Arc関数を呼び出すときは、 境界長方形の座標と半径を指定します。上記の図は、 境界長方形と半径を点線で示し、 実際の円弧を実線で描画しています。

円弧を別の方向に描画するには、 SetArcDirection関数とGetArcDirection関数を使ってオブジェクトを描画するときの方向 (時計回り、 反時計回り) を制御してください。円弧などを描画するときのデフォルトの方向は反時計回りです。

Windows用アプリケーションは、 だ円やその一部を描画するほかに、 ベジエ スプライン (Bezier spline) と呼ばれる非正規曲線を描画できます。もともと、 スプラインという用語は、 非正規曲線を製図するための道具のことを指していました。しかし、 グラフィック インターフェイスの進歩によって、 この用語は曲線自体を指すようになりました。「ベジエ スプライン」とは、 4つの制御点 (p1p2 p3p4) で曲率が定義される非正規曲線です。制御点p1p4は曲線の始点と終点を定義し、 制御点p2p3は、 曲線の向きが逆転する点を示すことによって曲線の形を定義します。

非正規曲線を描画するには、 適切な制御点を指定してPolyBezier関数を呼び出します。

 

 

直線と曲線の組み合わせ

Windows用アプリケーションは、 直線や曲線を個別に描画するほかに、 直線と曲線の組み合わせを1つの関数で描画できます。たとえば、 円グラフのアウトラインを描画するには、 AngleArc関数を呼び出します。

AngleArc関数は、 円の外周の一部である円弧を描画し、 その円の中心と円弧の端点を結ぶ直線を描画します。上記の図の円グラフは、 AngleArc関数を5回連続して呼び出して作成しています。Windows用アプリケーションは、 AngleArc関数のほかにも、 PolyDraw関数を使って、 直線と非正規曲線を組み合わせて描画できます。

 

 

直線と曲線の属性

デバイス コンテキストには、 直線や曲線の出力に影響する属性があります。この属性には、 現在位置、 ブラシのスタイル、 ブラシの色、 ペンのスタイル、 ペンの色、 座標変換などがあります。

デバイス コンテキストのデフォルトの現在位置は、 論理 (またはワールド) 空間の点 (0, 0) です。現在位置を新しい位置に設定するには、 新しい座標を指定してMoveToEx関数を呼び出します。

注: Windowsは、 2種類の直線描画関数と曲線描画関数を用意しています。1つは、 デバイス コンテキストの現在位置を変更しません。もう1つは、 現在位置を変更します。現在位置を変更する関数は、 関数名でわかります。関数名が“To”で終わっているときは、 その関数は、 最後に描画した直線の終点に現在位置を設定します (LineTo、 ArcTo、 PolylineTo、 PolyBezierTo)。関数名が“To”で終わっていないときは、 現在位置を変更しません (Arc、 Polyline、 PolyBezier)。

デフォルトのブラシは白のソリッド ブラシです。新しいブラシを作成するには、 CreateBrushIndirect関数を呼び出します。ブラシを作成したら、 SelectObject関数を呼び出して、 そのブラシをデバイス コンテキストで選択します。Windowsは、 デバイス コンテキストでブラシを作成、 選択、 変更するための関数のセットを用意しています。これらの関数とブラシの一般的な情報について、 詳しくはブラシの概要を参照してください。

デフォルトのペンは、 1ピクセル幅の黒いソリッド ペンです。ペンを作成するには、 ExtCreatePen関数を使います。ペンを作成したら、 SelectObject関数を呼び出して、 そのペンをデバイス コンテキストで選択します。Windowsは、 デバイス コンテキストでペンを作成、 選択、 変更するための関数のセットを用意しています。これらの関数とペンの一般的な情報について、 詳しくはペンの概要を参照してください。

デフォルトの座標変換は (単位行列で示される) 恒等変換です。新しい座標変換を指定するには、 SetWorldTransform関数を呼び出します。Windowsは、 直線や曲線を変換して幅、 位置などの外観を変更するための関数のセットを用意しています。これらの関数について、 詳しくは座標空間および座標変換の概要を参照してください。

 

 

 

直線と曲線の使用

直線関数や曲線関数を使って、 事実上任意の図形やオブジェクトをアプリケーション ウィンドウのクライアント領域に描画できます。ここでは、 直線関数や曲線関数を使用したコード例を2つ示します。

 

 

マーカーの描画

マーカーを描画するには、 直線関数を使います。マーカーとは、 点の位置を示す記号です。描画アプリケーションでは、 マーカーを使って、 始点や終点、 制御点などを示します。表計算アプリケーションでは、 マーカーを使って、 図やグラフ上の点を示します。

次に示すコード例のアプリケーション定義のMarker関数は、 MoveToEx関数とLineTo関数を使ってマーカーを作成します。ここでは、 カーソルの真上に、 交差する20ピクセルの直線を2つ描画しています。

 

void Marker(LONG x, LONG y, HWND hwnd)
{
HDC hdc;

hdc = GetDC(hwnd);
MoveToEx(hdc, (int) x - 10, (int) y, (LPPOINT) NULL);
LineTo(hdc, (int) x + 10, (int) y);
MoveToEx(hdc, (int) x, (int) y - 10, (LPPOINT) NULL);
LineTo(hdc, (int) x, (int) y + 10);
ReleaseDC(hwnd, hdc);
}

Windowsは、 ユーザーが左マウス ボタンを押すと、 WM_LBUTTONDOWNメッセージのlParamパラメータにカーソルの座標を設定します。次のコード例は、 アプリケーションがこの座標を取得してカーソルがクライアント領域内にあるかどうかを判断し、 Marker関数にその座標を渡してマーカーを描画する方法を示しています。

 

/* Line- and arc-drawing variables */

static BOOL bCollectPoints;
static POINT ptMouseDown[32];
static int index;
POINTS ptTmp;
RECT rc;

case WM_LBUTTONDOWN:


if (bCollectPoints && index < 32){

/* Create the region from the client area. */

GetClientRect(hwnd, &rc);
hrgn = CreateRectRgn(rc.left, rc.top,
rc.right, rc.bottom);

ptTmp = MAKEPOINTS((POINTS FAR *) lParam);
ptMouseDown[index].x = (LONG) ptTmp.x;
ptMouseDown[index].y = (LONG) ptTmp.y;

/* Test for a hit in the client rectangle. */

if (PtInRegion(hrgn, ptMouseDown[index].x,
ptMouseDown[index].y)) {

/* If a hit occurs, record the mouse coordinates. */

Marker(ptMouseDown[index].x, ptMouseDown[index].y,
hwnd);
index++;
}
}
break;

 

 

円グラフの描画

円グラフを描画するには、 直線関数と曲線関数を使います。円グラフを描画するときに中心となる関数はAngleArc関数です。この関数には、 扇形の中心の座標、 扇形の半径、 開始角度、 描画角度を指定します。ユーザーがこれらの値を入力するためのダイアログ ボックスを次に示します。

次の例は、 アプリケーションのリソース スクリプト (.RC) ファイル内のダイアログ ボックス テンプレートを示しています。このテンプレートは、 上記のダイアログ ボックスの特性 (高さ、 コントロール、 スタイル) を示しています。

 

AngleArc DIALOG 6, 18, 160, 100
STYLE WS_DLGFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Pie Chart"
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDD_X, 18, 22, 25, 12, ES_AUTOHSCROLL
LTEXT "X", 102, 4, 24, 9, 8
EDITTEXT IDD_Y, 18, 39, 25, 12, ES_AUTOHSCROLL
LTEXT "Y", 104, 5, 42, 12, 8
LTEXT "Center", 105, 19, 11, 23, 8
EDITTEXT IDD_RADIUS, 103, 9, 32, 12, ES_AUTOHSCROLL
EDITTEXT IDD_STARTANGLE, 103, 31, 32, 12, ES_AUTOHSCROLL
EDITTEXT IDD_SWEEPANGLE, 103, 53, 32, 12, ES_AUTOHSCROLL
LTEXT "Radius", 109, 73, 11, 25, 8
LTEXT "Start Angle", 110, 59, 33, 42, 8
LTEXT "Sweep Angle", 111, 55, 55, 43, 8
PUSHBUTTON "OK", IDD_OK, 9, 82, 40, 14
PUSHBUTTON "Cancel", IDD_CANCEL, 110, 82, 40, 14
END

次の例は、 アプリケーションのソース ファイル内のダイアログ ボックス プロシージャを示しています。このプロシージャは、 次に示す手順でデータ (中心の座標、 円弧の半径、 開始角度と描画角度) を取得します。

1. アプリケーション定義のClearBits関数で、 ユーザー入力を受け取る配列を0で初期化します。

2. アプリケーション定義のGetStrLngth関数で、 ユーザーが入力した文字列の長さを取得します。

3. アプリケーション定義のRetrieveInput関数で、 ユーザーが入力した値を取得します。

 

 

BOOL CALLBACK ArcDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
CHAR chInput[4]; /* receives control-window input */
int cch; /* array-size and count variable */

switch (uMsg) {
case WM_INITDIALOG:
return FALSE;

case WM_COMMAND:
switch (wParam){

/*
* If the user pressed the OK button, retrieve the
* data that was entered in the various AngleArc
* controls.
*/

case IDD_OK:

/*
* Retrieve the x-coordinate of the arc's
* center.
*/

ClearBits(chInput, sizeof(chInput));
GetDlgItemText(hdlg, IDD_X, chInput,
sizeof(chInput));
cch = GetStrLngth(chInput);
nX = (int)RetrieveInput(chInput, cch);

/*
* Retrieve the y-coordinate of the arc's
* center.
*/

ClearBits(chInput, sizeof(chInput));
GetDlgItemText(hdlg, IDD_Y, chInput,
sizeof(chInput));
cch = GetStrLngth(chInput);
nY = (int)RetrieveInput(chInput, cch);

/* Retrieve the radius of the arc. */

ClearBits(chInput, sizeof(chInput));
GetDlgItemText(hdlg, IDD_RADIUS, chInput,
sizeof(chInput));
cch = GetStrLngth(chInput);
dwRadius = (DWORD) RetrieveInput(chInput, cch);

/* Retrieve the start angle. */

ClearBits(chInput, sizeof(chInput));
GetDlgItemText(hdlg, IDD_STARTANGLE, chInput,
sizeof(chInput));
cch = GetStrLngth(chInput);
xStartAngle = (float) RetrieveInput(chInput, cch);

/* Retrieve the sweep angle. */

ClearBits(chInput, sizeof(chInput));
GetDlgItemText(hdlg, IDD_SWEEPANGLE, chInput,
sizeof(chInput));
cch = GetStrLngth(chInput);
xSweepAngle = (float) RetrieveInput(chInput, cch);

EndDialog(hdlg, FALSE);
return TRUE;

/*
* If user presses the CANCEL button, close the
* dialog box.
*/

case IDD_CANCEL:
EndDialog(hdlg, FALSE);
return TRUE;
} /* end switch (wParam) */

break;

default:
return FALSE;
} /* end switch (message) */

UNREFERENCED_PARAMETER(lParam);
}


void ClearBits(LPTSTR cArray, int iLength)
{
int i;

for (i = 0; i < iLength; i++)
cArray[i] = 0;
}

int GetStrLngth(LPTSTR cArray)
{
int i = 0;

while (cArray[i++] != 0);
return i - 1;
}

DWORD RetrieveInput(LPTSTR cArray, int iLength)
{
int i, iTmp;
double dVal, dCount;

dVal = 0.0;
dCount = (double) (iLength - 1);

/* Convert ASCII input to a floating-point value. */

for (i = 0; i < iLength; i++) {
iTmp = cArray[i] - 0x30;
dVal = dVal + (((double)iTmp) * pow(10.0, dCount--));
}

return (DWORD) dVal;
}

円グラフの各部分を描画するには、 ユーザーが入力した値をAngleArc関数に渡します。現在のブラシを使って円グラフを塗りつぶすには、 パス ブラケット中でAngleArc関数を呼び出します。次の例は、 パス ブラケットとAngleArc関数の呼び出しを示しています。

 

int nX;
int nY;
DWORD dwRadius;
float xStartAngle;
float xSweepAngle;

case (IDM_ANGLEARC):

DialogBox((HINSTANCE) GetModuleHandle (NULL),
(LPTSTR) "AngleArc",
hwnd, (DLGPROC) ArcDlgProc);

hdc = GetDC(hwnd);
BeginPath(hdc);
SelectObject(hdc,
GetStockObject(GRAY_BRUSH));
MoveToEx(hdc, nX, nY, (LPPOINT) NULL);
AngleArc(hdc, nX, nY, dwRadius,
xStartAngle, xSweepAngle);
LineTo(hdc, nX, nY);
EndPath(hdc);
StrokeAndFillPath(hdc);
ReleaseDC(hwnd, hdc);
break;

 

 

直線と曲線の関数

直線と曲線に関する関数を次に示します。

AngleArc

Arc

ArcTo

GetArcDirection

LineDDA

LineDDAProc

LineTo

MoveToEx

PolyBezier

PolyBezierTo

PolyDraw

Polyline

PolylineTo

PolyPolyline

SetArcDirection

 

 

▲ページトップに戻る

【本を読んでもよくらからない】 … 個別指導でわかりやすくお教えします
inserted by FC2 system