Страница 7 из 15
Обработка вводимой информации из клавиатуры Следующий пример показывает, как использовать каретку в обычном редакторе текста. Пример модифицирует позицию каретки, поскольку пользователь вводит с клавиатуры печатные символы и использует различные клавиши, чтобы двигаться по рабочей области. #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; }
|