Создание поля для ввода текста на WinAPI
Создание поля для ввода текста на WinAPI
Создание поля для ввода текста на WinAPI Источник: http://decoding.narod.ru/api/edit/edit.html Сегодня мы добавим в наше приложение поле для ввода текста. Если провести аналогию с VCL, то у нас получится TEdit. Мы узнаем, как отреагировать на изменение содержимого в этом поле (аналогично событию OnChange), и каким образом можно работать с текстом в окне. Для этого текст, который мы будем вводить в наше поле, будет также отображаться в другом поле, аналогичном TLabel в VCL. Начнем с объявления констант и переменных, необходимых для работы с этими полями. const EditID = 1; StaticID = 2; var Edit: HWND; Static: HWND; Переходим непосредственно к созданию полей. // Создаем текстовое поле (аналог TEdit) Edit := CreateWindowEx( WS_EX_CLIENTEDGE, ?Edit?, ??, ES_AUTOHSCROLL or WS_CHILD or WS_VISIBLE, 10, 10, 270, 20, Wnd, EditID, hInstance, nil ); SendMessage( Edit, WM_SETFONT, GetStockObject( ANSI_VAR_FONT ), 0 ); // Создаем текстовое поле (аналог TLabel) Static := CreateWindowEx( 0, ?Static?, ??, WS_CHILD or WS_VISIBLE, 10, 46, 270, 20, Wnd, StaticID, hInstance, nil ); SendMessage( Static, WM_SETFONT, GetStockObject( ANSI_VAR_FONT ), 0 ); Эти функции нам уже знакомы, посмотрим, что же в них изменилось. Первое, на что надо обратить внимание, это имя класса создаваемого окна. В первом случае это ?Edit?, а во втором ?Static?. Текстовое поле имеет расширенный стиль, а именно, бордюр. Этого мы добились, используя флаг WS_EX_CLIENTEDGE. Отсутствие этого флага привело бы к созданию "плоского" (Flat) поля (такой эффект мы можем наблюдать у поля Static). Также обратим внимание на флаг ES_AUTOHSCROLL при задании стиля окна. Благодаря этому, текст в окне будет автоматически прокручиваться, если его ширина превысит ширину текстового поля (на поле Static этот флаг не действует). Теперь посмотрим, как нужно работать с этим полем. function WindowProc( Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM ): LRESULT; stdcall; var p: PChar; n: integer; begin case Msg of WM_DESTROY: begin PostQuitMessage( 0 ); Result := 0; Exit; end; WM_SETFOCUS: SetFocus( Edit ); WM_COMMAND: begin case LoWord( wParam ) of EditID: case HiWord( wParam ) of EN_CHANGE: begin n := GetWindowTextLength( lParam ) + 1; GetMem( p, n ); GetWindowText( lParam, p, n ); SetWindowText( Static, p ); FreeMem( p, n ); end; end; end; end; else Result := DefWindowProc( Wnd, Msg, wParam, lParam ); end; end; Обработка сообщения WM_SETFOCUS сделана для того, чтобы передавать фокус ввода текстовому полю каждый раз, когда форма становится активной. С сообщением WM_COMMAND мы уже знакомы. Если наше текстовое поле (LoWord(wParam)=EditID) послало сообщение, что его содержимое изменилось (HiWord(wParam)=EN_CHANGE), то мы отображаем этот текст в поле Static. Используя функцию GetWindowTextLength, мы узнаем длину текста в окне (handle окна передается в функцию в качестве параметра). Эта функция возвpащает длину текста в байтах, но не включает пустой символ окончания. По этому мы делаем +1. Далее выделяем память, и, воспользовавшись функцией GetWindowText, получаем текст окна. Аналогично, функцией SetWindowText, вставляем полученный текст в нужное окно. И в конце не забываем отчистить память.