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

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

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

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

Windows API リージョンの概要

Microsoft(R) Windows(TM) では、 リージョンとは、 長方形や多角形、 だ円 (またはその組み合わせ) で、 塗りつぶし、 ペイント、 反転、 境界線の描画が可能であり、 ヒット テスト (カーソル位置のテスト) に使えます。

次に示すトピックでは、 リージョンについて説明しています。

リージョンの作成と選択

リージョンの操作

リージョンによる出力のクリップ

リージョンによるヒット テスト

リージョン関数

塗りつぶして境界線を描画した3種類のリージョンを次に示します。

 

 

リージョンの作成と選択

リージョンを作成するには、 各図形に応じた関数を呼び出します。標準の図形それぞれに対応した関数を次に示します。

 

図形 関数

長方形リージョン CreateRectRgn CreateRectRgnIndirect

角が丸い長方形リージョン CreateRoundRectRgn

だ円リージョン CreateEllipticRgn CreateEllipticRgnIndirect

多角形リージョン CreatePolygonRgn CreatePolyPolygonRgn

 

 

各リージョン作成関数は、 新しいリージョンを識別する関数を返します。リージョンをデバイス コンテキストで選択するには、 このハンドルを2番目の引数に指定してSelectObject関数を呼び出します。リージョンをデバイス コンテキストで選択すると、 そのリージョンに対してさまざまな操作ができるようになります。

 

リージョンの操作

リージョンは、 組み合わせ、 比較、 内部のペイントや反転、 境界線の描画、 寸法の取得、 カーソルが境界内にあるかどうかのテストなどができます。

 

組み合わせ

2つのリージョンを組み合わせるには、 CombineRgn関数を呼び出します。この関数を使って、 2つのリージョンの交差部分や、 2つのリージョンの交差部分以外の部分、 2つのリージョン全体などを作成できます。リージョンの5つの組み合わせを次に示します。

 

値 説明

RGN_AND 元の2つのリージョンの交差部分が新しいリージョンになります。

RGN_COPY (元の2つのリージョンのうち) 1番目のリージョンのコピーが新しいリージョンになります。

RGN_DIFF 1番目のリージョンのうち2番目のリージョンに交差しない部分が新しいリージョンになります。

RGN_OR 元の2つのリージョンが新しいリージョンになります。

RGN_XOR 2つのリージョンのうち互いに重ならない部分が新しいリージョンになります。

 

CombineRgn関数を呼び出して作成した正方形リージョンと円リージョンの5種類の組み合わせを次に示します。

 

比較

2つのリージョンを比較して、 同じかどうか調べるには、 EqualRgn関数を呼び出します。2つのリージョンのサイズと形が同じならば、 EqualRgnは、 2つのリージョンを同等とみなします。

 

塗りつぶし

リージョンの内部を塗りつぶすには、 特定のブラシを識別するハンドルを指定してFillRgn関数を呼び出します。アプリケーションがFillRgnを呼び出すと、 Windowsは、 指定されたデバイス コンテキストの現在の塗りつぶしモードを使って、 ブラシでリージョンを塗りつぶします。塗りつぶしモードには、 交互 (alternate) と全域 (winding) の2種類があります。デバイス コンテキストの塗りつぶしモードを設定するには、 SetPolyFillMode関数を呼び出します。また、 デバイス コンテキストの現在の塗りつぶしモードを取得するには、 GetPolyFillMode関数を呼び出します。

2つの同じリージョンを次に示します。一方は交互モードで塗りつぶされ、 もう一方は全域モードで塗りつぶされています。

 

交互モード

交互モードが指定されているとき、 Windowsは、 ピクセルを塗りつぶすかどうかを次に示す方法で判断します。

1. リージョンの内部の点を1つ選択します。

2. 選択したピクセルからxの正方向の無限遠に向って、 仮想的な線を引きます。

3. この線が境界線と交わるたびに、 カウント値を1つ増やします。

 

カウント値が奇数ならば、 Windowsはピクセルを塗りつぶします。

 

全域モード

全域モードが指定されているとき、 Windowsは、 ピクセルを塗りつぶすかどうかを次に示す方法で判断します。

