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

Сайт Польоту
 

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

Думаю, нікому не треба пояснювати, що за елемент керування кнопка :). Ми уже мали з нею справу в попередньому розділі. Хоча ми і розглядаємо її найпершою, політівська кнопка - досить наворочений елемент керування :). Для знайомих з Delphi скажу, що вона поєднує в собі можливості Button, BitBtn, SpeedButton та ToolButton.

Отже, почнемо спочатку.




Створення кнопки
Function Button_Create(Prog:PProg; VCaption:String;
  VPicture:Pointer; VPicturePos:TPicturePos;
  VOnPress:TCtlHandler): PControl;
  • Prog - вказівник на програму, що створює кнопку (практично завджи це Me :).
  • VCaption - напис на кнопці (без коментарів).
  • VPicture - вказівник на картинку на кнопці. Якщо вказати Nil, картинки не буде. Взагалі-то, поки ми не говорили про ресурси, із цими картинками заждемо. Хіба що можу сказати по секрету, що тут крім Nil можна юзати ще деякі "магічні" слова, наприклад Kernel.PicOK.
  • VPicturePos - положення картинки на кнопці. Може бути ppLeft (картинка зліва від напису) або ppTop (картинка над написом). Якщо картинки немає, краще вказувати ppLeft. При ppLeft висота кнопки дорівнює 21 пікселю, при ppTop - 36 пікселям.
  • VOnPress - обробник кліку на кнопці. Тип TCtlHandler описаний у модулі Types так:
    TCtlHandler=Procedure(Me:PProg; Control:PControl);
    Майте на увазі, що ця подія відбувається не лише при кліку мишкою на кнопці, а ще й у таких випадках:
    • при натисненні пробіла, коли кнопка активна (у синій рамочці);
    • натиснення Enter / Esc / F1, якщо кнопка прописана як ButtonEnter / ButtonEsc / ButtonF1 відповідно (про це ми ще поговоримо);
    • внаслідок виклику Kernel.ClickCtl для нашої кнопки.


Малювання кнопки
Procedure Button_Paint(Me:PControl; VX1,VY1,VX2:Integer);
  • VX1, VX2 - координати X лівого та правого країв кнопки (нагадую, відносно лівої сторони нашого вікна). Якщо напис не вміститься по ширині кнопки, він буде скорочений (наприклад, "Відм...").
  • VY1 - коорд. Y верху кнопки (аналогічно відносно верхньої межі вікна). Y2 кнопка визначає сама залежно від свого PicturePos: при ppLeft Y2=Y1+20, при ppTop Y2=Y1+35.


Мінімальна ширина кнопки
Function Button_PrefWidth(Me:PControl): Integer;
Функція повертає мінімальну ширину, при якій на кнопці повністю вміщається її підпис (і, якщо є, картинка). Іноді зручно використовувати при малюванні кнопки:
Ctl.Button_Paint(BtnTest, 10, 10, 10+Ctl.Button_PrefWidth(BtnTest));
Саме так, до речі, малюється кнопка "Старт" на Панелі задач.



Змінити підпис кнопки
Procedure Button_SetCaption(Me:PControl; VCaption:String);
Процедура встановлює новий напис на кнопці. За умовчанням кнопка відразу автоматично перемальовується з новим підписом (про це поговоримо потім).
VCaption - новий підпис.



Отримати підпис кнопки
Function Button_GetCaption(Me:PControl): String;
Відповідно, функція повертає поточний підпис кнопки. Це буває потрібно, коли напис на кнопці юзер вибирає з меню (це можна побачити в багатьох панелях настройок).



Змінити картинку на кнопці
Procedure Button_SetPicture(Me:PControl; VPicture:Pointer);
Встановлює нову картинку для кнопки. Процедура аналогічна Button_SetCaption.
VPicture - вказівник на нову картинку (тут також можна юзати Nil, Kernel.PicOK і так далі).



Отримати картинку на кнопці
Function Button_GetPicture(Me:PControl): Pointer;
Функція повертає вказівник на поточну картинку на кнопці.



Змінити підпис та картинку на кнопці
Procedure Button_SetCapAndPic(Me:PControl; VCaption:String;
  VPicture:Pointer);
Разом міняє підпис та картинку для кнопки. Іноді це зручніше, і перемальовується кнопка лише один раз.
  • VCaption - новий підпис.
  • VPicture - вказівник на нову картинку.


Встановити стан "натисненості" кнопки
Procedure Button_SetDown(Me:PControl; VDown:Boolean);
Політівські кнопки мають властивість "натисненості". Якщо вона встановлена в True, кнопка виглядає натисненою, навіть коли ніхто її не клікає. Хороший приклад цього стану кнопок можна побачити на Панелі задач: кнопка активної програми виглядає натисненою.
VDown - стан: True - натиснена, False - звичайна (відпущена) кнопка.



