Carets 사용
이 섹션에는 다음 작업에 대한 코드 샘플이 있습니다.
Caret 만들기 및 표시
키보드 포커스를 받으면 창에서 캐리트를 만들고 표시해야 합니다. CreateCaret 함수를 사용하여 지정된 창에서 caret를 만듭니다. 그런 다음 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를 동일한 횟수로 호출할 때까지 caret가 표시되지 않습니다.
캐리트 파괴
창에 키보드 포커스가 끊어지면 시스템에서 WM_KILLFOCUS 메시지를 창으로 보냅니다. 애플리케이션은 DestroyCaret 함수를 사용하여 이 메시지를 처리하는 동안 caret를 삭제해야 합니다. 다음 코드에서는 더 이상 키보드 포커스가 없는 창에서 caret를 삭제하는 방법을 보여 주세요.
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 함수는 사용자가 깜박임 시간을 설정할 수 있는 애플리케이션에서만 호출해야 합니다.
키보드 입력 처리
다음 예제에서는 간단한 텍스트 편집기에서 caret를 사용하는 방법을 보여 줍니다. 이 예제에서는 사용자가 인쇄 가능한 문자를 입력하고 다양한 키를 사용하여 클라이언트 영역을 이동할 때 caret 위치를 업데이트합니다.
#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;
}