Processing Keyboard Input

The following example demonstrates how to use a caret in a simple text editor. The example updates the caret position as the user types printable characters and uses various keys to move through the client area.

#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; // x and y coordinates to use in 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;

}

Software for developers
Delphi Components
.Net Components
Software for Android Developers
More information resources
MegaDetailed.Net
Unix Manual Pages
Delphi Examples