Убрать значки с "Рабочего стола" и создать ОЧЕНЬ быструю панель можно нажав на "трэе" (там, где часы) правую кнопку мыши. В меню выбрать "Панели инструментов" - поставить галочку "Рабочий стол" (если там такового нет - нажать "создать" и там выбрать "Рабочий стол"). При этом слева от трэя появится оная перемещаемая панелька со стрелкой, разворачивающей всё содержимое "Стола". После этого зайти в свойства экрана, вкладка "Эффекты" и там установить галку "Прятать содержимое стола, если...".
Всё! Вся фишка в том, что:
1. не захламляются ваши обои и
2. (самое главное!) через эту менюшку можно практически мгновенно добраться до ЛЮБОЙ точки вашего компа НЕ ЗАПУСКАЯ ПРИ ЭТОМ ВСЯКИХ "ПРОВОДНИКОВ", "КОММАНДЕРОВ" и т.д., (заодно и ресурсы экономятся!) Попробуйте, не пожалеете!
З.Ы. Для 98 Выньды. Для остальных - не знаю, есть ли там такое... ;)
Если вам надо постоянно обращаться к какому-то элементу Панели управления, то можно создать ярлык на "Рабочем столе" с такой командной строкой: "CONTROL.EXE desk.cpl,,3". Desk.cpl указывает вызываемую функцию "Панели управления". Например, appwiz.cpl откроет окно "Установка и удаления программ", а цифра следующая после двух запятых - номер нужной вкладки, начиная с нуля.
Отключение Error Reporting - навязчивого желания ХР постоянно отсылать сообщения разработчикам по случаю возникновения каждой ошибки (например, зависания того или иного приложения). Эти желания режутся на корню просто, но со вкусом:
В Контрольной Панели выбирается Система (System).
Закладка Advanced, далее - Error Reporting.
Включается опция Disable Error Reporting. Опцию But Notify me When critical errors occur (уведомлять меня о возникновении критических ошибок) я оставил, чтобы не пребывать в неведении по поводу неожиданных сбоев (пока бог миловал).
Для того, чтобы вставить любое слово рядом с часами нужно сделать следующее:
1. Зайти на "Панель управления", затем "Язык и стандарты"
2. Перейти на вкладку "Время"
3. В поле "Формат времени" измените формат на "ЧЧ:мм:сс оо" (оо набирать русскими), в полях обозначения времени до и после полудня введите ваше слово.
После установки Windows можно переместить системную папку "Мои документы" на рабочий диск, предназначенный для хранения всего содеянного пользователем (я обычно присваиваю ему метку тома Documents). Все необходимые изменения в реестре Windows сделает самостоятельно.
Вы пользуетесь пунктом контекстного (всплывающего) меню файла или папки "Отправить"? Если нет, то вы много теряете! Когда вы кликаете правой кнопкой на файле или папке выбираете пункт "Отправить" и там выбираете, куда хотите отправить, то выбранный вами файл копируется (перемещается) в ту папку, которую вы выбрали. Здорово, правда?
Так вот ярлычки для пунктов назначения (папок) хранятся в X:\%windir%\SendTo, т.е. если у вас Windows установлена на диске C, то путь к папке SendTo будет выглядеть так: C:\windows\SendTo. Очень удобно!
Так вот суть этого совета:
1) Вы создаёте ярлык для папки SendTo.
2) Извращаетесь над ним (меняете иконку, переименовываете).
3) Копируете этот ярлык в папку SendTo.
Теперь, когда вы много всего копируете(перемещаете) в определённую папку, то создаёте для неё ярлык и отправляете в Отправить! Очень удобно! Сам испытал!
По сути не совет, а прикол для тех кому понравился вариант использования функции "Послать".
Если вы работаете в Инете, то слово "Послать" у вас ассоциируется с отправкой письма, а если вы к тому же и гражданин бывшего СССР, то и ещё кое с чем 8). Берём, создаём ярлык ссылающийся на корзину и переименовываем его в "На...*". Потом переносим этот ярлык в папку ..windows/SendTo/
Пользуйтесь на здоровье.
---
Сноска * - зависит только от вашей фантазии :)
Примечание - большая часть написанного здесь текста с примерами взята по памяти (пару лет назад изучал достаточно подробно, поэтому может что-то в алгоритмах не работать - я ведь их не копировал откуда-то, а прямо тут же и писал, так что за синтаксические ошибки не пинайте) - на данный момент я активно OLE не пользуюсь (не из-за каких-то проблем с самим OLE, а из-за отсутствия надобности в его использовании в текущий момент).
Основные преимущества, благодаря которым OLE активно используется:
* Для вызывающей базы "по барабану" - какой тип вызываемой базы (DBF или SQL)
* Объектами вызываемой базы можно управлять всеми известными методами работы с объектами в 1С (т.е. со справочниками работают методы ВыбратьЭлементы(), ИспользоватьДату() и т.п., с документами - ВыбратьДокументы() и т.п.), соответственно, можно напрямую решить - стоит отрабатывать конкретные объекты базы OLE или пропустить их.
Пример 1. Присоединение к базе 1С через OLE.
БазаОле=СоздатьОбъект("V77.Application"); // Получаем доступ к OLE объекту 1С
Локальная версия (на одного пользователя): V77L.Application
Сетевая версия: V77.Application
Версия SQL: V77S.Application
Далее вместо термина "вызываемая база" будет написано просто "база OLE", а вместо термина "вызывающая база" - "местная база"
Теперь, мы должны знать несколько параметров для запуска базы OLE: Каталог базы, имя пользователя и пароль. Ну, наверное, еще и желание запустить 1С в монопольном режиме :)
Комментарий: функции СокрЛП() стоят в примере на случай, если пользователь захочет указанные выше переменные сделать в форме диалога, а проблема при этом состоит в том, что в алгоритм программа передаст полное значение реквизита (т.е. допишет в конце значения то количество пробелов, которое необходимо для получения полной длины строки (указана в свойствах реквизита диалога)).
Пример 2. Доступ к объектам базы OLE.
Запомните на будущее как непреложный факт:
1. Из местной базы в базу OLE (и, соответственно, наоборот) напрямую методом присвоения можно перенести только числовые значения, даты и строки ограниченной длины!!! Т.е. местная база поймет прекрасно без дополнительных алгоритмов преобразования полученного значения только указанные типы значений. Кроме того, под ограничением строк подразумевается проблемы с пониманием в местной базе реквизитов объектов базы OLE типа "Строка неограниченной длины". К этому же еще надо добавить и периодические реквизиты. Естественно, под методом присвоения подразумеваются и попытки сравнить объекты разных баз в одном условии (например, в алгоритмах "Если" или "Пока" и т.п.).
2. Есть проблемы при попытке перенести "пустую" дату - OLE может ее конвертировать, например, в 31.12.1899 года и т.п. Поэтому вам лучше заранее выяснить те значения, которые могут появится в местной базе при переносе "пустых" дат, чтобы предусмотреть условия преобразования их в местной базе.
A) Доступ к константам базы OLE:
Б) Доступ к справочникам и документам базы OLE (через функцию "CreateObject"):
После создания объекта справочника или документа к ним применимы все методы, касающиеся таких объектов в 1С:
Заметьте, что если вместо "Сообщить(Спр.Наименование)" вы укажете "Сообщить(Спр.ТекущийЭлемент())", то вместо строкового/числового представления этого элемента программа выдаст вам в окошке сообщение "OLE". Именно это я и имел в виду, когда говорил, что напрямую мало что можно перенести. Т.е. не будут работать следующие методы (ошибки 1С не будет, но и результат работы будет нулевой). Рассмотрим следующий пример:
Однако, сработает следующий метод:
Отсюда вывод: возможность доступа к объектам базы 1С через OLE требуется, в основном, только для определенной задачи - получить доступ к реквизитам определенного элемента справочника или документа. Однако, не забываем, что объекты базы OLE поддерживают все методы работы с ними, в т.ч. и "Новый()", т.е. приведем пример противоположный предыдущему:
В) Доступ к регистрам базы OLE (Не сложнее справочников и документов):
Г) Доступ к перечислениям базы OLE (аналогичен константе):
ЗначениеПеречисленияOLE = БазаОле.Перечисление.Булево.НеЗнаю; // :)
Заметьте, что пользы для местной базы от переменной "ЗначениеПеречисленияOLE" особо-то и нет, ведь подобно справочнику и документу перечисление также напрямую недоступно для местной базы. Пожалуй, пример работы с ними может быть следующим (в качестве параметра условия):
По аналогии со справочниками и документами работает объект "Периодический", план счетов работает по аналогии с ВидомСубконто, ну и далее в том же духе… Отдельную главу посвятим запросу, а сейчас… стоп. Еще пункт забыл!
Ж) Доступ к функциям и процедурам глобального модуля базы OLE!
Как же я про это забыл-то, а? Поскольку при запуске базы автоматически компилируется глобальный модуль, то нам становятся доступны функции и процедуры глобального модуля (поправлюсь - только те, у которых стоит признак "Экспорт"). Плюс к ним еще и различные системные функции 1С. А доступны они нам через функцию 1С OLE - EvalExpr(). Приведем примеры работы с базой OLE:
На самом деле, в последней строке примера я исхитрился и забежал немного вперед. Дело в том, что как и запрос (см. отдельную главу), так и EvalExpr() выполняются внутри базы OLE, причем команды передавается им обычной строкой, и поэтому надо долго думать, как передать необходимые ссылки на объекты базы OLE в строке текста местной базы. Так что, всегда есть возможность поломать голову над этим…
Алгоритмы преобразования объектов в "удобоваримый вид" между базами.
Ясно, что алгоритмы преобразования нужны не только для переноса объектов между и базами, но и для такой простой задачи, как попытки сравнить их между собой.
И еще раз обращу внимание: ОБЪЕКТЫ ОДНОЙ БАЗЫ ПРЕКРАСНО ПОНИМАЮТ ДРУГ ДРУГА, ПРОБЛЕМЫ ВОЗНИКАЮТ ТОЛЬКО ТОГДА, КОГДА ВЫ НАЧИНАЕТЕ СВЯЗЫВАТЬ МЕЖДУ СОБОЙ ОБЪЕКТЫ РАЗНЫХ БАЗ, т.е. команда
будет прекрасно работать без ошибок. Не забывайте это, чтобы не перемудрить с алгоритмами!
Итак, повторяюсь, что напрямую перенести, да и просто сравнить можно только даты (причем не "пустые"), числа и строки ограниченной длины. Итак, как же нам сравнить объекты разных баз (не числа, не даты, не строки), т.е. как их преобразовать в эту самую строку/число/дату.
А) Преобразование справочников/документов базы OLE (если есть аналогичные справочники/документы в местной базе). В принципе, преобразование их было уже рассмотрено в примерах выше и сводится к поиску их аналогов в местной базе. Могу еще раз привести пример, заодно с использованием регистров:
Б) Преобразование перечислений и видов субконто (подразумевается, что в обоих базах есть аналогичные перечисления и виды субконто). Вся задача сводится к получению строкового или числового представления перечисления или вида субконто.
Не поймите это как прямую команду воспользоваться функцией Строка() или Число() :)) Нет. Для этого у нас есть обращение к уникальному представлению перечисления и вида субконто - метод Идентификатор() или ЗначениеПоНомеру(). Второй вариант не очень подходит, так как зачастую в разных базах даже перечисления бывают расположены в другом порядке, а вот идентификаторы стараются держать одинаковыми в разных базах. Отсюда вывод, пользуйтесь методом Идентификатор(). Кстати, не путайте вид субконто с самим субконто! Привожу пример преобразования:
То же самое относится и к плану счетов - принцип у него тот же, что и у вида субконто…
В) Преобразование счетов:
Во многом объект "Счет" аналогичен объекту "Справочник". Отсюда и пляшем:
Работа с запросами и EvalExpr().
Наконец-то добрались и до запросов. Надо пояснить несколько вещей, касаемых запросов (да и EvalExpr() тоже). Самое главное - компиляция текста OLE-запроса (т.е. разбор всех переменных внутри запроса), как и сами OLE-запросы выполняются внутри базы OLE и поэтому ни одна переменная, ни один реквизит местной базы там недоступны, да и запрос даже не подозревает, что его запускают по OLE из другой базы!!! Поэтому, чтобы правильно составить текст, иногда требуется не только обдумать, как передать параметры запроса в базу OLE, но и обдумать, что нужно добавить в глобальный модуль той самой OLE-базы, чтобы как-то собрать для запросы переменные!
1. Поскольку сам текст запроса и функции EvalExpr() является по сути текстом, а не набором параметров, то напрямую передать ему ссылку на элемент справочника, документ, счет и т.п. нельзя. Исключение может быть составлено для конкретных значений перечислений, видов субконто, констант, планов счетов и т.п.
2. Хоть и многим и так понятно, что я скажу дальше, но я все-таки уточню: при описании переменных в тексте запроса не забывайте, что объекты базы надо указывать напрямую, без всяких префиксов типа "БазаОле".
3. Отрабатывать запрос сложно тем, что ошибки, например, при компиляции напрямую не увидеть. Поэтому начинаем пошагово готовится к отработке запроса в базе OLE.
Вначале допишем в глобальном модуле базы OLE немного строк, которые нам помогут в работе:
Теперь начинаем потихоньку писать сам запрос. Что мы имеем:
В форме диалога местной базы несколько реквизитов диалога (либо местные переменные):
* Даты периода (НачДата и КонДата)
* Элементы справочников для фильтрации (ВыбТовар, ВыбФирма, ВыбКлиент, и т.д.)
* Какие-либо флажки (ТолькоЗамерзающийЗимойТовар , ..)
Мы начинаем писать запрос и сразу попадаем в такую ловушку:
ТекстЗапроса = " Период с НачДата по КонДата; ";
Вроде все в порядке, но такой запрос не выполнится в базе OLE, так как там понятия не имеют, что такое НачДата и КонДата :)) Ведь эти переменные действительны только для местной базы! Переписываем запрос заново:
Казалось бы все очень просто. По аналогии - если уникальность для товаров ведется по наименованию, то простой заменой слова "код" на "наименование" мы решаем вопрос и здесь. Теперь рассмотрим, когда мы выбрали группу, т.е. текст условия должен будет выглядеть так:
И здесь, правда можно проблему решить "двумями путями" :)) Первый пусть - когда мы имеем дело с двухуровне вымсправочником. Тогда проблема группы решается также просто, как и в 1-м варианте:
А если справочник очень даже многоуровневый? Вот для этого мы и используем написанную ранее функцию. Предположим, что список значений запроса с индексом массива " 1 " мы будем использовать для хранения подобных значений (например, хранить в нем группы товаров, клиентов) для хитрых условий. Итак, например, в ВыбТовар у нас указана группа товаров, а в ВыбКлиент - группа клиентов, которым мы товары группы ВыбТовар продавали. Кроме того, мы должны пропустить накладные возвратов поставщикам, и не забыть, что товары надо еще отбирать по флажку ТолькоЗамерзающийЗимойТовар:
Ну, а с реквизитами запроса разбираемся так же, как указано было выше в предыдущих разделах… И не забываем, что кроме хранения конкретных значений, можно использовать другие списки значений запроса. Например, можно заполнить какой-либо список значений запроса списком клиентов и использовать его в запросе:
I. Вступление
II. Таблицы 1С и Excel.
III. Получение данных из Excel.
IV. Вывод данных в Excel.
V. Часто используемые методы для чтения/установки значений в Excel.
Вступление.
Многие знают, что Excel гораздо старше 1С. На мой взгляд, это очень успешный продукт, и нареканий о нем я не слышал. Excel прост и универсален. Он способен выполнять не только простые арифметические операции, но и сложные вычисления, построение графиков и т.п. Знаю примеры, когда организации до перехода на 1С вели часть бухгалтерии в Excel. Многие и сейчас параллельно используют две программы. В этой статье рассмотрим способы обмена данными между 1С и Excel.
Таблицы 1С и Excel.
Многие пользователи для удобства работы сохраняют таблицы 1С (печатные формы) в формате Excel (*.xls). После чего в полученном файле делают различные группировки, сортировки, вычисления и т.п. Связано это с тем, что в таблицах 1С нет такого огромного функционала как в таблицах Excel. Но в версии 1С 8.0 есть нововведения, делающих работу с таблицами более комфортной.
На сайте 1С (www.1C.ru) есть полезная программка, которая дает возможность открывать таблицы 1С в Excel и сохранять лист Excel как таблицу 1С. Это пригодится в том случае, если таблицу 1С не сохранили в формате Excel, а на том компьютере, где нужно открыть эту таблицу не установлена 1С. Да и постоянно помнить о том, что сохранить таблицу 1С нужно в формате Excel, не будет необходимости.
Полная информация о программе находится здесь.
Скачать программу можно здесь (архив zip 682 739 байт).
Замечание: В Excel разделителем дробной части считается символ ",". Поэтому перед сохранением таблицы 1С в формате Excel замените в ней другой разделитель (например ".") на ",". Иначе в Excel с этими числами не удастся произвести вычисления, или они вообще не будут отображаться как числа. Например, в таблице 1С "15.2" отобразится в Excel как "15.фев".
Получение данных из Excel.
Доступ из 1С к Excel производится посредством OLE. Например, код
позволит нам получить доступ через переменную "Эксель" к запущенному приложению Excel. А далее уже можно получить доступ к книге (файлу), листу и ячейке с данными. Далее примеры кода.
Открытие книги (файла):
ПутьКФайлу - полный путь к файлу книги Excel.
Выбор листа книги для работы с ним:
НомерЛиста - номер листа в книге, ИмяЛиста - имя листа в книге.
Получение значения ячейки листа:
НомерСтроки, НомерКолонки - номер строки и номер колонки, на пересечении которых находится ячейка.
Важно: не забывайте поле выполнения нужных действий добавлять код Эксель.Quit(); , иначе запущенный процесс останется незавершенным и будет занимать память и процессор компьютера.
Вывод данных в Excel.
Для вывода (выгрузки) данных в Excel необходимо либо открыть существующую книгу, либо создать новую, и выбрать рабочий лист для вывода данных. Открытие существующей книги описано выше, а для создания новой книги нужно использовать следующий код:
Так как при создании книги в Excel автоматически создаются листы (Сервис->Параметры->Общие->Листов в новой книге), то нужно лишь произвести выбор листа, с которым будет вестись работа:
либо добавить в книгу новый лист, если необходимо:
Следующим шагом будет установка значения ячейки:
НомерСтроки, НомерКолонки - номер строки и номер колонки, на пересечении которых находится ячейка.
И в конце нужно произвести запись созданной книги:
П
ПутьКФайлу - полный путь к файлу книги Excel (включая имя).
Важно: не забывайте, что в имени файлов не должно содержаться символов \ / : * ? " > < |.
Часто используемые методы для чтения/установки значений в Excel.
Эксель = СоздатьОбъект("Excel.Application");
Получение доступа к приложению Excel.
В этой статье мы рассмотрим технику создания инифайлов их назначение и применение. Начнем с ответа на вопрос зачем же нужны эти инифайлы?! Предположим, что вы создали приложение, в котором пользователь может настраивать цвет фона, шрифт надписей и так далее. Когда он повторно включит вашу программу он очень сильно разочаруется, так как всего его старания по настройке интерфейса вашей программы пропали даром - программа будет иметь такой вид, который сделали вы при проектировании программы. Так вот чтобы эти настройки сохранять, лучше всего пользоваться инифайлами.
Одно из главных преимуществ инифайлов заключается в том, что эти файлы подерживают переменные разных типов (String, Integer, Boolean). В этих файлах очень удобно хранить различные настройки, например параметры шрифта, цвет фона, какие checkbox'ы выбрал пользователь и многое другое.
Теперь начнем разбираться с этими инифайлами. Для начала создайте новое приложение. Добавьте в секцию uses слово inifiles. Сохраните и откомпилируйте ваше приложение. Теперь сделаем, чтобы при каждом открытии программы форма имела такие размеры, какие установил пользователь последний раз. Для начала нам надо создать объект типа Inifile. Создается он методом Create(Filename:string); причем если в переменной Filename не указан путь к фалу, то он создаться в директории Windows, что не очень-то удобно. Поэтому мы создадим этот файл в директории нашей программы. Напишем это в обработчик события OnDestroy для формы:
Если файл с таким именем существует, то он откроется для чтения, а если нет - то он будет создан. Это очень удобно, так как не надо обрабатывать возможные исключительные ситуации, которые могут возникнуть при обращении к файлу.
Вот файл MyIni.ini после завершения работы программы (у вас естественно значения будут другими):
Теперь подробно разберемся как записывать информацию в инифайлы:
После того, как вы создали инифайл, в него можно записывать три вида переменных: Integer, String, Boolean, это осуществляется соответствующими процедурами: WriteInteger, WriteString, WriteBool. У всех этих процедур одинаковые параметры. В общем объявление этих процедур выглядит так:
Здесь Section -это имя секции, куда будут помещены параметры и значения. В файле имена секций заключены в квадратные скобки. Обычно в секции объединяют схожие параметры.
Ident - это название параметра, которому будет присваиваться какое-нибудь значение.
Value - это собственно значение, которое будет присвоено параметру. В файле оно стоит после знака равно.
Теперь напишем обработчик события OnCreate для формы, в котором будем считывать значения из файла и изменять размеры формы в соответствии с полученными значениями. Код должен иметь такой вид:
В этом коде все просто: открыли файл, прочитали из соответствующих секций необходимые параметры и присвоили их форме. Чтение значений из инифайла по сути ничем не отличается от записи в них. Указываете секцию, где хранится необходимый параметр, указываете параметр и читаете его значение. Как вы видите все просто!
Теперь я отвечу еще на один вопрос, который может появиться - почему не обычные текстовые файлы и не реестр? Отвечаю: из текстового файла очень сложно получить и обработать необходимую информацию. Многие рекомендуют для Win95/98/2000/Me, короче для всех 32-разрядных ОС использовать именно реестр, но лично я считаю, что инифайлы удобнее, так как при при переносе программы на другой компьютер, нужно перенести только один инифайл, а во-вторых, если вы что-нибудь в реестре случайно удалите, то может случиться каюк.
В данной статье рассмотрены принципы, помогающие компилятору Delphi генерировать более оптимальный с точки зрения скорости код. Если Вы не хотите вникать в подробности, в конце статьи есть «свод правил», которые рекомендуется соблюдать при написании программ.
Компилятор Delphi относится к разряду оптимизирующих. Но насколько качественно проводится оптимизация? Как «помочь» компилятору создать более быстрый код? Давайте разберемся с этим на экспериментах.
Оптимизация константных выражений
Пример 1:
С точки зрения оптимизации код можно упростить еще на этапе компиляции до
Но написанный выше листинг преобразуется в
С одной стороны компилятор не «сообразил», что значение переменной «a» можно преобразовать в константу и сложить с другой константой (которая, заметим, подставлена именно как константа) на этапе компиляции, с другой стороны был применен весьма хитрый трюк с LEA (об этом ниже). Тем не менее, код
в любом случае быстрее и короче.
Пример 2:
Скомпилированный код будет выглядеть
А ведь значение, присвоенной переменной «а» являлось константой и наш пример можно было бы переписать как:
Пример 3:
После компиляции получаем:
Т.е. компилятор преобразовал код так, как он был написан, а ведь можно было бы просто записать:
Оптимизация алгебраических выражений
Пример 4:
После компиляции эти переменные будут удалены, причем с предупреждением
Пример 5:
Код скомпилируется как есть! Таким образом мы обманули компилятор псевдо использованием переменных. Delphi не исправляет нашей «кривости», поэтому эта задача ложится исключительно на плечи программиста.
Пример 6:
Данный код можно оптимизировать до
И этого Delphi за нас не сделает.
Пример 7:
В данном примере первую строчку можно безболезненно удалить, что Delphi делать умеет.
Пример 8:
В данном случае можно избавится от одной операции умножения, присвоив значение выражения a*b временной переменной. Анализ ассемблерного листинга показывает, что компилятор именно так и поступает. Тем не менее, поменяв второе подвыражение на ((b*a)>0), компилятор принимает выражения за разные и генерирует умножение для обоих случаев, не смотря на то, что результат одинаков.
Оптимизация арифметических операций
Сложение и вычитание
Применение инструкции LEA вместо ADD позволяет производить сумму 3х операндов (двух переменных и одной константы) за один такт. Трюк заключается в том представление ближних указателей эквивалентно их фактическому значению, поэтому результат, возвращенный LEA равен сумме ее операндов. При возможности Delphi производит такую замену.
Деление
Операция деления требует гораздо больше тактов процессора, нежели умножение, поэтому замена деления на умножение может значительно ускорить работу. Существуют формулы, позволяющие выполнять такое преобразование. Тем не менее, Delphi не использует такую оптимизацию. Деление на степень двойки можно заменять сдвигом вправо на n бит, но даже в этом случае получаем следующий код:
Здесь учитывается особенность самой операции div – округление в большую сторону. Поэтому, если можно пренебрегать округлением, используйте c:=a shr 1 вместо с:=a div 2.
Умножение
Умножение на степень двойки можно заменять сдвигами битов. Delphi заменяет умножение сдвигами при умножении на 4,8,16 итд. При умножении на 2 производится суммированием переменной с собой.
Умножать на 3,5,6,7,8,10 и т. д. можно и без операции умножения – расписав выражение по формуле (a shl n)+a, где n – показатель степени двойки. Например, при умножении на 3 n=1. Delphi при возможности прибегает к этому трюку. Заметим, операнд LEA умеет умножать регистр на 2,4,8, что также при возможности используется компилятором. Например, умножение на 3 преобразуется в инструкцию
Оптимизация case of
Анализ скомпилированного кода показывает, что Delphi проводит утрамбовку дерева. Т.е. значения case сортируются и выбор нужного элемента производится при помощи двоичного поиска.
В случае, если элементы case of выстраиваются в арифметической прогрессии, компилятор формирует таблицу переходов. Т.е. создается массив указателей с индексами элементов, поэтому выбор нужно элемента выполняется за одну итерацию независимо от количества элементов.
Оптимизация циклов
Разворачивание циклов – не производится. Разворачивание циклов весьма спорный момент в оптимизации, поэтому принять грамотное решение может только человек. Delphi не производит разворачивания ни больших, ни маленьких циклов.
Слияние циклов – не производится. Если два цикла, следующие друг за другом имеют одинаковые границы итерационной переменной, разумно оба цикла объединить в один.
Вынесение инвариантного кода за пределы цикла – не выносится. Наиболее распространенный недочет – условие цикла записывается как:
Delphi будет при каждой итерации вызывать метод count, вычитать из результата 1 и потом уже сверять. Настоятельно рекомендуется переписывать подобный код как
Весь код VCL написан с нарушением этого правила. Очевидно, что проще подобного рода оптимизацию встроить в компилятор, нежели переписывать VCL :)
Замена циклов с предусловием на циклы с постусловием – производится. Циклы с постусловием имеют главное преимущество над другими видами циклов (с предусловием и с условием в середине) – они содержат всего одно ветвление. Delphi производит такую замену.
Замена инкремента на декремент – не производится. Более того, даже декрементный цикл компилируется в неоптимальный код, т.к. не используется флаг ZF. Вместо этого происходит сравнивание значения регистра с 0.
Удаление ветвлений – не производится.
Вывод:
1. Не используйте переменные для временного хранения констант или обязательно объявляйте «магические» числа как const, либо подставляйте в код непосредственные значения
2. Неиспользуемыми объявлениями и присвоениями можно безболезненно пренебрегать – Delphi умеет их вычищать.
3. Внимательно следите за использованием переменных, в частности лишним присвоениям их значений друг другу. Такого рода оптимизации Delphi делать не умеет.
4. Используйте свернутые математические выражения. (например, (3*a - a) /2 упрощается до a). Delphi не умеет упрощать математические выражения. (Да и что говорить, даже MathCAD не всегда грамотно умеет делать такие преобразования).
5. Не используйте конструкции типа a:=10*sin(45*pi/180); Delphi не вычислит эту константу на этапе компиляции, напротив, будет послушно вызывать sin и pi по ходу выполнения программы! В случае, если угол является переменной, по крайней мере pi можно заменить константой 3,1415...
6. Delphi прекрасно справляется с выражениями, полностью составленных из констант – они вычисляются на этапе компиляции.
7. Внимательно следите за условиями и их границами. Компилятор Delphi не умеет обнаруживать заведомо ложных условий. Также он не умеет удалять заведомо лишние условия. Например, (a>0) and (a<15616) and (a<>0)
8. Если в условии несколько раз проверяется одно и тоже выражение, следите, чтобы оно было выражено во всех конструкциях одинаково. В противном случае скомпилированный код будет не оптимален. Например, if ((a*b)>0) and ((a*b)<1024) then... При перестановке во втором случае b*a смысл выражения не изменится, но код будет иметь уже на одну операцию умножения, а две. Можно временно присвоить проверяемое выражение временной переменной, а затем уже проверять полученное значение.
9. Сообщение «Combining signed and unsigned types – widened both operands» сообщает не только о потенциальной ошибке – также вследствие преобразования мы теряем производительность. Например, z – объявлена как ineteger. условие if z>$abcd6123 then z:= $abcd6123; несмотря на его правильность вызовет данное предупреждение. Сгенерированный код будет, выполнять преобразования величин до 64-х бит, и дальнейшее уже сравнение 64-х битных операндов. Если изменить тип z на cardinal, мы избавимся от предупреждения и получим 3 строки кода, вместо 8 !
10. Delphi умеет оптимизировать сложение, умножение и частично деление. При делении на степень двойки, если не важно округление до большего, рекомендуется пользоваться shr 1 вместо div 2.
11. В case of при возможности используйте элементы, расположенные в арифметической прогрессии. Тем не менее, даже при невыполнении данного условия мы получим качественный код после утрамбовки дерева.
12. Выносите инвариантный код за тело цикла. Наиболее частая ошибка – for i:=1 to length(str) do... Дело в том, что при каждой итерации будет вызываться функция length, что пагубно скажется на производительности. Рекомендуется длину строки заранее присвоить переменной. Также не включайте в тело цикла код, заведомо не зависящий от изменения итерационной переменной.
Сравнивая Delphi с компиляторами Visual C++, WATCOM, Borland C++ (тестирование данных компиляторов приведено в [1]) приходим к выводу, что Delphi по своим оптимизирующим свойствам аналогичен Borland C++ (а кто сомневался? ;) ). Учитывая, что Borland C++ по итогам сравнения оказался последним, делаем несложный вывод. Весьма печален и тот факт, что большинство кода VCL написано с точки зрения «красоты» кода, а не его оптимальности с точки зрения скорости. Например, не соблюдается правило 12.
Настройки по умолчанию в Кореле не очень удобны. В любом графическом редакторе всегда хочется иметь как можно больше рабочего пространства. Настройки по умолчанию хороши лишь для изучения редактора, так как все руководства, справка и книги написаны под них. Когда же всё изучено и опробовано, можно настроить интерфейс «под себя». А некоторые опции просто необходимо скорректировать для комфортной работы.
Настраиваем сами Corel Draw.
Настройки по умолчанию в Кореле не очень удобны. В любом графическом редакторе всегда хочется иметь как можно больше рабочего пространства. Настройки по умолчанию хороши лишь для изучения редактора, так как все руководства, справка и книги написаны под них. Когда же всё изучено и опробовано, можно настроить интерфейс «под себя». А некоторые опции просто необходимо скорректировать для комфортной работы.
Для настройки интерфейса обычно используют меню Customization. Но в этой статье часто будет использоваться ещё один способ. Заключается он в том, что элементы интерфейса можно перетаскивать, зажав клавишу Alt, если при перетаскивании воспользоваться сочетанием Ctrl+Alt то перемещаемые элементы дублируется. Чтобы просто удалить элемент достаточно кликнуть на нем правой кнопкой мыши и в появившемся контекстном меню выбрать Customize>Toolbar Item>Delete. Сами «бары» перетаскиваются за двойную линию с левого или верхнего края.
Настройка внешняя.
Удаляем всё лишнее.
В верхней части интерфейса находятся Menu Bar (стандартные File, Edit, View и т.д.), Standard toolbar (панель, где находятся пиктограммы New, Open, Save...) и Property Bar (панель свойств, где устанавливаются параметры страницы, единицы измерения и прочие параметры документа). Menu Bar имеет привычное для большинства Windows приложений расположение, поэтому можно оставить его без изменений. Сэкономить место, здесь можно разместив Standard toolbar и Property Bar в один ряд, что станет возможно, если удалять с Standard toolbar. Лишние элементы, начиная, справа это выпадающее меню масштаба (zoom level), которое дублируется при выбранном Zoom Tool`е, затем кнопки «Access the Corel Graphics Community Web site» и «Start Corel applications», кнопки импорта и экспорта заменят легко запоминающиеся сочетания Ctrl+I и Ctrl+E. Всем знакомы такие сочетания как Ctrl+Z и Ctrl+Shift+Z, соответственно кнопкам со стрелочками «Undo» и «Restore» не место в новом интерфейсе. Опять же копирование/вставка – стандартные во всех приложениях Ctrl+C/X/V, да и в контекстном меню они присутствуют, так что тоже можно смело удалять. В общем, что оставить в Standard toolbar`е и оставлять ли его вообще дело индивидуальное, главное поставить его вряд с Property Bar`ом, что расширит рабочую область аж на 32 пиксела. Беспокоится о неправильных действиях и удалении чегото нужного сильно не стоит. Стандартные панели можно вернуть к прежнему виду в меню Tools>Customization>Command Bars, выделив нужную и нажав кнопку Reset. Либо через контекстное меню Customize>[Toolbar Name]>Reset to Default. Сбросить же все настройки на дефолтные если вдруг ваши эксперименты совсем выйдут из под контроля можно стартовав CorelDRAW с зажатой клавишей F8. То что находится внизу называется Status Bar и по умолчанию занимает неоправдано много места, показывая такие ненужные вещи как позиция курсора, доступные команды для инструментов и свойства объектов которые дублируются на панели свойств. Удалив все лишнее можно разместить вряд Object Information, Object Detalis, Fill Color и Outline color таким образом уменьшив размер панели состояния вдвое.
Ну и наконец немного расширить рабочую область можно отключив линейки, двойной клик и в появившемся окне снять галочку Show Rulers, существенный минус это отсутствие возможности вытягивать из них направляющие (Guidelines) и выставлять нулевые координаты в нужное место. Как вариант можно вынести кнопку включения/отключения линеек в какое-нибудь удобное место, находится она в меню Tools>Customization>Commands выпадающем списке View и называется Rulers.
Панель инструментов (Toolbox).
Та часть интерфейса, в которой расположены инструменты (Pick, Zoom, Shape, Bezier Tools и т.д.) интерактивные эффекты (Blend, Transparency, Envelope и т.д.) и прочее необходимое в работе и есть Toolbox или панель инструментов. По умолчанию она расположена неподвижно в крайней левой части окна и все инструменты расположены в один столбик, а некоторые объеденены в группы. Такой порядок не очень удобен опытному пользователю и уж тем более профессионалу или векторному маньяку.
Расположение в два столбика более практично и удобно, с этого и следует начать – перетащить Toolbox за верхний край со стандартного места в свободную область и растянуть до расположения инструментов в два столбца. Теперь руководствуясь собственным опытом и манерой работы нужно выставить инструменты в нужном порядке. Например Shape Tool можно вынести отдельно от группы и расположить рядом с Pick Tool`ом, также с инструментом Hend, а в выпадающих группах подвинуть наиболее используемые инструменты ближе к левому краю.
Чтобы новая панель выглядела аккуратней можно убрать верхнюю часть с названием и крестиком закрытия, для этого нужно кликнуть на панели правой кнопкой мыши, в контекстном меню выбрать Customize>Toolbox Toolbar>Properties... и в появившемся окне снять галочку «Show title when toolbar is floating».
Докеры (Dockers).
Особенностью интерфейса CorelDRAW является то что многие полезные функции и эффекты реализованы в виде докеров – панелей по умолчанию открывающихся справа. Там им самое место, вот только открывать каждый раз нужный докер не очень удобно, располагаются они в разных частях меню, хотя почти все их можно найти в меню Window>Dockers и на многие уже назначены сочетания клавиш. Наиболее удобный выход держать их открытыми, только в свернутом состоянии, так они будут расположены в нужном порядке удобными вкладками и при надобности разворачиваться одним кликом и так же легко сворачиваться. Определившись с наиболее удобным порядком (чтобы чаще используемые были выше) нужно поочередно открыть их через меню Window>Dockers. После этих действий правая часть экрана будет занята набором удобных закладок.
При желании расположить их можно и не привязывая к экрану, перетаскиваются они также как и другие элементы. В «плавающем» состоянии докеры представляют собой отдельные окошки, напоминающие аналогичные в «Адобовских» продуктах, которые так же легко сворачиваются и объединяются в группы.
Палитру цветов так же можно расположить более удобно, горизонтально например или в виде той же плавающей панели, форма и место расположения практически ничем не ограничиваются.
С принципом настройки интерфейса и некоторыми вариантами модификации, думаю, все понятно, она на то и кастомизация чтобы каждый мог изменить рабочее пространство на удобное ему. Теперь о настройках внутренних.
Настройка внутренняя.
Горячие клавиши.
Здесь каждый вправе сам решать что нужнее всего и достойно назначения клавиш.
В меню Tools>Customization>Commands во вкладке Shortcut Keys назначить свое сочетание клавиш можно любой функции. Совет: при установке горячих клавиш включите режим Navigate to conflict on Assign это позволит не допустить повтора уже существующих сочетаний. И ещё один важный совет: многим в Corel`е не хватает аналога функции Hand Tool в Photoshop`е и Illustrator`е, которой можно перемещаться по рабочей области зажав пробел не отрываясь от основных действий и не переключая инструментов. Такая функция присутствует, но по умолчанию не задействована, исправить ситуацию можно назначив горячую клавишу инструменту Pan (можно тот же пробел) который находится в меню Tools>Customization>Commands в выпадающем списке View.
Опции.
Пройдясь по опциям можно настроить некоторые параметры, сделав работу еще более удобной и продуктивной, начнем по порядку: Tools>Options (Ctrl+J)>Workspace>General тут можно установить количество шагов отката (Undo levels) для основных операций (Regular) и операций с растрами (Bitmap effects), примерные значения 50-100 и 5-10 соответственно.
Тут же можно отключить звуки (снять пометку с Enable sounds). Вкладка Display интересна опцией Enable node Tracking знакомой по ранним версиям CorelDraw (напомню: при активном инструменте Pick Tool и наведении на узлы он превращается в Shape Tool, таким образом можно скруглять углы прямоугольников и перемещать узлы не переключаясь на шейпер). Опция удобная и многим привычная, но не всегда востребованная, а лазить каждый раз в опции для ее включения не очень удобно. Альтернатива есть: в уже знакомом меню Tools>Customization>Commands нужно выбрать в выпадающем списке Edit, найти опцию Tracking и вытащить ее в удобное место на рабочей области или назначить ей сочетание клавиш. Теперь активация функции Node Tracking займет считанные секунды.
Далее во вкладке Edit следует снять галочку с опции Edit Auto-center new PowerClip contents, эта опция размещает объект в центре контейнера поверклипа, что нужно очень редко и если уж возникла такая необходимость, решается предварительным выравниванием объектов клавишами «C» (по вертикали) «E» (по горизонтали).
Следующая вкладка обязательная к посещению Memory, тут следует увеличить объем оперативной памяти используемой приложением со стандартных 25% до 50-75% в зависимости от объема доступной памяти.
Во вкладке Text>Quick Correct нужно снять галочку с одной из самых надоедливых функций CorelDRAW «Capitalize first letter of sentence» которая всюду при наборе текста делает первую букву предложения заглавной, что совершенно не требуется в большинстве случаев.
Часто CorelDRAW импортирует файлы в формате EPS в виде растровых объектов либо не импортирует вообще, для корректного импорта необходимо использовать фильтр «EPS, PS, PRN – PostScript», можно конечно выбирать его вручную в диалоговом окне импорта в выпадающем меню Files of type, но проще назначить его фильтром по умолчанию. Для этого в меню Global > Filters в списке List of active filters нужно выделить нужный фильтр и кнопкой Move Up поднять его выше фильтра «EPS - Encapsulated PostScript». Теперь нужный фильтр будет отвечать за импорт *.eps файлов постоянно.
Ну вот пожалуй и все основные и нуждающиеся в корректировке опции. На последок можно отметить некоторые возможности рассчитанные скорей на любителя нежели необходимые в работе. В меню Customization>Commands в выпадающем списке Status Bar можно найти такие функции как Time, которая как ясно из названия показывает время, Memory Allocated, которая проинформирует о занятой открытыми файлами памяти, а также индикатор статуса привязки Snap Status, и еще ряд подобных мелочей. Их можно расположить как например в том же Status Bar так и назначать горячие клавиши, после нажатия которых информация выведется рядом с курсором.
Node Color Coding.
По умолчанию отключенное нововведение CorelDRAW X3 (похоже, не всегда корректно работает), из название понятно – цветовое выделение узлов, т.е. подсвечивает узлы с разными свойствами (cusp, smooth, simmetrical) своим цветом. Кроме того, выделяется «начальный» узел, что в работе с блендами весьма полезно.
Включается через реестр (Пуск>Выполнить...>regedit):
в ветке
HKEY_CURRENT_USER > Software > Corel > CorelDRAW > 13.0 > CorelDRAW > Application Preferences > Base Tool Pref
присваиваем параметру
"NodeColorCoding"
значение "1".
сохраняем с расширением .reg, и запускаем, после подтверждения функция включится.
Как вы видите CorelDRAW крайне гибкий по части настроек и кастомизации. И каждый не поленившийся потратить часок другой на ковыряние опций и настройку интерфейса без сомнения сэкономит уйму рабочего времени впоследствии и превратит стандартный редактор в индивидуально заточенный инструмент.
На примере создания иллюстрации можно понять основные приемы работы с Blend Tool, а также некоторые нюансы, которые следует учитывать для достижения положительных результатов. Это не прямое руководство, это лишь способ, один из многих, который позволяет понять алгоритм основных действий и решать в дальнейшем более сложные и конкретные задачи.
Не обычное применение Blend Tool.
На примере создания иллюстрации можно понять основные приемы работы с Blend Tool, а также некоторые нюансы, которые следует учитывать для достижения положительных результатов. Это не прямое руководство, это лишь способ, один из многих, который позволяет понять алгоритм основных действий и решать в дальнейшем более сложные и конкретные задачи.
Свеча на рисунке выглядит достаточно реалистичной, для ее создания использовалась техника описания ниже. Забегая вперед, скажу что время, затраченное автором не превышает одного часа, в рисунке использовалось шестнадцать нарисованных вручную элементов, все остальное сделано автоматически инструментом Blend Tool.
Для начала определимся с основными формами. В данном случае это пламя, ореол света, фитиль и собственно свеча. Те самые шестнадцать элементов это парные объекты, начальные и конечные, между которыми и производится операция перетекания, благодаря чему цвета плавно распределяются и рисунок выглядит реалистично. Это не маловажный аспект, цвет конечного (в данном случае внешнего) объекта языка пламени должен совпадать с цветом начального (внутреннего) объекта ореола, а цвет конечного объекта ореола с цветом фона.
Инструментом Bezier Tool по контрольным точкам нарисуем кривую. Следует отметить, что операции с кривыми требующие определенной точности нужно проводить именно Bezier Tool или Pen Tool, и изначально рисовать прямыми линиями, то есть определить на глаз где должны находится узлы и соединить их прямыми линиями. Инструмент Freehand Tool здесь не подойдет из-за неточности. Итак, когда линия проведена, делаем двойной клик на инструменте Shape Tool, двойной клик выделит все узлы элемента и все линии легко сделать кривыми командой Convert Line To Curve на панели свойств (Property Bar) активной при выбранном инструменте. Оставив активным инструмент Shape Tool отредактируем кривую до нужного вида, для хорошего перетекания важно чтоб все было плавно.
Не торопитесь с построением следующего объекта, здесь есть один важный нюанс. В идеале начальный объект дублируется и путем редактирования превращается в конечный. Дублируем кривую нажатием «+» на цифровой клавиатуре и инструментом Shape Tool тянем узлы на нужные позиции, с помощью направляющих линии доводятся до нужной степени изогнутости. Таким образом, получается кривая с тем же количеством схожих по свойствам узлов, что обеспечивает бес проблемное выполнение операции перетекания (Blend).
Далее руководствуясь теми же принципами рисуются остальные элементы рисунка. Язык пламени достаточно сложный объект, в нем используется три пары кривых, три последовательных перетекания.
Когда все пути готовы можно приступать к выбору цветовой гаммы. Здесь тоже следует обратить внимание на некоторые нюансы. Например не следует осуществлять переход от темно-желтого к светло-желтому в системе CMYK таким образом: из C0:M20:Y100:K20 в C0:M0:Y60:K0, так как в промежутке появятся «грязные» цвета типа C0:M11:Y81:K11, что значительно испортит вид рисунка. Такой переход лучше осуществить в два этапа: из C0:M20:Y100:K20 в C0:M0:Y100:K0, а из последнего в C0:M0:Y60:K0. Это стоит запомнить, руководствуясь таким принципом строятся и качественные градиенты, программные средства не идеальны, не следует полностью доверять им в таком важном аспекте как работе с цветом. Здесь не стоит ленится и жалеть времени, это один из завершающих этапов создания иллюстрации, следует уделить ему внимание, по экспериментировать и получить впоследствии картинку с яркими и сочными цветами, достойную глянцевой обложки.
Подготовительный, рутинный и самый сложный этап работы закончен. Теперь осталось самая приятная часть – создание переходов между объектами, превращение набора плашек в фотореалистичную иллюстрацию.
Выбираем инструмент Interactive Blend Tool или открываем докер Effects>Blend, делаем переход от объекта к объекту вручную или выбираем пару и нажимаем кнопку Apply в докере. В зависимости от исходного размера рисунка устанавливаем количество шагов (Steps).
Проблем возникнуть не должно если все сделано правильно, но все же если что-то упущено вместо ровного перехода может возникнуть цепочка из непонятных «рваных» объектов, не имеющих на первый взгляд никакого отношения к оригинальным и тем более к задуманному. Не стоит отчаиваться, для настоящего профессионала нет проблем которые нельзя решить. Такая ситуация может возникнуть в двух случаях: пути объектов имеют разное направление или несовпадающие узлы (даже если узлов одинаковое количество). Первая проблема решается просто, инструментом Shape Tool выделяется один объект и инвертируется направление кривой командой Reverse curve direction на панели свойств. Если не помогло придется самому назначить начальные и конечные узлы перетекания (предварительно убедившись что их одинаковое количество), для этого у инструмента есть набор опций Miscellaneous Blend Options (иконка с плюсиком на Property Bar, или последняя в докере), а в нем функция Map Nodes. После клика по ней курсор превратится в изогнутую стрелку и на одном из исходных объектов отобразятся узлы в виде увеличенных квадратиков, после клика на одном из таких квадратиков активируется второй объект с аналогичным отображением узлов, теперь следует кликнуть по узлу соответствующему первому выбранному, и повторить если потребуется на всех контрольные точки, хотя на практике все стает на свои места после «синхронизации» двух-трех узлов. Функция Split тоже достаточно интересна, она позволяет выделить любой объект из уже сделанного перетекания и сделать его третьим (средним) исходным и произвести над ним манипуляции (изменить цвет, размер, форму и т.д.) таким образом изменив все перетекание, в некоторых случаях достаточно удобно.
И на последок хотелось бы отметить. Данная статья лишь иллюстрирует на небольшом примере возможности программы и ее инструментов. Многие пользователи CorelDRAW недооценивают возможности Blend Tool и пренебрегают ее использованием, но при хорошо освоенной технике и достаточной практике с помощью инструмента без особого труда можно создавать сложные фотореалистичные, технически грамотные иллюстрации и элементы дизайна. Пламя, хромовые, матовые и глянцевые поверхности, объемные предметы и фигуры, тени – все это далеко не полный перечень того что можно изобразить этой техникой.
Главное о чем стоит упомянуть это, что ваш хранитель экрана будет работать в фоновом режиме и он не должен мешать работе других запущенных программ. Поэтому сам хранитель должен быть как можно меньшего объема. Для уменьшения объема файла в описанной ниже программе не используется визуальные компоненты Delphi, включение хотя бы одного из них приведет к увеличению размера файла свыше 200кб, а так, описанная ниже программа, имеет размер всего 20кб!!!
Технически, хранитель экрана является нормальным EXE файлом (с расширением .SCR), который управляется через командные параметры строки. Например, если пользователь хочет изменить параметры вашего хранителя, Windows выполняет его с параметром "-c" в командной строке. Поэтому начать создание вашего хранителя экрана следует с создания примерно следующей функции:
Поскольку нам нужно создавать небольшое окно предварительного просмотра и полноэкранное окно, их лучше объединить используя единственный класс окна. Следуя правилам хорошего тона, нам также нужно использовать многочисленные нити. Дело в том, что, во-первых, хранитель не должен переставать работать даже если что-то "тяжелое" случилось, и во-вторых, нам не нужно использовать таймер.
Процедура для запуска хранителя на полном экране - приблизительно такова:
Во-первых, мы проинициализировали некоторые глобальные переменные (описанные далее), затем прячем курсор мыши и создаем окно хранителя экрана. Имейте в виду, что важно уведомлять Windows, что это - хранителя экрана через SystemParametersInfo (это выводит из строя Ctrl-Alt-Del чтобы нельзя было вернуться в Windows не введя пароль). Создание окна хранителя:
Теперь окна созданы используя вызовы API. Я удалил проверку ошибки, но обычно все проходит хорошо, особенно в этом типе приложения.
Теперь Вы можете погадать, как мы получим handle родительского окна предварительного просмотра ? В действительности, это совсем просто: Windows просто передает handle в командной строке, когда это нужно. Таким образом:
Как Вы видите, window handle является вторым параметром (после "-p").
Чтобы "выполнять" хранителя экрана - нам нужна нить. Это создается с вышеуказанным CreateThread. Процедура нити выглядит примерно так:
Нить просто заставляет обновляться изображения в нашем окне, спит на некоторое время, и обновляет изображения снова. А Windows будет посылать сообщение WM_PAINT на наше окно (не в нить !). Для того, чтобы оперировать этим сообщением, нам нужна процедура:
Если мышь перемещается, кнопка нажала, мы спрашиваем у пользователя пароль:
Это также демонстрирует использование registry на уровне API. Также имейте в виду как мы динамически загружаем функции пароля, используюя LoadLibrary. Запомните тип функции?
TVSSFunc ОПРЕДЕЛЕН как:
Теперь почти все готово, кроме диалога конфигурации. Это запросто:
Трудная часть -это создать диалоговый сценарий (запомните: мы не используем здесь Delphi формы!). Я сделал это, используя 16-битовую Resource Workshop (остался еще от Turbo Pascal для Windows). Я сохранил файл как сценарий (текст), и скомпилированный это с BRCC32:
Почти также легко сделать диалоговое меню:
После того, как пользователь выбрал некоторые установочные параметры, нам нужно сохранить их.
Загружаем параметры так:
Легко? Нам также нужно позволить пользователю, установить пароль. Я честно не знаю почему это оставлено разработчику приложений ! Тем не менее:
Мы динамически загружаем (недокументированную) библиотеку MPR.DLL, которая имеет функцию, чтобы установить пароль хранителя экрана, так что нам не нужно беспокоиться об этом.
TPCPAFund ОПРЕДЕЛЕН как:
(Не спрашивайте меня что за параметры B и C ! :-)
Теперь единственная вещь, которую нам нужно рассмотреть, - самая странная часть: создание графики. Я не великий ГУРУ графики, так что Вы не увидите затеняющие многоугольники, вращающиеся в реальном времени. Я только сделал некоторые ящики.
И последнее - глобальные переменные:
Затем исходная программа проекта (.dpr). Красива, а!?
Ох, чуть не забыл! Если, Вы используете SysUtils в вашем проекте (например фуекцию StrToInt) вы получите EXE-файл больше чем обещанный в 20k. :) Если Вы хотите все же иметь20k, надо как-то обойтись без SysUtils, например самому написать собственную StrToInt процедуру.
Если все же очень трудно обойтись без использования Delphi-форм, то можно поступить как в случае с вводом пароля: форму изменения параметров хранителя сохранить в виде DLL и динамически ее загружать при необходимости. Т.о. будет маленький и шустрый файл самого хранителя экрана и довеска DLL для конфигурирования и прочего (там объем и скорость уже не критичны).
Эта заметка не имеет непосредственного отношения к DELPHI, уж извините :) Но получив в очередной раз письмо с предложение за два клика заработать $5000 я не выдержал, душа просит высказаться!
Я рассмотрю несколько вариантов заработка денег в internet с описанием, их плюсами и минусами. Сразу предупреждаю, это мое личное мнение, никак не претендую на глубину и всесторонность обзора.
1. Начнем с наиболее правильного и близкого нам программистам :) SHAREWARE.
Написание программы с целью ее продажи. Решаясь на подобное сначала все хорошенько обдумайте и взвесьте, зарабатывать на shareware можно и нужно, но… всегда есть проклятое "но" :) Для создания хорошо продаваемой программы вам придется не мало потрудиться. Срок от начала написания до реальных продаж вряд ли получится менее полугода. Вам придется много работать и главное думать. Здесь нет руководителя, который напишет Т.З. и скажет когда и что нужно сделать :( Все самому, а еще лучше команде. Одному человеку трудно быть одновременно хорошим программистом, генератором идей, дизайнером, маркетологом и т.д. и т.п. Лучше, если каждый будет заниматься тем, что умеет делать лучше всего. И тогда… по непроверенным данным ReGet получат более $50.000 в месяц! ;)
Как этого добиться? Здесь нет никаких строгих правил, все зависит от вашего таланта и, наверное, везения. Вот один из вариантов: выбрать направление программы, лучше, если это будет то, что требуется большому количеству людей каждый день в их постоянной работе за компьютером. Потратить с месяц или более, на сбор и анализ существующих подобных программ в интернете (трудно придумать что-то совсем уж уникальное :) обязательно уже есть аналоги, необходимо выяснить слабые и сильные стороны каждой программы и составить Т.З. для своей программы, включая туда самое лучшее. Кстати, не обязательно делать самостоятельную программу, это вполне может быть что-то прикладное к уже имеющимся. Например, каждый браузер умеет сам закачивать файлы из internet и тем не менее, "качалок" великое множество! Почему? Да потому что они удобнее в использовании и имеют дополнительные функции.
Далее самый плодотворный процесс - написание самой программы. На это уходит от месяца до года (больше не надо, а то она за это время бесконечно устареет :) По окончании написания программы, ее отладка и анализ, а действительно ли она так хороша, как предполагалось в начале?! ;) На этом этапе лучше выложить для скачивания бесплатную beta-версию на русском языке. И, зарегистрировавшись в русских каталогах, предлагать нашим тестировать новое чудо современных технологий! После чего, вы получите массу писем с ошибками и пожеланиями, все учитываете и дорабатываете, дорабатываете… На это может уйти даже больше, чем на написание основного кода программы. Когда считаете, что программа отшлифована и проверена на самых различных конфигурациях компьютеров, можно готовить английскую версию, выкладывать на сайт, регистрироваться в системах, которые помогут вам получать деньги от буржуев (например RegNow) и раскрутка вашего детища - регистрация в поисковых системах, а главное в каталогах для ShareWare программ, которых в инете великое множество. И с замиранием сердца ждать :) анализировать статистику заходов на ваш сайт, откуда приходят, почему с других мест не идут? Сколько людей пришло и "дошло" до скачивания и оплаты. На каком этапе вы потеряли клиента, почему? Все надо довести до идеала, клиенту нужно максимально упростить способ расставания с деньгами! :) Как видите, непосредственно программирование здесь занимает очень малую долю, и можно даже сказать, не главную! (Билл Гейтс ведь смог же продавать геморрой за деньги! :) :)
Рекомендую вам подписаться на рассылку российских шароварщиков swrus.com, узнаете много нового и полезного. А главное, общение с людьми, которые реально зарабатывают на этом! Плюсы:Это станет вашим основным заработком. Сумма, получаемая вами ежемесячно, ничем не ограничена, только вашим талантом! При удачной раскрутке, можно создавать свою фирму, становиться начальником, нанимая других программистов ;) Если на вас обратит внимание крупная западная фирма, то можно выгодно "продаться" :) Минусы: Вам придется долгое время вкалывать за красивую мечту. Никто, ничего не гарантирует. Вы с большой вероятностью можете в итоге оказаться у разбитого корыта :( Придется запастись терпением!
2. Создание сайта.
Вы создаете сайт, делаете его интересным для как можно большей доли посетителей интернета и как следствие, высокую посещаемость. После чего можно продавать рекламное место на своем сайте или зарабатывать через баннерные сети, что платят за показы или клики. Важно правильно выбрать тематику сайта, рекламодателям должно быть выгодно именно у вас размещать свою рекламу. Возьмем к примеру этот сайт (Мастера DELPHI), сайт сильно специфичен, рассчитан на очень малый процент людей в сети, мало того что именно программист, так еще и обязательно на DELPHI :) Потому добиться действительно высокой посещаемости его просто не реально. Но не это главное, кто из рекламодателей захочет здесь разместить рекламу? Ведь, понятно, его реклама должна ему же приносить деньги, т.е. чаще всего это или продажа своей программы, или привлечение целевой аудитории. Сайт русскоязычный, а русские не привыкли покупать программы, да и зачастую не на что! Вот и получается, что работаем мы над этим сайтом, только ради альтруизма и пользы вам, наши дорогие посетители :)
Или другой пример, сайт NoNaMe. Ему пол года, и за это время автор сайта добился блестящих результатов! (потому что сайт действительно интересен, всегда можно найти для себя что-то полезное. Рекомендую всем!) На данный момент до 9тыс. уникальных посетителей! Но… опять же, сайт специфичен, публикация кряков к программам оставляет весьма сомнительную вероятность того, что кто-то захочет рекламировать там свой продукт ;)
Лучше всего, конечно же, сайт рассчитанный на широкую публику: поисковые системы, каталоги, новости… игровые/развлекательные сайты здесь не лучшем положении (мой знакомый, автор сайта netcross.ru раскрутил его весьма хорошо, а сейчас практически забросил. Создал свою фирму по дизайну, и она за два месяца принесла денег больше чем за все время существования netcross.ru :) Плюсы:Широчайшее поле для творчества. Ваш доход ничем не ограничен. Интернет развивается бешенными темпами. И помните! Совсем недавно list.ru был продан за $5.000.000 !!! Вполне хватит на карманные расходы ;) Минусы: Вам придется в поте лица работать над своим сайтом и, как и в первом случае, большая вероятность остаться у разбитого корыта :(
3. Интернет услуги.
Создаете свою компанию по оказанию каких-либо интернет услуг: дизайн, интернет магазин, хостинг, регистрация, раскрутка и т.д. и т.п. Вполне реальный способ заработка, здесь нечего добавить. Практически в любом случае вы будете получать доход, доход лишь зависит от вашего желания работать и от того, откуда у вас растут руки :) Лично я напрямую связан с предоставлением хостинга российским компаниям, и со всей ответственностью заявляю, на хостинге можно и нужно зарабатывать. Помните, русский интернет сейчас развивается очень быстро, и потребность в различных видах услуг велика. Плюсы: Вы получаете реальные деньги за реальную работу. Все сводится только к поиску и привлечению людей, которым ваши услуги необходимы. Минусы: Зачастую требует начальных капиталовложений. Здесь нет халявы, не получится почивать на лаврах (как при удачном раскладе в первых двух пунктах), работать, работать и еще раз работать :)
На этом позвольте закончить вторую часть. Это не все о заработке, возможно я продолжу этот цикл, если вам конечно интересно :)
Анимированное кино существует и развивается уже сто лет. Оно стало считаться одним из видов искусства. Год от года неуклонно возрастет число анимационных проектов. Такие картины, как Final Fantasy, Shrek, Little Stuart, The Incredibles, Finding Nemo претендуют на престижную премию Оскара. Возможно наступит момент, когда актеров заменят их трехмерные двойники.
Трехмерные сцены становятся все реалистичными, а их себестоимость снижается. Без трехмерных декораций не обходится ни один современный экшн.
Как создается трехмерная анимация.
Анимированное кино существует и развивается уже сто лет. Оно стало считаться одним из видов искусства. Год от года неуклонно возрастет число анимационных проектов. Такие картины, как Final Fantasy, Shrek, Little Stuart, The Incredibles, Finding Nemo претендуют на престижную премию Оскара. Возможно наступит момент, когда актеров заменят их трехмерные двойники.
Трехмерные сцены становятся все реалистичными, а их себестоимость снижается. Без трехмерных декораций не обходится ни один современный экшн.
Трехмерная анимация постепенно вытесняет классическую двухмерную мультипликацию. Многие мультяшные герои или "уходят на пенсию" (с ними просто больше не делают новых мультфильмов), или обретают новую жизнь в 3D. Например, мультфильм с моряком Папаем, сделанный при помощи 3D-редактора Softimage|XSI.
В 2004-ом году известная анимационная студия Blur Studio представила первый анимационный трехмерный проект про Микки Мауса и других диснеевских героев.
Три мультфильма общей продолжительностью 40 минут стали самым крупным проектом за девятилетнюю историю Blur Studio.
Работа над проектом велась совместно 3D-аниматорами Blur и художниками Disney Studios, которые в свое время рисовали Дональда, Плуто и прочих персонажей. Для того чтобы максимально сохранить особенности движения и внешнего вида персонажей при переносе их в трехмерный мир, ведущий аниматор студии Disney Андреас Дежа (Andreas Deja) все время давал советы коллегам-3D-художникам. Результатом остались довольны все, и в Blur и в Studio надеются, что проект не будет последним.
Метод ключевых кадров.
Современная техника анимации кардинально отличается от анимационных фильмов выпускавшихся двадцать, пятьдесят лет назад.
А до появления трехмерной графики существовала так называемая кукольная анимация. Делалась она так: снимался один кадр с мультипликационным героем, затем, например, руку персонажа передвигали на очень небольшое расстояние и опять снимали один кадр. Вся работа состояла в том, чтобы снять на пленку все положения руки мультяшного героя. Что же касается рисованной анимации, каждый кадр рисовался вручную.
В компьютерной анимации все гораздо проще. Аниматор задает в программе только два положения руки - верхнее и нижнее, а все промежуточные положения просчитываются компьютером. Кадры, которые фиксируют начальное и конечное положение тела, называютсяключевыми.
Используя метод ключевых кадров, можно "оживить" практически любые параметры анимационной сцены. Продолжительность анимации зависит от количества промежуточных кадров между ключевыми.
Если математически отобразить зависимость анимированного параметра (или ключа анимации, как его еще называют) от времени, каждый ключевой кадр будет характеризоваться двумя кривыми, которые определяют функциональные зависимости анимированного параметра на промежутке между текущим ключевым кадром и предыдущим, а также настоящим ключевым кадром и следующим. Во многих редакторах для работы с трехмерной графиков подобной графической зависимостью можно управлять, определяя характер анимации.
Преимущество метода ключевых кадров перед классической техникой создания анимации очевидно: аниматор тратит на создание проекта гораздо меньше времени. Большая часть рутинной работы, которая ранее выполнялась вручную, сегодня переложена на компьютер.
Проблемы при создании анимации методом ключевых кадров.
Несмотря на универсальность и простоту техники ключевых кадров, существуют случаи, когда использование этого метода не позволяет добиться желаемого результата. Это касается тех сцен, в которых необходимо отобразить эффекты, подчиняющиеся законам физики.
В реальной жизни все, что нас окружает, постоянно изменяется - шторы слабо двигаются, по озеру бежит мелкая рябь и так далее. Аниматору очень трудно воссоздать такую картину методом ключевых кадров.
Если сцена содержит большое количество анимированных объектов, установить для каждого из них свой набор ключевых кадров очень сложно. Поскольку подбор параметров значений анимированных параметров в каждом из ключевых кадров производится методом проб и ошибок, на подгонку такой сцены уйдет очень много времени.
Кроме этого, при помощи ключевых кадров 3D-аниматору бывает очень сложно воссоздать реалистичную анимацию некоторых объектов: жидкости, материи, огня, волос, разбивающихся предметов. Алгоритм решения этих проблем настолько сложен, что его разработкой занимаются целые институты.
Каждая программа для создания динамики в трехмерных сценах по-своему уникальна, имеет свои преимущества и недостатки. Поэтому при выборе программного обеспечения руководитель анимационного проекта обычно учитывает задачи, которые планируется выполнить на данном этапе.
Помимо проблем, связанных с моделированием физических процессов, существует еще одна трудность, связанная с анимированием большого количества объектов в сцене. Создать простую, на первый взгляд, сцену с горящим бенгальским огнем при помощи ключевых кадров невозможно. Вручную задать траекторию движения для каждой из огромного количества разлетающихся искр - задача практически невыполнимая. В этом случае в трехмерной анимации используются так называемые источники частиц. Их особенность в том, что они позволяют одновременно управлять большим количеством объектов. Значимость частиц в трехмерной графике столь велика, что некоторые 3D-редакторы имеют сложные системы управления источниками частиц, которые позволяют тонко настроить анимационные эффекты с учетом изменения скорости движения частиц, размера, цвета, формы, изменения положения в пространстве и т.д.
Персонажная анимация.
Создание персонажной анимации - это один из важнейших этапов создания трехмерного проекта.
Любую анимацию можно условно разделить на два типа: реалистичная и нереалистичная. Персонажная анимация может быть как реалистичной, так и нереалистичной, однако, зрителем она лучше воспринимается, если напоминает движения, совершаемые реальными существами. Даже если персонаж анимации - это вымышленное существо, плод воображения художника, лучше, чтобы его движения были правдоподобны. В противном случае персонаж будет выглядеть безжизненным манекеном.
Характер движения любого существа определяется анатомическим строением его скелета. Поэтому при создании трехмерной анимации сначала создается модель скелета существа, на который позже "одевается" оболочка.
"Одевание" оболочки - это тоже достаточно трудоемкий процесс, ведь нужно "привязать" кости к соответствующим частям тела таким образом, чтобы при изменении положения скелета оболочка деформировалась реалистично.
Создавать анимацию скелета будущего персонажа можно двумя способами: вручную, с помощью ключевых кадров, и используя систему захвата движения Motion Capture. Последний способ получил широкое распространение и используется практически по всех коммерческих анимационных проектах, так как имеет ряд преимуществ перед методом ключевых кадров.
Технология Motion Capture использовалась, например, в анимационном фильме - <Полярный экспресс> (The Polar Express). В этом фильме известный актер Том Хенкс, играл сразу несколько ролей: маленького мальчика, проводника поезда, бродягу и Санта Клауса. При этом, во многих анимационных сценах актер играл сам с собой. Конечно же, все герои мультфильма были трехмерными, но Том Хенкс управлял их действиями, жестами и даже мимикой. Актер одевал специальное одеяние с датчиками, напоминающее гидрокостюм, совершал действия перед специальным устройством, а компьютер получал информацию об изменении положения отметок на костюме и моделировал, таким образом, движения трехмерного персонажа. Подобные датчики были установлены и на лице актера, что позволило переносить на анимационных героев его мимику.
Понятно, что анимация персонажей, созданная с использованием технологии Motion Capture, более реалистична, чем полученная методом ключевых кадров.
Мимика персонажа.
Для создания мимики трехмерного персонажа, кроме метода Motion Capture, используется также метод морфинга. Все современные 3D-редакторы обычно имеют средства для создания морфинга.
Добиться высокой реалистичности при имитации мимики методом Motion Capture не всегда удается. Чтобы она была правдоподобной, необходимо имитировать движения огромного количества мускулов, а ведь на каждый мускул датчик повесить невозможно.
Поэтому для имитации мимики используется метод морфинга. Он заключается в том, что на основе модели, которая будет анимирована, создается определенное количество клонированных объектов. Затем каждый из этих объектов редактируется вручную - форма лица изменяется таким образом, чтобы на нем присутствовала та или иная гримаса. При создании мимики очень важно, чтобы лицо персонажа при анимации не выглядело однообразным. Для этого необходимо использовать модели-заготовки с самыми разными гримасами. Пусть на одной заготовке персонаж будет моргать, на другой - щуриться, на третьей - надувать щеки и т.д.
На основе этих моделей при помощи метода морфинга создается анимация. При этом, просчитывается, как изменяется лицо персонажа при переходе от выражения лица одной модели до гримасы, созданной на второй модели и т.д. Таким образом, каждая из моделей служит ключом анимации, в результате использования морфинга форма объекта изменяется, и создается мимика персонажа.
3D-аниматор, который профессионально занимается "оживлением" персонажей, должен быть не только художником, но и знатоком анатомии. Знания о строении тела и работе мускулов помогают создать реалистичные движения и выражения лица.
Если же персонаж не только ходит и кривляется, но еще и говорит, 3D-аниматор обязан превратиться еще и в лингвиста. Каждый звук, который произносит человек, сопровождается определенными движениями его губ, языка, челюсти. Для того чтобы перенести эти движения на трехмерную анимацию, нужно уметь разбивать речь на фонемы и создавать соответствующие их произношению движения на лице персонажа.
Виртуальные камеры.
Многие трехмерные анимационные эффекты создаются с помощью виртуальных камер. Эти вспомогательные объекты предназначены для того, чтобы изменять положение точки съемки в виртуальном пространстве.
Виртуальные камеры обладают всеми основными параметрами, которые присущи настоящим камерам. Так, например, для виртуальной камеры можно указать фокусное расстояние, установить свой тип линз и т.д.
Виртуальная камера, в отличие от настоящей, - это лишь вспомогательный объект, которого вы никогда не увидите на трехмерной анимации.
Трехмерная анимация заметно упрощает реализацию многих спецэффектов. Так, например, хорошо всем известный "эффект Матрицы", когда, камера медленно объезжает вокруг человека, замершего в прыжке, гораздо проще создать при помощи виртуальной камеры. Для реализации этого эффекта в фильме "Матрица" использовалось большое количество камер, расположенных вокруг объекта съемки. Все они зафиксировали положение человека в один и тот же момент времени. Из этих кадров была создана анимация, имитирующая "облет" вокруг объекта.
В трехмерной анимации законы физики не действуют, поэтому для создания такого эффекта достаточно зафиксировать в прыжке трехмерную модель человека и задать плавное движение виртуальной камеры вокруг него.
В реальном мире при съемке фото или видеокамерой быстро движущиеся объекты остаются на полученном изображении смазанными. Причем, размытие изображения в конкретном кадре указывает на направление движения заснятого объекта. Присутствие этого эффекта в трехмерной анимации делает ее более реалистичной.
Эффект смазанного движения (Motion Blur) позволяет создать в трехмерных анимированных сценах смазанный шлейф от быстродвижущихся объектов, и отобразить их такими, какими они выглядят при реальных съемках. Возможность использования эффекта смазанного движения имеется практически во всех модулях просчета изображения, которые используются в 3D-графике.
Сегодня 3D-анимация находится на ранней стадии своего развития но за ней большое будущее. Потребуется еще немало времени, пока в 3D будут созданы анимационные шедевры, которые можно будет сравнить с лучшими образцами классической анимации.
А пока все с удовольствием смотрят мультфильмы, выпущенные много лет назад. Такой например как мультфильм "Бемби", созданный студией Диснея шестьдесят три года назад и отреставрированный при помощи современных средств видеообработки.
Хочется надеяться, что такую же популярность, нерушимую временем, смогут снискать и трехмерные анимационные проекты будущего.
Информация в кабельных локальных сетях передается в закодированном виде, то есть каждому биту передаваемой информации соответствует свой набор уровней электрических сигналов в сетевом кабеле. Модуляция высокочастотных сигналов применяется в основном в бескабельных сетях, в радиоканалах. В кабельных сетях передача идет без модуляции или, как еще говорят, в основной полосе частот.
Правильный выбор кода позволяет повысить достоверность передачи информации, увеличить скорость передачи или снизить требования к выбору кабеля. Например, при разных кодах предельная скорость передачи по одному и тому же кабелю может отличаться в два раза. От выбранного кода напрямую зависит также сложность сетевой аппаратуры (узлы кодирования и декодирования кода). Код должен в идеале обеспечивать хорошую синхронизацию приема, низкий уровень ошибок, работу с любой длиной передаваемых информационных последовательностей.
Некоторые коды, используемые в локальных сетях, показаны на рис. 3.8. Далее будут рассмотрены их преимущества и недостатки.
Наиболее распространенные коды передачи информации
Рис. 3.8. Наиболее распространенные коды передачи информации
Код NRZ
Код NRZ (Non Return to Zero – без возврата к нулю) – это простейший код, представляющий собой обычный цифровой сигнал. Логическому нулю соответствует высокий уровень напряжения в кабеле, логической единице – низкий уровень напряжения (или наоборот, что не принципиально). Уровни могут быть разной полярности (положительной и отрицательной) или же одной полярности (положительной или отрицательной). В течение битового интервала (bit time, BT), то есть времени передачи одного бита никаких изменений уровня сигнала в кабеле не происходит.
К несомненным достоинствам кода NRZ относятся его довольно простая реализация (исходный сигнал не надо ни специально кодировать на передающем конце, ни декодировать на приемном конце), а также минимальная среди других кодов пропускная способность линии связи, требуемая при данной скорости передачи. Ведь наиболее частое изменение сигнала в сети будет при непрерывном чередовании единиц и нулей, то есть при последовательности 1010101010..., поэтому при скорости передачи, равной 10 Мбит/с (длительность одного бита равна 100 нс) частота изменения сигнала и соответственно требуемая пропускная способность линии составит 1 / 200нс = 5 МГц (рис. 3.9).
Скорость передачи и требуемая пропускная способность при коде NRZ
Рис. 3.9. Скорость передачи и требуемая пропускная способность при коде NRZ
Передача в коде NRZ с синхросигналом
Рис. 3.10. Передача в коде NRZ с синхросигналом
Самый большой недостаток кода NRZ – это возможность потери синхронизации приемником во время приема слишком длинных блоков (пакетов) информации. Приемник может привязывать момент начала приема только к первому (стартовому) биту пакета, а в течение приема пакета он вынужден пользоваться только внутренним тактовым генератором (внутренними часами). Например, если передается последовательность нулей или последовательность единиц, то приемник может определить, где проходят границы битовых интервалов, только по внутренним часам. И если часы приемника расходятся с часами передатчика, то временной сдвиг к концу приема пакета может превысить длительность одного или даже нескольких бит. В результате произойдет потеря переданных данных. Так, при длине пакета в 10000 бит допустимое расхождение часов составит не более 0,01% даже при идеальной передаче формы сигнала по кабелю.
Во избежание потери синхронизации, можно было бы ввести вторую линию связи для синхросигнала (рис. 3.10). Но при этом требуемое количество кабеля, число приемников и передатчиков увеличивается в два раза. При большой длине сети и значительном количестве абонентов это невыгодно.
В связи с этим код NRZ используется только для передачи короткими пакетами (обычно до 1 Кбита).
Большой недостаток кода NRZ состоит еще и в том, что он может обеспечить обмен сообщениями (последовательностями, пакетами) только фиксированной, заранее обговоренной длины. Дело в том, что по принимаемой информации приемник не может определить, идет ли еще передача или уже закончилась. Для синхронизации начала приема пакета используется стартовый служебный бит, чей уровень отличается от пассивного состояния линии связи (например, пассивное состояние линии при отсутствии передачи – 0, стартовый бит – 1). Заканчивается прием после отсчета приемником заданного количества бит последовательности (рис. 3.11).
Определение окончания последовательности при коде NRZ
Рис. 3.11. Определение окончания последовательности при коде NRZ
Наиболее известное применение кода NRZ – это стандарт RS232-C, последовательный порт персонального компьютера. Передача информации в нем ведется байтами (8 бит), сопровождаемыми стартовым и стоповым битами.
Три остальных кода (RZ, манчестерский код, бифазный код) принципиально отличаются от NRZ тем, что сигнал имеет дополнительные переходы (фронты) в пределах битового интервала. Это сделано для того, чтобы приемник мог подстраивать свои часы под принимаемый сигнал на каждом битовом интервале. Отслеживая фронты сигналов, приемник может точно синхронизовать прием каждого бита. В результате небольшие расхождения часов приемника и передатчика уже не имеют значения. Приемник может надежно принимать последовательности любой длины. Такие коды называются самосинхронизирующимися. Можно считать, что самосинхронизирующиеся коды несут в себе синхросигнал.
Откроем замечательную векторную программу Adobe Illustrator и попробуем нарисовать кусочек сыра (если вы не знаете, что такое векторный и подобные вещи, то читайте статью «Первые шаги - компьютерная графика и графические редакторы»).
Изучаем векторную графику (Adobe Illustrator).
Откроем замечательную векторную программу Adobe Illustrator и попробуем нарисовать кусочек сыра (если вы не знаете, что такое векторный и подобные вещи, то читайте статью «Первые шаги - компьютерная графика и графические редакторы»).
Для начала нужно создать новый документ (лист бумаги, на котором будем рисовать). В меню выбираем File - New...
Выбираем нужные размеры документа, и наживаем OK, чтобы его создать (в данном случае, взяты значения, те, что предложил Иллюстратор по умолчанию).
Так как рисуем сыр с нуля и еще не умеем, то воспользуемся сыром образцом (будем срисовывать).
Чтобы поместить не векторное изображение на лист, выбираем в меню: File - Place... - выбираем рисунок, который надо разместить на листе.
Прежде чем начать работать с сыром, его надо увеличить. Чтобы сделать саму картинку с сыром больше, надо кликнуть по ней левой кнопкой мыши - таким образом, выделится объект и вокруг него появится рамочка. Потянем за уголок - и таким образом можно изменить размер картинки. Чтобы при этом картинка не деформировалась и сохраняла пропорции, то придерживаем, когда тянем за уголок, клавишу Shift на клавиатуре.
Чтобы изменить видимый размер картинки (приблизить - отдалить) - выберем инструмент лупа (zoom tool) на основной панели инструментов. Этот инструмент, наводим на картинку, кликаем левой кнопкой мыши - изображение приблизится. Если наоборот, отдалить, то кликаем мышью по изображению, придерживая кнопку Alt на клавиатуре. Чтобы снова работать с изображением (т.е. выйти из режима лупы), надо выбрать другой инструмент на панели инструментов (например, следующий инструмент, с которым вы будете работать).
Итак, видимый размер куска сыра увеличен, чтобы было удобнее его обрисовывать, теперь фиксируем картинку с сыром на листе, чтобы, когда с ней начнем работать, она никуда не сдвинулась нечаянно. Для этого выбираем на панели инструментов черную стрелку (selecтion tool), после чего кликаем по рисунку, чтобы его выделить (всегда, объект, с которым работаем, должен быть выделен), затем в меню выбираем Object - Lock - Selecтion.
На панели инструментов выбираем инструмент перо (pen tool), с помощью него обрисовываем сыр. Но прежде чем, обрисовать сыр, надо убрать заливку объекта. Квадраты - белый и черный - внизу панели инструментов, указывают, какой цвет будет у объекта, который рисуем - он будет белым, и вокруг него будет черная граница.
Чтобы изменить цвет границы или цвет объекта - кликаем два раза по нужному квадрату (если нужно изменить границу - то по черному, в данном случае, если цвет объекта - по белому), и появится окошко, где можно выбрать другой, нужный цвет. Но в этом случае, другой цвет не нужен, надо, чтобы объект не был закрашен, и было видно только границу (контур объекта) - так будет удобнее срисовывать. Поэтому одним кликом мыши выбираем белый квадрат, и под ним выбираем иконку с квадратом, перечеркнутым красной полосой - таким образом, говорим иллюстратору - отмени заливку объекта белым цветом, и он это сделает.
Теперь начнем обрисовывать сыр, сначала светлую верхнюю плоскость, а затем нижнюю. Кликнем, допустим, в одном из уголков сыра, затем, повторяя контур сыра, кликаем дальше. Чтобы все линии (отрезки, которые появятся при этом), были прямыми, то когда надо кликнуть мышью, чтобы создать очередную точку, не отпуская левую клавишу мыши, тогда удерживая ее и двигая мышью, можно выгнуть отрезок, как угодно, и таким образом более точно обвести сыр.
Если был сделан отрезок кривым (выгнутым), то прежде чем продолжать обрисовывать объект, надо кликнуть левой кнопкой мыши по последней точке, которую поставили, и только затем создавать новую точку и отрезок. Если этого не сделаете, то следующий отрезок выгнется подобно предыдущему.
Если не верно поставлена точка, если отрезок как-то не так выгнут, то чтобы отменить действие, нажимаем на клавиатуре Ctrl+Z. Если отменили предыдущее действие ошибочно, то нажмите Ctrl+Shift+Z, чтобы вернуть все обратно.
Чтобы завершить обрисовывать верхнюю часть сыра надо обязательно закончить в той точке, с которой начали, чтобы получить цельный объект (т.е. замкнуть наш контур).
Аналогично первому создаем второй контур (объект).
Чтобы нагляднее было видно, что на картинке два контура: второй, недорисованный контур, немного сдвинут в сторону. При этом создание объекта не было прервано. Что делать, если надо довести контур объекта, после того как прервались? Чтобы продолжить работу, надо ткнуть кнопкой мышки в точку объекта, на которой прервались и можно дорисовывать объект дальше (естественно, при этом на панели инструментов должно быть выбрано перо, если надо дорисовать объект; если же надо подвигать объект, то переключаемся на selecтion tool - черная стрелка, только не забыть переключаться на нужные инструменты, прежде чем выполнять какие-то действия над объектом).
Когда нарисованы нужные объекты, следует их закрасить. Как это делается, объяснялось ранее: выделяем объект, и внизу панели через квадраты оперируем цветом. Есть и другие пути: можно вызвать цветовую палитру, чтобы она всегда на экране: Window - Color (опять же выделяем объект, прежде, чем дать ему цвет). Также можно, выделив объект, выбрать инструмент пипетка (eyedroррer tool) на панели инструментов, и ткнуть пипеткой по другому объекту на листе (например, по картинке с сыром, чтобы дать новому объекту такой же цвет, как цвет куска сыра, с которого срисовываем).
На данном примере три куска сыра: один - с какого срисовываем, второй - кусок сыра, которому дали такие же цвета, как сыру на картинке, но т.к. цвета не сырные, заплесневелые, то были подобранны другие цвета, которые можно видеть на третьем куске сыра. Если еще трудно сделать последнее самим, то сохраните картинку с примером на компьютере, поместите ее на лист бумаги в иллюстраторе и при помощи пипетки, дайте вашему куску сыра такие же яркие и приятные цвета, как у третьего куска сыра на картинке с примерами.
Как перемещать и копировать нарисованные объекты? Перемещать объекты надо следующим образом: выделить объект, предварительно выбрав инструмент selecтion tool (черная стрелка) на панели инструментов, а затем при помощи мышки перетащить выбранный объект. Если надо переместить сразу несколько объектов: опять же выбираем selecтion tool, и далее либо удерживая левую кнопку мыши выделяем все объекты, либо кликаем на нужные нам объекты поочередно, удерживая клавишу Shift на клавиатуре. После того как были выделены все нужные объекты, их можно перемещать, куда угодно. Также, выделив объекты, можно скопировать их Edit - Copy. Чтобы вставить скопированные объекты на лист - Edit - Paste. Чтобы удалить, выделенные объекты - Edit - Clear.
После придания куску, который рисуем, нужные цвета, рисуем на нем сырные дырки, чтобы придать ему еще большую схожесть с сыром. Дырки не будем срисовывать с фотографии куска сыра, а нарисуем сами. Дырка - это круг. Круги рисуют при помощи инструмента elliрse tool. Чтобы найти этот инструмент на панели инструментов надо кликнуть мышкой по инструменту квадрат (rectangle tool), удерживая мышку, выпадет меню, в котором надо выбрать elliрse tool. Далее кликаем на нашем листе в любом месте и рисуем круг.
Нарисовав круг, даем ему цвет более насыщенный и темный, чем боковая сторона сыра (т.к. дырка для этой стороны, а дырка она визуально более темная по цвету, чем сама сторона). Если переместить, нарисованный круг, на кусок сыра, то станет понятно, что он еще не смотрится дыркой, не хватает "глубины", так что надо приблизить круг (дырку) ближе к реальности, добавив ей бликов и теней.
Итак, скопируем круг, и вставим скопированное на лист (как это делается, рассказывалось ранее). Затем совместим круги так, как показано на рисунке (в итоге должно быть три круга - один исходный, и два которые, скопировав исходный круг, вставили на лист, а затем совместили между собой новые круги, как показано на рисунке):
Теперь порежем эти круги при помощи Pathfinder. Вызываем его через меню: Window - Pathfinder. Далее оба круга выделяем, и нажимаем в окошке Pathfinder инструмент Divide. Если сейчас попытаться подвигать круги, то обнаружите, что они слиплись в один объект. На самом деле, Divider порезал наши круги на много маленьких объектов, но для удобства, он их потом сгруппировал (вдруг захочется их передвинуть сразу куда-нибудь). Поэтому надо рассгруппировать все объекты. Выделяем нашу группу объектов, выбираем в меню - Object - Ungroup.
Если теперь попробовать мышкой подвигать круги, то видим, что их все-таки разрезали, и получили в итоге три очень интересных объекта: два полумесяца и объект похожий на дыню. Круги и резали, т.к. нужны были полумесяцы. Скопируем один из полумесяцев, вставим на лист, дадим ему цвет чуть бледнее, чем цвет круга, и переместим на круг, как показано на нашем рисунке (см. чуть выше).
Затем еще раз копируем полумесяц и вставляем его на лист, делаем его еще светлее, и переносим на наш круг, как показано на рисунке:
Теперь нужен другой полумесяц, зеркальный тем, что копировали до этого. Берем полумесяц, копируем, даем ему самый темный цвет по сравнению с другими объектами, перемещаем на круг так, как показано на рисунке:
Вот и все, сырная дырка готова, теперь надо переместим ее на сыр. Для этого надо сгруппировать все объекты, имеющие отношение к сырной дырке, чтобы потом было легче их копировать и перемещать при необходимости. Чтобы сгруппировать объекты, их нужно выделить, а затем группируем их, выбрав в меню Object - Group (если надо будет снова разбить объекты, отклеить друг от друга, то выделяем сгруппированные объекты, и при помощи уже знакомого Object - Ungroup).
Итак, переместили дырку на сыр, теперь скопируем ее, и вставим еще несколько новых дырок на боковую сторону сыра. Сделаем их размеры разными (как, уменьшать-увеличивать размер объекта говорили в начале статьи). В итоге, должны получить, вот такой сыр:
Чтобы сыр был похож на настоящий, добавим еще одну полудырку, а так же теней и рефлексов на края.
Для этого берем готовую дырку, копируем, вставляем на лист (отдельно от сыра), и затем при помощи Pathfinder и Divider ее ополовиниваем. Также копируем два полумесяца, которые потом, вставим на край сыра. Получаются две следующие картинки:
Теперь и половинку дырки, и два полумесяца немного развернем при помощи инструмента rotate tool. Края сыра идут немного под наклоном, и чтобы совместить дырки с краями куска сыра, их надо привести в соответствие. Теперь наложим их на кусок сыра, если надо еще чуть-чуть поразворачиваем, и в итоге должны получить следующее:
Итак, кусок сыра почти нарисовали, теперь надо нарисовать дырки для верхней плоскости (копируем уже имеющиеся дырки, и немного изменяем им цвет на посветлее, затем немного их трансформируем до овалов, и разворачиваем при помощи rotate tool):
Теперь еще для красоты можно нарисовать при помощи пера парочку рефлексов и теней, и сыр готов:
Можете идти ловить мышей. Хотя... умея рисовать картинки в Иллюстраторе, вам будет не до мышей.
Событие - это какое-либо действие, осуществляемое пользователем либо браузером. Например, когда мы щелкаем (кликаем) на ссылке - осуществляется событие, его перехватывает специальный обработчик и перенаправляет нас на нужную страницу; при наведении курсора (указателя мыши) на ссылку в строке состояния (обычно находится в нижней части окна браузера) отображается адрес, так как обработчик "наведения курсора на объект (в данном случае на ссылку)" помещает туда этот адрес и так далее...
а). onmouseout и onmouseover
Для начала наведем курсор на кнопку "Сброс" или "Отправить" и обратим внимание на строку состояния. Вы должны увидеть там надпись с объяснением значения кнопки. Теперь отведите курсор и строка состояния очистится.
Содержимое строки состояния хранится в переменной window.status. Переменная это некоторый объект (можно представить себе ящик), значение которого (содержимое которого) можно изменять. Изменение значения осуществляется операцией присваивания (=), а выглядит она следующим образом:
имя_переменной = "значение"; (какие использовать кавычки: одинарные или двойные значения не имеет)
Поэтому для того, чтобы изменить надпись в строке состояния, нам нужно присвоить переменной window.status нужное нам значение (подсказку к кнопке), а когда курсор будет убран - присвоить пустую строку("").
Вся задача сводится к тому, чтобы определить когда пользователь наводит курсор на кнопку, а когда убирает его. Для этого нужно "сказать" обработчикам этих событий выполнить нужное нам действие. Обработчик события "наведение курсора" - onmouseover, а "отведение курсора" - onmouseout.
Очень многие тэги имеют атрибуты, начинающиеся с on (onclick, onmouseout, onfocus и т. д.). Значение этих атрибутов и есть, задача которую необходимо выполнить соответствующему обработчику. То есть для обработчика onmouseout есть атрибут onmouseout, для onmouseover - onmouseover. И в итоге мы получаем следующее определение кнопок:
Как Вы видите, атрибут onmouseover имеет в качестве значения JavaScript-код: window.status='Щелкните для отправки данных', как только курсор достигает кнопки, обработчик события mouseover - onmouseover, смотрит, что хранится в атрибуте onmouseover и выполняет необходимое действие(присвоение значения переменной window.status). Аналогично действует и обработчик события onmouseout: как только курсор уводиться от кнопки (то есть выполняется событие mouseout), то обработчик события - onmouseout выполняет код, содержащийся в атрибуте onmouseout.
То же самое и со второй кнопкой.
б). <a href="Java Scriptfunction()">Function</a>
Теперь щелкните на ссылке и откроется окошко с подсказкой. Но заметьте, что окно небольших размеров и у него нет панели инструментов - такого силами html не сделаешь! В данном примере мы имеем окно размером 300x200, без панелей инструментов, содержащее документ help.html.
Для того чтобы создать такое окошко существует следующий JavaScript-код:
где:
1. helpWindow - это имя переменной (как window.status, только в данном случае имя выбирается произвольно). Эта переменная нужна для последующей работы с окном (например, закрыть его нестандартным способом - с помощью JavaScript-сценария).
- Зачем? Не проще ли указывать просто имя открывающейся страницы, например help.html?
- А если у нас две копии одной и той же страницы? Или две страницы с одинаковым именем(например, в разных папках)? Вот для того, чтобы не перепутать страницы и свободно работать именно с тем окном с которым предполагаешь и сделанно, так чтобы "окно" присваивалось переменной, так как имя переменной можно выбрать любое.
2. window.open(что-то) - это функция. Функции выполняют определенную задачу, в данном случае window.open() открывает новое окно.
3. help.html - это страница, которую нужно открыть.
4. "" - В кавычках должно быть имя окна, но оно нам не пригодится, поэтому там нулевая строка. В следующих кавычках указываются "параметры открываемого окна": оно не должно содержать панели инструментов (toolbar=0) и должно быть шириной 300 пикселей, а высотой - 200 (width=300,height=200, соответственно).
Теперь все, что нужно это по событию "щелчка" выполнить этот код, однако есть два "но". Во-первых строка очень длинная, чтобы присвоить ее какому-либо атрибуту - будет некрасиво смотреться, да и вызывать неудобства при чтении кода страницы. Во-вторых, первоначальное предназначение ссылки - это переход на другую страницу, но нам переходить никуда не нужно, нам нужно выполнить вместо этого JavaScript-код.
Первое решается написанием функции. Как я уже говорил функция выполняет некоторую задача, причем для использования функции достаточно указать ее имя. Можно не только использовать предопределенные(функции, которые имеется в языке и без нас), но и писать их самому. Обычно функции определяются(пишутся) в разделе HEAD документа, в котором используются:
"function" значит, что дальше будет написана наша функция; help() - это имя функции (оно будет указываться вместо тела функции (между { и })).
Вторая проблема решается тоже довольно просто. Адрес страницы указывается в атрибуте href, а нам надо выполнить JavaScript код вместо перехода по ссылке:
"Java Script" означает, что дальше должен идти JavaScript-код, и что он должен выполняться вместо стандартного перехода по ссылке. В данном случае наш JavaScript-код - это созданная нами функция help().
в). onclick
Нам не остается ничего более, как закрыть окно со справкой. Для этого воспользуемся кнопкой "Закрыть". Но нас интересует то, как работает эта кнопка, а имеет она следующий вид:
Дабы закрыть окно мы сделали щелчок(Click) на кнопке "Закрыть", а щелчок это нажатие и отпускание кнопки мыши, причем и то и другое должно быть произведено на одном и том же элементе (например, на кнопке). Кликая, на кнопке мы активируем обработчик события onClick, который выполняет для нас JavaScript-код, прописанный в атрибуте onclick нашей кнопки. Помните мы открывали окно? Мы писали window.open(), а здесь тоже самое только window.close(). window - это текущее окно, а close() - закрыть.
Это одно из наиболее частоупотребляемых событий.
г). onfocus и onblur
Ну что ж будем ближе подбираться к вводу требуемой от нас информации.
Как я уже говорил: элемент получает фокус когда на нем происходит нажатие кнопки мыши, или на него осуществляется переход посредством клавиши табуляции (Tab), а теряет, когда фокус получает другой элемент. Наше поле для ввода получит фокус тогда, когда пользователь решиться ввести информацию. При этом было бы удобно, чтобы текст с подсказкой ("Введите Ваше имя") автоматически выделялся и посетитель мог его удалить одним нажатием на del, а не удалять по одному символу, или выделять текст вручную. Удобство пользователя свято. Итак, для этого мы воспользуемся событием focus. Для выделения текста используется метод select(). То есть атрибутом к полю надо прописать: onfocus="this.select();", this обозначает, что выделение должно происходить именно в этом текстовом поле (а можно прописать путь и к другому, но это не целесообразно).
А теперь попробуйте ничего не изменяя (или все удалив) убрать фокус (например, щелкнув в любом месте окна, или нажав Tab). Это событие blur, я прописал в нем выполнение функции: onblur="check();". Сама же функция имеет следующий вид (в разделе head страницы с формой между <script> и </script>):
document.forms[0].name.value - это то, что введено в текстовое поле. document - это текущий документ, forms[0] - первая форма на нашей страницы (отсчет с нуля), name = имя поля (задается атрибутом name (<input name="name">)), а value это и есть нужное нам значение (то, что введенно в текстовое поле, к которому м ы и написали путь). Введенное в поле мы присваиваем переменной val (var значит, что дальше идет имя переменной), чтобы в дальнейшем каждый раз не писать весь путь целиком.
Следующее это оператор if(если). Он выглядит следующим образом:
Мы сравниваем содержание переменной val с пустой строкой ('') и с начальной строкой ('Введите Ваше имя'). Обратите внимание, что сравнение не как в математике(с одним =), а сравниваются двума ==. || - или. Функция alert выводит окно с ошибкой (то, что в скобках - это текст ошибки). То есть:
И на всякий случай приведу целиком строку с кодом поля input:
д). onreset и onsubmit
Допустим, что пользователь заполнил форму неправильно, и он хочет очистить все поля формы одновременно: для этого он воспользуется стандартной кнопкой reset. Но что если пользователь щелкнет на ней по случайности (рука дрогнет, или в суете спутает с кнопкой submit), а форма была огромная, и он долго мучился ее заполнять..., ему будет грустно, и еще он будет долго материться. Поэтому хорошо бы у него дополнительно спросить: действительно ли он хочет очистить форму.
Вообще событие reset обрабатывается до очистки формы. А чтобы отменить очистку вообще, нам просто напросто надо вернуть обработчику события значение false, то есть прописать в соответствующем атрибуте: "return false;", а чтобы продолжить очистку: "return true;". А теперь вспомним функцию, которая выдает вопрос пользователю на подтверждение чего-либо, эта функция: "confirm('Вопрос?');". При нажатии "Ok", эта функция заменяется на true, а при нажатии "Cancel" на false. То есть все что от нас требуется, это прописать в теге <form> атрибут: onreset="return confirm('Вы действительно хотите сбросить форму?');". Тогда при нажатии "Ok" там на самом деле будет "return true;", и форма будет очищена, а если "Cancel", то "return false;" и очистка формы будет отменена.
Подобным образом действует событие submit, которое возникает при попытке отправить форму. Поскольку в нашем случае форму отправлять никуда не надо, то у меня просто написано: onsubmit="return false;". И сколько бы Вы не щелкали ничего не изменится (разве что Вы JavaScript отключите).
Обычно же обработчик onsubmit используется для верификации формы (то есть проверки на заполнение всех необходимых полей, правильность их заполнения, скажем, проверка по определенному шаблону и т. п.), для этого создается функция, которая выполняет все действия. Функция должна содержать операторы "return true" и "return false", которые позволяют, заменить функцию на true или false, соответственно, в зависимости от результатов проверки (если успешно, то true, если нет false). Но верификация данных это обширная тема, которая не может быть рассмотрена здесь. Один из примеров базовой верификации я привел, когда объяснял событие blur - подобную функцию можно использовать и здесь. Тогда <form> будет содержать атрибут: onsubmit="return function();".
Но не забывайте, что нельзя ограничиваться одной лишь проверкой языком JavaScript, ибо его поддержка может быть отключена у посетителя, и тогда все Ваши труды по защите...
е). onmousedown и onmouseup
Еще одна пара событий не нашла достойного места на странице, но я ее реализовал в виде кнопки "Button". Причем это не обычная html-кнопка, она реализована в виде двух картинок. Исходная кнопка хранится в файле с именем npressed.jpg, а нажатая - pressed.jpg. Чтобы достичь эффекта нажатия кнопки нам необходимо, чтобы при при щелчке на ней(this) значение атрибута src (путь к картинке) тега <img> менялось на pressed.jpg, а при отпускании обратно на npressed.jpg. Нажатие кнопки обрабатывает onmousedown, а отпускание - onmouseup, то есть здесь все просто:
ж). onload, onunload и onabort
Обработчик события onload активируется, когда начинает загружаться графическая часть страницы (все тексты, графика и т.п.). onload является атрибутом тега <body>. Если честно я не вижу сколько бы реального применения этому событию, зато я нашел, что можно сделать с onunload. onunload это тоже атрибут тега <body>. Событие unload происходит когда мы пытаемся покинуть данную страницу (переходим по ссылке на другую, закрываем окно браузера, обновляем страницу и т. д.). Откройте еще раз окошко справки. Допустим, что пользователь прочитал справку, и хочет отправить форму, или уйдет с нашего сайта, но при этом он забыл закрыть это маленькое окошко с подсказкой, мы на выходе закроем его сами. А для этого тег <body> (у начального документа) у нас будет выглядеть следующим образом:
Вы должны бы помнить, что helpWindow это имя нашего окна (ведь именно этой переменной мы присваивали его открытие: helpWindow = window.open("help.html", "", "toolbar=0,width=300,height=200")), а метод close() закрывает это окно. Некоторые нехорошие люди используют это событие, чтобы когда посетители уходили с его страницы, появлялись какие-либо окна, так называемые pop-up.
onabort - атрибут тега <img>. Когда пользователь отменяет загрузку изображения происходит событие abort. Но отмена загрузки изображения может не входить в наши плане. И в качестве предупреждения у нас может быть написано нечто похожее на
ЗАКЛЮЧЕНИЕ
Есть некоторые события о которых я здесь нарочно не упомянул, потому что не нашел им достойного применения, но Вам они возможно пригодятся, поэтому я уделю им немного внимания.
onchange - обработчик события, который активируется, когда Вы изменяете содержимое текстового элемента или текстовой области (<TEXTAREA>) (например, когда Вы вводите или удаляете очередную букву какого-либо текстового поля).
onselect - обработчик события выбора текста. То есть это событие происходит, когда пользователь пытается выделить текст в текстовом элементе или текстовой области.
onerror - обработчик события error, которое возникает при ошибке загрузки документа или изображения (то есть onerror это атрибут тегов <body> и <img>). Оно возникает при синтаксической ошибке JavaScript-кода (но Вы ведь не будете специально делать в нем ошибки), либо ошибкой времени выполнения (например, если Ваш скрипт выполняет какие-либо вычисления и у Вас по ошибке получится так, что некое число будет делиться на ноль, а это недопустимо - это и есть одна из ошибок времени выполнения).
Так же не забывайте, что я привел лишь по одному примеру из десятков возможных на каждое событие. Здесь главное Ваша фантазия и навыки. Например, события mouseout, mouseover, mouseup, mousedown часто используются для создания выпадающих меню и других визуальных эффектов, но это весьма трудный материал, который требует более глубоких знаний, причем не одного JavaScript.
Image Styler - замечательная программа для создания графики для Web. Особенно эта программа нравиться новичкам (тем, кто никогда не имел дело с графическими редакторами, или толком в них не разбираются).
Графика без труда (Image Styler).
Image Styler - замечательная программа для создания графики для Web. Особенно эта программа нравиться новичкам (тем, кто никогда не имел дело с графическими редакторами, или толком в них не разбираются).
Открываем Image Styler. По умолчанию программа уже создала новый документ. Теперь надо предать этому документу необходимый размер. Для этого надо выбрать пункты Edit - Canvas Size - и появится табличка, в которой можно задать нужные размеры листа. Создадим лист побольше ( width - 600, а height - 500). Потом можно сохранить свое меню как угодно, одной картинкой или несколькими, поэтому не обязательно делать много документов.
Что можно нарисовать на первых страницах? – кнопки и несложный логотип.
Как создавать кнопки.
Вызываем меню с основными функциями, выбрав пункт в верхнем меню Window - Tools.
В появившемся меню видны изображения: квадрата, квадрата с закругленными краями, круга и многоугольника - берем одну из этих опций (пусть будет квадрат) и рисуем квадрат нужных размеров.
Чтобы квадрат, который рисуем на белом фоне, был виден, надо задать ему цвет. Для этого выбираем пункт меню (вверху) Window - Color - появится таблица с цветами. И в этой таблице ищем нужный цвет квадрата.
Можно задать цвет сразу нескольких объектов, для этого надо выделить их все. Если надо создать кнопку определенных размеров, то тогда надо выбрать пункт меню Window - Tranform - здесь можно задать положение квадрата относительно листа (X, Y), размеры квадрата в пикселях (W, H), вращение (rotation) в градусах и наклон (skew) относительно горизонтали или вертикали. Для первого раза понадобятся параметры высоты и ширины (width и height). Допустим, что кнопку надо сделать на основе многоугольника. Рисуем - получаем ромб. Как сделать, чтобы углов было больше (пятиугольник, шестиугольник и т.д.)? Или меньше (треугольник)? Идем в меню: Window - Properties. Для работы с объектом (ромбом), надо его выделить. Теперь можно сделать его пятиугольником (шести... и т.д.) - sides - этот параметр задает количество сторон многоугольника (максимум 10). Можно сделать его рамкой-контуром (outlinе) и снова наполненным (fill). Если сделать многоугольник контуром, то нужно задать толщину контура (width) в пикселях.
Для разных объектов properties (свойства) разные. Чтобы понять работу со свойствами надо с ними поэкспериментировать.
Вернемся к квадрату. Нарисовали, раскрасили, задали нужный размер. Теперь как его сделать кнопкой? Очень просто - Window - Styles. Появится окошко со стилями. Выделяем квадрат или квадраты и выбираем нужный стиль (с тенью, без тени и любой другой).
Сделать надпись на кнопке тоже не очень сложно. Вернемся к основному меню (Tools). Жмем кнопку с буквой Т - это означает текст. Теперь левой кнопкой мыши щелкаем в любом месте нашего "листа" (помните, текст такой же объект как квадрат, вы можете задать ему Стиль, поменять также цвет, задать вращение и так далее). Появится обычная табличка (стандартная для всех графических и текстовых редакторов) со свойствами только для текста. Выбираем нужный шрифт, нужный размер шрифта, нужное расстояние между буквами. Когда все готово, выделяем текст и перемещаем его так, чтобы он был на квадрате - кнопка с текстом готова.
Стайлер может не понимать русский шрифт. В таком случае пишется нужный текст русскими буквами в блокноте (или другом текстовом редакторе), копируется и вставляется в Image Styler. Это неудобно, но не надо делать картинкой очень много текста.
Чтобы создать идентичные кнопки, но с другими надписями - выделяется квадрат с текстом. Edit - Copy. Edit - Paste. Появится точно такой же квадрат с точно таким же текстом. Отодвигаем его на свободное пространство листа (или выравниваем относительно первой кнопки с надписью). А теперь надо только изменить текст на новой кнопке. Для этого два раза щелкаем левой кнопкой мыши по тексту и вставляем (пишем) новую надпись. Вот так вы очень быстро можно создать меню.
Теперь как сохранить полученный рисунок? Как задать нужный формат (jpg, gif, png)? И можно ли чтобы программа сама написала HTML код для этого рисунка?
Опции для Экспорта картинок: Window - Export. Здесь можно выбрать нужный формат, выбрать какого качества будет картинка. И самое интересное - можно еще до сохранения увидеть, как будет выглядеть картинка, когда ее экспортируют (active preview - только надо поставить галочку).
Теперь немного о логотипе. Его также можно создать с помощью Image Styler. Рисуется опять квадрат. Теперь выбирается пункт меню Window - Shapes. Выделить квадрат и придать ему нужную форму. С помощью этой опции можно создавать много разных рисунков, хотя и незатейливых.
Также можно импортировать текстуры, картинки, нарисованные не в Image styler: File - Place as Texture. Таким образом, можно задать текстуру для всего листа (фон), для отдельного объекта, только надо не забывать перед эти нужное выделять.
P.S. Image Styler уже довольно старая программа и Adobe отказалась от ее совершенствовании. Но не стоит расстраиваться программа-то функциональная, да и одно из новых детищ Adobe - Live Motion - как близнец похоже на Image Styler (+ имеет новые, упрощающие вашу жизнь возможности)..
В этой статье я попытаюсь дать оценку быстродействию файловых систем, используемых в операционных системах WindowsNT/2000. Статья не содержит графиков и результатов тестирований, так как эти результаты слишком сильно зависят от случая, методик тестирования и конкретных систем, и не имеют почти никакой связи с реальным положением дел. В этом материале я вместо этого постараюсь описать общие тенденции и соображения, связанные с производительностью файловых систем. Прочитав данный материал, вы получите информацию для размышлений и сможете сами сделать выводы, понять, какая система будет быстрее в ваших условиях, и почему. Возможно, некоторые факты помогут вам также оптимизировать быстродействие своей машины с точки зрения файловых систем, подскажут какие-то решения, которые приведут к повышению скорости работы всего компьютера.
В данном обзоре упоминаются три системы - FAT (далее FAT16), FAT32 и NTFS, так как основной вопрос, стоящий перед пользователями Windows2000 - это выбор между этими вариантами. Я приношу извинение пользователям других файловых систем, но проблема выбора между двумя, внешне совершенно равнозначными, вариантами со всей остротой стоит сейчас только в среде Windows2000. Я надеюсь, всё же, что изложенные соображения покажутся вам любопытными, и вы сможете сделать какие-то выводы и о тех системах, с которыми вам приходится работать.
Данная статья состоит из множества разделов, каждый из которых посвящен какому-то одному вопросу быстродействия. Многие из этих разделов в определенных местах тесно переплетаются между собой. Тем не менее, чтобы не превращать статью в кашу, в соответствующем разделе я буду писать только о том, что имеет отношение к обсуждаемый в данный момент теме, и ни о чем более. Если вы не нашли каких-то важных фактов в тексте - не спешите удивляться: скорее всего, вы встретите их позже. Прошу вас также не делать никаких поспешных выводов о недостатках и преимуществах той или иной системы, так как противоречий и подводных камней в этих рассуждениях очень и очень много. В конце я попытаюсь собрать воедино всё, что можно сказать о быстродействии систем в реальных условиях.
Теория
Самое фундаментальное свойство любой файловой системы, влияющее на быстродействие всех дисковых операций - структура организации и хранения информации, т.е. то, как, собственно, устроена сама файловая система. Первый раздел - попытка анализа именно этого аспекта работы, т.е. физической работы со структурами и данными файловой системы. Теоретические рассуждения, в принципе, могут быть пропущены - те, кто интересуется лишь чисто практическими аспектами быстродействия файловых систем, могут обратиться сразу ко второй части статьи.
Для начала хотелось бы заметить, что любая файловая система так или иначе хранит файлы. Доступ к данным файлов - основная и неотъемлемая часть работы с файловой системой, и поэтому прежде всего нужно сказать пару слов об этом. Любая файловая система хранит данные файлов в неких объемах - секторах, которые используются аппаратурой и драйвером как самая маленькая единица полезной информации диска. Размер сектора в подавляющем числе современных систем составляет 512 байт, и все файловые системы просто читают эту информацию и передают её без какой либо обработки приложениям. Есть ли тут какие-то исключения? Практически нет. Если файл хранится в сжатом или закодированном виде - как это возможно, к примеру, в системе NTFS - то, конечно, на восстановление или расшифровку информации тратится время и ресурсы процессора. В остальных случаях чтение и запись самих данных файла осуществляется с одинаковой скоростью, какую файловую систему вы не использовали бы.
Обратим внимание на основные процессы, осуществляемые системой для доступа к файлам:
Поиск данных файла
Выяснение того, в каких областях диска хранится тот или иной фрагмент файла - процесс, который имеет принципиально разное воплощение в различных файловых системах. Имейте в виду, что это лишь поиск информации о местоположении файла - доступ к самим данным, фрагментированы они или нет, здесь уже не рассматривается, так как этот процесс совершенно одинаков для всех систем. Речь идет о тех "лишних" действиях, которые приходится выполнять системе перед доступом к реальным данным файлов.
На что влияет этот параметр: на скорость навигации по файлу (доступ к произвольному фрагменту файла). Любая работа с большими файлами данных и документов, если их размер - несколько мегабайт и более. Этот параметр показывает, насколько сильно сама файловая система страдает от фрагментации файлов.
NTFS способна обеспечить быстрый поиск фрагментов, поскольку вся информация хранится в нескольких очень компактных записях (типичный размер - несколько килобайт). Если файл очень сильно фрагментирован (содержит большое число фрагментов) - NTFS придется использовать много записей, что часто заставит хранить их в разных местах. Лишние движения головок при поиске этих данных, в таком случае, приведут к сильному замедлению процесса поиска данных о местоположении файла.
FAT32, из-за большой области самой таблицы размещения будет испытывать огромные трудности, если фрагменты файла разбросаны по всему диску. Дело в том, что FAT (File Allocation Table, таблица размещения файлов) представляет собой мини-образ диска, куда включен каждый его кластер. Для доступа к фрагменту файла в системе FAT16 и FAT32 приходится обращаться к соответствующей частичке FAT. Если файл, к примеру, расположен в трех фрагментах - в начале диска, в середине, и в конце - то в системе FAT нам придется обратиться к фрагменту FAT также в его начале, в середине и в конце. В системе FAT16, где максимальный размер области FAT составляет 128 Кбайт, это не составит проблемы - вся область FAT просто хранится в памяти, или же считывается с диска целиком за один проход и буферизируется. FAT32 же, напротив, имеет типичный размер области FAT порядка сотен килобайт, а на больших дисках - даже несколько мегабайт. Если файл расположен в разных частях диска - это вынуждает систему совершать движения головок винчестера столько раз, сколько групп фрагментов в разных областях имеет файл, а это очень и очень сильно замедляет процесс поиска фрагментов файла.
Вывод: Абсолютный лидер - FAT16, он никогда не заставит систему делать лишние дисковые операции для данной цели. Затем идет NTFS - эта система также не требует чтения лишней информации, по крайней мере, до того момента, пока файл имеет разумное число фрагментов. FAT32 испытывает огромные трудности, вплоть до чтения лишних сотен килобайт из области FAT, если файл разбросан разным областям диска. Работа с внушительными по размеру файлами на FAT32 в любом случае сопряжена с огромными трудностями - понять, в каком месте на диске расположен тот или иной фрагмент файла, можно лишь изучив всю последовательность кластеров файла с самого начала, обрабатывая за один раз один кластер (через каждые 4 Кбайт файла в типичной системе). Стоит отметить, что если файл фрагментирован, но лежит компактной кучей фрагментов - FAT32 всё же не испытывает больших трудностей, так как физический доступ к области FAT будет также компактен и буферизован.
Поиск свободного места
Данная операция производится в том случае, если файл нужно создать с нуля или скопировать на диск. Поиск места под физические данные файла зависит от того, как хранится информация о занятых участках диска.
На что влияет этот параметр: на скорость создания файлов, особенно больших. Сохранение или создание в реальном времени больших мультимедийных файлов (.wav, к примеру), копирование больших объемов информации, т.д. Этот параметр показывает, насколько быстро система сможет найти место для записи на диск новых данных, и какие операции ей придется для этого проделать.
Для определения того, свободен ли данный кластер или нет, системы на основе FAT должны просмотреть одну запись FAT, соответствующую этому кластеру. Размер одной записи FAT16 составляет 16 бит, одной записи FAT32 - 32 бита. Для поиска свободного места на диске может потребоваться просмотреть почти всего FAT - это 128 Кбайт (максимум) для FAT16 и до нескольких мегабайт (!) - в FAT32. Для того, чтобы не превращать поиск свободного места в катастрофу (для FAT32), операционной системе приходится идти на различные ухищрения.
NTFS имеет битовую карту свободного места, одному кластеру соответствует 1 бит. Для поиска свободного места на диске приходится оценивать объемы в десятки раз меньшие, чем в системах FAT и FAT32.
Вывод: NTFS имеет наиболее эффективную систему нахождения свободного места. Стоит отметить, что действовать "в лоб" на FAT16 или FAT32 очень медленно, поэтому для нахождения свободного места в этих системах применяются различные методы оптимизации, в результате чего и там достигается приемлемая скорость. (Одно можно сказать наверняка - поиск свободного места при работе в DOS на FAT32 - катастрофический по скорости процесс, поскольку никакая оптимизация невозможна без поддержки хоть сколь серьезной операционной системы).
Работа с каталогами и файлами
Каждая файловая система выполняет элементарные операции с файлами - доступ, удаление, создание, перемещение и т.д. Скорость работы этих операций зависит от принципов организации хранения данных об отдельных файлах и от устройства структур каталогов.
На что влияет этот параметр: на скорость осуществления любых операций с файлом, в том числе - на скорость любой операции доступа к файлу, особенно - в каталогах с большим числом файлов (тысячи).
FAT16 и FAT32 имеют очень компактные каталоги, размер каждой записи которых предельно мал. Более того, из-за сложившейся исторически системы хранения длинных имен файлов (более 11 символов), в каталогах систем FAT используется не очень эффективная и на первый взгляд неудачная, но зато очень экономная структура хранения этих самих длинных имен файлов. Работа с каталогами FAT производится достаточно быстро, так как в подавляющем числе случаев каталог (файл данных каталога) не фрагментирован и находится на диске в одном месте.
Единственная проблема, которая может существенно понизить скорость работы каталогов FAT - большое количество файлов в одном каталоге (порядка тысячи или более). Система хранения данных - линейный массив - не позволяет организовать эффективный поиск файлов в таком каталоге, и для нахождения данного файла приходится перебирать большой объем данных (в среднем - половину файла каталога).
NTFS использует гораздо более эффективный способ адресации - бинарное дерево, о принципе работы которого можно прочесть в другой статье (Файловая система NTFS). Эта организация позволяет эффективно работать с каталогами любого размера - каталогам NTFS не страшно увеличение количества файлов в одном каталоге и до десятков тысяч.
Стоит заметить, однако, что сам каталог NTFS представляет собой гораздо менее компактную структуру, нежели каталог FAT - это связано с гораздо большим (в несколько раз) размером одной записи каталога. Данное обстоятельство приводит к тому, что каталоги на томе NTFS в подавляющем числе случаев сильно фрагментированы. Размер типичного каталога на FAT-е укладывается в один кластер, тогда как сотня файлов (и даже меньше) в каталоге на NTFS уже приводит к размеру файла каталога, превышающему типичный размер одного кластера. Это, в свою очередь, почти гарантирует фрагментацию файла каталога, что, к сожалению, довольно часто сводит на нет все преимущества гораздо более эффективной организации самих данных.
Вывод: структура каталогов на NTFS теоретически гораздо эффективнее, но при размере каталога в несколько сотен файлов это практически не имеет значения. Фрагментация каталогов NTFS, однако, уверенно наступает уже при таком размере каталога. Для малых и средних каталогов NTFS, как это не печально, имеет на практике меньшее быстродействие.
Преимущества каталогов NTFS становятся реальными и неоспоримыми только в том случае, если в одно каталоге присутствуют тысячи файлов - в этом случае быстродействие компенсирует фрагментированность самого каталога и трудности с физическим обращением к данным (в первый раз - далее каталог кэшируется). Напряженная работа с каталогами, содержащими порядка тысячи и более файлов, проходит на NTFS буквально в несколько раз быстрее, а иногда выигрыш в скорости по сравнению с FAT и FAT32 достигает десятков раз.
Практика
К сожалению, как это часто бывает во всевозможных компьютерных вопросах, практика не очень хорошо согласуется с теорией. NTFS, имеющая, казалось бы, очевидные преимущества в структуре, показывает не настолько уж фантастические результаты, как можно было бы ожидать. Какие еще соображения влияют на быстродействие файловой системы? Каждый из рассматриваемых далее вопросов вносит свой вклад в итоговое быстродействие. Помните, однако, что реальное быстродействие - результат действия сразу всех факторов, поэтому и в этой части статьи не стоит делать поспешных выводов.
Объем оперативной памяти (кэширование)
Очень многие данные современных файловых систем кэшируются или буферизируются в памяти компьютера, что позволяет избежать лишних операций физического чтения данных с диска. Для нормальной (высокопроизводительной) работы системы в кэше приходится хранить следующие типы информации:
Данные о физическом местоположении всех открытых файлов. Это, прежде всего, позволит обращаться к системным файлам и библиотекам, доступ к которым идет буквально постоянно, без чтения служебной (не относящейся к самим файлам) информации с диска. Это же относится к тем файлам, которые исполняются в данный момент - т.е. к выполняемым модулям (.exe и .dll) активных процессов в системе. В эту категорию попадают также файлы системы, с которыми производится работа (прежде всего реестр и виртуальная память, различные .ini файлы, а также файлы документов и приложений).
Наиболее часто используемые каталоги. К таковым можно отнести рабочий стол, меню "пуск", системные каталоги, каталоги кэша интернета, и т.п.
Данные о свободном месте диска - т.е. та информация, которая позволит найти место для сохранения на диск новых данных.
В случае, если этот базовый объем информации не будет доступен прямо в оперативной памяти, системе придется совершать множество ненужных операций еще до того, как она начнет работу с реальными данными. Что входит в эти объемы в разных файловых системах? Или, вопрос в более практической плоскости - каким объемом свободной оперативной памяти надо располагать, чтобы эффективно работать с той или иной файловой системой?
FAT16 имеет очень мало данных, отвечающих за организацию файловой системы. Из служебных областей можно выделить только саму область FAT, которая не может превышать 128 Кбайт (!) - эта область отвечает и за поиск фрагментов файлов, и за поиск свободного места на томе. Каталоги системы FAT также очень компактны. Общий объем памяти, необходимый для предельно эффективной работы с FAT-ом, может колебаться от сотни килобайт и до мегабайта-другого - при условии огромного числа и размера каталогов, с которыми ведется работа.
FAT32 отличается от FAT16 лишь тем, что сама область FAT может иметь более внушительные размеры. На томах порядка 5 - 10 Гбайт область FAT может занимать объем в несколько Мбайт, и это уже очень внушительный объем, надежно кэшировать который не представляется возможным. Тем не менее, область FAT, а вернее те фрагменты, которые отвечают за местоположение рабочих файлов, в подавляющем большинстве систем находятся в памяти машины - на это расходуется порядка нескольких Мбайт оперативной памяти.
NTFS, к сожалению, имеет гораздо большие требования к памяти, необходимой для работы системы. Прежде всего, кэширование сильно затрудняет большие размеры каталогов. Размер одних только каталогов, с которыми активно ведет работу система, может запросто доходить до нескольких Мбайт и даже десятков Мбайт! Добавьте к этому необходимость кэшировать карту свободного места тома (сотни Кбайт) и записи MFT для файлов, с которыми осуществляется работа (в типичной системе - по 1 Кбайт на каждый файл). К счастью, NTFS имеет удачную систему хранения данных, которая не приводит к увеличению каких-либо фиксированных областей при увеличении объема диска. Количество данных, с которым оперирует система на основе NTFS, практически не зависит от объема тома, и основной вклад в объемы данных, которые необходимо кэшировать, вносят каталоги. Тем не менее, уже этого вполне достаточно для того, чтобы только минимальный объем данных, необходимых для кэширования базовых областей NTFS, доходил до 5 - 8 Мбайт.
[pagebreak]
К сожалению, можно с уверенностью сказать: NTFS теряет огромное количество своего теоретического быстродействия из-за недостаточного кэширования. На системах, имеющих менее 64 Мбайт памяти, NTFS просто не может оказаться быстрее FAT16 или FAT32. Единственное исключение из этого правила - диски FAT32, имеющие объем десятки Гбайт (я бы лично серьезно опасался дисков FAT32 объемом свыше, скажем, 30 Гбайт). В остальных же случаях - системы с менее чем 64 мегабайтами памяти просто обязаны работать с FAT32 быстрее.
Типичный в настоящее время объем памяти в 64 Мбайта, к сожалению, также не дает возможности организовать эффективную работу с NTFS. На малых и средних дисках (до 10 Гбайт) в типичных системах FAT32 будет работать, пожалуй, немного быстрее. Единственное, что можно сказать по поводу быстродействия систем с таким объемом оперативной памяти - системы, работающие с FAT32, будут гораздо сильнее страдать от фрагментации, чем системы на NTFS. Но если хотя бы изредка дефрагментировать диски, то FAT32, с точки зрения быстродействия, является предпочтительным вариантом. Многие люди, тем не менее, выбирают в таких системах NTFS - просто из-за того, что это даст некоторые довольно важные преимущества, тогда как типичная потеря быстродействия не очень велика.
Системы с более чем 64 Мбайтами, а особенно - со 128 Мбайт и более памяти, смогут уверенно кэшировать абсолютно всё, что необходимо для работы систем, и вот на таких компьютерах NTFS, скорее всего, покажет более высокое быстродействие из-за более продуманной организации данных. В наше время этим показателям соответствует практически любой компьютер.
Быстродействие накопителя
Влияют ли физические параметры жесткого диска на быстродействие файловой системы? Да, хоть и не сильно, но влияют. Можно выделить следующие параметры физической дисковой системы, которые по-разному влияют на разные типы файловых систем:
Время случайного доступа (random seek time). К сожалению, для доступа к системным областям на типичном диске более сложной файловой системы (NTFS) приходится совершать, в среднем, больше движений головками диска, чем в более простых системах (FAT16 и FAT32). Гораздо большая фрагментация каталогов, возможность фрагментации системных областей - всё это делает диски NTFS гораздо более чувствительными к скорости считывания произвольных (случайных) областей диска. По этой причине использовать NTFS на медленных (старых) дисках не рекомендуется, так как высокое (худшее) время поиска дорожки дает еще один плюс в пользу систем FAT.
Наличие Bus Mastering. Bus Mastering - специальный режим работы драйвера и контроллера, при использовании которого обмен с диском производится без участия процессора. Стоит отметить, что система запаздывающего кэширования NTFS сможет действовать гораздо более эффективно при наличии Bus Mastering, т.к. NTFS производит отложенную запись гораздо большего числа данных. Системы без Bus Mastering в настоящее время встречаются достаточно редко (обычно это накопители или контроллеры, работающие в режиме PIO3 или PIO4), и если вы работаете с таким диском - то, скорее всего, NTFS потеряет еще пару очков быстродействия, особенно при операциях модификации каталогов (например, активная работа в интернете - работа с кэшем интернета).
Кэширование как чтения, так и записи на уровне жестких дисков (объем буфера HDD - от 128 Кбайт до 1-2 Мбайт в современных дорогих дисках) - фактор, который будет более полезен системам на основе FAT. NTFS из соображений надежности хранения информации осуществляет модификацию системных областей с флагом "не кэшировать запись", поэтому быстродействие системы NTFS слабо зависит от возможности кэширования самого HDD. Системы FAT, напротив, получат некоторый плюс от кэширования записи на физическом уровне. Стоит отметить, что, вообще говоря, всерьез принимать в расчет размер буфера HDD при оценке быстродействия тех или иных файловых систем не стоит.
Подводя краткий итог влиянию быстродействия диска и контроллера на быстродействия системы в целом, можно сказать так: NTFS страдает от медленных дисков гораздо сильнее, чем FAT.
Размер кластера
Хотелось бы сказать пару слов о размере кластера - тот параметр, который в файловых системах FAT32 и NTFS можно задавать при форматировании практически произвольно. Прежде всего, надо сказать, что больший размер кластера - это практически всегда большее быстродействие. Размер кластера на томе NTFS, однако, имеет меньшее влияние на быстродействие, чем размер кластера для системы FAT32.
Типичный размер кластера для NTFS - 4 Кбайта. Стоит отметить, что при большем размере кластера отключается встроенная в файловую систему возможность сжатия индивидуальных файлов, а также перестает работать стандартный API дефрагментации - т.е. подавляющее число дефрагментаторов, в том числе встроенный в Windows 2000, будут неспособны дефрагментировать этот диск. SpeedDisk, впрочем, сможет - он работает без использования данного API. Оптимальным с точки зрения быстродействия, по крайней мере, для средних и больших файлов, считается (самой Microsoft) размер 16 Кбайт. Увеличивать размер далее неразумно из-за слишком больших расходов на неэффективность хранения данных и из-за мизерного дальнейшего увеличения быстродействия. Если вы хотите повысить быстродействие NTFS ценой потери возможности сжатия - задумайтесь о форматировании диска с размером кластера, большим чем 4 Кбайта. Но имейте в виду, что это даст довольно скромный прирост быстродействия, который часто не стоит даже уменьшения эффективности размещения файлов на диске.
Быстродействие системы FAT32, напротив, можно довольно существенно повысить, увеличив размер кластера. Если в NTFS размер кластера почти не влияет на размер и характер данных системных областей, то в системе FAT увеличивая кластер в два раза, мы сокращаем область FAT в те же два раза. Вспомните, что в типичной системе FAT32 эта очень важная для быстродействия область занимает несколько Мбайт. Сокращение области FAT в несколько раз даст заметное увеличение быстродействия, так как объем системных данных файловой системы сильно сократиться - уменьшается и время, затрачиваемое на чтение данных о расположении файлов, и объем оперативной памяти, необходимый для буферизирования этой информации. Типичный объем кластера для систем FAT32 составляет тоже 4 Кбайт, и увеличение его до 8 или даже до 16 Кбайт - особенно для больших (десяток и более гигабайт) дисков - достаточно разумный шаг.
Другие соображения
NTFS является достаточно сложной системой, поэтому, в отличие от FAT16 и FAT32, имеются и другие факторы, которые могут привести к существенному замедлению работы NTFS:
Диск NTFS был получен преобразованием раздела FAT16 или FAT32 (команда convert). Данная процедура в большинстве случаев представляет собой тяжелый случай для быстродействия, так как структура служебных областей NTFS, скорее всего, получится очень фрагментированной. Если есть возможность - избегайте преобразования других систем в NTFS, так как это приведет к созданию очень неудачного диска, которому не поможет даже типичный (неспециализированный) дефрагментатор, типа Diskeeper-а или встроенного в Windows 2000.
Активная работа с диском, заполненным более чем на 80% - 90%, представляет собой катастрофический для быстродействия NTFS случай, так как фрагментация файлов и, самое главное, служебных областей, будет расти фантастически быстро. Если ваш диск используется в таком режиме - FAT32 будет более удачным выбором при любых других условиях.
Выводы
В данной заключительной части "одной строчкой" собраны ключевые особенности быстродействия этих трех файловых систем.
FAT - плюсы:
Для эффективной работы требуется немного оперативной памяти.
Быстрая работа с малыми и средними каталогами.
Диск совершает в среднем меньшее количество движений головок (в сравнении с NTFS).
Эффективная работа на медленных дисках.
FAT - минусы:
Катастрофическая потеря быстродействия с увеличением фрагментации, особенно для больших дисков (только FAT32).
Сложности с произвольным доступом к большим (скажем, 10% и более от размера диска) файлам.
Очень медленная работа с каталогами, содержащими большое количество файлов.
NTFS - плюсы:
Фрагментация файлов не имеет практически никаких последствий для самой файловой системы - работа фрагментированной системы ухудшается только с точки зрения доступа к самим данным файлов.
Сложность структуры каталогов и число файлов в одном каталоге также не чинит особых препятствий быстродействию.
Быстрый доступ к произвольному фрагменту файла (например, редактирование больших .wav файлов).
Очень быстрый доступ к маленьким файлам (несколько сотен байт) - весь файл находится в том же месте, где и системные данные (запись MFT).
NTFS - минусы:
Существенные требования к памяти системы (64 Мбайт - абсолютный минимум, лучше - больше).
Медленные диски и контроллеры без Bus Mastering сильно снижают быстродействие NTFS.
Работа с каталогами средних размеров затруднена тем, что они почти всегда фрагментированы.
Диск, долго работающий в заполненном на 80% - 90% состоянии, будет показывать крайне низкое быстродействие.
Хотелось бы еще раз подчеркнуть, что на практике основной фактор, от которого зависит быстродействие файловой системы - это, как ни странно, объем памяти машины. Системы с памятью 64-96 Мбайт - некий рубеж, на котором быстродействие NTFS и FAT32 примерно эквивалентно. Обратите внимание также на сложность организации данных на вашей машине. Если вы не используете ничего, кроме простейших приложений и самой операционной системы - может случиться так, что FAT32 сможет показать более высокое быстродействие и на машинах с большим количеством памяти.
NTFS - система, которая закладывалась на будущее, и это будущее для большинства реальных применений сегодняшнего дня еще, к сожалению, видимо не наступило. На данный момент NTFS обеспечивает стабильное и равнодушное к целому ряду факторов, но, пожалуй, всё же невысокое - на типичной "игровой" домашней системе - быстродействие. Основное преимущество NTFS с точки зрения быстродействия заключается в том, что этой системе безразличны такие параметры, как сложность каталогов (число файлов в одном каталоге), размер диска, фрагментация и т.д. В системах FAT же, напротив, каждый из этих факторов приведет к существенному снижению скорости работы.
Только в сложных высокопроизводительных системах - например, на графических станциях или просто на серьезных офисных компьютерах с тысячами документов, или, тем более, на файл-серверах - преимущества структуры NTFS смогут дать реальный выигрыш быстродействия, который порой заметен невооруженным глазом. Пользователям, не имеющим большие диски, забитые информацией, и не пользующимся сложными программами, не стоит ждать от NTFS чудес скорости - с точки зрения быстродействия на простых домашних системах гораздо лучше покажет себя FAT32.