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

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

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

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

Windows API パスの概要

「パス」とは、 塗りつぶしたり輪郭を描画する図形です。Microsoft(R) Windows(TM) 用のアプリケーションは、 さまざまな方法でパスを利用できます。パスは、 描画アプリケーションやペイント アプリケーションで使われます。また、 CADアプリケーションは、 パスを使って、 特別なクリッピング リージョンを作成したり、 不規則な図形の輪郭を描画したり、 その内部を塗りつぶします。「不規則な図形」とは、 ベジエ (Bezier) 曲線と直線で構成される図形です (「規則的な図形」には、 だ円、 円、 長方形、 多角形があります)。

次に示すトピックでは、 パスについて説明しています。

パスの輪郭描画と塗りつぶし

パスの座標変換

クリップ パス

パスからリージョンへの変換

曲線パス

パスの使用

パス関数

パスは、 デバイス コンテキストに関連付けられているオブジェクトの1つです。しかし、 新しいDCの一部になるデフォルト オブジェクト (ペンやブラシ、 フォント) とは異なり、 デフォルトのパスはありません。デバイス コンテキストについて、 詳しくはデバイス コンテキストの概要を参照してください。

パスを作成してデバイス コンテキストで選択するには、 まず、 パスを記述する点を定義します。点を記述するには、 BeginPath関数を呼び出してから、 適切な描画関数を呼び出して、 最後にEndPath関数を呼び出します。この関数の組み合わせ (BeginPath、 描画関数、 EndPath) によって、 「パス ブラケット」が構成されます。パス ブラケットでは、 次に示す関数が使えます。

 

AngleArc LineTo Polyline

Arc MoveToEx PolylineTo

ArcTo Pie PolyPolygon

Chord PolyBezier PolyPolyline

CloseFigure PolyBezierTo Rectangle

Ellipse PolyDraw RoundRect

ExtTextOut Polygon TextOut

 

アプリケーションがEndPath関数を呼び出すと、 Windowsは、 対応するパスを指定されたDCで選択します (DCで別のパスがすでに選択されていれば、 Windowsはそのパスを保存せずに削除します)。WindowsがパスをDCで選択したら、 アプリケーションは、 次に示す用途にパスを利用できます。

・ (現在のペンによる) パスの輪郭の描画

・ (現在のブラシによる) パスの内部のペイント

・ パスの輪郭の描画と内部の塗りつぶし

・ パスの修正 (曲線から直線の集合への変換)

・ パスからクリップ パスへの変換

・ パスからリージョンへの変換

・ パスの各曲線を一連の線分に変換することによるパスの平滑化

・ パスを構成する直線や曲線の座標の取得

 

 

 

パスの輪郭描画と塗りつぶし

パスの輪郭を描画するには、 StrokePath関数を呼び出します。パスの内部を塗りつぶすには、 FillPath関数を使います。また、 パスの輪郭を描画し、 同時に内部を塗りつぶすには、 StrokeAndFillPath関数を使います。

アプリケーションがパスを塗りつぶすとき、 Windowsは、 デバイス コンテキストの現在の塗りつぶしモードを使います。このモードを取得するには、 GetPolyFillMode関数を呼び出します。また、 塗りつぶしモードを設定するには、 SetPolyFillMode関数を呼び出します。

次の図は、 CADアプリケーションでパスの輪郭を描画して塗りつぶすことによって作成した部品の断面図を示しています。

 

 

パスの座標変換

パスは、 論理単位と現在の座標変換で定義されます (SetWorldTransform関数が呼び出されていれば、 論理単位はワールド単位になります。この関数が呼び出されていなければ、 論理単位はページ単位になります)。アプリケーションは、 ワールド座標変換を使って、 パスを定義する直線やベジエ (Bezier) 曲線のスケーリング、 回転、 傾斜、 平行移動、 反転 (線対称移動) を行うことができます。

注: パス ブラケット内での座標変換は、 座標変換が設定された後の直線や曲線だけに影響します。座標変換を設定する前に描画した直線や曲線には影響しません。ワールド座標変換について、 詳しくは座標空間および座標変換の概要を参照してください。

