Класът TWinControl и неговите наследници

Автори: Евгений Веселов Михаил Голованов Източник: Списание RSDN #3-2003

неговите

Въведение

Само контролите на прозореца имат свой собствен прозорец (по-правилно манипулатор на прозорец). Каква е разликата между дизайна на прозоречните компоненти и дизайна на графичните компоненти, обсъдени в предишната статия? В контекста на VCL разликата е, че графичните контроли са деца на TGraphicControl, докато контролите на прозорци са деца на TWinControl. Благодарение на усилията на екипа на Borland, разработването на прозоречни контроли като цяло е много подобно на разработването на графични (и това ще видим малко по-късно).

TWinControl и с какво се яде...

Повечето контроли в операционната система Windows са прозорци. От техническа гледна точка прозорецът е запис във вътрешната системна таблица, който съответства на елемент, който се показва на екрана и в резултат на това има изпълним код, свързан с него.

Този "код" обикновено се нарича прозоречна функция или прозоречна процедура. На всеки прозорец се присвоява така наречената прозоречна процедура, която определя "поведението" на прозореца. Когато възникне събитие, се изпраща съобщение до един от прозорците, които в момента отговарят за обработката на събития от този тип. Прозорецът, който е получил това съобщение, разбира се, трябва да го обработи. Тази обработка се извършва от функцията прозорец. Класът TWinControl се използва като базов клас за създаване на компоненти, които имат собствен прозорец. Като такъв, той има различни свойства, методи и събития, които са общи за всеки контрол на прозореца.

На първо място, TWinControl предоставя свойство Handle, което е препратка към ID на прозореца на основната контрола. Важен факт обаче ече когато се създаде екземпляр от типа TwinControl, автоматично се създава манипулатор на прозорец, съответстващ на него. Всъщност Delphi използваотложена инициализация. Това означава, че контролът се създава само когато е необходим. Това обикновено се случва при достъп до гореспоменатото свойство Handle. След това се извиква веригата от методи HandleNeeded ->. CreateHandle и едва тогава се появява извикването CreateWnd, което ще бъде обсъдено по-долу.

Какво следва от това? На първо място, че е възможно да се съхрани контрола в паметта, чийто манипулатор ще бъде създаден само когато този елемент бъде поискан, например, когато Visible е зададено на true.

Тази идея предполага създаване на икономичен контрол, който ще се създаде само като прозорец, когато се показва на екрана. Вземаме обикновен бутон (TButton) като основа.Ако Visible:=False унищожаваме дескриптора, ако Visible:=True го създаваме.

Кодът на компонента е даден по-долу:

Между другото, самият опит да се уверите чрез извикване на метода Handle, че този бутон наистина унищожава прозореца си, ще означава невнимателно четене на тази статия :).

И така, в Delphi всеки от класовете, извлечени от TWinControl, замества метода WndProc, който капсулира горната процедура на прозореца. Същият ефект може да се постигне чрез присвояване на нова стойност на свойството WindowProc. Въпреки че кодът по-долу или използваният в примера може значително да опрости разработката на компонента, все пак е желателно да се използват специални манипулатори на събития или фактът, че VCL преобразува системните събития в събития от VCL библиотека, т.е. работа с тях на високо ниво.

Сегаразгледайте метода CreateWnd, който се извиква всеки път, когато трябва да се създаде прозорец и да се получи неговият ID. В този случай CreateWnd извиква метода CreateParams, за да зададе настройките за създавания прозорец, и след това метода CreateWindowHandle, за да създаде прозореца и да получи манипулатора му. Много често наследниците на TWinControl заместват методите CreateWnd и CreateParams.

Методът CreateParams се отменя, ако е необходимо да се зададат специфични настройки за прозореца на компонента, които са различни от тези по подразбиране. Най-често конфигурирани: