Изграждане на графичен потребителски интерфейс с Windows Forms


Библиотеките на .NET за изграждане на GUI



страница2/16
Дата27.09.2016
Размер1.09 Mb.
#10985
1   2   3   4   5   6   7   8   9   ...   16

Библиотеките на .NET за изграждане на GUI


Средствата на .NET Framework за изграждане на графичен потребителски интерфейс са дефинирани в пространствата от имена System.Drawing и System.Windows.Forms, които са реализирани съответно в асемблитата System.Drawing.dll и System.Windows.Forms.dll. Тези пространства за­едно с пространствата, съдържащи се в тях, са изобразени на фигурата:


Пространството System.Windows.Forms


Класовете и типовете от пространството System.Windows.Forms осигу­ря­ват средства за работа с прозорци, диалози, контроли за въвеж­дане на текст, контроли за избор, менюта, ленти с инструменти, таблици, дървета и др.

Пространството System.Windows.Forms.Design


Пространството System.Windows.Forms.Design съдържа класове, които поддържат конфигурирането на компонентите и дефинират поведението на Windows Forms контролите по време на дизайн.

Пространството System.Drawing


Класовете и типовете от пространството System.Drawing и неговите под­пространства осигуряват достъп до GDI+ функциите на Windows: работа с повърхности, точки, линии, четки, моливи, геометрични фигури, картин­ки, текст и шрифтове и др.

Програмни компоненти


В софтуерното инженерство компонентите са преизползваеми (reusable) програмни единици (класове), които решават специфична задача. Всеки компонент има ясно дефиниран интерфейс, който описва неговите свой­ства, методи и събития. Компонентите се използват като части от други компоненти или програми – те са градивните елементи на софтуера.

Компонентен модел


В софтуерното инженерство компонентният модел дефинира стандартите за разработка и използване на програмните компоненти и техния жизнен цикъл. Тези стандарти описват чрез интерфейси модела на поведение и взаимодействие на всички компоненти в дадена среда.

Компонентният модел на .NET Framework


Компонентният модел на .NET Framework дефинира програмния модел (система от правила) за създаване и използване на .NET компоненти. Този програмен модел се реализира чрез определени класове и интерфейси, които поддържат описанието на компонентите.

В .NET Framework компонентният модел позволява дефиниране на пове­дението на компонентите по време на дизайн (design-time behavior) и по време на работа (runtime behavior).


Компоненти и контейнери


В .NET Framework са дефинирани два вида преизползваеми обекти: ком­поненти и контейнери. Компонентите са функционални единици, които решават някаква задача, а контейнерите са обекти, които съдържат спи­сък от компоненти.

Преизползваемост на компонентите


Благодарение на междуезиковата съвместимост, която CLR осигурява, .NET компонентите могат директно да се преизползват във всички .NET езици за програмиране. Възможно е .NET компоненти да бъдат използвани и от Win32 приложения, но за целта трябва да се публикуват във вид на COM обекти.

Пространството System.ComponentModel


Компоненти се използват не само в Windows Forms, а навсякъде в .NET Framework. По тази причина основната функционалност на компонентния модел на .NET се намира в пространството System.ComponentModel. В него са дефинирани основните интерфейси IComponent и IContainer и техните имплементации Component и Container.

Windows Forms и компонентният модел на .NET


В архитектурата на Windows Forms залягат концепциите на компонентния модел на .NET Framework. Компонентният модел на .NET дефинира компо­ненти и контейнери. По подобен начин Windows Forms дефинира контроли и контейнер-контроли.

Контроли и контейнер-контроли


Контролите в Windows Forms са всички компоненти, които са видими за потребителя (имат графично изображение). Те биват два вида: контей­нер контроли (форми, диалози, панели и т.н.) и контроли (бутони, тексто­ви полета, етикети, списъчни контроли и т.н.). Контейнерите са предназ­начени да съдържат в себе си други контроли (включително и други кон­тейнер контроли), докато контролите са предназначени да се съдържат в контей­нер контролите.

