Verwenden von Carets
Dieser Abschnitt enthält Codebeispiele für die folgenden Aufgaben:
- Erstellen und Anzeigen eines Caret-Strichs
- Ausblenden eines Caret-Strichs
- Zerstören eines Caret-Strichs
- Anpassen der Blinkzeit
- Verarbeiten von Tastatureingaben
Erstellen und Anzeigen eines Caret-Strichs
Nach Erhalt des Tastaturfokus sollte das Fenster das Caretzeichen erstellen und anzeigen. Verwenden Sie die CreateCaret-Funktion , um ein Caretzeichen im angegebenen Fenster zu erstellen. Anschließend können Sie SetCaretPos aufrufen, um die aktuelle Position des Caretzeichens festzulegen, und ShowCaret , um das Caret sichtbar zu machen.
Das System sendet die WM_SETFOCUS Nachricht an das Fenster, das den Tastaturfokus erhält. Daher sollte eine Anwendung das Caret während der Verarbeitung dieser Nachricht erstellen und anzeigen.
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;
Um ein Caretzeichen basierend auf einer Bitmap zu erstellen, müssen Sie bei Verwendung von CreateCaret ein Bitmaphandle angeben. Sie können eine Grafikanwendung zum Erstellen der Bitmap und einen Ressourcencompiler verwenden, um die Bitmap den Ressourcen Ihrer Anwendung hinzuzufügen. Ihre Anwendung kann dann die LoadBitmap-Funktion verwenden, um das Bitmaphandle zu laden. Sie können beispielsweise die CreateCaret-Zeile im vorherigen Beispiel durch die folgenden Zeilen ersetzen, um ein Bitmap-Caretzeichen zu erstellen.
// Load the application-defined caret resource.
hCaret = LoadBitmap(hinst, MAKEINTRESOURCE(120));
// Create a bitmap caret.
CreateCaret(hwnd, hCaret, 0, 0);
Alternativ können Sie die Funktion CreateBitmap oder CreateDIBitmap verwenden, um das Handle der Caretbitbitte abzurufen. Weitere Informationen zu Bitmaps finden Sie unter Bitmaps.
Wenn Ihre Anwendung ein Bitmaphandle angibt, ignoriert CreateCaret die Parameter für Breite und Höhe. Die Bitmap definiert die Größe des Caretzeichens.
Ausblenden eines Caret-Strichs
Wenn Ihre Anwendung einen Bildschirm während der Verarbeitung einer anderen Nachricht als WM_PAINT neu zeichnet, muss sie das Caret mithilfe der HideCaret-Funktion unsichtbar machen. Wenn ihre Anwendung mit dem Zeichnen fertig ist, zeigen Sie das Caret-Zeichen mit der ShowCaret-Funktion erneut an. Wenn Ihre Anwendung die WM_PAINT-Meldung verarbeitet, ist es nicht erforderlich, das Caret auszublenden und erneut anzuzeigen, da diese Funktion dies automatisch ausführt.
Im folgenden Codebeispiel wird gezeigt, wie Die Anwendung das Caretzeichen ausblenden kann, während sie ein Zeichen auf dem Bildschirm zeichnet und die WM_CHAR-Nachricht verarbeitet.
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);
}
Wenn Ihre Anwendung die HideCaret-Funktion mehrmals aufruft , ohne ShowCaret aufzurufen, wird das Caret erst angezeigt, wenn die Anwendung ShowCaret ebenso oft aufruft .
Zerstören eines Caret-Strichs
Wenn ein Fenster den Tastaturfokus verliert, sendet das System die WM_KILLFOCUS Meldung an das Fenster. Ihre Anwendung sollte das Caret während der Verarbeitung dieser Nachricht mithilfe der Funktion DestroyCaret zerstören. Der folgende Code zeigt, wie ein Caret in einem Fenster zerstört wird, das nicht mehr über den Tastaturfokus verfügt.
case WM_KILLFOCUS:
// The window is losing the keyboard focus, so destroy the caret.
DestroyCaret();
break;
Anpassen der Blinkzeit
In 16-Bit-Windows könnte eine Windows-basierte Anwendung die GetCaretBlinkTime-Funktion aufrufen, um die aktuelle Blinkzeit zu speichern, und dann die SetCaretBlinkTime-Funktion aufrufen, um die Blinkzeit während der Verarbeitung der WM_SETFOCUS-Nachricht anzupassen. Die Anwendung würde die gespeicherte Blinkzeit für die Verwendung anderer Anwendungen wiederherstellen, indem setCaretBlinkTime während der Verarbeitung der WM_KILLFOCUS-Nachricht aufgerufen wird. Diese Technik funktioniert jedoch nicht in Multithreadumgebungen. Insbesondere wird die Deaktivierung einer Anwendung nicht mit der Aktivierung einer anderen Anwendung synchronisiert, sodass eine andere Anwendung weiterhin aktiviert werden kann, wenn eine Anwendung angehalten wird.
Anwendungen sollten die vom Benutzer gewählte Blinzelzeit berücksichtigen. Die SetCaretBlinkTime-Funktion sollte nur von einer Anwendung aufgerufen werden, die es dem Benutzer ermöglicht, die Blinkzeit festzulegen.
Verarbeiten von Tastatureingaben
Im folgenden Beispiel wird veranschaulicht, wie ein Caret in einem einfachen Text-Editor verwendet wird. Im Beispiel wird die Caretposition aktualisiert, während der Benutzer druckbare Zeichen eingibt, und es werden verschiedene Schlüssel verwendet, um durch den Clientbereich zu navigieren.
#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;
}