Обработка строки ввода
Рассмотрим элемент окна, называемый Edid Box. Другими словами это просто строка ввода. Ясно, что ввод текста в поле этого элемента должно осуществляться с помощью клавиатуры. И здесь мы встречаемся с новой для нас тематикой: обработка ввода с клавиатуры. Пример, который я приведу ниже уже довольно сложен. Я разберу один из приемов обаботки ввода с клавиатуры, применительно к конкретному элементу. Проблема в том, что если элемент Edit Box активен, то функция не получает информацию о нажатии клавиши, а только об изменении содежимого элемента. В других примерах я покажу, как можно заставить функцию получать сообщения о нажатых клавишах, если активен элемент управления. Но сейчас попробуем обойтись только 'подручными' средствами.

И так при изменении содержимого элемента Edit Box как и следовало приходит сообщение WM_COMMAND. Причем дважды. Перед тем как содержимое будет изменено и после этого. Соответственно события для Edit Box будут EN_UPDATE и EN_CHANGE. Мы сосредоточим свои усилия на первом событии. Задачу сформулируем так: запретить ввод любых символов кроме цифр: 0,1,2,3,4,5,6,7,8,9. И так рассмотрим программу.

#include <Windows.h>
LRESULT CALLBACK winproc( HWND, UINT, WPARAM, LPARAM);
WNDCLASSEXW ws; //струкутра для регистрации класса окон
wchar_t * wn = L"class1"; //имя класса
MSG msg; //для сообщения
HWND hwnd,hb1; //для дескриптора окна
HINSTANCE h;
int flag;
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
{
h=hInstance;
ws.cbSize = sizeof(WNDCLASSEXW); ws.cbClsExtra = 0;
ws.cbWndExtra = 0; ws.hIcon = LoadIcon( NULL, IDI_APPLICATION );
ws.hCursor = LoadCursor( NULL, IDC_ARROW );
ws.hbrBackground = CreateSolidBrush(RGB(0, 80, 80));
ws.hIcon = NULL; ws.hInstance = hInstance;
ws.lpszClassName = wn; ws.lpszMenuName = NULL;
ws.lpfnWndProc = (WNDPROC)winproc; ws.style = CS_VREDRAW|CS_HREDRAW;
//зарегистрировать класс окна
if(RegisterClassExW(&ws)==0){
MessageBoxExW(0,L"Ошибка регистрации!",L"Сообщение", 0, 0);
return 0;
};
//создать окно
hwnd= CreateWindowExW(0, wn,
L"Окно в 64-битово системе!", WS_OVERLAPPEDWINDOW|WS_TABSTOP,
10, 10, 400, 300, NULL, NULL, hInstance, NULL);
//сделать окно видимым
ShowWindow( hwnd, nCmdShow );
//обновить содержимое
UpdateWindow(hwnd );
//цикл обработки сообщений
while ( GetMessage( &msg, NULL, NULL, NULL ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
//выход из программы
return (int)msg.wParam;
}
//функция окна
LRESULT CALLBACK winproc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
wchar_t bf[100],bf1[100];
int i,j, b ,e;
switch ( uMsg ) {
case WM_CREATE:
hb1=CreateWindowExW(0,L"Edit", L"",
WS_CHILD | WS_VISIBLE |WS_TABSTOP | ES_AUTOHSCROLL | WS_BORDER,
10, 50, 200, 20, hWnd, 0, h, NULL);
break;
case WM_COMMAND:
if(lParam==(int)hb1&&flag==0){
if(HIWORD(wParam)==EN_UPDATE){
flag=1; SendMessage(hb1, EM_GETSEL, (WPARAM)&b, (LPARAM)&e);
GetWindowTextW(hb1, bf, 99 ); j=0;
for(i=0; i<wcslen(bf); i++){
if(bf[i]<L'0'||bf[i]>L'9')continue;
bf1[j]=bf[i]; j++;
}
bf1[j]=L'\0';
SetWindowTextW(hb1,bf1);
SendMessage(hb1,EM_SETSEL,b,b);
}
}else{
flag=0;
}
break;
case WM_DESTROY:
PostQuitMessage(0); break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
};
Ну что же, давайте попытаемся разобраться в представлнной программе. Я уже ранее сказал, что расчитываю на людей, знакомых с программированием. Поэтому буду объяснять основные, опорные моменты программы. Сообщение WM_COMMAND с кодом EN_UPDATE (или сообщение EN_UPDATE для элемента Edit Box) приходит до того, как содержимое элемента изменилось. Однако измененная строка уже содержится в буфере. Функции API GetWindowTextW (получить строку) и SetWindowTextW (изменить строку) как раз и работают с этим буфером. По выходу из функции окна содержимое буфера переносится в видимою часть элемента. Отметим теперь значение переменной flag. Она играет роль индикатора. Смысл вот в чем. Поскольку мы меняем содержимое элемента, то система неминуема должна опять прислать сообщение EN_UPDATE. И вот чтобы не было зацикливания, мы и используем переменную flag.

Обратим теперь внимание на интереснейшую функцию SendMessage. С помощью этой функции можно посылать сообщения окнам. Однако наше поле ввода по сути ведь тоже является окном. SendMessage(hb1, EM_GETSEL, (WPARAM)&b, (LPARAM)&e) - получаем координаты выделенной области. Если область не выделена, то значения b и e совпадут, т.е мы получим положение курсора. Значение b мы в дальнейшем используем для установления курсора в нужное место: SendMessage(hb1,EM_SETSEL,b,b);. Наконец цикл переносит массив двухбайтовых строк из bf в bf1. При этом исключаются все символы, кроме цифр. Вот собственно и весь алгоритм и вся программа.

Ну вот пока все. Наслаждайтесь программированием.

 Назад       Заметки       Сайт       Страница-портал       Журнал
(c) Copyright Владислава Юрьевич Пирогов