В Windows Forms всяка контрола може да се използва като контейнер-контрола, но за някои контроли това е безсмислено. Например няма смисъл и не е правилно в бутон да се поставят примерно други бутони или текстови полета.


Програмен модел на Windows Forms


Програмният модел на Windows Forms дефинира класовете за работа с форми, диалози и контроли, събитията на контролите, жизнения цикъл на приложенията, модела на пречертаване на контролите, модела на получа­ване и обработка на събитията и модела на управление на фокуса. Нека разгледаме всички тези елементи от този програмен модел.

Форми


Windows Forms предлага стандартни класове за работа с форми (това са прозорците и диалозите в GUI приложенията). Формите могат да бъдат модални и немодални (по една или по много активни едновременно). Формите са контейнер-контроли и могат да съдържат други контроли, например етикети, текстови полета, бутони и т.н. Базов клас за всички форми е класът System.Windows.Forms.Form.

Контроли


Контролите в Windows Forms са текстовите полета, етикетите, бутоните, списъците, дърветата, таблиците, менютата, лентите с инструменти, статус лентите и много други. Windows Forms дефинира базови класове за кон­тролите и класове-наследници за всяка контрола. Базов клас за всички контроли е класът System.Windows.Forms.Control. Пример за контрола е например бутонът (класът System.Windows.Forms.Button).

Събития


Всички контроли от Windows Forms дефинират събития, които програмис­тът може да прихваща. Например контролата Button дефинира събитието Click, което се активира при натискане на бутона. Събитията в Windows Forms управляват взаимодействието между програмата и контролите и между самите контроли помежду им.

Жизнен цикъл на Windows Forms приложенията


Жизненият цикъл на GUI приложенията е базиран на съобщения. Графич­ната среда на операционната система прихваща всички потребителски действия (напр. движението на мишката, натискането на клавиши от клавиатурата и т.н.) и ги натрупва в специална опашка. След това всяко съобщение се предава към приложението, за което се отнася и по-точно към нишката (thread) от приложението, за която се отнася.

Нишки и многозадачност


В многозадачните операционни системи (каквито са например Windows и Linux) е възможно едно приложение да изпълнява няколко задачи пара­лелно като използва няколко нишки (threads) в рамките на процеса, в който работи програмата.

За целите на настоящата тема можем да си мислим, че нишките са нещо като отделни задачи в програмата, които се изпълняват едновременно (паралелно) в даден момент. По-нататък, в темата „Многонишково програмиране и синхронизация” [TODO: link] ще обърнем специално вни­мание на многозадачността, използването и синхронизацията на нишки.


Опашката от събития


Всяка нишка от всяко приложение си има своя собствена опашка, в която постъпват съобщенията за всички събития, идващи от потребителя или от други източници. Всяко съобщение носи информация за събитието, което е настъпило – часът на настъпване, идентификатор на прозорец, за който се отнася събитието, тип на събитието, параметри на събитието (напр. номер на натиснатия клавиш при събитие от клавиатурата или позиция на курсора при събитие от мишката) и т.н. В Windows Forms съобщенията са инстанции на структурата System.Windows.Forms.Message.

Главната нишка на всяко Windows Forms приложение извършва една единствена задача: в безкраен цикъл обработва опашката от съобщения за приложението и предава постъпилите съобщенията на контролата, за която са предназначени.

В Windows Forms приложенията винаги имат точно една нишка, която обработва всички съобщения идващи от графичните контроли и това е главната нишка на приложението. Графичният потребителски интерфейс на цялото приложение се управлява от тази нишка. При настъпване на събитие, свързано с някоя от формите на приложението или контролите в нея, в опашката на главната нишка постъпва съответно съобщение и то се обработва когато му дойде реда.

Само главната нишка трябва да взаимодейства с опашката от събития