また、 ペンがジオメトリック ペンならば、 SetWorldTransform関数を使って、 パスの輪郭の描画に使われるペンの形状を設定できます。ジオメトリック ペンについて詳しくは、 ジオメトリック ペンを参照してください。

 

 

クリップ パス

アプリケーションは、 クリッピングとパスを使って、 特殊なグラフィック効果を作成できます。次の図は、 大きなArialフォントで描画したテキスト文字列を示しています。

次の図は、 テキストをクリップ パスとして選択し、 文字列の左上を中心とする放射線を描画した結果を示しています。

注: GDIは、 ビットマップ フォントで作成されたテキストをアウトライン フォントかベクタ フォントに変換してからパスに追加します。

クリップ パスを作成するには、 パス ブラケットを生成してから、 SelectClipPath関数を呼び出します。クリップ パスをDCで選択すると、 パス内の出力だけが表示されます。

クリップパスは、 特殊なグラフィック効果の作成以外に、 イメージを拡張メタファイルで格納する場合にも役立ちます。(リージョンの指定にはデバイス単位が使われるのに対し) パスの指定には論理単位が使われるため、 パスによって、 デバイスに依存しないイメージを実現できます。

 

 

パスからリージョンへの変換

パスをリージョンに変換するには、 PathToRegion関数を呼び出します。PathToRegionは、 SelectClipPath関数と同様に、 特殊なグラフィック効果を作成するときに役立ちます。たとえば、 パスをオフセット移動する関数はありませんが、 リージョンをオフセット移動する関数 (OffsetRgn) はあります。アプリケーションは、 図形を定義するパスを作成し、 それをPathToRegionでリージョンに変換して、 (FillRgnOffsetRgnFillRgnなどの関数を呼び出して) リージョンを繰り返し描画、 移動、 消去することによって、 複雑な図形のアニメーションを実現できます。

 

 

曲線パス

パスの曲線を平滑化するには、 FlattenPath関数を呼び出します。この関数は、 曲線を含むパスの綾線にテキストを沿わせるときに特に役立ちます。テキストをパスに沿わせるには、 次に示す手順を実行します。

1. テキストを沿わせるパスを作成します。

2. FlattenPath関数を呼び出して、 パス内の曲線を線分に変換します。

3. GetPath関数を呼び出して、 パスの線分を取得します。

4. 各線分の長さと、 文字列の各文字の幅を計算します。

5. 線分の長さと文字幅のデータを使って、 各文字を曲線に沿って配置します。

 

 

 

 

パスの使用

ここでは、 特定のポイント サイズのフォントを ([フォントの指定]ダイアログ ボックスを使って) ユーザーが選択し、 (そのフォントで描画したテキストから) クリップ パスを作成し、 テキストによるクリップの結果を表示します。

このコードは、 クリップ パスの図を作成するのに使われています。

 

CHOOSEFONT cf; /* common dialog box font structure */
LOGFONT lf; /* logical font structure */
HFONT hfont; /* new logical font handle */
HFONT hfontOld; /* original logical font handle */
HDC hdc; /* display DC handle */
int nXStart, nYStart; /* drawing coordinates */
RECT rc; /* rectangle structure for painting window */
SIZE sz; /* size structure that receives text extents */
double aflSin[90]; /* sine of 0-90 degrees in 1 degree increments */
double aflCos[90]; /* cosine of 0-90 degrees in 1 degree increments */
double flRadius,a; /* radius of circle */
int iMode; /* clipping mode */
HRGN hrgn; /* clip region handle */

LRESULT APIENTRY MainWndProc(
HWND hwnd, /* window handle */
UINT message, /* type of message */
WPARAM wParam, /* additional information */
LPARAM lParam) /* additional information */

