キャレットの使用
このセクションには、次のタスクのコード サンプルがあります。
キャレットの作成と表示
キーボードフォーカスを受け取ると、ウィンドウはキャレットを作成して表示する必要があります。 CreateCaret 関数を使用して、指定されたウィンドウにキャレットを作成します。 その後 、SetCaretPos を呼び出して、キャレットと ShowCaret の現在位置を設定して、キャレットを表示できます。
システムは、キーボード フォーカスを受け取るウィンドウに WM_SETFOCUS メッセージを送信します。したがって、アプリケーションは、このメッセージの処理中にキャレットを作成して表示する必要があります。
HWND hwnd, // window handle
int x; // horizontal coordinate of cursor
int y; // vertical coordinate of cursor
int nWidth; // width of cursor
int nHeight; // height of cursor
char *lpszChar; // pointer to character
case WM_SETFOCUS:
// Create a solid black caret.
CreateCaret(hwnd, (HBITMAP) NULL, nWidth, nHeight);
// Adjust the caret position, in client coordinates.
SetCaretPos(x, y);
// Display the caret.
ShowCaret(hwnd);
break;
ビットマップに基づいてキャレットを作成するには、 CreateCaret を使用するときにビットマップ ハンドルを指定する必要があります。 グラフィックス アプリケーションを使用してビットマップを作成し、リソース コンパイラを使用して、ビットマップをアプリケーションのリソースに追加できます。 その後、アプリケーションで LoadBitmap 関数を使用してビットマップ ハンドルを読み込むことができます。 たとえば、前の例の CreateCaret 行を次の行に置き換えて、ビットマップ キャレットを作成できます。
// Load the application-defined caret resource.
hCaret = LoadBitmap(hinst, MAKEINTRESOURCE(120));
// Create a bitmap caret.
CreateCaret(hwnd, hCaret, 0, 0);
または、 CreateBitmap 関数または CreateDIBitmap 関数を使用して、キャレット ビットマップのハンドルを取得することもできます。 ビットマップの詳細については、「 ビットマップ」を参照してください。
アプリケーションでビットマップ ハンドルが指定されている場合、 CreateCaret は幅と高さのパラメーターを無視します。 ビットマップはキャレットのサイズを定義します。
キャレットを非表示にする
アプリケーションが WM_PAINT以外のメッセージの処理中に画面を再描画するたびに、 HideCaret 関数を使用してキャレットを非表示にする必要があります。 アプリケーションの描画が完了したら、 ShowCaret 関数を使用してキャレットを再表示します。 アプリケーションが WM_PAINT メッセージを処理する場合、この関数によって自動的に行われるため、キャレットを非表示にして再表示する必要はありません。
次のコード サンプルは、画面上で文字を描画しているときに、および WM_CHAR メッセージの 処理中に、アプリケーションでキャレットを非表示にする方法を示しています。
HWND hwnd, // window handle
HDC hdc; // device context
case WM_CHAR:
switch (wParam)
{
case 0x08:
// Process a backspace.
break;
case 0x09:
// Process a tab.
break;
case 0x0D:
// Process a carriage return.
break;
case 0x1B:
// Process an escape.
break;
case 0x0A:
// Process a linefeed.
break;
default:
// Hide the caret.
HideCaret(hwnd);
// Draw the character on the screen.
hdc = GetDC(hwnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
TextOut(hdc, x, y, lpszChar, 1);
ReleaseDC(hwnd, hdc);
// Display the caret.
ShowCaret(hwnd);
}
アプリケーションが ShowCaret を呼び出さずに HideCaret 関数を複数回呼び出した場合、アプリケーションが ShowCaret を同じ回数呼び出すまで 、キャレット は表示されません。
キャレットの破壊
ウィンドウがキーボードフォーカスを失うと、システムは WM_KILLFOCUS メッセージをウィンドウに送信します。 アプリケーションでは、 DestroyCaret 関数を使用して、このメッセージの処理中にキャレットを破棄する必要があります。 次のコードは、キーボード フォーカスがなくなったウィンドウ内のキャレットを破棄する方法を示しています。
case WM_KILLFOCUS:
// The window is losing the keyboard focus, so destroy the caret.
DestroyCaret();
break;
点滅時間の調整
16 ビット Windows では、Windows ベースのアプリケーションで GetCaretBlinkTime 関数を呼び出して現在の点滅時間を保存し、 SetCaretBlinkTime 関数を呼び出して 、WM_SETFOCUS メッセージの処理中に点滅時間を調整できます。 アプリケーションは、WM_KILLFOCUS メッセージの処理中に SetCaretBlinkTime を呼び出すことによって、他のアプリケーションを使用するために保存された点滅時間 を 復元します。 ただし、この手法はマルチスレッド環境では機能しません。 具体的には、あるアプリケーションの非アクティブ化は別のアプリケーションのアクティブ化と同期されないため、あるアプリケーションがハングした場合でも、別のアプリケーションをアクティブ化できます。
アプリケーションでは、ユーザーが選択した点滅時間を考慮する必要があります。 SetCaretBlinkTime 関数は、ユーザーが点滅時間を設定できるようにするアプリケーションによってのみ呼び出す必要があります。
キーボード入力の処理
次の例では、単純なテキスト エディターでキャレットを使用する方法を示します。 この例では、ユーザーが印刷可能な文字を入力するにつれてキャレット位置を更新し、さまざまなキーを使用してクライアント領域を移動します。
#define TEXTMATRIX(x, y) *(pTextMatrix + (y * nWindowCharsX) + x)
// Global variables.
HINSTANCE hinst; // current instance
HBITMAP hCaret; // caret bitmap
HDC hdc; // device context
PAINTSTRUCT ps; // client area paint info
static char *pTextMatrix = NULL; // points to text matrix
static int nCharX, // width of char. in logical units
nCharY, // height of char. in logical units
nWindowX, // width of client area
nWindowY, // height of client area
nWindowCharsX, // width of client area
nWindowCharsY, // height of client area
nCaretPosX, // x-position of caret
nCaretPosY; // y-position of caret
static UINT uOldBlink; // previous blink rate
int x, y; // coordinates for text matrix
TEXTMETRIC tm; // font information
LONG APIENTRY MainWndProc(
HWND hwnd, // window handle
UINT message, // type of message
UINT wParam, // additional information
LONG lParam) // additional information
{
switch (message)
{
case WM_CREATE:
// Select a fixed-width system font, and get its text metrics.
hdc = GetDC(hwnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc, &tm);
ReleaseDC(hwnd, hdc);
// Save the avg. width and height of characters.
nCharX = tm.tmAveCharWidth;
nCharY = tm.tmHeight;
return 0;
case WM_SIZE:
// Determine the width of the client area, in pixels
// and in number of characters.
nWindowX = LOWORD(lParam);
nWindowCharsX = max(1, nWindowX/nCharX);
// Determine the height of the client area, in
// pixels and in number of characters.
nWindowY = HIWORD(lParam);
nWindowCharsY = max(1, nWindowY/nCharY);
// Clear the buffer that holds the text input.
if (pTextMatrix != NULL)
free(pTextMatrix);
// If there is enough memory, allocate space for the
// text input buffer.
pTextMatrix = malloc(nWindowCharsX * nWindowCharsY);
if (pTextMatrix == NULL)
ErrorHandler("Not enough memory.");
else
for (y = 0; y < nWindowCharsY; y++)
for (x = 0; x < nWindowCharsX; x++)
TEXTMATRIX(x, y) = ' ';
// Move the caret to the origin.
SetCaretPos(0, 0);
return 0;
case WM_KEYDOWN:
switch (wParam)
{
case VK_HOME: // Home
nCaretPosX = 0;
break;
case VK_END: // End
nCaretPosX = nWindowCharsX - 1;
break;
case VK_PRIOR: // Page Up
nCaretPosY = 0;
break;
case VK_NEXT: // Page Down
nCaretPosY = nWindowCharsY -1;
break;
case VK_LEFT: // Left arrow
nCaretPosX = max(nCaretPosX - 1, 0);
break;
case VK_RIGHT: // Right arrow
nCaretPosX = min(nCaretPosX + 1,
nWindowCharsX - 1);
break;
case VK_UP: // Up arrow
nCaretPosY = max(nCaretPosY - 1, 0);
break;
case VK_DOWN: // Down arrow
nCaretPosY = min(nCaretPosY + 1,
nWindowCharsY - 1);
break;
case VK_DELETE: // Delete
// Move all the characters that followed the
// deleted character (on the same line) one
// space back (to the left) in the matrix.
for (x = nCaretPosX; x < nWindowCharsX; x++)
TEXTMATRIX(x, nCaretPosY) =
TEXTMATRIX(x + 1, nCaretPosY);
// Replace the last character on the
// line with a space.
TEXTMATRIX(nWindowCharsX - 1,
nCaretPosY) = ' ';
// The application will draw outside the
// WM_PAINT message processing, so hide the caret.
HideCaret(hwnd);
// Redraw the line, adjusted for the
// deleted character.
hdc = GetDC(hwnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
TextOut(hdc, nCaretPosX * nCharX,
nCaretPosY * nCharY,
&TEXTMATRIX(nCaretPosX, nCaretPosY),
nWindowCharsX - nCaretPosX);
ReleaseDC(hwnd, hdc);
// Display the caret.
ShowCaret(hwnd);
break;
}
// Adjust the caret position based on the
// virtual-key processing.
SetCaretPos(nCaretPosX * nCharX,
nCaretPosY * nCharY);
return 0;
case WM_CHAR:
switch (wParam)
{
case 0x08: // Backspace
// Move the caret back one space, and then
// process this like the DEL key.
if (nCaretPosX > 0)
{
nCaretPosX--;
SendMessage(hwnd, WM_KEYDOWN,
VK_DELETE, 1L);
}
break;
case 0x09: // Tab
// Tab stops exist every four spaces, so add
// spaces until the user hits the next tab.
do
{
SendMessage(hwnd, WM_CHAR, ' ', 1L);
} while (nCaretPosX % 4 != 0);
break;
case 0x0D: // Carriage return
// Go to the beginning of the next line.
// The bottom line wraps around to the top.
nCaretPosX = 0;
if (++nCaretPosY == nWindowCharsY)
nCaretPosY = 0;
break;
case 0x1B: // Escape
case 0x0A: // Linefeed
MessageBeep((UINT) -1);
break;
default:
// Add the character to the text buffer.
TEXTMATRIX(nCaretPosX, nCaretPosY) =
(char) wParam;
// The application will draw outside the
// WM_PAINT message processing, so hide the caret.
HideCaret(hwnd);
// Draw the character on the screen.
hdc = GetDC(hwnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
TextOut(hdc, nCaretPosX * nCharX,
nCaretPosY * nCharY,
&TEXTMATRIX(nCaretPosX, nCaretPosY), 1);
ReleaseDC(hwnd, hdc);
// Display the caret.
ShowCaret(hwnd);
// Prepare to wrap around if you reached the
// end of the line.
if (++nCaretPosX == nWindowCharsX)
{
nCaretPosX = 0;
if (++nCaretPosY == nWindowCharsY)
nCaretPosY = 0;
}
break;
}
// Adjust the caret position based on the
// character processing.
SetCaretPos(nCaretPosX * nCharX,
nCaretPosY * nCharY);
return 0;
case WM_PAINT:
// Draw all the characters in the buffer, line by line.
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
for (y = 0; y < nWindowCharsY; y++)
TextOut(hdc, 0, y * nCharY, &TEXTMATRIX(0, y),
nWindowCharsX);
EndPaint(hwnd, &ps);
case WM_SETFOCUS:
// The window has the input focus. Load the
// application-defined caret resource.
hCaret = LoadBitmap(hinst, MAKEINTRESOURCE(120));
// Create the caret.
CreateCaret(hwnd, hCaret, 0, 0);
// Adjust the caret position.
SetCaretPos(nCaretPosX * nCharX,
nCaretPosY * nCharY);
// Display the caret.
ShowCaret(hwnd);
break;
case WM_KILLFOCUS:
// The window is losing the input focus,
// so destroy the caret.
DestroyCaret();
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return NULL;
}