Много е важно, когато разработвате Windows Forms приложения да се съобразявате със следното правило:



Графичният потребителски интерфейс на приложението трябва да се управлява само и единствено от неговата главна нишка.

Ако не спазвате това правило, ще се сблъскате с много странни и неприятни проблеми. Например, ако стартирате едновременно няколко нишки и от всяка от тях от време на време променяте съдържанието на дадено текстово поле, от време на време приложението ще „зависва”.

Всяка контрола обработва собствените си събития


Когато главната нишка на Windows Forms приложение получи съобщение, свързано с някоя от неговите форми, тя препраща съобщението до обра­ботчика на съобщения на съответната форма. Този обработчик от своя страна проверява дали съобщението е за самата форма или за някоя нейна контрола. Ако съобщението е за формата, то се обработва директно от съответния обработчик на събития. Ако съобщението е за някоя от контролите във формата, то се предава на нея. Контролата, която получи съобщението може да е обикновена контрола или контейнер-контрола. Когато обикновена контрола получи съобщение, тя го обработва директ­но. Когато контейнер-контрола получи съобщение, тя проверява дали то е за нея директно или е за някоя от вложените контроли. Процесът продъл­жава докато съобщението достигне до контролата, за която е предназ­начено.

По описаната схема всяко съобщение преминава от главната нишка на приложението през формата, за която се отнася, и евентуално през още една или няколко други контроли докато си намери обработчика.


Обработка на събитие – пример


Нека имаме някакво приложение, което се състои от една форма, в която има един бутон. Да предположим, че натиснем левия бутон на мишката докато курсорът е върху бутона във формата. Какво се случва?

Главната нишка на приложението получава съобщение „натиснат ляв бутон на мишка”, в което са записани координатите, в които е бил курсорът на мишката в момента на натискането. Операционната система подава тези координати относително спрямо горния ляв ъгъл на формата.

Докато обработва съобщението главната нишка на приложението открива формата, за която се отнася събитието (това е най-горната от всички форми, в които попада курсора на мишката), и го предава на нейния обработчик на събития.

Формата получава съобщението и вижда, че то се отнася за някаква позиция, в която се намира някаква нейна контрола (в случая това е бутонът). Формата преценява, че съобщението не е за нея, а е за бутона и му го предава.

Бутонът получава събитието и вижда, че то е предназначено точно за него. Събитието бива погълнато (консумирано) от обработчика на събития на бутона и съответно бутонът преминава в състояние „натиснат”. Самият бутон малко след това изпраща събитие за пречертаване до самия себе си (на пречертаването ще обърнем внимание след малко). Когато това събитие достигне по същия път до бутона, той се пречер­тава в натиснато състояние.

Прекратяване на Windows Forms приложение


При затваряне на главната форма на Windows Forms приложение, към нея се изпраща съобщение за затваряне. Формата се затваря в момента, в който получи съобщението и го обработи. В резултат на затварянето на формата се прекратява цикълът, в който главната нишка на приложението обработва пристигащите за нея съобщения и приложението приключва изпълнението си.

Модел на пречертаване на контролите


В Windows Forms контролите често се пречертават, например при пре­местване на прозорец, при смяна на активния прозорец или при промяна на размера, позицията или състоянието на някоя контрола. При всяко от изброените действия една или няколко контроли, които попадат в обсега на даден засегнат регион, се обявяват за невалидни и се активира проце­сът на пречертаване.

Процесът на пречертаване


Процесът на пречертаване на контрола, която е засегната от промяна в нея самата, от промяна на контейнер-контролата, в която се намира, или от промяна в други съседни контроли, се извършва на два етапа:

  1. За контролата се извиква методът Invalidate(), който обявява за невалидна дадената контрола или отделен неин участък и изпраща заявка за пречертаване. Invalidate() реално маркира регионите от контролата, които по някаква причина имат нужда от пречертаване и след това й изпраща съобщение „пречертай” (WM_PAINT), което се изпълнява по-късно.

  2. В някакъв момент цикълът за обработка на съобщения на текущата нишка получава съобщението "пречертай" и в резултат изпълнява метода Paint() на съответната контрола. Този метод извършва самото графично обновяване на всички невалидни участъци от контролата или в частност я пречертава цялата.

