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

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

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

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

Windows API ブラシの概要

「ブラシ」とは、 多角形やだ円、 パスの内部を塗りつぶすために使われるグラフィック ツールです。描画アプリケーションでは、 ブラシを使って図形を描画します。ワード プロセッサでは、 ブラシを使って罫線を描画します。CADアプリケーションでは、 ブラシを使って断面図を描画します。また、 表計算アプリケーションでは、 ブラシを使って円グラフの扇形や棒グラフの棒を描画します。

アプリケーションは、 ブラシを作成する関数のいずれかを呼び出して、 論理ブラシを識別するハンドルを取得できます。アプリケーションがこのハンドルをSelectObject関数に渡すと、 対応するディスプレイまたはプリンタのデバイスドライバが物理ブラシを作成します。

次に示すトピックでは、 ブラシについて説明します。

ブラシの原点

論理ブラシの種類

ブラシの使用

ブラシ関数

ブラシの原点

図形を描画するためにアプリケーションが描画関数を呼び出すと、 Windowsは、 描画操作の始点にブラシの位置を設定し、 ブラシ ビットマップのピクセルをクライアント領域のウィンドウ原点にマップします (「ウィンドウ原点」とは、 ウィンドウのクライアント領域の左上隅です)。Windowsがマップするピクセルの座標は、 「ブラシの原点」と呼ばれます。デフォルトのブラシの原点は、 ブラシ ビットマップの左上隅 (0, 0) です。この後、 Windowsは、 ブラシ ビットマップと同じ高さのビットマップを作成して、 クライアント領域全体にブラシをコピーします。コピー操作は、 クライアント領域全体が塗りつぶされるまで、 1行ずつ行われます。しかし、 ブラシのパターンは、 指定された図形の内部でだけ表示されます。

デフォルトのブラシの原点を使ってはいけない場合があります。たとえば、 親ウィンドウと子ウィンドウの背景を同じブラシで描画し、 子ウィンドウの背景を親ウィンドウの背景と調和させなければならないとします。この場合、 SetBrushOrgEx関数を呼び出してブラシの原点をリセットし、 原点を必要なピクセル数だけシフトしなければなりません (現在のブラシの原点を取得するには、 GetBrushOrgEx関数を呼び出します)。

次の図は、 アプリケーションが定義したブラシで塗りつぶされた星形の図形を示しています。この図には、 ブラシを拡大したイメージと、 描画操作を開始するときにマップされる位置が示されています。

 

論理ブラシの種類

論理ブラシには、 次の図に示すように、 4つの種類 (ソリッド、 ストック、 ハッチ、 パターン) があります。

ストック ブラシとハッチ ブラシには、 ハッチ ブラシで説明するように、 定義済みのブラシがいくつかあります。

 

ソリッド ブラシ

「ソリッド ブラシ」とは、 同じ色のピクセルを64個含む論理ブラシのことです。ソリッド論理ブラシを作成するには、 ブラシの色を指定して、 CreateSolidBrush関数を呼び出してください。ソリッド ブラシを作成したら、 デバイス コンテキストに選択し、 塗りつぶされた図形の描画に使用してください。

 

ストック ブラシ

グラフィック デバイス インターフェイスが管理する定義済み論理ストック ブラシは7つあります。また、 ウィンドウ管理インターフェイス (USER) が管理する定義済み論理ストック ブラシは21個あります。

7つの定義済みストック ブラシを使って描画された長方形を次に示します。

7つのストック ブラシのいずれかを識別するハンドルを取得するには、 ブラシの種類を指定して、 GetStockObjectを呼び出してください。

ウィンドウ管理インターフェイスが管理する21個の定義済み論理ストック ブラシは、 メニュー、 スクロール バー、 ボタンなどのウィンドウ要素に対応しています。特定のウィンドウ要素に対応する色を取得するには、 GetSysColor関数を呼び出してください。ウィンドウ要素に対応する色を設定するには、 SetSysColors関数を呼び出してください。

 

ハッチ ブラシ

GDIが管理する定義済み論理ハッチ ブラシは6つあります。6つの定義済みハッチ ブラシを使って描画された長方形を次に示します。

ハッチ ブラシを作成するには、 6つのハッチ スタイルのいずれかを指定して、 CreateHatchBrush関数を呼び出してください。

 

パターン ブラシ