1. 各境界線の描画方向を調べます。

2. リージョンの内部の点を1つ選択します。

3. 選択したピクセルからxの正方向の無限遠に向って、 仮想的な線を引きます。

4. y方向の変化量が正の境界線と仮想線が交わるたびに、 カウント値を1つ増やします。また、 y方向の変化量が負の境界線と仮想線が交わるたびに、 カウント値を1つ減らします。

 

カウント値が0以外ならば、 Windowsはピクセルを塗りつぶします。

 

ペイント

デバイス コンテキストで現在選択されているブラシでリージョンの内部を塗りつぶすには、 PaintRgn関数を使います。この関数は、 現在の多角形塗りつぶしモード (交互または全域) を使います。

 

反転

リージョン内の色を反転するには、 InvertRgn関数を呼び出します。モノクロ ディスプレイの場合、 InvertRgn関数は、 白のピクセルを黒にして、 黒のピクセルを白にします。カラー ディスプレイの場合、 反転方法は、 画面の色の生成に使われている方法によって異なります。

 

境界線の描画

リージョンのまわりに境界線を描画するには、 Windowsが境界線を描画するときの線幅とブラシ パターンを指定してFrameRgn関数を呼び出します。

 

境界長方形の取得

リージョンの境界長方形の寸法を取得するには、 GetRgnBox関数を呼び出します。リージョンが長方形ならば、 GetRgnBoxは、 リージョンの寸法を返します。リージョンがだ円ならば、 この関数は、 だ円を囲む最小の長方形の寸法を返します。長方形の長い方の辺の長さは、 だ円の長軸の長さと同じです。また、 長方形の短い方の辺の長さは、 だ円の短軸の長さと同じです。リージョンが多角形ならば、 GetRgnBoxは、 多角形全体を囲む最小の長方形の寸法を返します。

 

移動

リージョンを移動するには、 OffsetRgn関数を呼び出します。指定されたx方向とy方向のオフセットによって、 リージョンを上下左右に移動するときの論理単位数が決まります。

 

ヒット テスト

リージョンに対してヒット テストを実行することによって、 現在のカーソル位置が特定の範囲にあるか調べることができます。ヒット テストを行うには、 カーソルの座標とリージョンを識別するハンドルをPtInRegion関数に渡します。カーソルの座標を取得するには、 WM_LBUTTONDOWNWM_LBUTTONUPWM_RBUTTONDOWNWM_RBUTTONUPなどのマウス メッセージを処理します。PtInRegionは、 カーソルの位置が指定されたリージョン内にあるかどうかを示す値を返します。

 

 

リージョンの使用

ここの例では、 次に示す処理を実行するためのリージョンの操作方法を説明しています。

 

クリッピング リージョンの定義

出力のクリップ

リージョンによるヒット テスト

 

 

リージョンによる出力のクリップ

ここでは、 リージョンを使ってユーザーがクライアント領域の出力方法を定義できるようにする例を示します。このような目的に使われるリージョンは、 クリッピング リージョンと呼ばれます。

ここでの例は、 ユーザーがデスクトップ全体をキャプチャしてからそのイメージの一部を切り取って.BMPファイルとして保存するアプリケーションの一部です。

ユーザーは、 アプリケーションのメニューから[Define Clip Region]オプションを選択すると、 左マウス ボタンをクリックしてマウスをドラッグすることによってクリッピング リージョンを選択できるようになります。ユーザーがマウスをドラッグしている間、 アプリケーションは、 新しいクリッピング リージョンに対応する長方形を描画します。

[Clip]オプションを選択すると、 指定した長方形の境界内のイメージだけが切り取られて再描画されます。

 

 

 

クリッピング リージョンの定義

ユーザーが[Define Clip Region]オプションを選択すると、 Windowsは、 WM_COMMANDメッセージを発行します。このメッセージのwParamパラメータは、 アプリケーション定義のIDM_DEFINE定数になっています。IDM_DEFINEは、 ユーザーがこのオプションをメニューから選択したことを示します。アプリケーションは、 この入力を処理するとき、 ブール値フラグのfDefineRegionをセットします。コードを次に示します。

 

