Примечание - большая часть написанного здесь текста с примерами взята по памяти (пару лет назад изучал достаточно подробно, поэтому может что-то в алгоритмах не работать - я ведь их не копировал откуда-то, а прямо тут же и писал, так что за синтаксические ошибки не пинайте) - на данный момент я активно 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-разрядных ОС использовать именно реестр, но лично я считаю, что инифайлы удобнее, так как при при переносе программы на другой компьютер, нужно перенести только один инифайл, а во-вторых, если вы что-нибудь в реестре случайно удалите, то может случиться каюк.
Часто работая в Фотошоп, приходится выполнять целый ряд постоянно повторяющихся операций. Такие операции выстраиваясь определенным образом, образуют цепочку команд - макропоследовательностей. Чтобы не повторять последовательность одних и тех же команд снова и снова, можно задействовать инструменты автоматизации. Одним из таких инструментов является Actions.
Автоматизация работы в Photoshop.
Часто работая в Фотошоп, приходится выполнять целый ряд постоянно повторяющихся операций. Такие операции выстраиваясь определенным образом, образуют цепочку команд - макропоследовательностей. Чтобы не повторять последовательность одних и тех же команд снова и снова, можно задействовать инструменты автоматизации. Одним из таких инструментов является Actions. Action - это записанный набор команд, которые можно быстро повторить. За такими макропоследовательностями также можно закреплять клавиатурные сокращения, то есть для их выполнения достаточно нажать клавишу или сочетание клавиш.
Для работы с Actions используется одноименная палитра. Чтобы увидеть эту палитру, следует выполнить команду Window>Actions или нажать клавишу F9.
Стандартные Actions
По умолчанию в Photoshop уже есть стандартный набор записанных команд, поэтому списки последовательно выполняющихся команд можно создавать самостоятельно, а можно воспользоваться уже готовыми. Например, используя стандартный макрос для создания виньетки (Vignette), достаточно выделить область на изображении и нажать кнопку его запуска.
Таким образом, все макропоследовательности состоят из команд, которые являются последними ступеньками в раскрывающемся списке.
Для удобства работы, макропоследовательности объединяются в наборы - Sets. Например, можно создать набор, в котором будут собраны макросы для работы с текстом, для создания различных текстур и т.д. По умолчанию в Photoshop есть набор Default Actions.
Палитра Actions содержит наборы различных последовательностей. Чтобы их увидеть, необходимо щелкнуть на треугольнике, расположенном слева от названия набора. После этого перед вами появится список действий, любое из которых может быть выполнено. Если вы хотите увидеть, из каких операций состоят действия, то следует щелкнуть на треугольнике, расположенном слева от них.
Внизу палитры расположены кнопки, позволяющие управлять действиями - создавать новые, запускать и останавливать запись и т.д.
Просмотрите все предлагаемые Actions на изображении с небольшим разрешением (на нем макрокоманды будут выполняться быстрее). После такого просмотра можно сформировать свою палитру, оставив понравившиеся элементы и удалив те, которые вам никогда не пригодятся. Можно также изменить названия, чтобы стало понятнее, где какая возможность скрывается.
Если какое-нибудь действие вам очень понравилось, то посмотрите, как оно было сделано. Для этого следует обратиться к палитре Actions и, раскрыв все списки, просмотреть последовательность выполняемых операций.
Лучше всего не только просмотреть, как выполнялись операции, но и попытаться добиться такого же эффекта, проделав самостоятельно все действия, особенно если вы неопытный пользователь. Это поможет лучше узнать программу, а также ознакомиться с возможностями, которые она предоставляет. Кроме того, в процессе работы можно будет изменить некоторые параметры, подобрав их для конкретного изображения.
Создание собственных макрокоманд
Можно не только пользоваться готовыми макрокомандами, но и создавать свои собственные.
Приведем пример ситуации, в которой они могу оказаться полезными. Предположим, вы хотите выложить фотографии в интернете. Прежде чем публиковать их в сети, нужно выполнить цветокоррекцию и уменьшить размер. Допустим, вы решили делать цветокоррекцию в режиме Lab Color.
Рассмотрим список действий, которые необходимо выполнить с каждым изображением:
1) Выполнить команду Image>Mode>Lab Color, чтобы перевести снимок в цветовое пространство Lab Color.
2) Повысить четкость изображения, для чего нужно перейти на палитру Channels, выделить канал Lightness и применить к нему фильтр Sharpen>Unsharp Mask. Благодаря тому, что фильтр применяется в канале освещенности, можно повысить резкость изображения, не затрагивая цветовую составляющую.
3) Улучшить цвета на изображении, для чего нужно выделить цветовой канал b, вызвать окно редактирования кривых, выполнив команду Image>Adjustments>Curves или же используя сочетание клавиш CTRL+M, и изменить форму кривой. Чем круче график кривой, тем более контрастным становится изображение в канале, и тем более насыщенными становятся цвета на снимке.
4) Выделить цветовой канал a и проделать те же действия с изменением формы кривой.
5) Наконец, нужно изменить размер изображения, используя команду Image>Image Size.
Если после этого отобразить палитру History, можно увидеть, что пришлось выполнить целый ряд команд и действий, чтобы обработать фотографию. Эти действия нужно было бы повторять с каждой следующей фотографией, которую вы хотите выложить в интернете.
Задачу можно существенно упростить, используя Actions. Вернемся к исходному изображению, используя палитру History, и создадим собственный макрос. Сначала создадим новую группу для хранения макросов. Для этого нужно нажать кнопку Create New Set в нижней части палитры Actions.
В окне New Set введим название набора команд. Создадим в новой группе первый макрос, нажав кнопку Create New Action. В появившемся окне New Action выберем название макроса и клавишу, при нажатии которой он будет запускаться, например, F11. Для вызова макропоследовательностей можно использовать клавиши F2-F12, а также их сочетания с клавишами CTRL и Shift.
Для начала записи необходимо нажать кнопку Record в нижней части палитры Actions. Теперь любая команда, выполненная в Photoshop, будет запоминаться до тех пор, пока вы не остановите запись макроса.
Скроем палитру Actions, чтобы она не мешала, и повторим выполненные ранее действия: переведем изображение в Lab Color, увеличим резкость, изменим цветопередачу и уменьшим размер изображения при помощи команды Image Size.
После этого вернемся на палитру Actions и остановим запись, нажав кнопку Stop Playing/Recording. В списке нашего макроса можно увидеть записанную последовательность команд. Также рядом с названием макроса отображается горячая клавиша, которая выбрана для его запуска.
Чтобы проверить действие макроса, вернемся к исходному изображению, используя палитру History, и нажмем горячую клавишу, которую вы выбрали для выполнения макроса. Можно убедиться, что все действия выполняются автоматически и довольно быстро. Макрос также можно запускать, нажимая кнопку Play Selecтion в нижней части палитры Actions, если предварительно выделить его в списке макрокоманд.
Записав макрос, посмотрите, как макрокоманда сработает на другой фотографии. Откройте изображение в Photoshop и снова запустите макрос горячей клавишей. Как вы можете убедиться, макрос работает.
Таким образом, благодаря макросам на подготовку фотографий для публикации в интернете может уходить гораздо меньше времени. Достаточно нажать горячую клавишу - и можно сохранять изображение.
Сохранение макрокоманд
В ряде случаев, например, при переустановке системы или при необходимости использовать созданные ранее макросы на другом компьютере, возникает необходимость сохранить Actions. Такая возможность предусмотрена в Photoshop.
Actions нельзя сохранять по отдельности, только в наборах. Поэтому для сохранения макропоследовательностей выделите на палитре Actions тот набор, в который они входят, после чего нажмите миниатюрную кнопку, расположенную в верхней правой части палитры (под кнопкой для сворачивания палитры) и выберите команду Save Actions. Если при этом будет выделен не набор, а отдельный макрос, эта команда будет неактивна.
Наборы макросов сохраняются в файлы с расширением ATN. Для загрузки сохраненного ранее набора в Photoshop необходимо щелкнуть по той же кнопке на палитре Actions и выбрать команду Load Actions.
Инструмент Batch
В Photoshop есть еще одно средство для автоматизации, которое удобно использовать вместе с Actions. Это - инструмент пакетной обработки Batch. С его помощью можно применить макропоследовательность к группе файлов, даже не открывая их в Photoshop.
Приведем простой пример использования этого инструмента. Предположим, необходимо перед публикацией фотографий в интернете защитить свое авторское право. Для этого можно добавить на фотографии какой-нибудь текст, например, адрес сайта.
Для начала запишем в макрос все действия, которые необходимо выполнить. Создадим новый Action и начнем запись. Макрос будет состоять из трех действий: добавление на изображение текста, сохранение изображения в формате JPEG и закрытие исходного файла. После выполнения этих операций остановим запись макроса.
Выполним команду File>Automate>Batch. В окне Batch необходимо установить настройки пакетной обработки файлов. В разделе Play выбирается группа, в которую сохранен макрос и его название.
В разделе Source необходимо указать путь к папке, содержащей исходные файлы. Если установить флажок Include All Subfolders, то будут обработаны и файлы, которые находятся во вложенных папках.
В разделе Destination устанавливаются параметры сохранения файлов. Если выбрать в этом списке вариант None, то файлы не будут сохраняться автоматически. Вместо этого Photoshop будет выдавать запрос на сохранение каждого файла. При выборе варианта Save and close файлы будут сохранены в ту же папку, где хранятся исходные изображения.
Для того чтобы файлы были автоматически сохранены, нужно выбрать в списке Destination вариант Save and close. При выборе варианта Folder появляется возможность указать папку для сохранения обработанных файлов. Кроме этого, можно переименовать их, используя маску. Название файла может включать исходное имя, представленное строчными или заглавными буквами, дату выполнения операции в разных форматах, порядковый номер, букву алфавита, расширение.
Флажок Override Action Save As Commands нужно использовать осторожно. Если он установлен, то файлы будут сохранены только в том случае, если операция сохранения является одним из шагов макроса.
Для запуска пакетной обработки необходимо закрыть окно Batch, нажав кнопку OK. После этого файлы будут один за другим открываться в Photoshop, к ним будут применяться заданные операции, после чего они будут закрываться и сохраняться.
Batch и Actions - это очень полезные инструменты Photoshop, которые могут сэкономить не один час времени. Кроме этого, Actions могут стать хорошим пособием для изучения программы - загрузите в Photoshop наборы макропоследовательностей, созданные опытными пользователями, и пошагово разберите, как они работают.
Эта первая статья, которая открывает цикл статей о работе с графическим редактором Corel Draw. Думаю, они помогут всем желающим обучится работать с векторной графикой. Раскрыть для себя все возможности вектора.
Попробуем нарисовать время, а верней его оболочку в виде песочных часов.
Corel Draw. Рисуем часы.
Эта первая статья, которая открывает цикл статей о работе с графическим редактором Corel Draw. Думаю, они помогут всем желающим обучится работать с векторной графикой. Раскрыть для себя все возможности вектора.
Попробуем нарисовать время, а верней его оболочку в виде песочных часов.
1. Инструментом Ellipse Tool (F7) рисуем круг, для ровного круга зажимаем Ctrl, затем конвертируем круг в кривую Arrange-Convert to curves(Ctrl+Q)
взяв нижнюю точку, приспустим её вниз, как на рисунке!
2. Копируем этот овал (Shift+ тащим Pick Tool к середине объекта) и немного дорабатываем его форму, сделаем его немного тупее (кстати, скопируйте этот внутренний овал и положите его в уголок, он нам еще пригодится!).
3. выделим первые два объекта и скопируем их вниз (выделяем Pick tool, зажимаем Ctrl и тащим)
полученные объекты немного вытянем из верхней точки, как рисунке. На нём, кстати, не очень видно у вас должно быть поострее! Делаем мы это специально потому, что на наши будущие часы мы будем смотреть немного сверху!
4. Теперь инструментом Elipse Tool (F7) нарисуем овал, скопируем его и расположим как на рисунке, сверху инструментом Rectangle Tool рисуем прямоугольник!
5. Обрезаем кружками квадрат, для этого сначала выделяем круг, затем квадрат (зажав Shift) и щелкаем по кнопке Trim.
Повторяем это всё со вторым кругом.
6. Теперь выделим два больших овала и нажмем Weld! Смотрим, что получилось!
кстати, на этом этапе при объединении могут получиться лишние точки их надо удалить, и если надо поменять тип точки
7. Такой же трюк проделываем с внутренними овалами.
У нас уже есть колба для песка она конечно одна но будем называть её двумя объектами большой колбой и малой (внутренней).
Возьмите внутреннюю "колбу" и вырежьте отверстие. Но её не удаляйте!
8. Теперь берем опять инструмент Elise Tool (F7), рисуем овал, затем копируем его и размещаем две копии наверху,
чем выше круг тем он должен быть уже! Дорисуем два прямоугольника, как на рисунке!
9. Выделим пять последних фигур, скопируем и утащим вниз объекта ( отзеркалив их) и забудем о них на некоторое время!
10. Сосредоточим внимание на верхней части!
Объединим нижний овал с большим прямоугольником. Как объединять объекты вы уже знаете.
Теперь объединим средний овал и небольшой прямоугольник. Если вы зальёте эти объекты, получится как на рисунке.
11. Заливаем объекты инструментом Fountain Fill Dialog (F11) или кликаем по палитре сбоку левой кнопкой мыши.
Если вдруг у вас объекты будут расположены в другой последовательности, то для того что бы верхний овал был самым верхним, жмем Shift+Page Up (самым нижним Shift+Page Down) если надо сместить только на один слой Ctrl+Page Up (Down)
Не уделяйте сейчас внимание заливке, о ней поговорим потом.
12. Теперь пошли вниз. Почему мы просто не копируем верхнюю часть? Потому что линия горизонта над предметом низ нам видно больше и вид там будет совершенно другой.
Рисуем заново все объекты или используете то, что вначале утащили вниз в запасник!
Берем овал, обратите внимание, как он расположен и растяните его по высоте, теперь мы видим его больше. Смело копируйте его в середину!
Вырежьте меньшим дырку в большем. Он обозначен желтым цветом! Меньший положим сбоку, потом еще попользуем!
13. Скопируем колечко и уменьшим его немного, смотрите как на рисунке. Для того, что бы было понятнее, назовём колечки 1(большее) и 2(меньшее).
Берем колечко 1-нарисуйте любую форму и обрежьте им колечко, можно обрезать тем овалом, что мы отложили. Обратите внимание на уголки!
14. Берем запасное кольцо 2, располагаем, как на рисунке затем рисуем овал и обрезаем им колечко, с помощью Intersectin. Полученная форма выделена зеленым. Теперь совместим их.
Это будет наше преломление стеклом. Если бы у нас был фон с узорами, он бы тоже должен был преломиться!
15. Дальше уже известным нам методом объединения и обрезки, получаем из прямоугольника и овала, нижнюю часть подставки. Помним что овал у нас теперь очень широкий.
16. Дорисовываем основание подставки тем же методом, что и верх. Здесь используется объединение готовых форм потому что нам важно сделать симметричный объект. Возьмем отложенный овал и подложим его в самый низ!
17. Вот почти всё готово! Меньшую "колбу" заливаем и делаем ей прозрачность инструментом Interactive transparenci Tool
Заливаем все, чтоб нам было понятно, что это у нас такое! А это часы без песка!
18. Теперь рисуем сам песок. Сначала рисуем овал, наклоняем его, на рисунке песок сыплется немного наклонно.
Затем рисуем прямоугольник. Сначала выделяем малую ”колбу”, затем новоиспеченный прямоугольник и жмем Intersect!
Подгоняем точки по узкой форме и заливаем цветом песка. Можно продлить этот объект вниз и нарисовать как бы падающую струйку песка. Добавим несколько песчинок для декоративности.
19.На самом верхнем овале песка нарисуем поменьше, зальем более темным цветом и применим интерактивное перетекание Interactive Blend Tool.
Ниже нарисуем небольшую горку упавшего песка. И заливаем просто градиентной заливкой.
20. А теперь самое важное - рисуем блики. Чем больше бликов, тем лучше! Мы можем скопировать меньшую колбу и деформируя её по нескольким точкам также добавить блики. Очень удобно брать её как основу, потому что блики должны идти именно по её форме. Здесь нам пригодится отложенный в начале овал, его тоже удобней подгонять по форме колбы.
Рисуем мелкие блики, деформируя круги по точкам! Затем заливаем и применяем прозрачность.
21. Теперь дорабатываем заливку.
Добавим тени!
Рисуем овал, добавляем тень инструментом Interactive Droр Shadow Tool. Отделим тень от объекта Ctrl+K, удалим овал.
Таким же способом нарисуем тень на верхней подставке.
Еще можно добавить опорные ножки. Рисуют их так же как всё, объединяя квадрат и овал.
В этом уроке изложен принцип рисования подобной формы вы можете усложнить или облегчить саму форму, добавить красивых деталей, прорисовать блики, инкрустировать корпус камушками... В общем, фантазируйте!
Процесс создания cookies на ASP очень прост. После создания этих файлов, они будут храниться на компьютерах у посетителей вашего сайта. Одним из основных параметров у cookies является дата истечения срока их действия, т.е. expire date. Получается, что у вас, как у программиста, в руках жизнь этих файлов. Еще отмечу, что если не указать дату expire для cookies, то они существуют до тех пор, пока пользователь не закрыл свой браузер.
Для примера:
Сейчас возьмите и откройте свой любимый бразуер (мой выбор в пользу огненного лиса Firefox :) ) и вызовите страницу с cookie.
Теперь просто удалите в коде строку (1), закройте браузер и еще раз вызовите код. Как вы можете видеть, уже имя сайта не отображается.
Все дело в том, что мы не модифицировали дату истечения срока действия cookie и при закрытии браузера они были потеряны.
Теперь рассмотрим код с добавленной датой expiration date:
Теперь после закрытия браузера и повторного вызова кода можно видеть, что cookie по-прежнему продолжает существовать.
В практической работе приходится проводить импорт данных в "1С:Предприятие" из различных внешних приложений, обслуживающих базы данных. Встроенный язык программы "1С:Предприятие" и стандартизированные методы построения баз данных позволяют создавать универсальные обработки по импорту данных из внешних источников. Написание универсальной обработки, зачастую, - это сложный, но и достаточно увлекательный процесс. Сложным я могу назвать его потому, что на этапе разработки нужно заранее предусмотреть все возможные варианты импортирования и обработки данных. А увлекательным процесс написания универсальных обработок по импорту данных в 1С мне видится потому, что постоянно ощущаешь огромные выгоды от использования обработки в последующей работе.
Файловая система
Для начала давайте посмотрим, как проводится работа с файловой системой из программы 1С:Предприятие.
Импорт данных в 1С из MS Excel
Программу Microsoft Excel сегодня можно называть стандартом работы с электронными таблицами. Именно поэтому довольно часто приходится встречаться с ситуациями, когда массивы данных хранятся именно в файлах формата MS Excel. Для того, чтобы умело импортировать данные из файлов формата MS Excel в базу данных 1С:Предприятия, вы можете воспользоваться следующими примерами.
Импорт данных в 1С из текстового файла.
Основными преимуществами текстовых файлов являются их маленький размер и простота хранения данных внутри файла. Пожалуй, именно поэтому многие данные до сего дня передаются посредством текстовых файлов. Учитывая существующую потребность, вам могут потребоваться умения в импортировании данных в 1С из текстового файла. И нижеприведённые примеры помогут вам в приобретении необходимых знаний.
Самым распространённым случаем передачи данных текстовым файлом является способ выгрузки данных из системы Клиент-Банк. В примере, приведённом ниже, вы можете увидеть, каким образом производится загрузка данных о банковских операциях в 1С из текстового файла, в который предварительно выгружены данные из системы Банк-Клиент.
Импорт данных из файла формата DBF
Старый добрый формат dBase по-прежнему используется для хранения массивов данных. Чего уж говорить, если обычная версия 1С:Предприятия (не SQL) сама хранит базы данных в файлах с расширением DBF? Формат файлов DBF, на мой взгляд, очень удобен для передачи данных в базу 1С, поскольку преимуществами файла формата dBase являются маленький размер и матричная система хранения данных.
Программист 1С может встретиться с необходимостью импортировать данные в 1С из файла DBF, в который экспортированы данные о банковских операциях из системы Банк-Клиент. В нижеприведённом примере вы можете увидеть пример обработки файла DBF, из которого в 1С импортируется банковская выписка.
Импорт данных из файла формата XML
С недавних пор набирает популярность новый формат передачи многомерных массивов данных, который носит название eXtensible Markup Language или XML. Возможности нового языка разметки, используемого для хранения данных, огромны настолько, что его стали использовать даже для. передачи данных в программу 1С:Предприятие. Поэтому современный специалист по платформе 1С обязан уметь импортировать данные в 1С из файла, имеющего формат XML.
//процедура формирует печатную таблицу с данными, содержащимися в файле формата XML
Процедура Сформировать()
Перем Файл,Каталог;
Если ФС.ВыбратьФайл(0,Файл,Каталог,"Открытие документа XML","Документы XML|*.xml")=0 Тогда
Возврат;
КонецЕсли;
//таблица
Т=СоздатьОбъект("Таблица");
Т.ИсходнаяТаблица("");
Т.ВывестиСекцию("Шапка");
//документ
Анализатор=СоздатьОбъект("AddIn.XMLParser");
Д=Анализатор.СоздатьДокумент();
Д.Загрузить(Каталог+Файл);
//узлы
Узел=Д.ВыбратьУзел("Данные");
Для i=1 По Узел.КоличествоПодчиненных() Цикл
ТекУзел=Узел.ПолучитьПодчиненныйПоНомеру(i);
Состояние(ТекУзел.Текст);
//строка
тЭлемент=ТекУзел.Наименование;
тЗначение=ТекУзел.Значение;
Т.ВывестиСекцию("Строка");
КонецЦикла;
//таблица
Т.Опции(1,1,1,0);
Т.ПовторятьПриПечатиСтроки(1,1);
Т.ТолькоПросмотр(1);
Т.Показать("XML");
КонецПроцедуры
Ну вот собственно и все. Надеюсь данная статья оказалась вам полезна.
Векторные графические редакторы позволяют пользователю создавать и редактировать векторные изображения непосредственно на экране компьютера, а также сохранять их в различных векторных форматах, например, CDR, EPS, WMF или SVG.
Векторные графические редакторы и векторная графика.
Векторные графические редакторы позволяют пользователю создавать и редактировать векторные изображения непосредственно на экране компьютера, а также сохранять их в различных векторных форматах, например, CDR, EPS, WMF или SVG.
Векторные графические редакторы, позволяют вращать, перемещать, отражать, растягивать, скашивать, выполнять основные аффинные преобразования над объектами, изменять z-order и комбинировать примитивы в более сложные объекты.
Более изощрённые преобразования включают булевы операции на замкнутых фигурах: объединение, дополнение, пересечение и т. д.
Наиболее известные векторные редакторы.
Inkscape (Инкскейп) — векторный графический редактор, удобен для создания как художественных, так и технических иллюстраций.
OpenOffice.org Draw — векторный графический редактор, по функциональности сравнимый с CorelDRAW, входит в состав OpenOffice.org Skencil (бывший Sketch) - совместимый с UNIX системами, гибкий и мощный инструмент для иллюстраций, диаграмм и других целей. sK1 (форк Skencil) — редактор для работы с векторной графикой, распространяющийся на условиях LGPL, по набору функций схожий с CorelDRAW, Adobe Illustrator, Freehand и Inkscape.
Xara Xtreme for Linux - мощная, общая программа графики для платформ Unix, включая Linux, FreeBSD и (в развитии) РОТ-X.
Adobe Illustrator — один из популярных векторный графический редактор, разработанный и распространяемый фирмой Adobe Systems. Adobe Flash - программа разработки мультимедийного контента для платформы «Adobe Engagement Platform» (такого, как веб-приложения, игры и мультфильмы).
CorelDRAW — популярный векторный графический редактор, разработанный канадской корпорацией Corel. Текущая версия продукта — CorelDRAW Graphics Suite X4, доступна только для Microsoft Windows. Последняя версия для GNU/Linux — 9-я версия, выпущенная в 2000 году. В 2002 году вышла последняя 11-я версия для Macintosh.
Macromedia FreeHand — векторный графический редактор, разработанный фирмой Macromedia для Microsoft Windows и для Mac OS.
[center]Векторная графика.[/center]
Векторная графика — это использование геометрических примитивов, таких как точки, линии, сплайны и многоугольники, для представления изображений в компьютерной графике. Термин используется в противоположность к растровой графике, которая представляет изображения как матрицу пикселей (точек).
Современные компьютерные видеодисплеи отображают информацию в растровом формате. Для отображения векторного формата на растровом используются преобразователи, программные или аппаратные, встроенные в видеокарту.
Кроме этого, существует узкий класс устройств, ориентированных исключительно на отображение векторных данных. К ним относятся мониторы с векторной развёрткой, графопостроители, а также некоторые типы лазерных проекторов.
Термин «векторная графика» используется в основном в контексте двухмерной компьютерной графики.
Рассмотрим теперь способ хранения изображения векторной графики на примере окружности радиуса r.
Список информации, необходимой для полного описания окружности, таков:
1. радиус r;
2. координаты центра окружности;
3. цвет и толщина контура (возможно прозрачный);
4. цвет заполнения (возможно прозрачный).
Этот способ описания векторной графики имеет свои преимущества над растровой графикой.
Минимальное количество информации передаётся намного меньшему размеру файла, (размер не зависит от величины объекта).
Соответственно, можно бесконечно увеличить, например, дугу окружности, и она останется гладкой. С другой стороны, если кривая представлена в виде ломаной линии, увеличение покажет, что она на самом деле не кривая.
При увеличении или уменьшении объектов толщина линий может быть постоянной.
Параметры объектов хранятся и могут быть изменены. Это означает, что перемещение, масштабирование, вращение, заполнение и т. д. не ухудшат качества рисунка. Более того, обычно указывают размеры в аппаратно-независимых единицах, которые ведут к возможной наилучшей растеризации на растровых устройствах.
У векторной графики есть два фундаментальных недостатка.
Не каждый объект может быть легко изображен в векторном виде. Кроме того, количество памяти и времени на отображение зависит от числа объектов и их сложности.
Перевод векторной графики в растр достаточно прост. Но обратного пути, как правило, нет — трассировка растра обычно не обеспечивает высокого качества векторного рисунка.
Пример, показывающий эффект векторной графики при увеличении: (a) исходное векторное изображение; (b) иллюстрация, увеличенная в 8 раз как векторное изображение; (c) иллюстрация, увеличенная в 8 раз как растровое изображение. Растровые изображения плохо масштабируются тогда, как векторные изображения могут быть неограниченно увеличены без потери качества.
Векторная графика идеальна для простых или составных рисунков, которые должны быть аппаратно-независимыми или не нуждаются в фотореализме.
С появлением компьютеров и специальных программ (графических редакторов), с помощью которых можно обрабатывать и создавать изображения, кажется, что каждый может научиться с легкостью делать качественные рисунки, однако, это не так. Графические редакторы – инструмент сложный, чтобы хорошо его освоить, уйдет много времени, кроме того, они сами по себе не создают за вас изображения. Чтобы сделать рисунок, вам нужны минимальные художественные знания, т.е. вы должны представлять, что такое перспектива, светотень, как создавать иллюзию объема и т.д.
Первые шаги - компьютерная графика и графические редакторы.
С появлением компьютеров и специальных программ (графических редакторов), с помощью которых можно обрабатывать и создавать изображения, кажется, что каждый может научиться с легкостью делать качественные рисунки, однако, это не так. Графические редакторы – инструмент сложный, чтобы хорошо его освоить, уйдет много времени, кроме того, они сами по себе не создают за вас изображения. Чтобы сделать рисунок, вам нужны минимальные художественные знания, т.е. вы должны представлять, что такое перспектива, светотень, как создавать иллюзию объема и т.д.
О том, как научиться работать с графическими редакторами и о художественных средствах мы поговорим в других статьях. А эта будет посвящена обзору графических редакторов, какие они бывают, чем отличаются, а также другим вопросам, связанным с ними и обработкой изображений в компьютере.
Обычно, когда мы создаем оформление нашего сайта, то используем уже готовые изображения: фотографии, картины, рисунки, текстуры. А если воспользоваться графическим редактором то можно из нескольких разных фотографий создать необычный коллаж, который потом сможем использовать при оформлении нашего сайта.
Из данного примера видно как из одной фотографии и фрагмента картины художника-фантаста можно получить третье, совершенно отличное от двух предыдущих, изображение дамы-воительницы. Изображения, которые можно использовать для создания чего-то своего нового, есть в Интернете, на дисках в компьютерных магазинах, а также можно отсканировать свои фотографии, рисунки и использовать их.
Какие бывают графические редакторы, и как представляется графика в компьютере.
Графические редакторы, бывают двух типов: растровые и векторные, по тому, как они представляют объекты (изображения). Растровые редакторы представляют изображение в виде множества точек, это хорошо видно, если мы увеличим фотографию нашей дамы-воительницы, посмотрите, как выглядит ее глаз при многократном увеличении:
Минимальная неделимая точка в растровом изображении называется пиксель. Все изображения, которые вводятся в компьютер при помощи сканирования – растровые.
Самый популярный растровый графический редактор - Adobe Photoshop. Этот редактор многофункционален и по этому используется во всех дизайнерских студиях и конторах. Если кто-то захочет посвятить себя профессиям рекламный или веб-дизайн, то знание Adobe Photoshop просто необходимо. Для начинающих и любителей можно посоветовать для начала следующие растровые графические редакторы: Image Styler или Live Motion. Векторные графические редакторы представляют изображение в виде отрезков прямых, векторов. Вектор – направленный отрезок, то есть отрезок, у которого указаны начало (называемое также точкой приложения вектора) и конец. Для наглядности, посмотрим при большом приближении меч, в руке у дамы, который нарисован в векторном редакторе:
Изображения, сделанные в векторных редакторах, можно открыть и в растровом редакторе, в этом случае, оно будет восприниматься, как растровое. А вот растровое изображение, открытое в векторном редакторе, не станет само по себе векторным, придется его либо обрисовывать самим, чтобы получить нормальное векторное изображение, либо перевести в кривые при помощи специальных программ (например, Stream Line).
Один из популярных векторных графических редакторов Adobe Illustrator. Многофункционален. Используется во многих дизайнерских студиях и конторах. Программа конкурент - CorelDraw.
Пожалуй, и все, на этом наша статья закончена. Теперь можно смело приступать к изучению работы с графическими редакторами, в этом вам помогут статьи на нашем сайте, также вы можете изучить статьи по этой теме на других сайтах. И все-таки лучше всего приобрести в магазине не только диск с программой, но и книгу с упражнениями, выполняя которые, будет легче освоить графические редакторы.
Прародителем сети интернет была сеть ARPANET. Первоначально её разработка финансировалась Управлением перспективного планирования (Advanced Research Projects Agency, или ARPA). Проект стартовал осенью 1968 года и уже в сентябре 1969 года в опытную эксплуатацию был запущен первый участок сети ARPANET.
Сеть ARPANET долгое время являлась тестовым полигоном для исследования сетей с коммутацией пакетов. Однако кроме исследовательских, ARPANET служила и чисто практическим целям. Ученые нескольких университетов, а также сотрудники некоторых военных и государственных исследовательских институтов регулярно её использовали для обмена файлами и сообщениями электронной почты, а так же для работы на удалённых компьютерах. В 1975 году управление сетью было выведено из под контроля ARPA и поручено управлению связи Министерства обороны США. Для военных данная сеть представляла большой интерес, так как позволяла сохранять её работоспособность даже при уничтожении её части, например, при ядерном ударе.
В 1983 году Министерство обороны разделило ARPANET на две связанные сети. При этом за сетью ARPANET были сохранены её исследовательские функции, а для военных целей была сформирована новая сеть, которую назвали MILNET. Физически сеть ARPANET состояла приблизительно из 50 миникомпьютеров типа С30 и С300, выпущенных фирмой BBN Corporation. Они назывались узлами коммутации пакетов и были разбросаны по территории материковой части США и Западной Европы. Сеть MILNET состояла приблизительно из 160 узлов, причём 34 из них были расположены в Европе, а 18 в Тихом Океане и в Азиатско-Тихоокеанском регионе. Сами узлы коммутации пакетов нельзя было использовать для решения вычислительных задач общего плана.
Понимая, что в ближайшем будущем очень важным моментом в научных исследованиях будет процесс обмена данными, Национальный научный фонд (NFS) в 1987 году основал отделение сетевых и коммуникацинных исследований и инфраструктуры. В его задачи входило обеспеченье современными сетевыми коммуникационными средствами учёных и инженеров США. И хотя отделение фонда NFS финансировало основные исследовательские программы в области сетевых коммуникаций, сферой его основных интересов было расширение Internet.
Сеть NSFNET строилась в несколько этапов и быстро преобретала популярность не только в научно-исследовательских кругах, но и в коммерческой среде. К 1991 году фонд NFS и другие государственные учреждения США поняли, что масштабы Internet вышли далеко за отведённые её на этапе разработки рамки университетской и научной сети. К Internet стало подключаться множество организаций, разбросанных по всему Земному шару. Трафик в магистральном канале NSFNET вырос почти до миллиарда пакетов в день, и его пропускной способности 1.5 Мбит/с на отдельных участках стало уже не хватать. Поэтому правительство США начало проводить политику приватизации и коммерческого использования Internet. Фонд NFS принял решение предать магистральную сеть на попечение закрытой акционерной компании и оплачивать доступ к ней для государственных научных и исследовательских организаций.
Семейство TCP/IP
Познакомившись с историей, давайте подробнее рассмотрим, что собой представляют протоколы TCP/IP. TCP/IP - это семейство сетевых протоколов, ориентированных на совместную работу. В состав семейства входит несколько компонентов:
IP (Internet Protocol - межсетевой протокол) - обеспечивает транспортировку пакетов данных с одного компьютера на другой;
ICMP (Internet Control Message Protocol - протокол управляющих сообщений в сети Internet) - отвечает за различные виды низкоуровневой поддержки протокола IP, включая сообщения об ошибках, вспомогательные маршрутизирующие запросы и подтверждения о получении сообщений;
ARP (Address Resolution Protocol - протокол преобразования адресов) - выполняет трансляцию IP-адресов в аппаратные MAC-адреса;
UDP (User Datagram Protocol - протокол передачи дейтаграмм пользователя) и TCP (Transmission Control Protocol - протокол управления передачей) - обеспечивают доставку данных конкретным приложениям на указанном компьютере. Протокол UDP реализует передачу отдельных сообщений без подтверждения доставки, тогда как TCP гарантирует надёжный полнодуплексный канал связи между процессами на двух разных компьютерах с возможностью управления потоком и контроля ошибок.
Протокол представляет собой набор правил, использующихся для при обмене данными между двумя компьютерами. В нём оговариваются формат блоков сообщений, описывается реакция компьютера на получение определённого типа сообщения и указываются способы обработки ошибок и других необычных ситуаций. И что самое важное, благодаря протоколам, мы можем описать процесс обмена данными между компьютерами, не привязываясь к какой-то определённой комьютерной платформе или сетевому оборудованию конкретного производителя.
Сокрытие низкоуровневых особенностей процесса передачи данных способствует повышению производительности труда разработчиков. Во-первых, поскольку программистам приходится иметь дело с протоколами, относящимися к достаточно высокому уровню абстракции, им не нужно держать в голове (и даже изучать!) технические подробности испольуемого аппаратного обеспечения. Во-вторых, поскольку программы разрабатываются на основе модели, относящейся к высокому уровню абстракции, который не зависит от конкретной архитектуры компьютера или типа сетевого оборудования, в них не нужно вносить никаких изменений при переходе на другой тип оборудования или изменений конфигурации сети.
Замечание Говорить о том, что ARP входит в состав семейства протоколов TCP/IP не совсем корректно. Однако это неотъемлемая часть стека протоколов в сетях Ethernet. Для того чтобы отправить данные по сети, IP-адрес хоста должен быть преобразован в физический адрес машины получателя (уникальный адрес сетевой платы). Протокол ARP как раз и предназначен для такой цели.
Самым фундаментальным протоколом Интернета является протокол IP (от англ. Internet Protocol), обеспечивающий передачу данных между двумя удаленными компьютерами. Протокол IP является достаточно простым, и обеспечивает адресацию в сети. В ранних сетях адреса в сети были уникальные целые цифры, сейчас сеть построена по иерархическому принципу.
Стек протоколов TCP/IP имеет четыре основных уровня, поэтому часто говорят, что TCP/IP — это четырехуровневый стек протоколов. Внизу стека расположен интерфейсный уровень, посредством которого происходит связь с аппаратурой. За ним следует уровень IP, поверх которого построены транспортные протоколы TCP и UDP. На вершине стека находится уровень приложений, таких как ftp, telnet и т. д. Как мы уже говорили, IP — это простой протокол, не требующий установления соединения. При отсылке пакета данных, IP, как и все протоколы без соединения, послав пакет, тут же "забывает" о нем. При приеме пакетов с верхних уровней стека, этот протокол обертывает их в IP-пакет и передает необходимому аппаратному обеспечению для отправки в сеть. Однако именно в такой простоте и заключается основное достоинство протокола IP. Дело в том, что поскольку IP является простым протоколом, он никак не связан со структурой физической среды, по которым передаются данные. Для протокола IP главное, что эта физическая среда в принципе способна к передаче пакетов. Поэтому IP работает как в локальных, так и в глобальных сетях, как в синхронном, так и в асинхронном режиме передачи данных, как в обычных линиях связи, так и беспроводных и т. д. А поскольку протокол IP является фундаментом четырехуровнего сте-ка протоколов, то все семейство протоколов TCP/IP также может функционировать в любой сети с любым режимом передачи пакетов.
На сетевом уровне в семействе протоколов TCP/IP предусмотрено два обширных класса служб, которые используются во всех приложениях.
Служба доставки пакетов, не требующая установки соединения.
Надёжная потоковая транспортная служба.
Различие между службами, требующими установления надёжного соединения и службами, не требующими этого, является одним из самых основных вопросов сетевого программирования. Первое, на что следует обратить внимание, это то, что когда мы говорим об установлении соединения, то имеется в виду не соединение между компьютерами посредством физического носителя, а о способе передачи данных по этому носителю. Основное различие состоит в том, что службы, в которых устанавливается надёжное соединение, сохраняют информацию о состоянии и таким образом отслеживают информацию о передаваемых пакетах. В службах же, не требующих надёжного соединения, пакеты передаются независимо друг от друга.
Данные передаются по сети в форме пакетов, имеющих максимальный размер, определяемый ограничениями канального уровня. Каждый пакет состоит из заголовка и полезного содержимого (сообщения). Заголовок включает сведения о том, откуда прибыл пакет и куда он направляется. Заголовок, кроме того, может содержать контрольную сумму, информацию, характерную для конкретного протокола, и другие инструкции, касающиеся обработки пакета. Полезное содержимое – это данные, подлежащие пересылке.
Имя базового блока передачи данных зависит от уровня протокола. На канальном уровне это кадр или фрейм, в протоколе IP – пакет, а в протоколе TCP – сегмент. Когда пакет передаётся вниз по стеку протоколов, готовясь к отправке, каждый протокол добавляет в него свой собственный заголовок. Законченный пакет одного протокола становится полезным содержимым пакета, генерируемого следующим протоколом.
Определение
Пакеты, которые посылаются протоколом, не требующим соединения, называются дейтаграммами.
Каждая дейтаграмма является уникальной в том смысле, что никак не зависит от других. Как правило, при работе с протоколами без установления соединения, диалог между клиентом и сервером предельно прост: клиент посылает одиночный запрос, а сервер на него отвечает. При этом каждый новый запрос — это новая транзакция, т. е. инициируемые клиентом запросы никак не связаны друг с другом с точки зрения протокола. Протоколы без установления соединения ненадежны в том смысле, что нет никаких гарантий, что отправленный пакет будет доставлен по месту назначения.
Протоколами, требующие установления логического соединения, сохраняют информацию о состоянии, что позволяет обеспечивать надежную доставку пересылаемых данных. Когда говорится о сохранении состояния, имеется ввиду то, что между отправителем и получателем происходит обмен информацией о ходе выполнения передачи данных. К примеру, отправитель, посылая данные, сохраняет информацию о том, какие данные он послал. После этого в течении определенного времени он ожидает информацию от получателя о доставке этих данных, и, если такая информация не поступает, данные пересылаются повторно.
Работа протокола с установлением соединения включает в себя три основные фазы:
установление соединения;
обмен данными;
разрыв соединения.
Передача всех данных при работе с таким протоколом, в отличие от протокола без установления соединения, происходит за одну транзакцию, т. е. в фазе обмена данными не происходит обмена адресами между отправителем и получателем, поскольку эта информация передается на этапе установки соединения. Возвращаясь к телефонной аналогии, можно сказать, что нам в этом случае нет необходимости для того, чтобы сказать собеседнику очередное слово, вновь набирать его номер и устанавливать соединение. Заметим, что приводимая аналогия имеет одну неточность. Дело в том, что при телефонном разговоре все же устанавливается физическое соединение. Когда же мы говорим о соединении с точки зрения протоколов, то это соединение, скорее, умозрительное. К примеру, если вдруг при телефонном разговоре, неожиданно сломается телефонный аппарат вашего собеседника, вы тут же узнаете об этом, поскольку разговор незамедлительно прервется. А вот если происходит обмен данными между двумя хостами и один из них вдруг аварийно остановится, то для его "хоста-собеседника" соединение по прежнему будет существовать, поскольку для него не произошло ничего такого, что сделало бы недействительной хранящуюся у него информацию о состоянии.
В этом смысле работу с протоколом, требующим установления логического соединения можно сравнить с телефонным разговором. Когда мы звоним по телефону, мы сначала набираем номер (установление соединения), затем разговариваем (обмен данными) и по окончании разговора вешаем трубки (разрыв соединения).
Протокол без установления соединения обычно сравниваю с почтовой открыткой. Каждая открытка представляет собой самостоятельную единицу (пакет информации или дейтаграмму), которая обрабатывается в почтовом отделении независимо от других открыток. При этом на почте не отслеживается состояние переписки между двумя респондентами и, как правило, нет никакой гарантии, что ваша открытка попадет к адресату. Если на открытке указан неправильный адрес, она никогда не дойдет до получателя, и не возвратиться обратно к отправителю. А если вы захотите отправить вашему собеседнику новую порцию информации, то это уже будет другая транзакция, поскольку нужно будет писать новую открытку, указывать на ней адрес и т. д.
Как видим, у протоколов без установления соединения существует много недостатков и может возникнуть вопрос о надобности таких протоколов. Однако, использование проколов без установления логического соединения все-таки оправдано. Как правило, при помощи таких протоколов организуется связь одного хоста со многими другими, в то время как при использовании протоколов с установлением соединения связь организуется между парой хостов (по одному соединению на каждую пару). Важный момент заключается в том, что протоколы без установления логического соединения являются фундаментом, на котором строятся более сложные протоколы. К примеру, протокол TCP построен на базе протокола IP.
Протоколы транспортного уровня
Протоколами транспортного уровня в четырехуровневом стеке протоколов являются протоколы TCP и UDP.
Давайте рассмотрим, каким образом функционирует протокол TCP. Дело в том, что поскольку TCP-пакеты, иначе называемые сегментами, посылаются при помощи протокола IP, у TCP нет никакой информации о состоянии этих пакетов. Поэтому для того, чтобы хранить информацию о состоянии, TCP к базовому протоколу IP добавляет три параметра.
Во-первых, добавляется сегмент контрольной суммы содержащихся в пакете данных, что позволяет убедиться в том, что в принципе все данные дошли до получателя и не повредились во время транспортировки.
Во-вторых, к каждому передаваемому байту приписывается порядковый номер, что необходимо для определения того, совпадает ли порядок прибытия данных с порядком их отправки. И даже в том случае, если данные пришли не в том порядке, в котором были отправлены, наличие порядковых номеров позволит получателю правильно составить из этих данных исходное сообщение.
В-третьих, базовый протокол IP дополняется также механизмами подтверждения получения данных и повторной отправки, на тот случай, если данные не были доставлены.
Если с первыми двумя параметрами все более-менее понятно, то механизм подтверждения/повторной отправки достаточно сложен и его мы рассмотрим подробнее в другой раз.
В этой статье будет рассмотрен скрипт, который создает анимацию в виде падающего снега. Анимация воспроизводится в заданной области web-страницы. Анимационный эффект, создаваемый данным скриптом выглядит весьма привлекательно, поэтому скрипт вполне может быть использован для создания анимированных логотипов, или блоков новогодних объявлений и поздравлений на сайте.
Область web-страницы, в которой производится анимация, задается элементом DIV с идентификатором ID_ANIMATE. Принцип работы скрипта заключается в вертикальном перемещении (с небольшими стохастическими перемещениями по горизонтали) элементов IMG, представляющих изображение снежинки в пределах этого элемента (элемент DIV с идентификатором ID_ANIMATE является элементом-контейнером для элементов IMG).
Элемент-контейнер DIV с идентификатором ID_ANIMATE определяется при помощи HTML-разметки в документе, в котором содержится скрипт. В этот элемент может быть помещено произвольное гипертекстовое содержимое, которое будет располагаться "на фоне" падающих снежинок, либо на фоне которого будут падать снежинки (это зависит от значения позиционного уровня этого содержимого). Код фрагмента HTML-разметки, определяющей элемент-контейнер DIV и его содержимое в демо-примере, приложенном к статье (см. демо-пример), приведен далее:
Параметры элемента-контейнера DIV (его размеры, схема позиционирования, значение свойства переполнения, цвет фона, параметры границы), а также перемещаемых в нем элементов IMG (схема позиционирования, размер, значение позиционного уровня), определяются правилами внедренной в документ таблицы слилей CSS:
Как можно видеть из листинга, элементам IMG, являющимся потомками элемента DIV с идентификатором ID_ANIMATE, назначается значение позиционного уровня 1. Поэтому, если вы хотите, чтобы "снежинки" двигались "под" остальным содержимым этого элемента, содержимому следует задать значение позиционного уровня больше 1 (как это сделано в демо-примере). Обратите также внимание на то, что элементам IMG назначена схема абсолютного позиционирования.
Теперь рассмотрим непосредственно работу скрипта. Полный листинг кода скрипта приведен далее.
Как можно видеть из листинга, в начале скрипта производится инициализация нескольких переменных. В переменную oAnimate заносится ссылка на DOM-объект элемента DIV с идентификатором ID_ANIMATE. Переменные nWidth и nHeight инициализируются значениями значения ширины и высоты этого элемента. Переменная nFSize должна содержать значение высоты (в пикселях) элементов изображений-снежинок (оно должно быть таким же, как задано в таблице стилей). Переменная strFlakeURL содержит URI ресурса изображения снежинки. Значение переменной nCount определяет общее количество движущихся изображений. Массив aoFlakes предназначен для хранения ссылок на DOM-объекты элементов изображений-снежинок.
Создание элементов изображений, добавление их в дерево документа, ссылок на DOM-объекты этих элементов в массив aoFlakes производится в процессе инициализации скрипта (см. окончание листинга кода скрипта). Значению свойства src DOM-объектов элементов изображений при этом присваивается значение переменной strFlakeURL. Для установки параметров движения каждого созданного элемента, вызывается функция ResetFlake. Для позиционирования соответствующего элемента IMG относительно элемента-контейнера DIV - UpdateFlakePos.
Функция ResetFlake устанавливает значения свойствам m_nX, m_nY и m_nSpeed DOM-объекта элемента, ссылка на который содержится в элементе массива aoFlakes с индексом, равным значению первого параметра ResetFlake. Свойство m_nX объекта хранит текущую координату по оси X, а свойство m_nY - по оси Y соответствующего элемента относительно контейнера. Свойство m_nSpeed определяет "скорость" движения элемента (величину его вертикального смещения на каждом шаге анимации). Функция ResetFlake устанавливает случайные значения свойствам m_nX и m_nSpeed. Свойству m_nY случайное значение устанавливается только в том случае, если параметр bRandY функции вычисляется в true (в этом случае элемент изображения снежинки будет иметь случайную позицию по вертикали). Иначе свойству m_nY устанавливаетя значение -nFSize (при этом изображение будет позиционироваться так, что оно будет полностью скрыто за верхней границей элемента-контейнера). При создании элементов изображений в процессе инициализации скрипта, ResetFlake вызывается со значением параметра bRandY, равным true.
Функция UpdateFlakePos принимает в качестве единственного параметра значение индекса в массиве aoFlakes и производит позиционирование элемента, ссылка на DOM-объект которого содержится в элементе массива aoFlakes с данным индексом в соответствии со значениями его свойств m_nX и m_nY.
Перемещение всех изображений-снежинок осуществляется функцией OnTimer, которая является обработчиком событий таймера, запускаемого в процессе инициализации скрипта.
Как можно видеть из приведенного ранее листинга кода скрипта, в функции OnTimer производится перебор всех DOM-объектов элементов изображений снежинок. Значение свойства m_nY каждого из этих объектов наращивается на величину его свойства m_nSpeed. Значение свойства m_nX изменяется на случайную величину, которая находится в диапазоне [-1..1] (так достигается случайное горизонтальное движение "снежинок"). В случае, если элемент изображения вышел за нижнюю границу элемента-контейнера, вызывается функция ResetFlake, которая устанавливает случайные значения свойств m_nX и m_nSpeed соответствующего объекта, а значение его свойства m_nY устанавливаетт в -nFSize. Затем вызывается функция UpdateFlakePos для перемещения конкретного элемента IMG в нужную позицию.
В состав библиотеки MFC входит ряд классов, представляющих стандартные диалоговые панели. Эти классы позволяют легко реализовать такие часто используемые операции, как открытие и сохранение файла, выбор цвета, выбор шрифта и т.д. Все эти классы наследуются от CCommonDialog, который в свою очередь является производным по отношению к базовому классу CDialog.
Приведем классы стандартных диалоговых панелей и их назначение:
CColorDialog - Панель для выбора цвета
CFileDialog - Панель выбора файлов для открытия и сохранения на диске
CFindReplaceDialog - Панель для выполнения операции поиска и замены
CFontDialog - Панель для выбора шрифта
CPrintDialog - Панель для вывода документа на печать
CPageSetupDialog - Панель выбора формата документа
COleDialog - Панель для управления технологией OLE
Классы, управляющие стандартными диалоговыми панелями, определены в файле afxdlgs.h. Поэтому при использовании этих классов в приложении необходимо включить этот файл в исходный текст при помощи директивы #include.
Панель выбора цвета (класс CColorDialog)
Чтобы отобразить на экране стандартную диалоговую панель выбора цвета, надо создать объект класса CColorDialog, а затем вызвать метод DoModal. При создании объекта класса СColorDialog используется следующий конструктор:
Все параметры конструктора необязательны, однако в некоторых случаях использование этих параметров может помочь.
Первый параметр clrInit позволяет указать цвет, выбранный по умолчанию сразу после открытия диалоговой панели. Если параметр не будет указан, в качестве цвета, выбранного по умолчанию, будет использоваться черный цвет.
Параметр dwFlags содержит набор флагов, управляющих диалоговой панелью выбора цвета. При помощи него блокировать или разрешать работу некоторых элементов управления диалоговой панели выбора цвета. Если при создании объекта класса CColorDialog не указать параметр dwFlags, тем не менее можно выполнить настройку диалоговой панели, обратившись непосредственно к элементу m_cc данного класса. Параметр dwFlags, указанный в конструкторе, используется для инициализации m_cc. Изменения в элемент m_cc должны быть внесены до того, как панель будет отображаться на экране.
Последний параметр pParentWnd можно использовать, чтобы указать родительское окно диалоговой панели.
Методы класса CСolorDialog
Чтобы вывести диалоговую панель выбора цвета на экран, необходимо использовать метод DoModal. После отображения панели на экране пользователь может выбрать из нее цвет и нажать кнопки OK или Cancel для подтверждения выбора цвета или отказа от него. Когда диалоговая панель закрывается, метод DoModal возвращается значения IDOK и IDCANCEL, в зависимости от того, какую кнопку нажал пользователь:
На экране появится стандартная диалоговая панель выбора цвета Color. В верхней половине диалоговой панели расположены 48 прямоугольников, имеющих различные цвета. Они представляют так называемые основные цвета (Basic colors). Можно выбрать один из этих цветов и нажать кнопку OK. После того, как диалоговая панель закрыта (метод DoModal завершил свою работу), можно воспользоваться методами класса CColorDialog, чтобы узнать цвета, выбранные пользователем.
Для определения цвета, выбранного пользователем, можно обратиться к методу GetColor класса CColorDialog. Данный метод возвращает значение COLORREF, соответствующее выбранному цвету.
Если пользователю недостаточно основных цветов, представленных в диалоговой панели Color, он может выбрать до 16 дополнительных цветов. Для этого он должен нажать кнопку DefineCustom Colors. Диалоговая панель изменит свой внешний вид - появятся дополнительные органы управления, позволяющие выбрать любой из 16 777 216 цветов. Когда цвет выбран, нужно нажать кнопку Add Custom Colors. Выбранный цвет будет добавлен к дополнительным цветам (Custom colors) - один из свободных прямоугольников окрасится соответствующим цветом.
При помощи метода GetSavedCustomColors класса CColorDialog можно определить дополнительные цвета, выбранные пользователем в диалоговой панели Color. Этот метод возвращает указатель на массив из 16 элементов типа COLORREF. Каждый элемент массива описывает один дополнительный цвет.
Когда диалоговая панель Color отображается приложением первый раз, все прямоугольники, отображающие дополнительные цвета, имеют белый цвет. Дополнительные цвета, выбранные пользователем, сохраняются во время работы приложения. После перезапуска приложения дополнительные цвета сбрасываются.
Панель выбора файлов (класс CFileDialog)
Среди стандартных диалоговых панелей, для которых в библиотеке MFC создан специальный класс, есть панели для работы с файловой системой - Open и Save As. Диалоговая панель Open позволяет выбрать один или несколько файлов и открыть их для дальнейшего использования. Диалоговая панель Save As позволяет выбрать имя файла для записи в него документа.
Для управления диалоговыми панелями Open и Save As предназначен один класс CFileDialog. Рассмотрим конструктор класса CFileDialog более подробно:
Объекты класса CFileDialog представляют диалоговые панели Open или Save As в зависимости от параметра bOpenFileDialog. Если параметр bOpenFileDialog содержит значение TRUE, то создается объект, управляющий диалоговой панелью Open, а если FALSE - диалоговой панелью Save As.
Параметр bOpenFileDialog является единственным обязательным параметром, который необходимо указать. Остальные параметры конструктора класса CFileDialog задают различные режимы работы панели и могут не указываться.
Чтобы создать объект класса CFileDialog , представляющий диалоговую панель для открытия файлов (mFileOpen), и объект, представляющий диалоговую панель для сохранения файлов (mFileSaveAs), можно воспользоваться следующими вызовами конструктора класса:
Во многих случаях имена файлов, которые нужно открыть или закрыть, имеют определенное расширение. Параметр lpszDefExt позволяет задать расширение файлов, используемое по умолчанию. То есть, если пользователь при определении имени файла не укажет расширение, имени файла автоматически присваивается расширение, принятое по умолчанию. Если при определении свойств диалоговой панели программист присвоит параметру lpszDefExt значение NULL, то расширение файлов должно задаваться пользователем явно.
В некоторых случаях требуется, чтобы диалоговые панели отображались с уже выбранным именем файла. Чтобы указать имя файла, используемое по умолчанию, применяется параметр lpszFileName. Если параметр lpszFileName имеет значение NULL, данная возможность не реализуется.
С помощью флага dwFlags можно изменить внешний вид и некоторые другие характеристики стандартных диалоговых панелей класса CFileDialog. В него можно записать комбинацию флагов, управляющих различными характеристиками этих панелей. Например, флаг OFN_HIDEREADONLY означает, что из диалоговой панели удаляется переключатель "Read Only", а флаг OFN_OVERWRITEPROMPT (используемый для панели Save As) - что необходимо выводить диалоговую панель с предупреждением, если пользователь выбирает для сохранения имя уже существующего файла.
Диалоговые панели выбора файлов обычно имеют список так называемых фильтров, включающих названия типов файлов и расширения имен файлов данного типа. Выбрав фильтр, пользователь указывает, что он желает работать только с файлами определенного типа, имеющими соответствующее расширение. Файлы с другими расширениями в диалоговых панелях не отображаются.
Список фильтров можно указать через параметр lpszFilter. Одновременно можно указать несколько фильтров. Каждый фильтр задается двумя строками - строкой, содержащей имя фильтра, и строкой, в которой перечислены соответствующие ему расширения имен файлов. Если одному типу соответствует несколько расширений, они разделяются символом ;. Строка, содержащая имя фильтра, отделяется от строки с расширениями файлов символом |. Если используется несколько фильтров, то они также отделяются друг от друга символом |. Например, в качестве строки, задающей фильтры, можно использовать строку вида:
Диалоговые панели, представленные объектами класса CFileDialog, могут иметь или не иметь родительского окна. Чтобы указать родительское окно, нужно передать конструктору CFileDialog указатель на него через параметр pParentWnd.
Методы класса CFileDialog
Создание объекта класса CFileDialog еще не вызывает отображения соответствующей диалоговой панели. Для этого необходимо воспользоваться методом DoModal класса CFileDialog.При вызове метода DoModal для ранее созданного объекта класса CFileDialog на экране открывается соответствующая диалоговая панель. После того, как пользователь завершает работу с диалоговой панелью, метод DoModal вернет значение IDOK или IDCANCEL в случае успешного завершения и нуль - в случае возникновения ошибок:
После того, как пользователь закроет диалоговую панель и метод DoModal вернет управление, можно воспользоваться другими методами класса CFileDialog , чтобы определить имена выбранных файлов:
GetPathName - Определяет полный путь файла
GetFileName - Определяет имя выбранного файла
GetFileExt - Определяет расширение имени выбранного файла
GetFileTitle - Позволяет определить заголовок выбранного файла
GetNextPathName - Если диалоговая панель позволяет выбрать сразу несколько файлов, то этот метод можно использовать для определения полного пути следующего из выбранных файлов
GetReadOnlyPref - Позволяет узнать состояние атрибута "только для чтения" (read-only) выбранного файла
GetStartPosition - Возвращает положение первого элемента из списка имен файлов
Наиболее важный метод - GetPathName. Он получает полный путь файла, выбранного из диалоговых панелей Open или Save As. Если диалоговая панель позволяет выбрать сразу несколько файлов, тогда метод GetPathName возвращает массив строк, состоящий из нескольких строк, заканчивающихся двоичным нулем. Первая из данных строк содержит путь к каталогу, в котором расположены выбранные файлы, остальные строки содержат имена выбранных файлов. Выделение строки, содержащей путь к каталогу, проблем не вызывает, а чтобы получить имена выбранных файлов, необходимо воспользоваться методами GetStartPosition и GetNextPathName.
[pagebreak]
Метод GetStartPosition возвращает значение типа POSITION. Оно предназначено для передачи методу GetNextPathName и получения очередного имени выбранного файла. Если пользователь не выбрал ни одного файла, метод GetStartPosition возвращает значение NULL. Значение, полученное этим методом, следует записать во временную переменную типа POSITION и передать ссылку на нее методу GetNextPathName. Метод GetNextPathName вернет полный путь первого из выбранных в диалоговой панели файлов и изменит значение переменной pos, переданной методу по ссылке. Новое значение pos можно использовать для последующих вызовов метода GetNextPathName и получения путей всех остальных выбранных файлов. Когда метод GetNextPathName вернет имена всех выбранных файлов, в переменную pos записывается значение NULL.
В панелях Open и Save As имеется переключатель "ReadOnly". По умолчанию этот преключатель не отображается. Если есть необходимость воспользоваться этим переключателем, то нужно отказаться от использования флага OFN_HIDEREADONLY.
Метод GetReadOnlyPref позволяет определить положение переключателя "ReadOnly". Если переключатель включен, то метод GetReadOnlyPref возвращает ненулевое значение. В противном случае GetReadOnlyPref возвращает нуль.
Панель выбора шрифта (класс CFontDialog)
Стандартная диалоговая панель Font предназначена для выбора шрифта. Эта панель отображает список шрифтов, установленных в системе, и позволяет выбрать название шрифта, его начертание и другие параметры.
Для управления диалоговой панелью Font в библиотеку классов MFC включен класс CFontDialog. Методы этого класса можно использовать для отображения панели Font и определения характеристик шрифта, выбранного пользователем. Конструктор класса CFontDialog:
Все параметры конструктора являются необязательными. Настройка стандартной панели выбора шрифта, которая выполняется конструктором класса CFontDialog по умолчанию, удовлетворяет большинству пользователей.
Параметр lplfInitial является указателем на структуру LOGFONT, описывающую логический шрифт. Если этот параметр используется, то в диалоговой панели по умолчанию будет выбран шрифт, наиболее соответствующий шрифту, описанному в структуре LOGFONT.
Параметр dwFlags задает набор флагов, управляющий различными режимами работы панели. Например, флаг CF_EFFECTS позволяет пользователю создавать подчеркнутые и перечеркнутые буквы, определять цвет букв, а флаг CF_SCREENFONTS - разрешает выбирать только экранные шрифты.
Через параметр pdcPrinter можно передать конструктору контекст отображения принтера, шрифты которого будут представлены в диалоговой панели Font. Данный параметр используется только в том случае, если в параметре dwFlags указаны флаги CF_PRINTERFONTS или CF_BOTH.
Через параметр pParentWnd можно указать родительское окно для диалоговой панели Font.
Методы класса CFontDialog
Для отображения диалоговой панели Font предназначен виртуальный метод DoModal. Если пользователь выбрал шрифт и нажал кнопку OK, метод DoModal возвращает идентификатор IDOK, если пользователь отменил выбор шрифта, метод DoModal возвращает идентификатор IDCANCEL:
Остальные методы класса предназначены для определения характеристик выбранного пользователем шрифта.
Метод GetCurrentFont позволяет сразу определить все характеристики выбранного шрифта, записав их в структуру LOGFONT.
Остальные методы класса позволяют определить только отдельные характеристики выбранного шрифта:
GetFaceName - Возвращает имя выбранного шрифта
GetStyleName - Возвращает имя стиля выбранного шрифта
GetSize - Возвращает размер выбранного шрифта
GetColor - Возвращает цвет выбранного шрифта
GetWeight - Возвращает плотность выбранного шрифта
IsStrikeOut - Определяет, является ли шрифт выделенным перечеркнутой линией
IsUnderline - Определяет, является ли шрифт выделенным подчеркиванием
IsBold - Определяет, является ли шрифт жирным
IsItalic - Определяет, является ли шрифт наклонным
Панель для вывода документов на печать (класс CPrintDialog)
Класс CPrintDialog можно использовать для создания двух видов диалоговых панелей, предназначенных для печати документов и выбора форматов документов. Кроме класса CPrintDialog можно также использовать класс CPageSetupDialog. Он позволяет создать диалоговую панель для выбора формата документа, имеющую несколько иной вид.
В приложениях, подготовленных с использованием средств MFC AppWizard и построенные по модели документ-облик, по умолчанию встроена возможность вывода редактируемого документа на печать.
В меню File такого приложения находятся три строки (Print, Print Preview и Print Setup), которые управляют процессом печати документов, подготовленных в приложении. Чтобы распечатать документ, достаточно выбрать из меню File строку Print. На экране появится диалоговая панель Print. В ней можно выбрать печатающее устройство для печати документов (группа Name), указать, будет печататься весь документ либо его часть (группа Print range), а также сколько копий документа будет напечатано (группа Copies). Также можно настроить различные характеристики печатающего устройства, если нажать кнопку Properties в группе Printer.
Если требуется определить только печатающее устройство и формат документа, из меню File следует выбрать строку Printer Setup. В группе Printer можно указать печатающее устройство и настроить его соответствующим образом. Группа Paper задает формат бумаги и режим подачи бумаги в печатающее устройство. Группа Orientation включает только один переключатель, определяющий ориентацию бумаги. Он принимает положение Portrait для вертикальной ориентации изображения на бумаге (режим "портрет") или Landscape для горизонтальной ориентации изоборажения на бумаге (режим "ландшафт").
Строка Print Preview меню File выбирается для предварительного просмотра документа перед печатью. При этом главное окно приложения изменит свой внешний вид и можно будет просмотреть, как будет выглядеть документ после печати.
Если не требуется выполнять специфическую обработку документа перед печатью, то вряд ли понадобится самостоятельное добавление программного кода, отвечающего за процесс печати. Просто следует отметить, что процедура создания панелей, связанных с печатью документа, практически ничем не отличается от создания выше описанных стандартных диалоговых панелей.
Панель для выполнения поиска и замены (класс CFindReplaceDialog)
Класс CFindReplaceDialog предназначен для управления диалоговыми окнами Find и Replace. Диалоговая панель Find используется для поиска известных строк в документе приложения, а панель Replace позволяет замену одной строки на другую.
Важным отличием диалоговых панелей Find и Replace от других стандартных диалоговых панелей является то, что они представляют собой немодальные диалоговые панели. Поэтому процесс создания этих панелей значительно отличается от процесса создания стандартных панелей для выбора цвета, шрифта и имен файла.
В этой статье мы поговорим о рекламе сайта. Статья состоит из двух частей, в первой я расскажу вам отдельно о рекламе домашних страничек, во второй мы поговорим подробнее и серьезнее о рекламе в интернете, как таковой. Надеюсь, вы не пропустите первую часть статьи, потому что, не смотря ни на что, она принципиально важна.
Реклама домашних страниц.
Реклама, как таковая.
1 - Первый этап. Каталоги.
2 - Второй этап. Обмен баннерами и ссылками с тематическими ресурсами.
3 - Третий этап. Добавление в поисковые системы.
4 - Четвертый этап. Баннерные системы.
5 - Пятый этап. Нетрадиционные способы.
6 - Шестой этап. Как не потерять вашего посетителя.
7 - Седьмой этап. Повторение этапов.
Сразу поясню, почему я хочу поговорить с вами о рекламе домашних страниц отдельно.
Давайте рассмотрим эволюцию пользователя в интернете: сначала он гость, посещающий чужие сайты, знакомящийся с новыми людьми, чтобы переписываться с ними по почте, общаться в чате или на форумах. Но наступает момент, когда так хочется обзавестись собственным домиком, чтобы показать свою состоятельность и полноправность в гигантской паутине.
И вот когда домик отстроен, первые гости переступили его порог, похвалили, возникает такое свербящее чувство, которое можно назвать желанием популярности, желанием привлечь в свой домик толпы и толпы гостей в абсолютно разных целях: чтобы увеличить количество виртуальных друзей, а может быть найти любовь, или просто приобрести популярность, или даже извлечь выгоду из своего труда, заработать денюжку.
Все это вполне справедливые желания, т.к. и в реальной жизни нам свойственно самоутверждаться, но Интернет - это не тень реальной жизни, это информационная сеть, а простые домашние странички (обо всем и ни о чем, а точнее о вас любимых), они становятся мусором, когда в поиске важной, нужной и полезной информации человек натыкается на них, а не на то, что ищет в действительности. Поэтому, прежде чем ударяться в рекламные акции всеми правдами и неправдами, стоит задуматься: а нужно ли это? а как сделать, чтобы моя страница не стала мусором, а помогла найти мне друзей? А заработать?
Итак, сразу скажу, что заработок в интернете на пустом месте, из ничего, благодаря странице с баннерами спонсоров – миф, поверьте мне, и лучше забудьте об этом, не тратьте зря ни свое, ни чужое время.
Другое дело желание общения, некой популярности. Реклама вашей страницы в данном случае будет бесполезна, это все равно, что дать объявление в газете: вот мой дом, я там живу. Ну, и что? Кто вы такой, чтобы мы заинтересовались и пришли в гости? Другое дело, когда вы идете в какое-нибудь общественное место, клуб, знакомитесь там с новыми людьми, и говорите им, давая свой адрес:
- Вот мой дом, я там живу.
- О! – скажут они, - мы обязательно придем, нам с тобой было интересно пообщаться, и мы хотим узнать о тебе побольше и пообщаться еще не раз.
Т.е. я веду к тому, что домашняя страница, это как ваша квартира, чем больше у вас друзей, тем чаще они приходят к вам в гости, они заинтересованы в вас, именно поэтому им интересна ваша страница. Итак, для того, чтобы ваша страница была популярной, вы сами должны быть популярными. Благо, в интернете для этого много способов. Есть чаты, сайты знакомств, конференции и сайты, где люди общаются по определенным интересам, игровые сайты. Посещайте их, общайтесь, если вы интересны, то, посмотрев вашу анкету на таком сайте, люди обязательно посетят, и не раз, вашу домашнюю страницу.
И если у вас на душе все равно свербит и хочется добавить свою домашнюю страницу в поисковые системы и каталоги, тогда будьте вежливы, добавляйте ее в категории для Домашних страниц, они везде есть специально для вас. Повторюсь, не надо мусорить, вы поступите очень не красиво, если из-за того, что на вашей странице вы рассказываете о своей игрушечной машине, вы начнете позиционировать вашу страницу, как замечательный сайт об автомобилях. Это не даст популярности вашему сайту, т.к. на самом деле это не сайт об автомобилях, а лишь ваша домашняя страница, это только вызывает раздражение и негативные эмоции у тех, кого вы обманули.
Реклама, как таковая.
Я рассказывал о том, как сделать домашнюю страницу популярной, и читал нотации вам не просто так. Самое главное понять, что вы хотите достичь рекламной кампанией, и нужно ли вам это на самом деле.
Почему надо к рекламе подходить серьезно? Почему слово раскрутка надо отмести, как не состоятельное? Почему вы должны подходить к рекламе цивилизованно, когда вы можете просто начать «крутить» свой сайт и можете получить в день до 1000 посетителей с нуля при помощи специальных программ?
Потому что раскрутка это всего лишь фикция. Это посетитель, которого не было, который не вернется, который не пойдет по вашему сайту дальше первой страницы. Это зря затраченные усилия и потраченное время.
Для нас самое главное найти своего посетителя и заинтересовать его в том, что мы хотим ему предложить.
Но давайте по порядку, прежде всего вам следует понять, что количество и постоянный приток посетителей на вашем сайте зависит не только от рекламы, а также от наличия интересной, определенной группе людей, информации, ради которой они будут посещать ваш ресурс. Так, например, некоторые крупные компании, создают тематические информационные порталы относительно области своей деятельности, чтобы таким образом привлечь не только посетителей на свой сайт, но и потенциальных клиентов. Т.е. первое, что мы должны сделать, это качественный и интересный ресурс, сами понимаете, жиденькие сайты с 2-мя-3-мя десятками страничек, с информацией ни о чем, не могут претендовать на звание качественного ресурса.
Также хочу заметить, если вы создаете сайт для коммерческой организации, то лучше всего этот процесс от начала до конца поручить специалистам: и разработку, и рекламу, потому что и то, и другое взаимосвязано. По сути, сайт – это что-то вроде вашей рекламной брошюры: во время рекламной кампании вы привлекаете к ней внимание, чтобы ее прочли, и если ваш сайт-брошюра не интересен и не заинтриговал человека, пришедшего по рекламному объявлению, то смысл рекламной компании сводится к нулю.
Итак, поскольку я считаю, что коммерческие организации могут потратиться на рекламу, и даже должны, а обычные информационные порталы и некоммерческие организации часто не имеют возможности позволить себе относительно дорогостоящую рекламу, поэтому моя статья скорее для владельцев ресурсов последнего типа, поэтому я буду вести речь о бесплатных, или не очень дорогих способах рекламы сайта.
Когда, мы имеем качественный ресурс, хорошо продуманный, выверенный, стоящий того, чтобы о нем узнали, не надо нестись сломя голову на сайты поисковых систем и каталогов, не торопитесь. Следует продумать, какая аудитория заинтересована в вашем ресурсе: возраст, пол, профессиональная занятость этой аудитории – например, грузчики они или учителя. После того, как вы определились какова ваша аудитория, надо понять, где ваша аудитория в интернете обитает: на какие сайты ходит, какие журналы читает, и т.д. И только после этого мы начинаем охоту, господа :) .
Первый этап. Каталоги.
Первым делом мы добавляем себя в каталоги. Да-да, именно в каталоги, а не в поисковые системы, чуть позже объясню почему. Для добавления в каталоги нам надо придумать рекламное не слишком длинное объявление, такое, которое по возможности выделит ваш сайт среди других, подобных вашему, и может заинтересовать вашего потенциального посетителя. Объявление должно быть написано без грамматических ошибок, проверьте себя, не поленитесь, прежде чем оставлять объявление в каталогах.
Какие каталоги нас интересуют? Желательно каталоги, которые собирают в себе сайты с тематикой, подобной нашей. Т.е. если наш сайт рассказывает о медицинских проблемах, то имеет смысл поместить его в каталог, который освящает медицинские ресурсы. От обычных каталогов мы тоже не отказываемся, если у них есть раздел для сайтов с нашей тематикой, если нет, то не имеет смысла пихать информацию о нашем ресурсе туда для количества, не тратьте время.
Весьма рекомендую вам сайт http://1ps.ru - лучшего ресурса в плане поиска каталогов и добавления себя в них вам не найти. Однако, не добавляйте свой сайт через него в поисковики, это лучше делать вручную, и не сразу.
Второй этап. Обмен баннерами и ссылками с тематическими ресурсами.
Когда мы добавляем наш сайт в каталоги, то стоит обратить там свое внимание на интересные и посещаемые ресурсы со сходной нашему ресурсу тематикой. Зачем? Потому что мы будем обмениваться с ними ссылками и баннерами (желательно маленькими баннерами, кнопками).
Выберите несколько наиболее интересных ресурсов, которые предлагают обмен ссылками и баннерами, и напишите их владельцам письма, в которых поинтересуйтесь, не захотят ли они обменяться с вами ссылками или баннерами. Письмо должно быть вежливым, содержать ссылку на ваш ресурс и информацию, где вы собираетесь разместить баннер/ссылку портала, с которым хотите обмениваться.
Письмо должно именно предлагать - наглые письма: мол, я разместил на вас ссылку, а вы теперь разместите на меня – нельзя писать ни в коем случае. Помните, владелец крупного ресурса, посещаемого и устоявшегося, делает вам одолжение, размещая баннер или ссылку на вас, а не вы ему.
Предложите разместить его ссылку на первой странице вашего сайта, при этом будьте готовы согласиться на то, что в ответ вашу ссылку повесят в разделе с не слишком большой посещаемостью, и уж, в любом случае, не на главной странице.
Зачем нам это нужно: потому что третьим этапом будет размещение в поисковых системах, от того, какие ресурсы по качеству и сколько ресурсов на вас ссылается, зависит ваша позиция в списке результатов, выдаваемых поисковой системой пользователю на какой-либо запрос. Поймите, когда отпадет надобность, и вы добьетесь нужных вам результатов и посещаемости, вы можете отказаться от обмена баннерами/ссылками с другим ресурсом, или же заключить новые условия обмена.
Кстати, на втором этапе ваши друзья и знакомые могут вам помочь, разместив на ваш портал ссылку у себя на сайтах.
Третий этап. Добавление в поисковые системы.
Вы должны понимать, что сразу ничего не делается, прежде чем все ваши действия принесут результаты, пройдет какое-то время. Не надо никуда торопиться, ваш ресурс некоммерческий, от того, что к вам сразу не будет притока посетителей, трагедии не случится. К тому же бесплатная реклама не может быть сопоставима по эффективности с той, в которую вы вложили деньги.
В поисковые системы мы добавляем информацию о нашем ресурсе через неделю-другую, после того, как мы разобрались с каталогами и обменом. Мы это делаем в надежде, что к тому времени, как мы будем добавлять о себе информацию в поисковики, они успеют проиндексировать (заметить), страницы других сайтов, где появилась информация о нас.
Для поисковых систем мы заготавливаем заранее ключевые слова - это слова, которые, как мы предполагаем, будет вводить для поиска человек, когда он ищет ресурсы, содержащие такую информацию, как на нашем сайте. Также для поисковых систем мы заготавливаем интересное описание, нашего ресурса.
На что стоит обратить внимание при составлении списка ключевых слов - ключевые слова, должны встречаться в обычном тексте на страницах нашего сайта. Так, если мы берем слово «медицина», как одно из ключевых, оно должно быть в тексте на первой странице нашего сайта, и не только на ней, т.к. поисковые системы смотрят, соответствуют ли заявленные ключевые слова тем, что содержатся в тексте ваших страниц. От этого тоже зависит ваша позиция в списке результатов, выдаваемых поисковой системой пользователю.
Более того, есть специальные META тэги, которые мы должны прописать в коде всех страниц нашего сайта, они содержат ключевые слова и описание вашего сайта. Содержимое мета-тэгов не видно посетителю вашей страницы, зато учитывается поисковыми системами.
Четвертый этап. Баннерные системы.
Участвовать в баннерных системах имеет смысл, только если они тематические – т.е. допустим, баннерная система, в которой участвуют только сайты с медицинской тематикой. В универсальных баннерных системах, не подчиненных единой тематике участвовать вам не имеет смысла. Это не эффективно, ведь вы сможете показывать в день столько баннеров, сколько было показано на страницах вашего сайта, т.е. мало, а если их при этом не видит ваш потенциальный посетитель, человек, который заинтересован в предлагаемой вами информации, то эффективность баннерной рекламы стремиться к нулю, незаинтересованный человек просто не перейдет по баннеру на ваш сайт.
Баннерные системы нас могут интересовать также в том случае, если вы все-таки решили немного потратиться на рекламу. В этом случае вы можете купить баннерные показы на каких-нибудь крупных сайтах, где обитает ваш потенциальный посетитель.
Пятый этап. Нетрадиционные способы.
Вы можете мне не поверить, но этот этап может быть самым эффективным, для повышения посещаемости вашего сайта.
Ваша задача придумать, как еще можно рекламировать свою страницу. К сожалению, общего рецепта тут быть не может. Но я расскажу, как я действовал в случае с Постройкой.ру, в свое время, чтобы вы поняли, что я имею ввиду.
Я сидел, думал, как же сделать сайт популярнее. И мне пришла в голову замечательная идея: у меня есть замечательный и уникальный учебник по html, если сделать оффлайн версию, положить в архив, тогда можно будет поместить мой учебник на сайты-сборники разных программ, ведь я ничего от этого не теряю. Конечно, прежде чем сделать это, я посмотрел, дают ли эти сайты такую возможность, оказалось, что на них имеются специальные разделы для обучающих программ и мой учебник подходит для размещения там. Решено, сделано. Я разместил учебник по всем крупным файловым архивам. В итоге, через какое-то время посещаемость моего сайта заметно возросла, потому что посетители, прочитав оффлайн версию уникального учебника приходили на сайт в поисках других интересных и полезных материалов, а также советов автора.
Конечно, этот способ подойдет не всем. Но вы можете написать несколько интересных статей, и поместить их на крупные порталы, если статьи будут интересные, то читатель зайдет на ваш сайт, ведь в статье всегда указываются при публикации данные об авторе.
Я полагаю, это далеко не единственные нетрадиционные способы, стоит только приложить чуточку выдумки, и вы найдете хороший способ для рекламы своего сайта. В любом случае, это не должен быть способ навязывания: некоторые несознательные граждане захламляют чужие форумы и гостевые следующим образом - “Здрасте, я Вася Пупкин, мне ваш сайт нравится. Посетите мой сайт.” - это неправильное позиционирование вас и вашего ресурса, так вы только выставляете себя в дурном свете.
Шестой этап. Как не потерять вашего посетителя.
Чтобы посетитель возвращался к вам вновь и вновь, нужно периодически добавлять на сайт новую информацию. Кроме того, нужно постоянно поддерживать с посетителем общение: установите форум или гостевую книгу, где посетители смогут задавать вам вопросы. Старайтесь каждый день просматривать форум, гостевую книгу, почту, и отвечать на вопросы ваших посетителей.
Вы также можете устраивать опросы, чтобы узнать мнение своего посетителя, что ему нужно, это создаст у него впечатление, что он принимает участие в развитии вашего ресурса, ему будет это приятно. Вы можете устраивать конкурсы с небольшими призами. Вы можете сделать новостную рассылку + рассылку с частью новых материалов, которые появляются на сайте. И много чего еще.
Не забывайте, главное, это заинтересованность вашего посетителя в том, что вы ему предлагаете, он нужен вам, а вы должны попытаться стать нужными ему. Когда вы нужны посетителю, когда у него остаются хорошие и теплые впечатления о вашем сайте, он начинает рекомендовать вас друзьям, знакомым. Он начинает сам упоминать о вас на форумах и чатах, где он общается. Он добавляет на вас ссылку на своей странице, чтобы поделиться с другими таким хорошим ресурсом, как ваш. А это и есть лучшая реклама, а это и есть признание того, что ваш ресурс действительно замечательный.
Седьмой этап. Повторение этапов.
Каждый день в интернете появляется много разных и новых ресурсов. В том числе и каталоги, и поисковые системы, и новые сайты, близкие по тематике вашему. Ваша задача следить за новыми ресурсами, добавлять свой сайт в новые каталоги и поисковые системы. Если вы будете заниматься рекламой периодически, то у вас больше шансов сделать свой сайт посещаемым, и привлечь больше новых посетителей.
Все началось до банального просто - любимый директор сказал "Хочу!". Аргументация была следующей:
* Переводится много бумаги для печати и отправки по факсу (клиентов много, потому отправленные счета сразу выбрасываются: найти нужный документ даже через день - нереально)
* Электронная почта "есть в наши дни у всех и каждого" (то, что сам директор ею не пользуется - другой вопрос :-) )
* Тратится меньше времени персонала (не нужно сидеть и ждать перед факсом, стартовать, "прошло"/"не прошло", ...)
* Легче вести учет когда и что было отправлено.
Сначала ставился вопрос отправки документов вообще - что может быть проще? Сохранить таблицу как файл MS-Excel, вызвать внешнюю программу отправки с параметрами - и все. Потом возникли сомнения:
* А вот клиенты отредактируют файл - и будут доказывать что мы такой и отправили,
* В файле передается рисунок печати - они его смогут использовать с какой-нибудь темной целью.
Сразу же было предложено отправить как рисунок, благо я знал, что это можно сделать, но как - еще не представлял. Согласие получено, и вот начались поиски соответствующих программ...
Подбор нужного инструментария
Некоторое время я стараюсь использовать бесплатные программы, а не ломать те, за которые нужно платить деньги. Так что одним из условий (не главным, но в результате выполненным почти на 100%) была бесплатность инструментария.
Понятно, что для получения рисунка на выходе нужен виртуальный принтер, на который можно печатать любой документ. Выходным форматом был выбран tiff как достаточно распространенный, предполагая что его можно будет конвертировать в любой формат, если возникнет необходимость. Были испробованы многие принтеры, встреченные в просторах Internet`а, как бесплатные, так и нет. Большинство из них умеют печатать кроме искомого tiff еще и pdf документы, но не один не удовлетворял условиям передачи в них внешних параметров (важно было указать место сохранения и возможно имя файла для уменьшения коллизий, поскольку работа происходит на сервере терминалов). В конечном итоге выбор пал на AFPL Ghostscript 8.14 for Win32 и драйвер переадресации порта принтера RedMon.
Ghost Script умеет конвертировать данные из ps, eps, pdf в разные форматы (те же ps, eps, pdf, языки принтеров вроде PCL6 от HP, и рисунки). Получать данные он может как из файла, так и из входящего потока (stdin для посвященных). RedMon умеет данные, полученные от драйвера принтера, передавать как входной поток выбранной программе. Кроме того устанавливает несколько системных переменных, одну из которых (%REDMON_USER% - имя пользователя, печатающего документ) мы будем использовать.
Итак - используемый режим связки: установка PS принтера в системе, указание ему виртуального порта RedMon, пересылка исходящего PS потока от принтера на Ghost Script, формирование tif по указанным настройкам.
Настройки для режима работы Ghost Script хранятся в файле одном для всех, потому в схему добавим еще одно звено: RedMon передает данные не Ghost Script, а скрипту WSH, а уже он откорректировав настройки под пользователя, передает дальше поток для Ghost Script. Потому еще одна программа, которая нам нужна: Windows Script 5.6 for Windows. Нужна именно версия 5.6, поскольку во встроенной в Windows 2000 версии 5.1 отсутствует необходимый метод Exec().
Еще возможно нам понадобится компонент для вывода рисунков с прозрачным фоном. Пока приходится использовать Active_BMP, упоминаемый на безвременно почившем hare.ru. Этот компонент умеет отображать прозрачными только 2-х цветные bmp (по крайней мере только с ними у меня получилось добиться прозрачности), но за неимением лучшего... :-) (Если кто знает бесплатный ActiveX компонент для отображения gif с прозрачным слоем - скажите в форум или мыло)
Собственно для отправки почты из командной строки я уже полгода пользуюсь Postie, потому искать ничего нового не пришлось.
Приступим (установка и регистрация программ)
Установка WSH проблем не вызывает (конечно, если вы не попытаетесь установить версию для 9X/NT4 на 2000/XP, как я это сделал, причем осознал это только взявшись за статью - уже месяц сервер живет в этом режиме :-) ): запуск scripten.exe (scr56en.exe), ответы на все вопросы, перезагрузка.
Установка Ghost Script не требует даже перезагрузки. Единственный момент - от пытается по умолчанию установится в каталог %SystemDrive%\gs - я его устанавливал в %SystemDrive%\Tools\gs - так мне удобнее. (ниже в скобках я буду писать свои настройки, с которыми у меня работает живая система).
Для установки RedMon нужно его распаковать в некий каталог (%SystemDrive%\Tools\RedMon) и запустить setup.exe из него. В файлах readme.txt и redmon.hlp находится подробная информация по установке и стандартной настройке redmon.
Регистрация Active_BMP осуществляется распаковкой файлов в каталог (%SystemDrive%\Tools\OLE\ActiveBMP) и запуском из этого каталога "regsvr32 Bmp_1c.ocx".
В дальнейшем каталоги с RedMon и Active_BMP нам не понадобятся, так что про них смело можно забыть (но не удалять совсем с диска :-) ).
Postie устанавливается простым извлечение его в нужный каталог (%SystemDrive%\Tools\Postie).
Теперь нам необходимо настроить принтер. Для этого из папки принтеры выбираем "Добавить". Тип принтера - локальный, отказываемся от автоматического поиска и добавляем порт: тип порта: Redirect Port, имя: RPT1. На следующем шаге выбираем модель PS-принтера (в RedMon рекомендуется Apple LaserWriter II NT или Apple Color LaserWriter 12/600 если вы хотите цветное изображение). Я использовал Apple LaserWriter II NT, т.к. мне нужно было черно-белое изображение. Сразу после этого я переименовал принтер в более соответствующее его функциям название: "Send EMail". Теперь нам необходимо настроить порт. Для этого открываем настройки принтера, ищем страницу "Порты" и жмем кнопку "Конфигурировать порт".
Дальнейшие настройки отличаются от стандартных, описанных в redmon.hlp:
* "Redirect this port to the program:"="cscript.exe" (без кавычек, естественно),
* "Arguments for this programs are:"="Наш\Скрипт\С\Полным\Путем.js" (%SystemDrive%\Tools\gs\PrnUser.js) (в кавычках, если путь содержит пробелы),
* "Output:"="Program handles output"
* "Run:"="Hidden"
* "Run as user" снята (у меня вызывало ошибку, если установлено)
* "Shut down delay:"="300"
Кнопка "Log file" нужна во время отладки всей системы отправки почты, хотя можно оставить запись лога и в рабочем режиме - все равно он перезаписывается, а не накапливается.
Соглашения о настройках
Скрипт, который мы указали в настройках порта, принимает данные с принтера и согласно настройкам, сохраненным из внешней программы (1С или другой), отправляет его по почте как рисунок (в скрипте предусмотрены проверки на корректность значений). Поскольку единственное, что мы можем получить из печатного задания - это имя пользователя (%REDMON_USER%), то с каждым пользователем мы будем работать в его каталоге, при этом одновременная печать 2-х заданий от одного пользователя невозможна. (Если вам удастся передать в скрипт другую информацию из 1С, например: уникальный идентификатор задания или имя файла - сообщите мне). У меня используется самописный компонент SysTools для получения профиля пользователя по его имени. Поскольку он еще только в альфа-версии выкладывать не буду, если кому нужен - вышлю по почте. Итак, предположим, у нас есть каталог, в котором хранятся данные пользователей (%MyProfiles%\User1, %MyProfiles%\User2, ...). К личном каталоге пользователя мы будем создавать подкаталог SendMail для отправки почты.
Временные файлы для работы мы будем хранить во временном каталоге (переменная %TEMP% для системы, поскольку запускаться скрипт будет от имени Local service).
Все остальные настройки и пути к файлам заданы в переменных вначале скрипта - их можно (и нужно) изменить для себя.
Файл, в котором 1С сохраняет настройки называется %UserProfile%\SendMail\mail.ini и имеет следующую структуру: каждая строка - поле=значение, кроме поля BODY, которое обязательно идет последним и может быть растянуто на несколько строк.
Пишем программу
В этом разделе будут показаны и пояснены тексты нескольких модулей, входящих в демонстрационную конфигурацию. Скрипт на языке JavaScript здесь описан не будет, поскольку несоответствует тематике раздела. Надеюсь - комментариев внутри скрипта будет достаточно для пожелавших разобраться в его работе.
Поскольку в 1С не предусмотрена модульная организация программ, то сложные вещи я обычно строю по такой схеме: законченная функциональность - во внешней обработке, параметры в которую передаются через СписокЗначений, и вспомагательная процедура/функция в глобальном модуле, которая этот список заполняет из параметров. Так было сделано и здесь.
Функция запроса параметров отправки почты (кому, от кого, тема и пр.) в глобальном модуле выглядит так:
[pagebreak]
В этой функции переданные параметры записываются в список значений, который передается внешней обработке ПараметрыОтправкиПочты.ert в подкаталоге ExtForms каталога базы данных. Запрос параметров имеет вид:
Возвращенные значения записываются в файл, параметры которого (путь, имя, и т.п.) заданы в конце глобального модуля.
В самой обработке ничего интересного нет: чтение параметров из списка, отображение и проверка параметров при нажатии кнопки Отправить. Если не заданы необходимые параметры (ОтКого, Кому) или адреса E-Mail указаны не правильно - будет выдано сообщение и форма не закроется.
Рассмотрим параметры вызова даной функции:
* Заголовок - заголовок формы, на рисунке - синяя надпись "Тестовый документ №3 от 30.04.04";
* Кому, ОтКого, Копия - E-mail или список E-Mail`ов (через ",");
* Тема, Сообщение - соответствующие параметры письма;
* Запретить - какие поля запрещены для редактирования (на рисунке - поле Тема);
* БезФормы - если 1: форма не отображается и при правильных параметрах письмо отправится автоматически.
Следующая функция вызывает эту и если все прошло успешно - вызывает внешнюю обработку для небольшой предподготовки таблицы при печати и отправки ее:
Здесь уже большая функциональность перенесена на обработку. Она (обработка) вообще не открывается, только выполняет некоторые действия. Рассмортим параметры:
* Таб - Значение типа "Таблица", которую и будем печатать;
* Заголовок, Кому, ОтКого, Копия, Тема, Сообщение, Запретить, БезФормы - просто передаются в функцию глПараметрыОтправкиПочты и подробно рассмотрены в ней;
* Масштаб - масштаб печати таблицы. Если не задан - автомасштаб по ширине.
В обработке всего 2 процедуры: ПроверитьПараметр для проверки корректности переданных значений и ПриОткрытии, в которой подготавливается и печатается таблица. Выглядит весь модуль обработки так:
Код: (1c)
Вот практически и все, что касается программы в 1С. Некоторые сервисные функции, которые не были описаны здесь, можно посмотреть в примере конфигурации. Таким образом ничего сложного здесь нет. Больше сложностей вызывает настройка системы для правильной работы. Выглядит отправленный документ приблизительно так:
Замечания в процессе эксплуатации
Сразу скажу - в боевом режиме система работает недолго (с 15.04.2004), но даже за это время были замечены некоторые "особенности" работы:
* Формат tiff оказался не таким уж стандартным. Потому пришлось его заменить на png. Сделать это нужно в двух местах: в суффиксе исходящего файла в скрипте (чтобы Postie правильно поставил его Content-Type:) и в настройках GS (параметр -sDEVICE=pngmono собственно и задает выходной формат файла). Можно заменить и на еще более стандартный jpeg, но при этом сильно вырастет размер файла. К сожалению gif уже не поддерживается в текущей версии GS (как я понял из документации - из-за возможных проблем с лицензированием этого формата). Можно добится поддержки gif, выдрав ее из исходников предыдущих версий и перекомпилировав текущую, но я пока этого не делал. Возникла мысль передавать в настроечном файле (%UserProfile%\SendMail\mail.ini) параметры, как отправлять изображения (jpeg, tif, png; color/mono; ...) и в скрипте динамически менять.
* PostScript шрифты, идущие в поставке GS, не так хорошо "вылизаны", как TrueType. Потому русские буквы выглядят жирнее англиских. Пока жалоб на это не было :-)
* В новой версии Postie у меня почему-то не работает ключ -bcc (ошибки не выдает, но и не отправляет по указанным адресам). Так и не разобрался - пришлось откатится на старую версию (POSTIE Version 4)
* Хотя ломать ничего и не пришлось, но все-таки мы нарушаем лицензию Postie, который "free for personal use". Может кто знает другую программу отправки почты из коммандной строки?
Благодарности
Моему любимому директору - за неуемный ум и новые интересные задания.
Вадиму Ханасюку - за неопубликованную здесь, но полезную компоненту SysInfo (получение каталога профиля пользователя по имени) и помощь в поиске нужного софта.
Всем сотрудникам, которые не мешали работать.
Очень часто при работе с запросами приходится менять SQL этого запроса. Например, при изменении порядка сортировки или при необходимости изменения фильтра, прописанного в where. Сделать это стандартными средствами можно, но довольно муторно, т.к. весь запрос хранится в одном месте (для TQuery и её потомков это свойство Sql). При желании изменить, например, количество или порядок следования полей в order by, нужно программно найти этот order by, написать свой, вставить его вместо старого и т.д. Для меня, честно говоря, загадка, зачем борланд пошла по такому ущербному пути: стандарт ANSI SQL-92, с которым (и только с которым!) работает Bde, подразумевает достаточно жёсткий синтаксис запроса, вполне допускающий обработку на уровне отдельных секций. Сегодня я хотел бы поделиться одним из вариантов реализации потомка TQuery, в котором задачи такого класса будут решаться на лету одной строчкой кода.
Смысл очень простой. Для того, чтобы уйти от ручной обработки текста sql-запроса, надо просто разбить его на стандартные секции. И менять их по отдельности. Ведь любой select-запрос имеет достаточно строгий синтаксис, состоя из определённого количества заранее известных секций (clauses), задаваемых в строго определённой последовательности. Рассмотрим этот синтаксис поподробнее на примере СУБД Interbase:
Как видим, обязательными являются две секции: SELECT и FROM.
Ещё восемь секций опциональны. Наша задача сводится к тому, чтобы значение каждой секции устанавливать отдельно, при необходимости переоткрывая запрос. Можно было бы плясать от стандартного свойства Sql, выделять нужную секцию, менять и вставлять обратно. Но зачем это, если можно сам Sql формировать на основе заданных секций? Конечно, этот подход имеет тот минус, что накрывается прямая установка Sql одной строкой, что может быть неудобно при хранении запроса в реестре, базе и т.д., но и это, при желании, можно побороть.
В общем-то, ничего заумного, реализация до смешного проста, но при использовании в проектах позволяет сэкономить массу времени и значительно увеличить читабельность кода.
Чтобы не писать отдельное свойство на каждую секцию, задавать их будем в виде массива строк. Для работы с этим массивом нам понадобятся индексы, которые тоже лучше определить заранее:
Определим тип нашего индексированного свойства и определим сам класс:
Свойство fClauses будет содержать все секции запроса, на основе которых и будет формироваться сам запрос. Занимается этим процедура UpdateSql. Ну а методы GetClause/SetClause стандартны, и служат для установки/чтения значений отдельных секций. Поглядим на сам код:
Всё достаточно прозрачно, отмечу лишь, что метод UpdateSql добавляет в текст Sql-запроса только те секции, для которых установлено начение, и переоткрывает квери, если она была открыта на момент изменения секции. Здесь есть мелкие недоработки, например, не проверяется выход индекса за пределы допустимых значений, я просто не хотел мусорить исходный код вещами, которые очевидны и принципиально не важны. Можно было бы привести код регистрации компонента в палире дельфи, но это также тривиально. Приведу лучше исходник тестового проекта, в котором используется этот квери. В этом проекте на форме находятся компоненты DbGrid1, подключенные к источнику данных DataSource1, динамически создаётся экземпляр TDynQuery, открывающий таблицу "biolife" из DbDemos, входящую в стандартную поставку Delphi. После этого изменяется по кликанью на заголовке (Title) грида меняется сортировка таблицы: