Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Глава 10. Объекты окон

             Объекты окон (или оконные объекты) - это интерфейсные объек-
        ты, предназначенные для облегчения работы с окнами. В данной гла-
        ве поясняется,  как создавать и заполнять  окна  приложения.  Это
        предусматривает следующие задачи:

             * Инициализацию оконных объектов.

             * Установку атрибутов создания.

             * Создание экранных элементов окна.

             * Установку атрибутов регистрации.

             * Использование специализированных окон.

             * Прокрутку окон.

                               Что такое объекты окон?
        -----------------------------------------------------------------

             Термин "объект окна" относится к любому интерфейсному объек-
        ту, представляющему окно, а в Windows это почти все, что выводит-
        ся на экран.  В качестве шаблона определения большей части фунда-
        ментального поведения  основного  окна и любого всплывающего окна
        приложения ObjectWindows использует тип TWindow.


                           Окна, которые не являются окнами
        -----------------------------------------------------------------

             TWindow имеет   три  типа-потомка:  TMDIWindow,  TControl  и
        TEditWindow, так что все они также являются  оконными  объектами,
        хотя на  самом  деле это не окна в полном смысле слова.  Типы MDI
        используются в приложениях ObjectWindows,  которые  соответствуют
        стандарту многодокументального интерфейса Windows.  Об MDI и этих
        типах рассказывается в Главе 14.  TControl определяет управляющие
        элементы, такие  как командные кнопки и блоки списков (см.  Главу
        12). Чаще всего  новые  оконные  типы  являются  производными  от
        TWindow.

             Эта глава  охватывает  типы TWindow и TEditWindow и содержит
        примеры регистрации новых классов окон.


                                Где найти объекты окон
        -----------------------------------------------------------------

             Каждое приложение Windows имеет основное окно.  Это окно мо-
        жет выводиться в виде пиктограммы или не выводиться снова  (скры-
        тое окно),  но существует всегда. Приложения ObjectWindows не яв-
        ляются исключением:  они должны иметь основное окно, представлен-
        ное оконным объектом.

             Примером минимальной   программы   ObjectWindows  ("скелета"
        программы) является TestApp в Главе 8.  Основное  окно  программы
        ObjectWindows является  обычно экземпляром TWindow или определяе-
        мого в программе наследующего типа.  Многие приложения имеют дру-
        гие окна,  которые обычно являются дочерними окнами основного ок-
        на. Эти дополнительные окна также являются  экземплярами  TWindow
        или одного из его потомков.

             Например, графическая  программа может определять для своего
        основного окна тип TPaintWindow, а для окна, показывающего графи-
        ческий рисунок  -  тип TZoomWindow.  В этом случае TPaintWindow и
        TZoomWindow являются наследниками TWindow.

                             Инициализация объектов окон
        -----------------------------------------------------------------

             Оконные объекты представляют элементы окна,  связанные через
        описатели, сохраненные  в  наследуемом  из  TWindowsObject   поле
        HWindow. Так как объект окна имеет две части, его создание требу-
        ет двух шагов:  инициализации объекта и создания визуального эле-
        мента.

             Инициализация окна  -  это процесс создания оконного объекта
        ObjectWindows путем вызова конструктора Init:

             Window1 := New(PWindow,Init(nil, 'Заголовок окна 1'));
             Window2 := New(PNewWindowType,Init(nil,'Заголовок окна 2'));

             Init создает новый оконный объект и устанавливает поле Title
        в Attr в передаваемый аргумент PChar. Первый аргумент вызова Init
        - это оконный объект порождающего окна. Если окно является основ-
        ным окном (не имеющим порождающего окна), то это nil.


                             Установка атрибутов создания
        -----------------------------------------------------------------

             Типичное приложение  Windows  имеет  много  различных  типов
        окон: перекрывающиеся или всплывающие, окна с рамкой, прокручива-
        емые окна,   окна с заголовком и др. Эти атрибуты стилей, а также
        заголовок и меню окна задаются при инициализации оконного объекта
        и используются при создании элементов окна.

             Атрибуты создания оконного объекта, такие как стиль, заголо-
        вок и меню,  записываются в  поле  Attr  объекта  -  записи  типа
        TWindowAttr. TWindowAttr содержит следующие поля:

                             Атрибуты создания окна          Таблица 10.1
        +------------+--------------+-----------------------------------+
        |    Поле    | Тип          |           Использование           |
        +------------+--------------+-----------------------------------|
        |    Title   | PChar        | Строка заголовка.                 |
        |            |              |                                   |
        |    Style   | Longint      | Комбинированная константа стиля.  |
        |            |              |                                   |
        |    Menu    | HMenu        | Описатель ресурса меню.           |
        |            |              |                                   |
        |    X       | Integer      | Горизонтальная  координата  экрана|
        |            |              | верхнего левого угла окна.        |
        |            |              |                                   |
        |    Y       | Integer      | Вертикальная   координата   экрана|
        |            |              | верхнего левого угла окна.        |
        |            |              |                                   |
        |    W       | Integer      | Начальная ширина окна в  координа-|
        |            |              | тах экрана.                       |
        |            |              |                                   |
        |    H       | Integer      | Начальная высота окна в  координа-|
        |            |              | тах экрана.                       |
        |            |              |                                   |
        +------------+--------------+-----------------------------------+


        ^################################################################
        #(0,0)###########################################################
        #####(X,Y)#######################################################
        #####v###########################################################
        #####+---------------------------------------+--+--+--###########
        #####| XXXXXXXXXXXXXXXX  Title XXXXXXXXXXXXXX|  |  | ^###########
        #####+---------------------------------------+--+--| |###########
        #####| Menu                                        | |###########
        #####+---------------------------------------------| |###########
        #####|                                             | |###########
        #####|                                             | |###########
        #####|                                             | H###########
        #####|                                             | |###########
        #####|                                             | |###########
        #####|                                             | |###########
        #####|                                             | |###########
        #####|                                             | |###########
        #####|                                             | v###########
        #####+---------------------------------------------+--###########
        #####|<------------------W------------------------>|#############
        #################################################################
        #################################################################

             Рис. 10.1 Атрибуты окна.

                       Используемые по умолчанию атрибуты окна
        -----------------------------------------------------------------

             По умолчанию   TWindow.Init   устанавливает   Attr.Style   в
        ws_Visible. Если окно  является  основным  окном  приложения,  то
        Style равно ws_OverlappedWindow or ws_Visible.

             Menu по умолчанию устанавливается в 0. Это означает, что ме-
        ню не определено.

             X, Y,  W и H устанавливаются в cw_UseDefault, что дает в ре-
        зультате перекрывающееся окно удовлетворительного размера.  Когда
        создается окно,  не являющееся основным,  значения X, Y, W и H вы
        обычно устанавливаете сами.



                 Переопределение используемых по умолчанию атрибутов
        -----------------------------------------------------------------

             При создании новых оконных типов, производных от TWindow, вы
        обычно определяете  новый  конструктор Init (особенно если хотите
        получить атрибут создания,  отличных от используемого по  умолча-
        нию). Если вы хотите переопределить Init, то можете заново задать
        атрибуты объекта,  непосредственно изменяя поле Attr после вызова
        Init.

             Если вы переопределили Init,  убедитесь,  что первое, что он
        делает - это вызов наследуемого метода TWindow.Init, устанавлива-
        ющего используемые  по умолчанию атрибуты.  Затем вы можете изме-
        нить по своему выбору любой из атрибутов. Например, типичное окно
        может определять конструктор Init,  который устанавливает атрибут
        Menu:

             constructor TWindowType.Init(AParent: PWindowsObject;
                                          ATitle: PChar);
             begin
                inherited Init(AParent, ATitle);
                Attr.Menu := LoadMenu(HInstance, 'TheMenu');
                AChildWindow := New(PChildWindowType, Init(@Self,
                                    'Заголовок дочернего окна'));
                List1 := New(PListBox, Init(@Self, id_ListBox,
                             201, 20, 20, 180, 80));
                    .
                    .
                    .
             end;

                              Атрибуты порожденного окна
        -----------------------------------------------------------------

             Конструктор TWindowType отвечает за построение его  дочерних
        объектов, таких  как всплывающие окна и блоки списка.  Тип порож-
        денного окна, в свою очередь, может устанавливать атрибуты в сво-
        ем собственном конструкторе Init:

             constructor TChilwWindowType.Init(AParent: PWindowsObject;
                                          ATitle: PChar);
             begin
                inherited Init(AParent, ATitle);
                with Attr do
                begin
                   Style := Style or ws_PopupWindow or ws_Caption;
                   X := 100; Y := 100; W := 300; H := 300;
                end;
             end;

             В качестве альтернативы  вы  можете  не  определять  потомка
        типа окна,  а сначала построить объект окна,  а затем переустано-
        вить его атрибуты (все это в конструкторе Init  порождающего  ок-
        на):

             constructor TWindowType.Init(AParent: PWindowsObject;
                                          ATitle: PChar);
             begin
                inherited Init(AParent, ATitle);
                Attr.Menu := LoadMenu(HInstance, 'TheMenu');
                AChildWindow := New(PChildWindowType, Init(@Self,
                                    'Заголовок дочернего окна'));
                with Attr do
                begin
                   Style := Style or ws_PopupWindow or ws_Caption;
                   X := 100; Y := 100; W := 300; H := 300;
                end;
                    .
                    .
                    .
             end;

                               Создание элементов окна
        -----------------------------------------------------------------

             После построения   оконного   объекта   вам  нужно  сообщить
        Windows, что  требуется создать связанные с объектом элементы эк-
        рана. Это делается с помощью вызова MakeWindow объекта приложения
        и передачи ему в качестве параметра указателя на объект окна.

             if Application^.MakeWindow(AWindow) <> nil then
                        { успешное создание }
             else       { неуспешное создание }

             MakeWindow вызывает два важных метода: ValidWindow и Create.
        ValidWindow проверяет успешность построение объекта окна,  прове-
        ряя поле Status.  Если по каким-либо причинам конструктор  завер-
        шился неуспешно,  то MakeWindow возвращает nil.  При успешном вы-
        полнении конструктора MakeWindow переходит на метод Create  окон-
        ного объекта.

             Create -  это  метод,  который фактически сообщает Windows о
        создании элемента  экрана.  Если  Create  завершается   неудачно,
        MakeWindow возвращает nil. В противном случае возвращается указа-
        тель на оконный объект. Для работы с элементом экрана Create так-
        же устанавливает поле HWindow.

             Хотя этот метод фактически создает элемент экрана, вы обычно
        не можете вызывать Create явно.  Основное окно приложения автома-
        тически создается      при      запуске     программы     методом
        TApplication.InitInstance.

             Все прочие окна приложения являются дочерними окнами,  прямо
        или косвенно порождаемыми основным окном,  а дочерние окна созда-
        ются обычно в методе SetupWindow или в  его  порождающих  оконных
        объектах, либо с помощью MakeWindow динамически на этапе выполне-
        ния.

                   Примечание: Дочерние окна и SetupWindow описываются  в
              Главе 9 "Интерфейсный объекты".

             В общем  случае  порождающие  окна обычно вызывают для своих
        дочерних окон методы Init и MakeWindow. Атрибуты оконного объекта
        обычно устанавливаются  их  методами  объекта  порождающего окна.
        Поскольку основное окно приложения не  имеет  порождающего  окна,
        объект приложения строит и создает его при запуске приложения.

                            Задание атрибутов регистрации
        -----------------------------------------------------------------

             В ходе инициализации оконного объекта путем заполнения  поля
        объекта Attr вы можете установить несколько атрибутов окна, такие
        как его стиль, расположение и меню. Эти атрибуты используются для
        создания соответствующего оконного элемента,  поэтому они называ-
        ются атрибутами создания.

             Другие атрибуты, включая фоновый цвет, пиктограмму представ-
        ления и курсора "мыши",  более тесно связаны с данным типом окон-
        ного объекта и не могут изменяться в ходе работы  программы.  Эти
        присущие окну атрибуты называются атрибутами регистрации, так как
        они устанавливаются при регистрации класса окна в Windows.


                                     Классы окон
        -----------------------------------------------------------------

             С каждым  типом оконного объекта связан список атрибутов ре-
        гистрации, которые называются классом окна.  Список атрибутов ре-
        гистрации во  многом напоминает список атрибутов создания,  запи-
        санных в поле записи Attr объекта окна.  Однако, атрибуты регист-
        рации сохраняются в записи с именем TWndClass,  который определя-
        ется и поддерживается Windows.

             Процесс связи класса окна с типом оконного объекта называет-
        ся регистрацией класса окна. ObjectWindows автоматизирует процесс
        регистрации. Таким образом, если вы хотите изменить какую-либо из
        используемых по  умолчанию  характеристик  объекта,  то можете не
        беспокоиться о классе регистрации окна.

             Поля записи TWndClass и их типы перечислены в следующей таб-
        лице:

                            Атрибуты регистрации окна        Таблица 10.2
        +-------------------------+-------------------+-----------------+
        |    Характеристика       | Поле              | Тип             |
        +-------------------------+-------------------+-----------------|
        |    стиль класса         | style             | Word            |
        |    пиктограмма          | hIcon             | HIcon           |
        |    курсор               | hCursor           | HCursor         |
        |    фоновый цвет         | hbrBackground     | HBrush          |
        |    меню по умолчанию    | lpszMenuName      | PChar           |
        +-------------------------+-------------------+-----------------+

                                Поля стиля класса

             Это поле стиля отличается от атрибута стиля окна (ws_),  за-
        даваемого при  инициализации  окна,  поскольку  задает поведение,
        присущее операциям окна (в отличие от их визуального  представле-
        ния). Это  поле  может  заполняться  комбинацией  констант  стиля
        (cs_).

             Например, cs_HRedraw приводит к повторному отображению  окна
        при изменении его размера по горизонтали;  cs_DoubleClk позволяет
        окну получать  сообщения  о  двойном   нажатии   кнопки   "мыши";
        cs_NoClose предотвращает  выбор  параметра Close меню Control,  а
        cs_ParentDC дает окну контекст дисплея порождающего окна.

                                Поле пиктограммы

             Это поле содержит описатель пиктограммы, которое использует-
        ся для представления окна в его минимизированном состоянии. Обыч-
        но  для  представления основного окна программы выбирается ресурс
        пиктограммы.

                                  Поле курсора

             Поле hCursor содержит описатель курсора, который использует-
        ся для представления указателя "мыши" при позиционировании его  в
        окне.

                               Поле фонового цвета

             Это поле задает фоновый цвет окна.  Для большинства приложе-
        ний используется стандартный назначаемый по умолчанию цвет  окна,
        который может устанавливаться пользователем в управляющей панели.
        Однако вы можете путем установки этого поля в описатель  физичес-
        кой кисти  подставить конкретный цвет.  Либо вы можете установить
        любое из значений цветов Windows,  такие как color_ActiveCaption.
        К любому значению цвета всегда добавляйте 1.

                      Поле используемого по умолчанию меню

             Это поле  указывает на имя ресурса меню,  которое служит ис-
        пользуемым по умолчанию меню для данного класса.  Например,  если
        вы определите  тип  EditWindow,  который всегда имеет стандартное
        меню редактирования,  то можете задать здесь это меню. Это устра-
        нит необходимость задания меню в методе Init.  Если данный ресурс
        меню имеет идентификатор 'MyMenu',  вы можете установить это поле
        следующим образом:

             AWndClass.IpszMenuName := 'MyMenu';


                    Используемые по умолчанию атрибуты регистрации
        -----------------------------------------------------------------

             Тип TWindow определяет класс  окна  'TurboWindow'  с  пустой
        пиктограммой, курсором-стрелкой  и  стандартным цветом окна.  Ис-
        пользуемый по умолчанию класс ObjectWindows  (TurboWindow)  имеет
        следующие атрибуты:

             * стиль:  cs_HRedraw  or  cs_VRedraw  (повторное отображение
               после каждого изменения размера);

             * пиктограмма: idi_Application (пустой прямоугольник);

             * курсор: idc_Arrow (стандартная стрелка Windows);

             * фоновый цвет: HBrush(color_Window + 1);

             * меню по умолчанию: nil.

                              Регистрация нового класса
        -----------------------------------------------------------------

             Чтобы изменить  атрибут  регистрации,  такой  как курсор или
        пиктограмму, вам  нужно  написать  два  метода  -  GetClassName и
        GetWindowClass - и определить новый класс окна. Каждый раз, когда
        вы изменяете атрибуты регистрации, вам нужно изменить имя класса.
        Если класс регистрации с  данным  именем  уже  зарегистрирован  в
        Windows, другие классы с тем же именем класса регистрироваться не
        будут - они получат атрибуты уже зарегистрированного класса.


                                Изменение имени класса
        -----------------------------------------------------------------

             GetClassName -  это функция,  которая возвращает имя (PChar)
        класса окна.  TWindow.GetClassName возвращает 'TurboWindow',  имя
        используемого по   умолчанию  класса  окна.  TWindow.GetClassName
        возвращает 'TurboWindow' - имя используемого по умолчанию  класса
        окна:

             function TWindow.GetClassName: PChar;
             begin
               GetClassName := 'TurboWindow';
             end;

             Чтобы определить тип объекта окна с именем IBeamWindow,  ко-
        торый использует  вместо  стандартной  стрелки I-образный курсор,
        переопределите наследуемый метод следующим образом:

             function TBeamWindow.GetClassName: PChar;
             begin
               GetClassName := 'IBeamWindow';
             end;

                   Примечание: Имя класса не обязательно должно соответс-
              твовать имени объектного типа.

             Имя класса должно быть уникальным.

                       Определение новых атрибутов регистрации
        -----------------------------------------------------------------

             Чтобы отклониться от стандартных  характеристик,  вы  должны
        заполнить поля  записи  TWndClass  с  различными данными в методе
        GetWindowClass.

             GetWindowClass воспринимает в качестве  аргумента-переменной
        запись TWndClass  и заполняет ее поля новыми атрибутами регистра-
        ции. Когда вы определяете новый метод GetWindowClass, вам следует
        всегда сначала  для установки значений по умолчанию вызывать нас-
        ледуемый метод TWindow.GetWindowClass,  а затем устанавливать по-
        ля, которые вы хотите изменить.

             Например, в поле hCursor хранится описатель ресурса курсора.
        Для IBeamWindow определяется метод GetWindowClass:

             procedure IBeamWindow.GetWindowClass(var AWndClass:
                                                  TWndClass);
             begin
               inherited GetWindowClass(AWndClass);
               AWndClass.hCursor := LoadCursor(0, idc_IBeam);
             end;

                   Примечание: idc_Beam  - это константа,  представляющая
              один из курсоров Windows.

             Кроме окон,  диалоговым окнам (не диалоговым блокам) необхо-
        димо регистрировать классы окна (см. Главу 11). Диалоговым блокам
        и управляющим элементам классы окон не требуются.


                        Использование специализированных окон
        -----------------------------------------------------------------

             ObjectWindows предусматривает два потомка TWindow, являющих-
        ся специализированными окнами для редактирования текста.  Объект-
        ный тип TEditWindow обеспечивает простой текстовый  редактор,  не
        обладающий  возможностями чтения из файла или записи в него.  Тип
        TFileWindow,  наследующий из TEditWindow,  обеспечивает текстовый
        редактор с возможностями чтения/записи файлов.

             Эти объекты можно использовать непосредственно как стандарт-
        ные компоненты ваших приложений. Вы можете также построить произ-
        водные от них типы и создать свои собственные  специализированные
        редакторы. Программы или модули, использующие окна редактирования
        или файловые  окна,  должны  включать в свой оператор uses модуль
        OStdWnds.

                          Использование окон редактирования
        -----------------------------------------------------------------

             Окно редактирования  -  это окно с управляющим элементом ре-
        дактирования, заполняющим его область  клиента.  TEditWindow.Init
        инициализирует поле Editor окна редактирования,  чтобы оно указы-
        вало на    управляющий    элемент     объекта     редактирования.
        TEditWindow.SetupWindow устанавливает  размеры  управляющего эле-
        мента редактирования в соответствии с  областью  клиента  окна  и
        создает экранный управляющий элемент редактирования.

             Метод WMSize  обеспечивает  изменение  размера  управляющего
        элемента редактирования при изменении  размера  его  окна.  Метод
        WMSetFocus обеспечивает,  что  управляющий элемент редактирования
        получает фокус ввода при получении окном сообщения wm_SetFocus.


             Показанная ниже программа EditWindowTester  использует  окно
        редактирования, чтобы  пользователь  мог  редактировать текст для
        простой (нефункциональной) электронной почты.

        +-----------------------------------------------------------+-+-+
        |#=#XXXXXXXXXXXXXXXXXXXXEdit Window TesterXXXXXXXXXXXXXXXXXX|^|v|
        +-----------------------------------------------------------+-+-|
        | Edit   Text                                                   |
        +---------------------------------------------------------------|
        | Кого это может касаться:                                      |
        |                                                               |
        | Я хотел бы зарегистрировать жалобу по поводу попугая, которого|
        | я купил в вашем магазине полгода назад. Он умер.              |
        |                        +-----------------------------------+  |
        | Брюс                   |#=#@@@@@@Передано сообщение@@@@@@@@|  |
        |                        +-----------------------------------|  |
        |                        |                                   |  |
        |                        |   6 строк послано                 |  |
        |                        |          +------------+           |  |
        |                        |          |####OK######|           |  |
        |                        |          +------------+           |  |
        |                        +-----------------------------------+  |
        |                                                               |
        +---------------------------------------------------------------+

             Рис. 10.2 Окно редактирования.

             program EditWindowTester;
             {$R EWNDTEST.RES}
             uses ODialogs, WinTypes, WinProcs, Strings, OStdWnds;
             const cm_sendText = 399;
             type
               TestApplication = object(TApplication)
                  procedure InitMainWindow; virtual;
               end;

               PMyEditWindow = ^MyEditWindow;
               MyEditWindow = object(TEditWindow)
                  constructor Init(AParent: PWindowsObject;
                                   ATitle: PChar);
                  procedure CMSendText(var Msg: TMessage); virtual
                                   cm_First + cm_SendText;
               end;

             constructor MyEditWindow.Init(AParent: PWindowsObject;
                                   Atitle: PChar);
             begin
               inherited Init(AParent, ATitle);
               Attr.Menu := LoadMenu(HInstance, MakeIntResource(102));
             end

             procedure MyEditWindows.CMSendText(var Msg: TMessage);
             var
               Lines: Integer;
               TestString: string[3];
               Text: array[020] of Char;
             begin
               Lines := Editor^.GetNumLines;
               Str(Lines, TextString);
               StrCat(Text, ' строк послано');
               MessageBox(HWindow, @Text, 'Передано сообщение', mb_Ok);
             end;

             procedure TestApplication.InitMainWindow;
             begin
               MainWindow := New(PMyEditWindow, Init(nil,
            'Окно редактирования - попробуйте набор и редактирование'));
             end;

             var TestApp: TestApplication;
             begin
               TestApp.Init('EditWindowTester');
               TestApp.Run;
               TestApp.Done;
             end.

                             Использование файловых окон
        -----------------------------------------------------------------

             Файловое окно  -  это  окно редактирования с дополнительными
        возможностями, позволяющими считывать и записывать данные в файл.
        TFileWindow.Init воспринимает в качестве аргумента заголовок окна
        и устанавливает поле FileDialog таким образом, чтобы оно указыва-
        ло на файловый диалоговый объект.


             Для работы с файлами TFileWindow имеет четыре метода. Методы
        Open, Save и SaveAs для вывода пользователю  подсказки  с  именем
        файла используют поле TFileWindow.FileDialog (см.  Главу 11). Ме-
        тод New дает пользователю возможность отмены, если редактирование
        нового файла  приведет к потере изменений текущего текста.  Чтобы
        дать пользователю возможность доступа к  этим  методам,  создайте
        свое меню со следующими идентификаторами меню:

             Методы и идентификаторы меню файлового окна     Таблица 10.3
        +---------------------+-----------------------------------------+
        |    Метод            |    Идентификатор меню для вызова        |
        +---------------------+-----------------------------------------|
        |    New              |    cm_FileNew                           |
        |    Open             |    cm_FileOpen                          |
        |    Save             |    cm_FileSave                          |
        |    SaveAs           |    cm_FileSaveAs                        |
        +---------------------+-----------------------------------------+

             Вы можете  использовать  файловые  окна  без модификации как
        простые автономные текстовые редакторы. Однако, иногда желательно
        создать производные от TFileWindow типы и обеспечить дополнитель-
        ные функциональные  возможности.  Например,  можно  предусмотреть
        средство поиска.  Помните, что вы все равно будете иметь доступ к
        управляющему элементу редактирования TFileWindow.Editor.

                              Прокрутка содержимого окон 
        -----------------------------------------------------------------

             В большинстве случаев для прокрутки текущей области просмот-
        ра пользователи используют полосы прокрутки вдоль  края  окна.  В
        отличие от стандартных управляющих элементов типа полос прокрутки
        полосы прокрутки окна являются частью самого окна.

             ObjectWindows управляет прокруткой окна, предоставляя каждо-
        му оконному  объекту  поле  Scroller,  которое может указывать на
        объект TScroller. Объект прокрутки TScroller обеспечивает автома-
        тизированный способ прокрутки в окнах текста и графики. Кроме то-
        го, TScroller может прокручивать окна, когда пользователь переме-
        щает "мышь"  за область клиента окна (это называется автоматичес-
        кой прокруткой и действует даже для окон,  которые не имеют полос
        прокрутки).


                             Что такое объект прокрутки?
        -----------------------------------------------------------------

             TScroller содержит значения,  определяющие, насколько должно
        прокручивается окно.  Эти  значения  записываются  в полях XUnit,
        YUnit,  XLine,  YLine,  XRange,  YRange,  XPage и  YPage  объекта
        TScroller.  Поля,  начинающиеся с буквы X,  представляют горизон-
        тальные значения, а начинающиеся с буквы Y - вертикальные.

                                Единицы прокрутки

             Единица прокрутки определяет минимальную величину прокрутки.
        Она задается в наименьших единицах устройства (обычно в элементах
        изображения, но может зависеть от текущего  режима  отображения),
        на которые  вы  можете  выполнять  прокрутку в горизонтальном или
        вертикальном направлении. Это значение обычно основывается на ви-
        де выводимой на экран информации.

             Например, если вы выводите текст с шириной символа 8 элемен-
        тов изображения и высотой 15,  то в  качестве  значений  XUnit  и
        YUnit полезно задать, соответственно, 8 и 15.

                           Строки, страницы и диапазон

             Другие атрибуты  прокрутки  - строка,  страница и диапазон -
        выражаются в единицах прокрутки.  Значения Line (строка)  и  Page
        (страница) - это число единиц, на которые выполняется прокрутка в
        ответ на запрос пользователя.  Запрос может  иметь  форму  щелчка
        кнопкой "мыши" на концах полосы прокрутки (построчная прокрутка).
        Щелчок "мышью" в самой полосе прокрутки (но не на маркере  полосы
        прокрутки) позволяет  выполнять постраничную прокрутку.  Атрибуты
        диапазона (XRange,  YRange) представляют общее число  единиц,  на
        которое можно выполнять прокрутку. Обычно этот диапазон определя-
        ется на основе размера редактируемого документа.


                            Типичный объект прокрутки

             В качестве примера рассмотрим текстовое окно редактирования.
        Если вы хотите вывести на экран текстовый файл, имеющий 400 строк
        текста с границей 80 символов и 50 строками на странице, то можно
        выбрать следующие значения:

                 Типичные значения для окна редактирования   Таблица 10.4
        +-----------------+-------------+-------------------------------+
        |    Поле         |   Значение  |            Смысл              |
        +-----------------+-------------+-------------------------------|
        |    XUnit        |    8        |  ширина символа               |
        |    YUnit        |   15        |  высота символа               |
        |    XLine, YLine |    1        |  1 единица на строку          |
        |    XPage        |   40        |  40 символов по горизонтали на|
        |                 |             |  страницу                     |
        |    YPage        |   50        |  50 символов по  вертикали  на|
        |                 |             |  страницу                     |
        |    XRange       |   80        |  максимальный   горизонтальный|
        |                 |             |  диапазон                     |
        |    YRange       |  400        |  максимальный вертикальный ди-|
        |                 |             |  апазон                       |
        +-----------------+-------------+-------------------------------+

             Объект TScroller с данными  значениями  позволяет  выполнять
        построчную или постраничную прокрутку.  С помощью полос прокрутки
        или автоматической прокрутки выполняется просмотр всего файла.

                              Значения по умолчанию

             По умолчанию XLine и YLine имеют значение 1, так что без яв-
        ной необходимости  устанавливать  их  в другие значения не нужно.
        Для установки значений прокрутки на страницу также существует ис-
        пользуемая по умолчанию схема, согласно которой страница прокрут-
        ки будет соответствовать текущей высоте или ширине области клиен-
        та окна (в зависимости от направлений прокрутки).  Если вы не хо-
        тите переопределить данный механизм, переустанавливать эти значе-
        ния не требуется.


                          Задание для окна объекта прокрутки
        -----------------------------------------------------------------

             Чтобы задать для окна объект прокрутки,  постройте  в  конс-
        трукторе своего оконного объекта объект TScroller и присвойте его
        полю Scroller.  Вам нужно установить начальный размер  единицы  и
        диапазона, но позднее вы можете их изменить.

             При использовании объекта прокрутки для автоматической прок-
        рутки полосы прокрутки не  требуются,  но  многие  прокручиваемые
        окна их имеют.  Чтобы добавить в окно полосы прокрутки,  добавьте
        в поле Attr.Style ws_VScroll, ws_HScroll (или то и другое).

             Приведем пример конструктора для текстового окна  редактиро-
        вания:

             constructor TTextWindow.Init(AParent: PWindowsObject;
                                          ATitle: PChar);
             begin
               inherited Init(AParent, ATitle);
               Attr.Style := Attr.Style or ws_VScroll or ws_YScroll;
               Scroller := New(PScroller, Init(@Self, 8, 15, 80, 400));
             end;

             В качестве  аргументов TScroller воспринимает прокручиваемое
        окно и начальные значения для полей XUnit, YUnit, XRange и YRange
        соответственно. Атрибуты  строки  и страницы получают значения по
        умолчанию.

             После вывода окна на экран содержимое  его  области  клиента
        можно прокручивать  вертикально  и  горизонтально,  используя для
        этого полосу прокрутки или автоматическую прокрутку.  Метод  Pant
        окна просто рисует на экране графическую информацию,  необходимую
        для уведомления о прокрутке. Как описывается в конце этого разде-
        ла, метод  Paint можно оптимизировать для вывода только части ри-
        сунка.

                                   Пример прокрутки
        -----------------------------------------------------------------

             Scroll - это полное приложение с графическим выводом, допус-
        кающим прокрутку. Показанная ниже программа рисует последователь-
        ность прямоугольников,  затем увеличивает их размер,  так что вся
        картинка не умещается в область клиента  окна,  отображенного  на
        обычном экране VGA.  С помощью полос прокрутки вы можете просмат-
        ривать различные части  рисунка  или  автоматически  прокручивать
        картинку, удерживая нажатой левую кнопку "мыши" и перемещая ее из
        области клиента.

             program Scroll;

             uses Strings, WinTypes, WinProcs, OWindows;

             type
               TScrollApp = object(TApplication)
                   procedure InitMainWindow; virtual;
               end;

               PScrollWindow = ^TScrollWindow;
               TScrollWindow = object(TWindow)
                 constructor Init(ATitle: PChar);
                 procedure Paint(PaintDC: HDC;
                                 var PaintInfo: TPaintStruct); virtual;
               end;

             procedure TScrollApp.InitMainWindow;
             begin
               MainWindow := New(PScrollWindow, Init('Boxes'));
             end;

             constructor TScrollWindow.Init(ATitle: PChar);
             begin
               inherited Init(nil, ATitle);
               Attr.Style := Attr.Style or ws_VScroll or ws_HScroll;
               Scroller := New(PScroller, Init(@Self, 8, 15, 80, 60));
             end;

             procedure TScrollWindow.PAint(PaintDC: HDC;
                                           var PaintInfo: TPaintStruct);
             var X1, Y1, I: Integer;
             begin
               for I := 0 to 49 do
               begin
                 X1 := 10 + I*8;
                 Y1 := 30 + I*5;
                 Rectangle(PaintDC, X1, Y1, X1 + X1, X1 + Y1 * 2);
               end;
             end;

             var ScrollApp: TScrollApp;

             begin
               ScrollApp.Init('ScrollApp');
               ScrollApp.Run;
               ScrollApp.Done:
             end.


                         Запрещение автоматической прокрутки
        -----------------------------------------------------------------

             Объект TScroller может по умолчанию выполнять автоматическую
        прокрутку, но установка поля AutoMode TScroller в значение  False
        отключает это  средство.  Окно-владелец может сделать это в конс-
        трукторе после построения объекта TScroller:

             Scroller := New(PScroller, Init(@Self, 8, 15, 80, 60));
             Scroller^.AutoMode :=False;

             Если AutoMode  равно  False,  то прокрутка может выполняться
        только с помощью полос прокрутки.  Полезная особенность автомати-
        ческой прокрутки состоит в том, что чем дальше вы сдвинете "мышь"
        от области клиента окна,  тем быстрее будет происходить прокрутка
        окна.  В  зависимости от удаления мыши приращение прокрутки будет
        обратно пропорционально значению параметра строк и прямо  пропор-
        ционально значению параметра страницы.

                             Отслеживание полос прокрутки
        -----------------------------------------------------------------

             В дополнение к автоматической  прокрутке,  приведенный  выше
        пример программы будет отслеживать запросы на прокрутку,  сдвигая
        при нажатой кнопке "мыши" маркер полосы прокрутки. Другими слова-
        ми картинка  сдвигается  уже при нажатой кнопке.  Эта особенность
        дает действительную обратную связь, и пользователь может сдвигать
        нужную часть изображения не отпуская кнопку "мыши".

             Однако, в некоторых случаях этот эффект нежелателен.  Напри-
        мер,  если вы просматриваете большой текстовый файл, такое отсле-
        живание может замедлить работу, поскольку возникает необходимость
        постоянно считывать информацию с диска и отображать порцию текста
        для каждого движения "мыши". В такой ситуации лучше отменить этот
        эффект:

             Scroller^.TrackMode:=False;

             Теперь никакой прокрутки не происходит до момента отпускания
        кнопки на мыши, и в области клиента будет лишь однократно показа-
        на нужная часть картинки.


                       Модификация единиц прокрутки и диапазона
        -----------------------------------------------------------------

             В приведенных  выше примерах мы предполагали,  что к моменту
        построения TScroller известны значения единиц  и  диапазонов.  Во
        многих  случаях  эта информация неизвестна или может меняться при
        изменении размеров отображаемой информации.  В этом случае  может
        потребоваться установить или изменить значения диапазона (а может
        быть и единиц) позднее.  Если значения заранее неизвестны,  то их
        можно задать как 0 в конструкторе TScroller.

                               Изменение диапазона

             Метод SetRange  воспринимает  два  целочисленных аргумента -
        число горизонтальных и вертикальных  единиц,  которые  определяют
        общий диапазон  прокрутки.  Метод  SetRange должен использоваться
        при изменении размеров картинки. Например, при подготовке изобра-
        жения  картинки шириной 1 0 единиц и высотой 300,  данная команда
        установит диапазон прокрутки надлежащим образом:

             Scroller^.setRange(100, 300);

                           Изменение единиц прокрутки

             Если при инициализации объекта TScroller единицы неизвестны,
        то их значения могут быть установлены непосредственно перед прок-
        руткой.  Например,  они  могут  быть  установлены  методом   окна
        SetupWindow:

             procedure ScrollWindow.SetupWindow;
             begin
                TWindow.SetupWindow;
                Scroller^.XUnit:=10;
                Scroller^.YUnit:=20;
             end;

                             Изменение позиции прокрутки
        -----------------------------------------------------------------

             Windows с  помощью  методов ScrollTo и ScrollBy может выпол-
        нять принудительную прокрутку. Каждый из них воспринимает два це-
        лочисленных   аргумента  в терминах горизонтальных и вертикальных
        единиц прокрутки.  Например,  если нужно переместиться  к  левому
        верхнему углу картинки, то используется ScrollTo:

             Scroller^.ScrollTo(0, 0);

             Приведем другой пример. Если картинка имеет длину 400 единиц
        в вертикальном направлении,  то позицию прокрутки можно  перемес-
        тить к середине картинки следующим образом:

             Scroller^.ScrollTo(0, 200);

             Метод ScrollBy  может перемещать позицию просмотра на задан-
        ное число единиц вверх,  вниз,  влево или  вправо.  Отрицательные
        значения осуществляют сдвиг к левому верхнему углу, а положитель-
        ные - к правому нижнему. Если нужно сместиться на 10 единиц впра-
        во и на 20 единиц вниз, то это можно сделать командой:

             Scroller^.ScrollBy(10, 20);

                             Установка размеров страницы
        -----------------------------------------------------------------

             По умолчанию размер страницы (XPage и YPage) устанавливается
        в  соответствии  с  размером области клиента окна.  При изменении
        размеров окна механизм прокрутки учитывает эту информацию.  Метод
        окна  WMSize вызывает метод прокрутки SetPageSize,  который уста-
        навливает поля объекта XPage и YPage на основании текущих  разме-
        ров  области  клиента  окна и значений XUnit и YUnit.  Для отмены
        этого механизма и непосредственной установки размеров страницы вы
        должны  переписать  унаследованный метод объекта окна WMSize и не
        вызывать SetPageSize:

             procedure TTestWindow.WMSize(var Msg: TMessage);
             begin
               DefWndProc(Msg);
             end;

             Затем вы  можете  непосредственно установить XPage и YPage в
        конструкторе окна (или в производном конструкторе TScroller):

             constructor ScrollWindow.Init(AParent:PWindowsObject;
                                           ATitle: PChar);
             begin
               inherited Init(AParent, ATitle);
               Attr.Style:=Attr.Style or ws_VScroll or ws_HScroll;
               Scroller:=New(PScroller, Init(@Self, 8, 15, 80, 400));
               Scroller^.XPage:=40;
               Scroller^.YPage:=100;
             end;

                       Оптимизация методов Paint для прокрутки
        -----------------------------------------------------------------

             В приведенном  выше примере рисуется 50 прямоугольников,  но
        не делается даже попытки определить,  все ли прямоугольники видны
        в области клиента окна.  Это может привести к излишним усилиям на
        дорисовку невидимых изображений. Для оптимизации рисования в окне
        методом Paint можно использовать метод TScroller.IsVisibleRect.

             Приведенный ниже    метод    ScrollWindow.Paint   использует
        IsVisibleRect для определения,  нужно ли вызывать функцию Windows
        Rectange. Rectange  воспринимает аргументы в единицах устройства,
        а VisibleRect в единицах прокрутки.  С этой целью вершина прямоу-
        гольника  X1  Y1  и  ширина  прямоугольника  (X2-X1) и его высота
        (Y2-Y1) должны быть разделены на соответствующее число единиц  до
        вызова IsVisibleRect:

             procedure TScrollWindow.Paint(PaintDC: HDC; var PaintInfo:
                                           TPaintStruct);
             var
               X1, Y1, X2, Y2, I: Integer;
             begin
                for I:=0 to 49 do
                begin
                   X1 := 10 + I * 8;
                   Y1 := 30 + I * 5;
                   X2 := X1 + X1;
                   Y2 := X1 + Y1 * 2;
                   if Scroller^.IsVisibleRect(X1 div 8,
                                              Y1 div 15, (X2-X1) div 8,
                                              (Y2-Y1) div 15) then
                   Rectangle(PaintDC, X1, Y1, X2, Y2);
                 end;
             end;
                              Назад | Содержание | Вперед
Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...