case WM_COMMAND:
switch (wParam) {

case IDM_DEFINE:
fDefineRegion = TRUE;
break;

ユーザーは、 [Define Clipping Region]オプションを選択すると、 マウスをクリックしてアプリケーションのクライアント領域内をドラッグすることによって、 長方形を描画できます。

ユーザーが左ボタンを押すと、 WindowsはWM_LBUTTONDOWNメッセージを発行します。このメッセージのlParamパラメータは、 カーソルの座標を示します。この座標は、 クリッピング リージョンを定義する長方形の左上隅として使われます。アプリケーションは、 WM_LBUTTONDOWNメッセージを次のように処理します。

 

/* These variables are required for clipping. 
				*/

static POINT ptUpperLeft;
static POINT ptLowerRight;
static POINT aptRect[5];
static POINT ptTmp;
static POINTS ptsTmp;
static BOOL fDefineRegion;
static BOOL fRegionExists;
static HRGN hrgn;
static RECT rctTmp;
int i;

switch (message) {

case WM_LBUTTONDOWN:
if (fDefineRegion) {

/* Retrieve the new upper left corner. */

ptsTmp = MAKEPOINTS(lParam);
ptUpperLeft.x = (LONG) ptsTmp.x;
ptUpperLeft.y = (LONG) ptsTmp.y;
}

if (fRegionExists) {

/* Erase the previous rectangle. */

hdc = GetDC(hwnd);
SetROP2(hdc, R2_NOTXORPEN);

if (!Polyline(hdc, (CONST POINT *) aptRect, 5))
errhandler("Polyline Failed", hwnd);
ReleaseDC(hwnd, hdc);

/* Clear the rectangle coordinates. */

for (i = 0; i < 4; i++) {
aptRect[i].x = 0;
aptRect[i].y = 0;
}

/* Clear the temporary point structure. */

ptTmp.x = 0;
ptTmp.y = 0;

/* Clear the lower right coordinates. */

ptLowerRight.x = 0;
ptLowerRight.y = 0;

/* Reset the flag. */

fRegionExists = FALSE;
fDefineRegion = TRUE;

/* Retrieve the new upper left corner. */

ptsTmp = MAKEPOINTS(lParam);
ptUpperLeft.x = (LONG) ptsTmp.x;
ptUpperLeft.y = (LONG) ptsTmp.y;
}
break;

ユーザーがマウスをドラッグする間、 Windowsは、 新しいカーソル座標をlParamパラメータに設定したWM_MOUSEMOVEメッセージを送ります。アプリケーションは、 WM_MOUSEMOVEメッセージを受け取ると、 以前の長方形があれば消去し、 長方形の4つの頂点の座標を指定してPolyline関数を呼び出して、 新しい長方形を描画します。この作業は、 次の例のように実行します。

 

/* These variables are required for clipping. 
				*/

static POINT ptUpperLeft;
static POINT ptLowerRight;
static POINT aptRect[5];
static POINT ptTmp;
static POINTS ptsTmp;
static BOOL fDefineRegion;
static BOOL fRegionExists;
static HRGN hrgn;
static RECT rctTmp;
int i;

switch (message) {

case WM_MOUSEMOVE:

if (wParam & MK_LBUTTON && fDefineRegion) {

/* Get a window DC. */

hdc = GetDC(hwnd);

if (!SetROP2(hdc, R2_NOTXORPEN))
errhandler("SetROP2 Failed", hwnd);


/*
* If previous mouse movement occurred, store the original
* lower right corner coordinates in a temporary structure.
*/

if (ptLowerRight.x) {
ptTmp.x = ptLowerRight.x;
ptTmp.y = ptLowerRight.y;
}

/*
* Get the new coordinates of the clipping region's lower
* right corner.
*/

ptsTmp = MAKEPOINTS(lParam);
ptLowerRight.x = (LONG) ptsTmp.x;
ptLowerRight.y = (LONG) ptsTmp.y;


/*
* If previous mouse movement occurred, erase the original
* rectangle.
*/

if (ptTmp.x) {
aptRect[0].x = ptUpperLeft.x;
aptRect[0].y = ptUpperLeft.y;
aptRect[1].x = ptTmp.x;
aptRect[1].y = ptUpperLeft.y;
aptRect[2].x = ptTmp.x;
aptRect[2].y = ptTmp.y;
aptRect[3].x = ptUpperLeft.x;
aptRect[3].y = ptTmp.y;
aptRect[4].x = aptRect[0].x;
aptRect[4].y = aptRect[0].y;

if (!Polyline(hdc, (CONST POINT *) aptRect, 5))
errhandler("Polyline Failed", hwnd);
}

aptRect[0].x = ptUpperLeft.x;
aptRect[0].y = ptUpperLeft.y;
aptRect[1].x = ptLowerRight.x;
aptRect[1].y = ptUpperLeft.y;
aptRect[2].x = ptLowerRight.x;
aptRect[2].y = ptLowerRight.y;
aptRect[3].x = ptUpperLeft.x;
aptRect[3].y = ptLowerRight.y;
aptRect[4].x = aptRect[0].x;
aptRect[4].y = aptRect[0].y;

if (!Polyline(hdc, (CONST POINT *) aptRect, 5))
errhandler("Polyline Failed", hwnd);

ReleaseDC(hwnd, hdc);
}
break;

 

出力のクリップ

ユーザーがメニューから[Clip]オプションを選択すると、 アプリケーションは、 ユーザーが作成した長方形の座標を使ってクリッピング リージョンを定義します。クリッピング リージョンを定義してアプリケーションのデバイス コンテキストで選択したら、 アプリケーションは、 ビットマップ イメージを再描画します。この作業は、 次の例のように行います。

 

/* These variables are required for clipping. 
				*/

static POINT ptUpperLeft;
static POINT ptLowerRight;
static POINT aptRect[5];
static POINT ptTmp;
static POINTS ptsTmp;
static BOOL fDefineRegion;
static BOOL fRegionExists;
static HRGN hrgn;
static RECT rctTmp;
int i;

case WM_COMMAND:
switch (wParam) {

case IDM_CLIP:

hdc = GetDC(hwnd);

/*
* Retrieve the application's client rectangle and paint
* with the default (white) brush.
*/

GetClientRect(hwnd, &rctTmp);
FillRect(hdc, &rctTmp, GetStockObject(WHITE_BRUSH));

/* Use the rectangle coordinates to define a clipping region. */

hrgn = CreateRectRgn(aptRect[0].x, aptRect[0].y,
aptRect[2].x, aptRect[2].y);
SelectClipRgn(hdc, hrgn);

/* Transfer (draw) the bitmap into the clipped rectangle. */

BitBlt(hdc,
0, 0,
bmp.bmWidth, bmp.bmHeight,
hdcCompatible,
0, 0,
SRCCOPY);

ReleaseDC(hwnd, hdc);
break;

 

リージョンによるヒット テスト

ブラシの概要の例では、 リージョンを使って、 8×8ピクセル モノクロ ビットマップの拡大表示をシミュレートしています。このビットマップのピクセルをクリックすることによって、 ユーザーは描画操作に適したカスタム ブラシを作成します。この例では、 ヒット テストを行うためのPtInRegion関数と、 リージョンの色を反転するためのInvertRgn関数の使い方について説明します。

 

リージョン関数

リージョンに関する関数を次に示します。

  • CombineRgn
  • CreateEllipticRgn
  • CreateEllipticRgnIndirect
  • CreatePolygonRgn
  • CreatePolyPolygonRgn
  • CreateRectRgn
  • CreateRectRgnIndirect
  • CreateRoundRectRgn
  • EqualRgn
  • ExtCreateRegion
  • FillRgn
  • FrameRgn
  • GetPolyFillMode
  • GetRgnBox
  • GetRegionData
  • InvertRgn
  • OffsetRgn
  • PaintRgn
  • PtInRegion
  • RectInRegion
  • SetPolyFillMode

 

▲ページトップに戻る

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