パターン (カスタム) ブラシは、 アプリケーション定義のビットマップやデバイスに依存しないビットマップ (DIB) から作成されます。さまざまなブラシを使って描画された長方形を次に示します。

論理パターン ブラシを作成するには、 まず、 ビットマップを作成してください。ビットマップを作成したら、 ビットマップ (またはDIB) を識別するハンドルを指定してCreatePatternBrush関数またはCreateDIBPatternBrush関数を呼び出して、 論理パターン ブラシを作成してください。上の図のブラシは、 モノクロ ビットマップから作成されています。

 

ブラシの使用

GDI関数を使うことによって、 事実上どんな図形の内部でもブラシで描画することができます。描画できる図形には、 長方形、 だ円、 多角形、 パスなどの内部があります。アプリケーションの必要に応じて、 特定の色のソリッド ブラシ、 ストック ブラシ、 ハッチ ブラシ、 パターン ブラシを使ってください。

この項では、 カスタム ブラシ ダイアログ ボックスの作成方法のサンプル コードを示します。ダイアログ ボックスには、 Windowsがブラシとして使用するビットマップを表す格子があります。ユーザーは、 この格子を使ってパターン ブラシ ビットマップを作成し、 [Test Pattern]ボタンをクリックしてカスタム パターンを表示させることができます。

[Custom Brush]ダイアログ ボックスで作成されたパターンを次の図に示します。

ダイアログ ボックスを表示するには、 まず、 ダイアログ ボックス テンプレートを作成しなければなりません。[Custom Brush]ダイアログ ボックスを定義するダイアログ ボックス テンプレートを次に示します。

CustBrush DIALOG 6, 18, 160, 118

STYLE WS_DLGFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION

CAPTION "Custom Brush"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "", IDD_GRID, "Static", SS_BLACKFRAME |
WS_CHILD, 3, 2, 83, 79
CONTROL "", IDD_RECT, "Static", SS_BLACKFRAME |
WS_CHILD, 96, 11, 57, 28
PUSHBUTTON "Test Pattern", IDD_PAINTRECT, 96, 47, 57, 14
PUSHBUTTON "OK", IDD_OK, 29, 98, 40, 14
PUSHBUTTON "Cancel", IDD_CANCEL, 92, 98, 40, 14
END

[Custom Brush]ダイアログ ボックスには、 ビットマップ格子ウィンドウ、 パターン表示ウィンドウ、 3つのプッシュ ボタン ([Test Pattern][OK][Cancel]) の計5つのコントロールがあります。ユーザーは、 [Test Pattern]プッシュ ボタンによってパターンを見ることができます。ダイアログ ボックス テンプレートでは、 ダイアログ ボックス ウィンドウの全体の寸法の指定、 各コントロールへの値の設定、 各コントロールの位置の指定などを行っています。

ダイアログ ボックス テンプレートのコントロールの値は、 アプリケーションのヘッダー ファイルで次のように定義されている定数です。

 

#define IDD_GRID 120
#define IDD_RECT 121
#define IDD_PAINTRECT 122
#define IDD_OK 123
#define IDD_CANCEL 124

ダイアログ ボックス テンプレートを作成してアプリケーションのリソース定義ファイルに付加したら、 ダイアログ プロシージャを作成します。このプロシージャは、 Windowsがダイアログ ボックスに送ったメッセージを処理します。次に示すアプリケーションのソース コードからの抜粋は、 [Custom Brush]ダイアログ ボックスのダイアログ ボックス プロシージャと、 そのプロシージャから呼び出される2つのアプリケーション定義の関数を示しています。

