캐럿 사용
이 섹션에는 다음 작업에 대한 코드 샘플이 있습니다.
Caret 만들기 및 표시
키보드 포커스를 받으면 창에서 캐리트를 만들고 표시해야 합니다. CreateCaret 함수를 사용하여 지정된 창에캐럿을 만듭니다. 그런 다음 SetCaretPos 호출하여 캐럿의 현재 위치를 설정하고 캐럿을 표시하도록 ShowCaret수 있습니다.
시스템에서 키보드 포커스를 받는 창에 WM_SETFOCUS 메시지를 보냅니다. 따라서 애플리케이션은 이 메시지를 처리하는 동안 caret를 만들고 표시해야 합니다.
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 너비 및 높이 매개 변수를 무시합니다. 비트맵은 caret의 크기를 정의합니다.
Caret 숨기기
애플리케이션이 WM_PAINT이외의 메시지를 처리하는 동안 화면을 다시 그릴 때마다 HideCaret 함수를 사용하여 캐리트를 보이지 않게 해야 합니다. 애플리케이션 그리기를 마치면 ShowCaret 함수를 사용하여 캐리트를 다시 표시합니다. 애플리케이션이 WM_PAINT 메시지를 처리하는 경우 이 함수가 자동으로 수행하므로 caret를 숨기고 다시 표시할 필요가 없습니다.
다음 코드 샘플에서는 화면에 문자를 그리는 동안 및 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;
}