Win32 API. Каретки
Страница 7. Обработка вводимой информации из клавиатуры


Обработка вводимой информации из клавиатуры

Следующий пример показывает, как использовать каретку в обычном редакторе текста. Пример модифицирует позицию каретки, поскольку пользователь вводит с клавиатуры печатные символы и использует различные клавиши, чтобы двигаться по рабочей области.

#define TEXTMATRIX(x, y) *(pTextMatrix + (y * nWindowCharsX) + x) 
// Глобальные переменные
HINSTANCE hinst;// текущий экземпляр программы
HBITMAP hCaret;// точечный рисунок каретки
HDC hdc;// контекст устройства
PAINTSTRUCT ps;// информация о прорисовке рабочей области
static char *pTextMatrix = NULL;// указатель на текстовую матрицу
static int
nCharX,// ширина символа в логических единицах
nCharY,// высота символа в логических единицах
nWindowX,// ширина рабочей области
nWindowY,// высота рабочей области
nWindowCharsX,// ширина рабочей области для символа
nWindowCharsY,// высота рабочей области для символа
nCaretPosX,// x-координата каретки
nCaretPosY;// y-координата каретки
static UINT uOldBlink;// предыдущая частота мерцания
int x, y;// x и y координаты, используемые в текстовой матрице
TEXTMETRIC tm;// информация о фонте

LONG APIENTRY MainWndProc(
HWND hwnd,// дескриптор окна
UINT message,// тип сообщения
UINT wParam,// дополнительная информация
LONG lParam)// дополнительная информация
{
switch (message)
{
case WM_CREATE:
// Выбор фиксированной ширины системного фонта и получение его текстовой матрицы.
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc, &tm);
ReleaseDC(hwnd, hdc);
// Сохранение средней высоты и ширины символов.
nCharX = tm.tmAveCharWidth;
nCharY = tm.tmHeight;
return 0;
case WM_SIZE:
// Определение ширины рабочей области, в пикселях и в количестве символов.
nWindowX = LOWORD(lParam);
nWindowCharsX = max(1, nWindowX/nCharX);
// Определение высоты рабочей области, в пикселях и в количестве символов.
nWindowY = HIWORD(lParam);
nWindowCharsY = max(1, nWindowY/nCharY);
// Очистка буфера, который содержит введенный текст.
if (pTextMatrix != NULL)
free(pTextMatrix);
// Если имеется достаточно памяти, распределите пространство для буфера ввода текста.
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) = ' ';
// Переместим каретку в начало координат
SetCaretPos(0, 0);
return 0;
case WM_KEYDOWN:
switch (wParam)
{
case VK_HOME:// в начало
nCaretPosX = 0;
break;
case VK_END:// в конец
nCaretPosX = nWindowCharsX - 1;
break;
case VK_PRIOR:// предыдущая страница
nCaretPosY = 0;
break;
case VK_NEXT:// следующая страница
nCaretPosY = nWindowCharsY -1;
break;
case VK_LEFT:// перемещение стрелкой влево
nCaretPosX = max(nCaretPosX - 1, 0);
break;
case VK_RIGHT:// перемещение стрелкой вправо
nCaretPosX = min(nCaretPosX + 1,
nWindowCharsX - 1);
break;
case VK_UP:// перемещение стрелкой вверх
nCaretPosY = max(nCaretPosY - 1, 0);
break;
case VK_DOWN:// перемещение стрелкой вниз
nCaretPosY = min(nCaretPosY + 1,
nWindowCharsY - 1);
break;
case VK_DELETE:// удалить
// Переместите все символы, которые следовали за удаленным символом (на той же самой строке) на один
// пробел обратно (влево) в матрице

for (x = nCaretPosX; x < nWindowCharsX; x++)
TEXTMATRIX(x, nCaretPosY) = TEXTMATRIX(x + 1, nCaretPosY);
// Замена последнего символа в строке с пробелом.
TEXTMATRIX(nWindowCharsX - 1,
nCaretPosY) = ' ';
// Прикладная программа будет рисовать вне обработки сообщения
// WM_PAINT, так скрывают каретку.

HideCaret(hwnd);
// Перерисовка строки для удаленного символа.
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
TextOut(hdc, nCaretPosX * nCharX,
nCaretPosY * nCharY,
&TEXTMATRIX(nCaretPosX, nCaretPosY),
nWindowCharsX - nCaretPosX);
ReleaseDC(hwnd, hdc);
// Показать каретку.
ShowCaret(hwnd);
break;
}
// Корректировать позицию каретки, основанную при обработке виртуальной клавиши
SetCaretPos(nCaretPosX * nCharX, nCaretPosY * nCharY);
return 0;
case WM_CHAR:
switch (wParam)
{
case 0x08:// Обратный Пробел (Back Space)
// Перемещение каретки на один пробел, а затем обработка этого действия подобно клавише DEL.
if (nCaretPosX > 0)
{
nCaretPosX--;
SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1L);
}
break;
case 0x09:// табуляция (Tab)
// Табуляция останавливается, проходя каждые четыре пробела, таким образом добавляются пробелы,
// до тех пор, пока пользователь нажимает следующий раз на клавишу табуляции.

do
{
SendMessage(hwnd, WM_CHAR, ' ', 1L);
} while (nCaretPosX % 4 != 0);
break;

case 0x0D:// возврат каретки
// Переход к началу следующей строки. Нижняя строка переносится по кругу в верхнюю часть.
nCaretPosX = 0;
if (++nCaretPosY == nWindowCharsY)
nCaretPosY = 0;
break;

case 0x1B:// Escape
case 0x0A:// перевод строки
MessageBeep((UINT) -1);
break;
default:
// Добавление символа в буфер текста.
TEXTMATRIX(nCaretPosX, nCaretPosY) = (char) wParam;
// Прикладная программа будет рисовать вне обработки сообщения WM_PAINT; так скрывают каретку.
HideCaret(hwnd);
// Прорисовка символа на экране
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
TextOut(hdc, nCaretPosX * nCharX,
nCaretPosY * nCharY,
&TEXTMATRIX(nCaretPosX, nCaretPosY), 1);
ReleaseDC(hwnd, hdc);
// Отобразим каретку
ShowCaret(hwnd);
// Подготовка переноса по словам с начала до конца, если Вы достигли конца строки
if (++nCaretPosX == nWindowCharsX)
{
nCaretPosX = 0;
if (++nCaretPosY == nWindowCharsY)
nCaretPosY = 0;
}
break;
}
// Регулировка позиции каретки, основанной на обработке символа.
SetCaretPos(nCaretPosX * nCharX, nCaretPosY * nCharY);
return 0;

case WM_PAINT:
// Прорисовка всех символов в буфере, строка за строкой.

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:
// Окно имеет фокус ввода. Загрузка каретки определенной ресурсом программного приложения.
hCaret = LoadBitmap(hinst, MAKEINTRESOURCE(120));
// Создание каретки
CreateCaret(hwnd, hCaret, 0, 0);
// Регулировка позиции каретки
SetCaretPos(nCaretPosX * nCharX, nCaretPosY * nCharY);
// Изображение каретки.
ShowCaret(hwnd);
break;
case WM_KILLFOCUS:
// Окно теряет фокус ввода, так что каретка уничтожается.
DestroyCaret();
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return NULL;
}

 
« Предыдущая статья   Следующая статья »