int APIENTRY BrushDlgProc(HWND hdlg, WORD message, LONG wParam,
LONG lParam)
{
static HWND hwndGrid; /* grid-window control */
static HWND hwndBrush; /* pattern-brush control */
static RECT rctGrid; /* grid-window rectangle */
static RECT rctBrush; /* pattern-brush rectangle */
static UINT bBrushBits[8]; /* bitmap bits */
static RECT rect[64]; /* grid-cell array */
static HBITMAP hbm; /* bitmap handle */
HBRUSH hbrush; /* current brush */
HBRUSH hbrushOld; /* default brush */
HRGN hrgnCell; /* test-region handle */
HDC hdc; /* DC handle */
int x, y, deltaX, deltaY; /* drawing coordinates */
POINTS ptlHit; /* mouse coordinates */
int i; /* count variable */

switch (message)
{
case WM_INITDIALOG:

/*
* Retrieve a window handle for the grid-window and
* pattern-brush controls
*/

hwndGrid = GetDlgItem(hdlg, IDD_GRID);
hwndBrush = GetDlgItem(hdlg, IDD_RECT);

/* Initialize the array of bits that define the
* custom brush pattern with the value 1 to produce a
* solid white brush).
*/
for (i=0; i<8; i++)
bBrushBits[i] = 0xFF;

/*
* Retrieve dimensions for the grid-window and pattern-brush
* controls.
*/

GetClientRect(hwndGrid, &rctGrid);
GetClientRect(hwndBrush, &rctBrush);

/* Determine the width and height of a single cell. */

deltaX = (rctGrid.right - rctGrid.left)/8;
deltaY = (rctGrid.bottom - rctGrid.top)/8;

/* Initialize the array of cell rectangles. */

for (y=rctGrid.top, i=0; y < rctGrid.bottom; y += deltaY){
for (x=rctGrid.left; x < (rctGrid.right - 8) && i < 64;
x += deltaX, i++) {
rect[i].left = x; rect[i].top = y;
rect[i].right = x + deltaX;
rect[i].bottom = y + deltaY;
}
}
return FALSE;


case WM_PAINT:


/* Draw the grid. */

hdc = GetDC(hwndGrid);

for (i=rctGrid.left; i<rctGrid.right;
i+=(rctGrid.right - rctGrid.left)/8){
MoveToEx(hdc, i, rctGrid.top, NULL);
LineTo(hdc, i, rctGrid.bottom);
}
for (i=rctGrid.top; i<rctGrid.bottom;
i+=(rctGrid.bottom - rctGrid.top)/8){
MoveToEx(hdc, rctGrid.left, i, NULL);
LineTo(hdc, rctGrid.right, i);
}
ReleaseDC(hwndGrid, hdc);
return FALSE;


case WM_LBUTTONDOWN:

/* Store the mouse coordinates in a POINT structure. */

ptlHit = MAKEPOINTS((POINTS FAR *)lParam);

/*
* Create a rectangular region with dimensions and
* coordinates that correspond to those of the grid
* window.
*/

hrgnCell = CreateRectRgn(rctGrid.left, rctGrid.top,
rctGrid.right, rctGrid.bottom);

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

hdc = GetDC(hwndGrid);

/* Select the region into the DC. */

SelectObject(hdc, hrgnCell);

/* Test for a button click in the grid-window rectangle. */

if (PtInRegion(hrgnCell, ptlHit.x, ptlHit.y)){

/*
* A button click occurred in the grid-window rectangle;
* isolate the cell in which it occurred.
*/

for(i=0; i<64; i++){
DeleteObject(hrgnCell);

hrgnCell = CreateRectRgn(rect[i].left, rect[i].top,
rect[i].right, rect[i].bottom);

if (PtInRegion(hrgnCell, ptlHit.x, ptlHit.y)){
InvertRgn(hdc, hrgnCell);

/* Set the appropriate brush bits. */

if (i % 8 == 0)
bBrushBits[i/8] = bBrushBits[i/8] ^ 0x80;
else if (i % 8 == 1)
bBrushBits[i/8] = bBrushBits[i/8] ^ 0x40;
else if (i % 8 == 2)
bBrushBits[i/8] = bBrushBits[i/8] ^ 0x20;
else if (i % 8 == 3)
bBrushBits[i/8] = bBrushBits[i/8] ^ 0x10;
else if (i % 8 == 4)
bBrushBits[i/8] = bBrushBits[i/8] ^ 0x08;
else if (i % 8 == 5)
bBrushBits[i/8] = bBrushBits[i/8] ^ 0x04;
else if (i % 8 == 6)
bBrushBits[i/8] = bBrushBits[i/8] ^ 0x02;
else if (i % 8 == 7)
bBrushBits[i/8] = bBrushBits[i/8] ^ 0x01;

/* Exit the "for" loop after the bit is set. */

break;
} /* end if */

} /* end for */

} /* end if */

/* Release the DC for the control. */

ReleaseDC(hwndGrid, hdc);
return TRUE;


case WM_COMMAND:
switch (wParam){
case IDD_PAINTRECT:

hdc = GetDC(hwndBrush);

/* Create a monochrome bitmap. */

hbm = CreateBitmap(8, 8, 1, 1,
(LPBYTE)bBrushBits);

/* Select the custom brush into the DC. */

hbrush = CreatePatternBrush(hbm);

hbrushOld = SelectObject(hdc, hbrush);

/* Use the custom brush to fill the rectangle. */

Rectangle(hdc, rctBrush.left, rctBrush.top,
rctBrush.right, rctBrush.bottom);

/* Clean up memory. */
SelectObject(hdc, hbrushOld);
DeleteObject(hbrush);
DeleteObject(hbm);

ReleaseDC(hwndBrush, hdc);
return TRUE;

case IDD_OK:

case IDD_CANCEL:
EndDialog(hdlg, TRUE);
return TRUE;

} /* end switch */
break;
default:
return FALSE;
}
}


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

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

}

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

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