Друг интересен метод, свързан с пречертаването на контролите е Update() методът. Той може да се използва след Invalidate() за незабавно пречертаване на дадена контрола чрез насилствено извикване на Paint(), без да се изчаква Paint() да бъде извикан от цикъла за обработка на съобщения за текущата нишка.

Съобщението „пречертай”


Съобщението „пречертай” (WM_PAINT) е специално съобщение. То се обра­ботва последно, едва след като всички останали съобщения от опашката на главната нишка вече са обработени и в нея останат само съобщения „пречертай”. Това осигурява намаляване на претрепванията на контроли­те, когато те се променят много пъти за кратко време.

Например, ако при обработката на дадено събитие на дадена контрола бъде изпратено 5 пъти съобщение „пречертай”, контролата ще изпълни само едно пречертаване и то едва след като формата е обработила всички останали съобщения и е станало ясно кои контроли са станали невалидни и трябва да се пречертаят.

Реалното графично изобразяване на заявените за пречертаване контроли се извършва, когато те обработват съобщението „пречертай”, което може да е много след като пречертаването е заявено.

Когато се пречертават няколко контроли последователно, те винаги се пречертават в реда, в който контролите са поставени в контейнер-контролата (т. нар. Z-order). Първи се пречертават най-рано поставените контроли, а последни – най-късно поставените.


Реализация на пречертаването


Всяка Windows Forms контрола може да дефинира програмен код, който реализира изчертаването на нейното съдържание (метод Paint()).

Windows Forms контролите могат да се поставят една върху друга със застъпване. Понеже при пречертаване контролите се изобразяват една след друга по реда на поставянето им, ако има застъпвания, последно поставената контрола закрива (частично или напълно) всички контроли, с които се застъпва.

По-нататък в настоящата тема ще дадем примерен код, който реализира пречертаването на контрола чрез използване на графичните примитиви от GDI+.

Управление на фокуса и навигация


В една форма в даден момент може някоя от контролите да е активна, т.е. да държи фокуса. Контролата, която е на фокус, обикновено показва това по някакъв начин – бутонът променя графичния си вид, текстовото поле показва мигащ курсор и т.н.

При настъпване на събитие от клавиатурата, то се получава първо от контролата, която е на фокус. Например, ако едно текстово поле е на фокус и потребителят натисне клавиш, който съответства на някоя буква, текстовото поле обикновено приема буквата и я изписва на позицията на курсора. Ако текстовото поле не обработи натиснатия клавиш (например ако това е клавиш за навигация, например [Tab]), той се обработва от контейнер-контролата.

Windows Forms осигурява навигация между контролите чрез клавишите [Tab] и [Shift+Tab], които преместват фокуса към следващата или пред­ходната контрола. Коя е следващата и коя е предишната контрола се определя от т. нар. “Tab Order”, който зависи от реда на поставяне на контролите във формата и от някои свойства на контролите.

Формите също могат да са на фокус (да са активни) или да не са. Фокусът между формите може да се променя от потребителя само при немодални форми. Модалните форми не позволяват друга форма да приема фокуса докато не бъдат затворени.

Текущата фокусирана контрола и форма могат да се променят както в резултат от потребителски действия от клавиатурата и мишката, така и програмно чрез изпращане на подходящи съобщения или извикване на подходящи методи. Има контроли, които не могат да приемат фокуса и контроли, които могат да го приемат, но се прескачат при натискане на [Tab] и [Shift+Tab].




Сподели с приятели:
1   2   3   4   5   6   7   8   9   ...   16




©obuch.info 2024
отнасят до администрацията

    Начална страница