Політ: книга програмера  
0. Вступ
1. Особливості політівських програм
2. Події та їх обробники
3. Елементи керування: принципи, Button, Label, Check, Radio,
InpLine, PicCtl, Header, Progress, Track, TimerCtl, Notebook,
SpinEdit, PopupBtn, Switcher, MainMenu, Splitter, Memo, ListBox

Сайт Польоту
 

Елементи керування
Поле вводу - InpLine (модуль Ctl)

Поле вводу дозволяє юзеру ввести (або відредагувати) текстовий рядок. Ну, а нам, програмерам - узнати, що він там ввів чи наредагував :). Внутрішньо це досить складний елемент керування: якщо Check.inc та Radio.inc займали 4-5 кілобайт, то InpLine.inc тягне на 24 кіло. Воно і не дивно - поле вводу дозволяє вводити, редагувати текст, прокручувати його, виділяти фрагменти та виконувати дії над ними, і все це можна робити як з клавіатури, так і мишкою. На щастя, використання поля вводу не складніше за уже розглянуті елементи керування і схоже на них. Втім, зараз побачите самі.

Політівські поля вводу дещо відрізняються від Windows'них. По-перше, якщо текст у полі надто довгий, по краях поля з'являються стрілочки; з їх допомогою юзер може прокручувати текст у полі мишкою. По-друге, при виділенні текста мишкою координата Y курсора фіксується (тобто мишка не може вискочити за межі поля, поки не буде відпущена її кнопка). Так само, як у Windows, правою кнопкою мишки на полі відкривається його контекстне меню з аналогічними командами - "Вирізати", "Зкопіювати", "Вставити", "Виділити все". Причому якщо Політ був запущений з-під Windows, ці команди працюватимуть із Windows'ним clipboard'ом.




Створення поля вводу
Function InpLine_Create(Prog:PProg; VText:String; 
  VIcon:Pointer): PControl;
  • VText - текст, що буде з самого початку показаний у полі вводу. Тут може бути порожній рядок '', але часто буває зручно вказувати якісь значення за умовчанням (або збережені десь в Ini-файлі). Перший метод використовується у Майстрі програм, а другий - у грі Танки (в її вікні нової гри).
  • VIcon - поле вводу може містити іконку (вона буде показана зліва перед текстом). Іноді це буває зручно, щоб указати юзеру на природу тексту в цьому полі вводу. Скажімо, діалог збереження файлів має поле вводу для імені файла: в ньому показана стандартна іконка файла. Звичайно, тут можна вказати Nil, і ніякої іконки в полі вводу не буде.


Встановити обробник зміни тексту в полі вводу
Procedure InpLine_SetOnChangeFunc(Me:PControl; 
  VOnChange:TInpLineChangeFunc);
Призначити функцію, що буде викликатися при зміні тексту в полі вводу (точніше, при вводі якогось символу). Зверніть увагу, тип цього обробника - не TCtlHandler, як було всюди до цього, а TInpLineChangeFunc. Він описується так:
TInpLineChangeFunc=Function(Me:PProg; 
  Control:PControl; Ch:String): String;
Це зроблено для того, щоб наш обробник міг проаналізувати, що за символ введено, і якщо треба замінити його на якийсь рядок, який і буде в результаті вставлено в поле вводу.
Ch - введений символ
Результат функції - текст, що буде вставлений в поле. Ясно, що за умовчанням текст цього обробника простий:
InpLineChangeDummy:=Ch
Тобто вставити той символ, який і натиснув юзер. Але можна робити і цікавіші речі. Наприклад, елемент керування SpinEdit (який ми розглянемо пізніше) базується на InpLine, зокрема заміняє його обробник OnChange. Цей обробник SpinEdit'а пропускає лише цифри ('0'..'9'), а для всіх інших символів повертає '' - не вставляти в поле нічого.

Як звичайно, майже завжди ця процедура викликається відразу після InpLine_Create - установити обробник раз і назавжди :).



Намалювати поле вводу
Procedure InpLine_Paint(Me:PControl;
  VX1, VY1, VX2:Integer);
Висота поля вводу фіксована і дорівнює 20 пікселям.



Встановити текст у полі вводу
Procedure InpLine_SetText(Me:PControl; VText:String);
VText - новий текст



Отримати текст у полі вводу
Function InpLine_GetText(Me:PControl): String;
Основний прийом роботи з полями вводу.



Програмка-приклад на цей раз хай буде така. У ній буде два поля вводу і кнопка. Коли юзер натисне кнопку, програма створить файл, використавши як його ім'я текст у першому полі вводу, та запише в нього текст із другого поля вводу. Створюємо заготовку TestInp і поїхали:
InpFName, InpContent, BtnWrite: PControl;
Створюємо:
InpFName:=Ctl.InpLine_Create(Me, 'file.txt', Nil);
InpContent:=Ctl.InpLine_Create(Me, '(кілька слів)', Nil);
BtnWrite:=Ctl.Button_Create(Me, 'Записати', Nil, ppLeft,
  OnWriteClick);
Пишемо обробник OnWriteClick:
Procedure OnWriteClick(Me:PProg; Control:PControl);
Var
  F: Text;
Begin
  With Me^, TTestInpData(Data^) Do
  Begin
    Assign(F, Ctl.InpLine_GetText(InpFName));
    Rewrite(F);
    Write(F, Ctl.InpLine_GetText(InpContent));
    Close(F);
    Kernel.ShowHint('Файл записано')
  End
End;
На ShowHint не звертайте уваги, це я так, для краси, про хінти ми будемо говорити пізніше. Малюємо все це:
Ctl.InpLine_Paint(InpFName, 10, 10, X2-X1-10);
Ctl.InpLine_Paint(InpContent, 10, 40, X2-X1-10);
Ctl.Button_Paint(BtnWrite, 10, 70, X2-X1-10);
Зверніть увагу - координати X2 у всіх елементів керування дорівнюють X2-X1-10, тобто "на 10 пікселів лівіше правого краю вікна".

Все, програмка має запускатись і працювати. Тепер пропоную зробити трохи цікавішу річ. Хай перше поле вводу (ім'я файла) при вводі літер кирилиці робить їх транслітерацію латинськими. Наприклад, друкуємо "Україна", а в полі з'являється "Ukrayina". Для цього можна скористатися обробником зміни тексту в полі вводу. Логіка його буде не дуже складна: якщо введений символ - літера кирилиці (in ['а'..'я', 'А'..'Я']), тоді замінити його на транслітерований, інакше повернути його ж. Транслітерацію можна було б робити так:
If Ch='а' Then TempStr:='a';
If Ch='б' Then TempStr:='b';
...
If Ch='я' Then TempStr:='ya';
If Ch='А' Then TempStr:='A';
...
OnInpLineChange:=TempStr;
На щастя, у політівському модулі D уже є така функція - TranslitLine (зробити транслітерацію рядка). Ось нею ми і скористаємося. Отже, пишемо обробник:
Function OnFNameChange(Me:PProg; Control:PControl; 
  Ch:String): String;
Begin
  If Ch[1] in ['а'..'я', 'А'..'Я']
    Then OnFNameChange:=D.TranslitLine(Ch)
    Else OnFNameChange:=Ch
End;
Ах да, і призначаємо цей обробник полю ввода відразу після його створення:
Ctl.InpLine_SetOnChangeFunc(InpFName, OnFNameChange);
Все, можна запускати програмку і гратися :).