|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Килограмм пиктограммДмитрий Румянцев Тот, кто приступил к изучению разработки программ с помощью Delphi, никогда за всю свою жизнь не создав ни одной программы (даже самой маленькой), имеет определенные преимущества перед теми, кто несет на своих плечах багаж опыта работы с кодом в классических средах разработки программ. Новички очень спокойно воспринимают идею "визуального программирования", и ничто не омрачает их счастливые беззаботные сны. Напротив того, тот, кто хорошо знаком с концепцией модульного программирования, испытывает известный дискомфорт от того, что не может охватить взглядом весь проект целиком. В самом деле, ну не бывает же так, чтобы вся программа состояла из тех нескольких строк текста, которые вводятся при создании какого-нибудь обработчика события (например, обработчика события о нажатой кнопке). Действительно - не может программа, предназначенная для выполнения в среде Windows, состоять из нескольких строк текста (хотя бы даже и на Object Pascal). В связи с этим очевидным фактом, думается, имеет смысл несколько слов сказать о том, как же все-таки устроен проект в Delphi. Почти каждая программа, запущенная в среде Windows (да, собственно, в любой многозадачной ОС, поддерживающей стандарт графического пользовательского интерфейса), выполняется в главном окне программы - прямоугольной области экрана, имеющей заголовок и рамку (полагаю, для читателей журнала Upgrade ничего нового в этой волнующей концепции нет). При программировании в Delphi шаблон для главного окна программы создается автоматически при начале любого нового проекта. Этот шаблон называется формой. Более того, формы создаются автоматически для любого дополнительного окна программы - будь то диалоговые панели или дочерние окна в программах, поддерживающих многооконный интерфейс. В среде Delphi форма имеет вид прямоугольной панели серого цвета в крапинку (сетка выравнивания). На форме, собственно, демиург (в смысле - творец приложения) и размещает компоненты, выбираемые им из библиотеки визуальных компонентов (Visual Components Library - VCL). Проектом в терминах Delphi называется совокупность всех модулей и файлов ресурсов, используемых в процессе разработки приложения. Проект имеет единственный главный файл c расширением dpr (Delphi PRoject) и набор файлов со стандартным расширением pas, в которых хранятся модули - по одному для каждой формы (в простейшем случае в проекте имеется всего одна форма - для главного окна). В состав проекта входит также файл ресурсов (res-файл), имеющий тоже имя, что и dpr-файл, а также по файлу формы (расширение dfm - Delphi ForM) для каждого модуля (pas) - и с теми же именами. В dfm-файлах хранится описание интерфейсных элементов (кнопок, списков, меню, панелей инструментов...), размещенных на данной форме (нажав Alt-F12, можно увидеть текст текущего dfm-файла). При компиляции каждый модуль порождает объектный файл с расширением dcu (Delphi Compiling Unit, надо полагать), а главный dpr-файл - исполняемый файл Windows (с раширением exe). Таким образом, "дельфийский" "экзешник" - не стандартный выполняемый файл, который полностью загружается в оперативную память в момент запуска программы, а набор сегментов, которые подгружаются по мере необходимости, так что не стоит очень волноваться по поводу размеров порождаемых Delphi exe-файлов. И последнее. Настройки среды разработки Delphi применительно к текущему проекту хранятся в файле с расширением dof (что обозначает это расширение, неизвестно; может быть Delphi of Ours - Forever?) и тем же именем, что и dpr-файл. Взаимосвязь файлов проекта проиллюстрирована на рисунке. При создании проекта Delphi автоматически присваивает ему типовую пиктограмму (не лишенную определенной эстетической привлекательности). Оно бы, в общем-то, ничего, да вот проблема: в графический пользовательский интерфейс идею пиктограмм (в терминах Windows - иконок) ввели, дабы иметь некий графический образ, позволяющий отличать одно приложение от другого. Авторы Delphi, разумеется, предусмотрели возможность присваивания приложению собственной пиктограммы, отличной от типовой. Давайте посмотрим. Выберите пункт Project > Options, чтобы открыть окно Project Options (Параметры проекта). Щелкните закладку Application (Приложение). На вкладке вы обнаружите кнопку Load Icon, с помощью которой можно присвоить очередному разрабатываемому приложению уникальную пиктограмму, если только на вашем диске имеются специальные файлы пиктограмм (файлы с расширением ico). А если их там нет? На этот случай разработчики Delphi включили в состав пакета специальный графический редактор - не такой, конечно, мощный, как Adobe Photoshop, но для создания пиктограмм вполне сносный. Однако чего они не предусмотрели, так это того, что далеко не каждый человек, собирающийся создавать прикладные программы (впрочем, как и системные), обладает художественными талантами, позволяющими ему нарисовать пиктограмму (вы сами попробуйте-ка на поле форматом 32 x 32 пикселя изобразить хоть что-то осмысленное). Мд-а-а... Тупичок... А ведь на диске любого компьютера хранятся целые килотонны этих самых пиктограмм в виде так называемых ресурсов. Вопрос только в том, как их намыть побольше. Решено: сегодня мы будем разрабатывать маленькую программу, предназначенную для того, чтобы "одалживать" (как говаривал в таких случаях папаша Гекльбери Финна) готовые пиктограммы у программ, созданных профессиональными разработчиками. А уж затем, создав коллекцию пиктограмм, будем использовать их в своем проекте "как есть" или с внесенными при помощи "дельфийского" графического редактора небольшими изменениями.
Сезонный сбор пиктограмм 1. Начните новый проект (меню File > New Application). 2. Сохраните проект (кнопка Save All) в отдельном каталоге. Файлу с расширением pas в момент сохранения присвойте имя MainForm.pas (я советую всегда давать это имя для главного модуля проекта, поскольку в более обширных проектах модулей может быть очень много), а для файла проекта имя PictoCollect.dpr. 3. Заголовок формы (свойство Caption) придумайте, исходя из своего литературного вкуса. Я, например, назвал форму "Коллекция пиктограмм". 4. Разместите на форме компонент MainMenu (закладка Standard палитры компонентов). Delphi автоматически присвоит этому компоненту имя MainMenu1. 5. Щелкните дважды по компоненту
MainMenu1 и введите следующие пункты: Если вам не нравятся эти названия, можете после ввода, не закрывая окна редактора меню, изменить свойство Caption каждого пункта. 6. В окне редактора меню сделайте активным пункт Exit (если вы потеряли окно редактора меню, нажмите Alt+0 и в появившемся окне Window List дважды щелкните по строке Form1.MainMenu1, чтобы вывести на передний план редактор меню).
7. Щелкните свойство ShortCut этого пункта и вместо (None) введите Alt+X и нажмите Enter. Ого-го! В названии пункта добавилась запись Alt+X! Это Delphi подтвердила, что поняла ваше желание установить клавиатурный эквивалент для данного пункта меню. В принципе, свойство ShortCut можно установить, выбрав нужный клавиатурный эквивалент из длинного раскрывающегося списка, но, поскольку комбинация Alt+X в нем отсутствует, приходится ее вводить вручную. 8. Теперь дважды щелкните по самому пункту Exit и в шаблоне обработчика этого пункта введите: Close. 9. Установите для пунктов "Открыть" и "Закрыть" клавиатурные эквиваленты - соответственно Ctrl+O и Ctrl+S (сами пункты мы пока трогать не будем). 10. Теперь самое ответственное - размещение сетки строк (компонент StringGrid вкладки Additional). Дважды щелкните по этому компоненту в палитре компонентов, и он - компонент - тут же появится в центре формы. Установите его свойства следующим образом.
Сохраните проект, отойдите на пару метров от монитора и полюбуйтесь на дело рук своих. Какой замечательный вид приобрела наша форма - вся такая в клеточку (вернее, в прямоугольничек), просто загляденье. 11. Теперь для свойства GridLineWidth введите значение 0. Сетка пропала! То есть пропали линии, отмечающие границы ячеек (их ширина стала равной 0 пикселей), но сами ячейки сохранились.
12. Откройте закладку Dialogs палитры компонентов и разместите на форме компоненты OpenDialog и SaveDialog. Кстати, если вам не очень хочется постоянно щелкать по разным вкладкам палитры компонентов и искать на них нужные компоненты, откройте окно Components (меню View > Component List), где все компоненты упорядочены по алфавиту и выберите нужный (правда, почему-то в списке указывается не имя компонента, а его тип, но в конечном итоге это не столь важно, поскольку имя от типа отличается только наличием впереди стоящей латинской литеры "T").
Подсвойство ofHideReadOnly (оно устанавливается в True для обоих диалогов) убирает ненужный флажок "Только для чтения" в диалоговой панели открытия и сохранения файла. Подсвойство ofOverwritePrompt (компонент SaveDialog1) страхует от случайного затирания уже существующего файла (при сохранении файла с именем, которое уже есть в указанном каталоге, будет выдаваться предупреждение и просьба подтвердить необходимость сохранения). 14. Дважды щелкнув по свойству
Filter компонентов OpenDialog1 и SaveDialog1, введите
следующие маски.
Сделать форму активной можно путем выбора в раскрывающемся списке компонентов инспектора объектов строки Form1: TForm1. Но можно поступить более "визуально". Нажмите клавишу Shift и, не отпуская ее, щелкните по компоненту SaveDialog1 (он должен оставаться активным после предыдущих манипуляций, если почему-либо активен другой компонент, то щелкать мышью нужно по нему). Тем самым вы активизируете саму форму.
16. Выберите закладку Events инспектора объектов и дважды щелкните по событию OnCreate. Шаблон обработчика этого события, которое происходит всякий раз в момент создания формы, замените кодом, данным во врезке "Установка начального каталога". Что, собственно, мы сделали? А сделали мы так, что свойство InitialDir компонента OpenDialog1, которое отвечает за каталог, устанавливаемый при самом первом обращении к диалогу открытия файлов, будет хранить имя того каталога, в который инсталлирована Windows. Проще говоря, после старта программы и выбора пункта "Открыть", пользователь сразу же попадет в каталог Windows - настоящий "клондайк" файлов, хранящих пиктограммы. Спрашивается: а почему бы сразу в инспекторе объектов не установить значение InitialDir компонента OpenDialog1 равным C:\Windows? Сделать это, конечно же, проще пареной репы, но вся штука в том, что операционная система необязательно находится в этом каталоге. Поскольку сам пользователь выбирает имя каталога в момент инсталляции, то на каком-нибудь конкретном компьютере Windows вполне может оказаться в каталоге C:\Mustdie, так что имеет смысл прибегнуть к услугам специальной функции GetWindowsDirectory, которая всегда безошибочно вернет имя реального каталога Windows. Поскольку функция GetWindowsDirectory входит в семейство Windows API (сотен функций с самыми головоломными названиями и скудной документацией, которые корпорация Microsoft любезно предоставляет в распоряжение разработчиков - см. врезку "Процедуры и функции Windows API"), а разрабатывалось это семейство на языке Си (а то и на ассемблере), который не знает паскалевского типа string и всегда работает только со строками ASCIIZ, то в обработчике события OnCreate пришлось объявлять специальную переменную WinDir, представляющую из себя массив символов (array of char) и передавать ее в качестве параметра функции GetWindowsDirectory, указывая вторым параметром ее длину. Но так как свойство InitialDir имеет тип string, то во второй строке обработчика в операторе присваивания была использована специальная функция Delphi StrPas, которая приводит строку ASCIIZ к типу string. В противном случае на стадии трансляции компилятор выдал бы сообщение о несовместимости типов и прекратил дальнейшую компиляцию программы. 17. В редакторе кода переместите курсор в самое начало модуля MainForm.pas (в секцию uses) и после модуля Grids добавьте модуль ShellApi, в котором хранятся функции этой подгруппы, в том числе и ExtractIcon (не забудьте поставить запятую после имени модуля Grids): uses 18. Нажмите F12, чтобы вернуться к шаблону формы. Щелкните меню "Файл", чтобы открыть подменю (оно откроется так, как будто это уже готовая программа) и выберите пункт "Открыть". Услужливая Delphi тотчас отправит вас прямиком к шаблону обработчика этого пункта меню. Вместо пары begin-end введите "Основной код". Это самый гигантский фрагмент кода в нашей маленькой программе, но без него никак не обойтись. Не обойтись нам и без небольшого разъяснения. Загрузка пиктограмм из файла (его имя хранится в свойстве Filename компонента OpenDialog1) начинается в том случае, если пользователь нажмет кнопку OK в диалоге открытия файла. Тогда метод Execute вернет True. При помощи функции ExtractFileName переменной fName присваивается имя открываемого файла без полного имени каталога, в котором он размещен. В переменной pName, представляющей из себя ASCIIZ-строку, сохраняется полное имя файла (при помощи функции StrPCopy). Свойства Col и Row сетки строк хранят информацию о строке и столбце текущей ячейки, в которой должна быть размещена считываемая из файла пиктограмма. Свойства ColCount и RowCount служат для определения общего количества столбцов и строк в сетке соответственно. Так называемая типизованная константа CurItem хранит информацию об общем количестве всех пиктограмм, запутавшихся в расставленной сетке и увеличивается на единицу после загрузки очередной пиктограммы.
Сами пиктограммы загружаются с помощью API-функции ExtractIcon, возвращающей дескриптор пиктограммы. Загруженная пиктограмма сохраняется в очередном элементе массива Objects. Этот массив является неотъемлемой частью сетки строк и может хранить любой объект, являющийся наследником класса TObject.
Другой массив сетки строк - Cells используется для хранения текста, который будет выводиться вместе с пиктограммой. Для того, чтобы вставить в строку текста числовое значение (CurItem) и другую строку (fName), использована функция Format. Загрузка пиктограмм из файла
происходит до тех пор, пока очередной
дескриптор, полученный от функции ExtractIcon,
не станет равным 1 или 0. 19. Но наша сетка пока еще не в состоянии отображать загружаемые пиктограммы. Чтобы компонент TStringGrid отобразил что-либо кроме текста, нужно прописать обработчик его события OnDrawCell, отвечающего за отрисовку каждой ячейки сетки. Сделайте активным компонент
TStringGrid, выберите закладку Events Инспектора
объектов и дважды щелкните по событию
OnDrawCell. В шаблоне TForm1.IconsDrawCell введите
вместо пары begin-end текст, приведенный во
врезке "Прорисовка пиктограмм". Если вы недоумеваете, откуда взялись переменные Rect, Col и Row, то посмотрите внимательнее на параметры обработчика события. Большинство обработчиков событий в Delphi имеют только параметр Sender, но обработчик события OnDrawCell получает в дополнение информацию о колонке (Col) и строке (Row) сетки, размере ячейки (класс TRect, к которому принадлежит передаваемый в качестве параметра объект Rect, является составным типом, указывающим координаты левого верхнего и правого нижнего углов некоего прямоугольника), а также статусе (State) ячейки: ячейка может быть выбранной, то есть по ней щелкнули мышкой (gdSelected), находиться в фокусе (gdFocused) или в фиксированном состоянии (gdFixed). Обработчик события OnDrawCell вызывается для каждой видимой ячейки, так что можете не беспокоиться - все загруженные пиктограммы отобразятся как надо. Статус ячейки при этом нас не интересует. Пара слов о свойстве Canvas. Это свойство имеют многие компоненты Delphi. Оно представляет из себя сложный класс со множеством методов, позволяющих рисовать на элементе управления, имеющем это свойство, различные графические примитивы, а также битовые изображения, например, загруженные из JPEG-файла, или пиктограммы. (Как-нибудь в следующий раз мы коснемся подробнее волнующей темы создания графических образов.)
20. Итак, теперь у нас все готово.
Остается только создать обработчик
пункта меню "Сохранить" с тем, чтобы
иметь возможность сохранять на диске
позаимствованные у других программ
пиктограммы. 21. Вот и все. Сохраните проект на диске. Сортировка урожая Итак, наступило время разобраться с результатами наших усилий. Приступим. Запустите программу. Выберите пункт меню "Открыть" (или нажмите Ctrl+O, если вы указали этот клавиатурный эквивалент для данного пункта). Вы сразу же оказываетесь в каталоге Windows. Войдите в подкаталог System и в строке ввода "Имя файла" введите: pifmgr.dll (этот файл вы можете и не увидеть в окне диалога - он скрыт от нескромных глаз, но на диске он есть, поверьте мне). Нажмите Enter. Ну как? Файл pifmgr.dll (это библиотека менеджера PIF-файлов) одержит одну из самых богатых коллекций пиктограмм Windows. Вы можете также полазать по каталогам (не забудьте заглянуть в Program Files и его подкаталоги), загружая все новые и новые россыпи пиктограмм. Затем, придирчиво рассматривая запутавшиеся в вашей сетке пиктограммы и выбирая самые жирные экземпляры, вы можете, щелкнув по понравившейся, тут же сохранить ее на диске (пункт меню "Сохранить" или комбинация Ctrl+S).
Теперь, имея богатую кладовую пиктографического материала, вы можете назначать вашим приложениям понравившиеся пиктограммы. Но среда Delphi не ограничивается тем, что предоставляет разработчику не только возможность изменения пиктограммы основного приложения. Можно также для каждой формы (а в будущем мы будем создавать приложения, состоящие из двух, трех и более форм) назначать собственную, особенную пиктограмму. Для этого у формы существует свойство Icons, дважды щелкнув по которому, можно открыть окно Picture Editor и загрузить нужную пиктограмму.
Источник: http://www.computery.ru/upgrade/
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Copyright © "Internet Zone", info@izcity.com |