Отримати стан "натисненості" кнопки
Function Button_GetDown(Me:PControl): Boolean;
Отримати стан натисненості кнопки (True - натиснена, False - "відпущена" кнопка).



Встановити тип "мітки" на кнопці
Procedure Button_SetMarkStyle(Me:PControl;
  MarkStyle:TButtonMarkStyle);
Політівські кнопки мають ще одну цікаву властивість - тип "мітки", маленького значка на правому кінці. Мітки бувають такі:
  • bmNone - нема мітки (проста кнопка)
  • bmMenuDown - стрілка вниз (кнопка відкриває меню)
  • bmMenuUp - стрілка вгору (кнопка відкриває меню, причому вгору; наприклад, кнопка "Старт" на панелі задач, розташованій внизу екрана)
  • bmSwitch - стрілка праворуч (кнопка-перемикач)
  • bmDialog - багатокрапка (кнопка відкриває діалогове вікно)
Взагалі-то вигляд цих міток залежить від поточного скіна, тут я назвав їх звичайний вигляд. Стилі bmMenuDown та bmSwitch зазвичай не варто чіпати вручну, ними користуються елементи керування-"нащадки" кнопки, PopupBtn та Switcher.



Перейдемо від нудної теорії до цікавої практики :). Запустіть Майстер програм. Вкажіть ім'я файла TestBtn, все інше залишіть за умовчанням і зробіть заготовку.

Отже, отже, отже. У нашій програмі буде кнопка, це факт. Хай ця кнопка реагує на клік. Як? Хай підпис свій міняє. Ми уже робили щось таке, але нічого, зробимо ще раз, "повторєніє - мать" і так далі :). Хай напис на кнопці міняється на один із двох написів по черзі, й іконка теж хай міняється.

Поїхали. Сперше описуємо змінну для кнопки у TTestBtnData:
BtnTest: PControl;
Потім створюємо кнопку в OnInit:
BtnTest:=Ctl.Button_Create(Me, 'Windows', Nil, ppLeft,
  OnBtnTestClick);
Відразу напишемо обробник кліку на кнопці (наприклад, після OnPaint):
Procedure OnBtnTestClick(Me:PProg; Control:PControl);
Begin
  With Me^, TTestBtnData(Data^) Do
    If Ctl.Button_GetCaption(BtnTest)='Windows'
      Then Ctl.Button_SetCapAndPic(BtnTest, 'mustdie',
        Kernel.PicClose)
      Else Ctl.Button_SetCapAndPic(BtnTest, 'Windows', Nil)
End;
Ну і малюємо кнопку (в OnPaint):
Ctl.Button_Paint(BtnTest, 10, 10, 100);
Не забудьте додати TestBtn у секцію Uses головної програми Polit.Pas. Все, можна запускати нашу програмку і переконуватись, що вона працює - і кліком мишки, і натисенням Пробіла міняється напис і картинка. Аналогічно можна, наприклад, міняти стан натисненості кнопки. Міняємо обробник OnBtnTestClick на такий:
Procedure OnBtnTestClick(Me:PProg; Control:PControl);
Begin
  With Me^, TTestBtnData(Data^) Do
    Ctl.Button_SetDown(BtnTest,
      Not Ctl.Button_GetDown(BtnTest))
End;
Ще один експериментик. Після створення кнопки давайте допишемо:
ButtonEnter:=BtnTest;
ButtonEsc:=BtnTest;
ButtonF1:=BtnTest;
Запустіть програму знову. Тепер клік на кнопці спрацьовує і при натисненні Enter, Esc, F1! Насправді зручно призначити як ButtonEnter кнопку типу ОК, ButtonEsc - Відмова або Закрити, ButtonF1 - відповідно, Допомога.

І остання фіча. Після цих рядків додаємо ще такий:
ActiveCtl:=Nil;
Запускаємо програму. А де синя рамочка навколо кнопки? Нема, ми самі попросили її не юзати. Іноді так буває краще. Зверніть увагу на Панель задач, там теж немає рамки навколо активної кнопки. Бо в ній так само прописано ActiveCtl:=Nil. Взагалі-то ActiveCtl - це поле запису TProg, що вказує на активний зараз елемент керування програми. У процедурі OnInit йому можна напряму присвоювати потрібний елемент керування (наприклад, ActiveCtl:=BtnTest) або Nil. В усіх інших місцях програми для вибору активного елемента керування треба юзати ось таку процедурку модуля Kernel:
Procedure SelectFocusCtl(Prog:PProg; VCtl:PControl);
Тут VCtl - елемент керування, який треба зробити активним. Наскільки я пам'ятаю, з Nil'ом цю процедуру краще не викликати.