{

PAINTSTRUCT ps;

switch (message) {

case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
break;

case WM_COMMAND: /* message: command from application menu */
switch (wParam) {

case IDM_VANISH: /* erases client area */
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rc);
FillRect(hdc, &rc, GetStockObject(WHITE_BRUSH));
ReleaseDC(hwnd, hdc);
break;

case IDM_AND: /* sets clip mode to RGN_AND */
iMode = RGN_AND;
break;

case IDM_COPY: /* sets clip mode to RGN_COPY */
iMode = RGN_COPY;
break;

case IDM_DIFF: /* sets clip mode to RGN_DIFF */
iMode = RGN_DIFF;
break;

case IDM_OR: /* sets clip mode to RGN_OR */
iMode = RGN_OR;
break;

case IDM_XOR: /* sets clip mode to RGN_XOR */
iMode = RGN_XOR;
break;

case IDM_CLIP_PATH:

/* Retrieve a cached DC for the window. */

hdc = GetDC(hwnd);


/*
* Use the font requested by the user in the
* Choose Font dialog box to create a logical font, and then
* select that font into the device context.
*/

hfont = CreateFontIndirect(cf.lpLogFont);
hfontOld = SelectObject(hdc, hfont);

/*
* Retrieve the dimensions of the rectangle
* that surrounds the text.
*/

GetTextExtentPoint32(hdc, "Clip Path", 9, &sz);

/*
* Set a clipping region using the rectangle that
* surrounds the text.
*/

hrgn = CreateRectRgn(nXStart, nYStart,
nXStart + sz.cx,
nYStart + sz.cy);

SelectClipRgn(hdc, hrgn);

/*
* Create a clip path using text drawn with
* the user's requested font.
*/

BeginPath(hdc);
TextOut(hdc, nXStart, nYStart, "Clip Path", 9);
EndPath(hdc);
SelectClipPath(hdc, iMode);

/* Compute the sine of 0, 1, 2, ... 90 degrees. */
for (i = 0; i < 90; i++) {
aflSin[i] = sin( (((double)i) / 180.0) * 3.14159);
}

/* Compute the cosine of 0, 1, 2, ... 90 degrees. */
for (i = 0; i < 90; i++) {
aflCos[i] = cos( (((double)i) / 180.0) * 3.14159);
}

/* Set the radius value. */

flRadius = (double)(2 * sz.cx);

/*
* Draw the 90 rays extending from the
* radius to the edge of the circle.
*/

for (i = 0; i < 90; i++) {
MoveToEx(hdc, nXStart, nYStart, (LPPOINT) NULL);
LineTo(hdc, nXStart + ((int) (flRadius * aflCos[i])),
nYStart + ((int) (flRadius * aflSin[i])));
}

/* Reselect the original font into the DC. */

SelectObject(hdc, hfontOld);

/* Delete the user's font. */

DeleteObject(hfont);

/* Release the DC. */

ReleaseDC(hwnd, hdc);

break;


case IDM_FONT:

/* Initialize necessary members. */

cf.lStructSize = sizeof (CHOOSEFONT);
cf.hwndOwner = hwnd;
cf.lpLogFont = &lf;
cf.Flags = CF_SCREENFONTS | CF_EFFECTS;
cf.rgbColors = RGB(0, 255, 255);
cf.nFontType = SCREEN_FONTTYPE;

/*
* Display the Font dialog box, allow the user to
* choose a font, and render text in the
* window with that selection.
*/

if (ChooseFont(&cf)) {
hdc = GetDC(hwnd);
hfont = CreateFontIndirect(cf.lpLogFont);
hfontOld = SelectObject(hdc, hfont);
crOld = SetTextColor(hdc, cf.rgbColors);
TextOut(hdc, nXStart, nYStart,
"Clip Path", 9);
SetTextColor(hdc, crOld);
SelectObject(hdc, hfontOld);
DeleteObject(hfont);
ReleaseDC(hwnd, hdc);
}

break;

default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
break;

case WM_DESTROY: /* message: window being destroyed */
PostQuitMessage(0);
break;

default: /* passes it on if unprocessed */
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}

 

 

パス関数

パスを作成、 変更、 描画する関数を次に示します。

AbortPath

BeginPath

CloseFigure

EndPath

FillPath

FlattenPath

GetMiterLimit

GetPath

PathToRegion

SetMiterLimit

StrokeAndFillPath

StrokePath

WidenPath

 

 

▲ページトップに戻る

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