return (DWORD)dVal;
}

[Custom Brush]ダイアログ ボックスのダイアログ ボックス プロシージャは、 次の表に示す4つのメッセージを処理します。

メッセージ 動作

WM_INITDIALOG 格子ウィンドウとパターン ブラシ コントロールのウィンドウ ハンドルと寸法を取得し、 格子ウィンドウ コントロールの隠せるの寸法を計算します。また、 格子セル座標の配列を初期化します。

WM_PAINT 格子ウィンドウ コントロールの格子パターンを描画します。

WM_LBUTTONDOWN ユーザーが左マウス ボタンを押したときにカーソルが格子ウィンドウ コントロール内にあるかどうか判断します。格子ウィンドウ コントロール内にあれば、 ダイアログ ボックス プロシージャは、 適切な格子セルを反転し、 カスタム ブラシのビットマップを作成するのに使われるビットの配列にそのセルの状態を記録します。

WM_COMMAND 3つのプッシュ ボタン コントロールに対する入力を処理します。ユーザーが[Test Pattern]ボタンを押したときは、 ダイアログ ボックス プロシージャは、 新しいカスタム ブラシ パターンで[Test Pattern]コントロールを描画します。ユーザーが[OK]ボタンか[Cancel]ボタンを押したときは、 ダイアログ ボックス プロシージャは、 適切な処理を実行します。

メッセージとメッセージ処理について詳しくは、 メッセージとメッセージ キューの概要を参照してください。

ダイアログ ボックス プロシージャを作成したら、 モジュール定義ファイルでエクスポートして、 プロシージャの関数定義をアプリケーションのヘッダー ファイルに追加してください。それから、 アプリケーションの適切な所でダイアログ ボックス プロシージャを呼び出してください。

次に示すモジュール定義ファイルからの抜粋は、 [Custom Brush]のダイアログ ボックス プロシージャのエクスポート方法を示しています。

; Export all functions that are called by a Windows routine.

EXPORTS
MainWndProc @1 ; name of window processing function
BrushDlgProc @2 ; name of custom-brush processing function

次に示すアプリケーションのヘッダー ファイルからの抜粋は、 ダイアログ ボックス プロシージャとそこから呼び出される2つの関数の定義を示しています。

 

int APIENTRY BrushDlgProc(HWND hdlg, WORD message, LONG wParam,
LONG lParam);
int GetStrLngth(LPTSTR cArray);
DWORD RetrieveWidth(LPTSTR cArray, int iLength);

アプリケーションのソース コードからダイアログ ボックス プロシージャを呼び出す方法を次のコードで示します。この例では、 ユーザーがアプリケーションのメニューからオプションを選択したときに、 ダイアログ ボックス プロシージャが呼び出されます。

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

case IDM_CUSTOMBRUSH:
DialogBox((HANDLE)GetModuleHandle(NULL),
(LPTSTR)"CustBrush", hWnd,
(DLGPROC)BrushDlgProc);
break;

 

ブラシ関数

ブラシに関する処理で使われる関数を次に示します。

CreateBrushIndirect

CreateDIBPatternBrush

CreateDIBPatternBrushPt

CreateHatchBrush

CreatePatternBrush

CreateSolidBrush

GetBrushOrgEx

SetBrushOrgEx 

使われなくなったか、 または削除された関数

FixBrushOrgEx

 

▲ページトップに戻る

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