Реферат: Протоколы и стандарты ООП - текст реферата. Скачать бесплатно.
Банк рефератов, курсовых и дипломных работ. Много и бесплатно. # | Правила оформления работ | Добавить в избранное
 
 
   
Меню Меню Меню Меню Меню
   
Napishem.com Napishem.com Napishem.com

Реферат

Протоколы и стандарты ООП

Банк рефератов / Программирование

Рубрики  Рубрики реферат банка

закрыть
Категория: Реферат
Язык реферата: Русский
Дата добавления:   
 
Скачать
Microsoft Word, 302 kb, скачать бесплатно
Заказать
Узнать стоимость написания уникального реферата

Узнайте стоимость написания уникальной работы

Протоколы и стандарты объектно-ориентированно го программирования П редисловие Наиболее распространенным языком программи рования последнего десятилетия безусловно являет ся С . Этому способствовали такие его особе нности , как лаконичность , мощность , гибкость , мо бильность . Вместе с тем , стремительное усложне ние приложений , дл я реализации которых применяются традиционные процедурно-ориентированнные языки программирования и , в частности С , заставляют говорить об определенном кризисе в их использовании , связанном прежде всего с недостаточной надежностью и выразительной способнос т ью. Подобных недостатков во многом лишены языки объектно-ориентированнго программирования (ОО П ), в основе которых лежит идея моделирова ния объектов посредством иерархически связанных классов . Отдельно взятый класс рассматривает ся как совокупность множества данных и операций над ними , причем доступ к эл ементам данных класса возможен только посредс твом операций этого класса . Установление четк ой взаимозависимости между данными и операция ми ведет к большой целостности данных и значительно повышает надежность п р ограмм по сравнению с традиционными языками программирования . Кроме того , идея программир ования с помощью классов во многом исполь зует тот же подход , который позволяет людя м формировать модели объектов реального мира. Впервые идеи ООП были реализов аны в се редине 60-х годов в языке программирования Симула -67. Последний , однако , не нашел в то время широкого распространени я как в силу своей относительно меньшей производительности по сравнению с традиционным и языками типа FORTRAN, ALGOL, PL/1 так и , возможно , н еадекватности предлагаемых средств решаемым в то время задачи . Еще одним важным ограничением для распространения Симулы -67 стали трудности , с которыми пришлось столкнуться большинству программистов при его изучении . Дело в том , что наряду с целым рядо м бе з условных достоинств , идеи ООП обладают и одним существенным недостатком - они далеко не просты для понимания и особенно для освоения с целью практическог о использования. С ++ - развитие С. С ++ - это объектно-ориентированыый язык , то есть язык , позволяющий программисту опери ровать объектами некоторых типов , предварительно им определенным . Название языка "С ++" отража ет эволюционный характер изменения языка С (запись "++", в языке С , означает , что к какой-то переменной прибавляется единица ). Он и меет еще боле е мощные и гибкие средства для написания эффективных программ , чем С , от которого он произошел . Чело век , программирующий на традиционных языках , м ожет просто потерять голову от тех возмож ностей , которые предоставляет С ++. Но не менее важным является то , чт о такой распространенный и универсальный язык , как С , сохранен в качестве основы . С прост , эффективен , переносим . Чего тольк о нет в языке С : строковых данных нет , матриц нет , средств параллельного программир ования тоже нет . Нет даже ввода-вывода. Типы , опер ации и операторы С о чень близки к тому , с чем мы имеем дело в Ассемблере -числа , адреса , арифметиче ские и логические действия , циклы ... Кроме т ого , многие особенности С недвусмысленно наме каю компилятору , как сократить код и время исполнения программы . Эт и характерн ые черты языка С позволяют написать эффек тивно работающий и не слишком сложный ком пилятор . И хотя в машинных кодах на ра зных компьютерах элементарные операции обозначаю тся по-разному , вряд ли разработчику компилято ра придет в голову интерпретиро в а ть простейшие выражения каким-нибудь оригинальным способом . Именно поэтому язык С "идет везде и на всем ", программы , написанные на нем , работают эффективно , и их можно п ереносить с одного компьютера на другой. Большинство языков программирования созданы д ля решения определенного круга зада ч . В них не только не хватает определе нных типов данных и функций , но и мног о лишнего с точки зрения человека , далеког о от области , на которую ориентирован язык . Специализированные типы данных или оператор ы , требующие не т ривиальной поддержки , затрудняют изучение языка и мешают вашей работе , если вы ими не собираетесь по льзоваться . Поэтому С , в котором нет ничег о лишнего , популярен среди широкого круга программистов . Соответствующие библиотеки могут д обавить к средствам яз ы ка специал изированные функции для работы со строками , файлами , списками , устройствами ввода-вывода , мат ематическими объектами и т.д . Остается только выбрать то , что нужно лично вам . Загол овочные файлы облегчают использование библиотек , предоставляют полез н ые типы данн ых , глобальные переменные , макроопределения ... Они во многом устраняют противоречие между эфф ективностью программы и удобством использования библиотечных функций . Они также позволяют не повторятся и не писать по несколько раз одно и тоже в раз л ич ных программах . Поскольку С был создан спе циально для системного программирования , он и меет возможности низкого уровня , позволяющие " играть без правил ". В зависимости от устро йства и операционной системы вашей машины вы можете "влезть " в видеопамять или использовать системные программы , находящиеся в оперативной памяти. В любом случае вы можете рассматриват ь код собственной программы как данные , а массив данных как код функции , квадратную матрицу как вектор , а текст как бинар ное дерево . Что бы ни находило сь в памяти - это всего лишь последовательная цепочка чисел . Если вы не боитесь риска - можете делать все , что вам вздумается. Современные программисты выбирают С не только из-за его преимуществ . В настоящее время мы имеем дело с цепной реакцией : чем больш е написано на С , тем больше на нем напишут еще . Это одна из причин , почему язык С ++ сохраняет С в качестве подмножества. По мнению автора С ++, Бьерна Страуструп а , различие между идеологией С и С ++ за ключается примерно в следующем : программ на С отражает "с пособ мышления " процессора , а С ++ - способ мышления программиста . Отвеч ая требованиям современного программирования , С ++ делает акцент на разработке новых типов данных , наиболее полно соответствующих концепци ям выбранной области знаний и задачам при ложени я . На С пишут библиотеки ф ункций , С ++ позволяет создавать библиотеки клас сов . Класс является ключевым понятием С ++. О писание класса содержит описание данных , треб ующихся для представления объектов этого типа , и набор операций для работы с подобн ыми объекта м и. В отличие от традиционных структур С или Паскаля , членами класса являются не только данные , но и функции . Функции-члены класса имеют привилегированный доступ к данным внутри объектов этого класса и обе спечивают интерфейс между этими объектами и остально й программой . При дальнейшей работе совершенно не обязательно помнить о внутренней структуре класса и механизме ра боты "встроенных функций ". В этом смысле кл асс подобен электрическому прибору - мало кто знает о его устройстве , но все знают , как им пользов а ться. Часто в целях повышения эффективности и упрощения структуры программы приходится заставлять ее работать с разнородными объе ктами так , как если бы они имели один и тот же тип . Например , окружность и квадрат естественно рассматривать как вариан ты геоме трической фигуры . Полезно составл ять списки фигур , нарисованных на экране , или функций , которые их размножают , двигают и т.д . О точном типе объекта приходится порой забывать . Список геометрических фигур "не знает ", что в нем находится - отрезк и или звездо ч ки . Не знает этог о и компилятор . Но все время , пока вы рисуете эти объекты , неизбежно приходится "помнить ", что они из себя представляют . Конечно , возможности низкого уровня позволяют "забывать " и "вспоминать " когда и как нам заблагорассудится , но при это м ко мпилятор теряет контроль над осмысленностью д ействий. Использование производных классов и вирту альных функций позволяет избежать рискованной техники и не заботится о том , в как ой форме объект типа "геометрическая фигура " хранит информацию о том , круг он или квадрат . (Кроме возможностей ООП , создание типов данных "треугольник " или "квадрат " ка к производные от базового класса "геометричес кая фигура " отражает логическую связь понятий ). Виртуальные функции , по существу , определяют , что именно можно делать с объ ектом , а не то , как это делать . Создава я класс "геометрическая фигура ", мы можем в ключить в него виртуальные функции рисования , увеличения , поворота . С использованием этих функций можно создать еще один член кл асса. Затем можно разработать библиотеку пр ограмм интерактивной графики , снабдив ее средствами диалога , функциями вроде дополнен ия некоторой области экрана одинаковыми геоме трическими фигурами и т.д . Библиотечные функци и будут вызывать функции-члены класса "геометр ическая фигура ": рисования , движе н ия , поворота , увеличения . А после того , как мы все это напишем , откомпилируем , спрячем текст функций , которые считаем своей интеллек туальной собственностью , начинается самое интерес ное . Теперь мы можем описать сколько угодн о новых типов фигур - многоуголь н и ков , звездочек , эллипсов - производных от класса "геометрическая фигура " и объяснить , как и х рисовать , увеличивать и поворачивать . Как двигать - объяснять не надо . Это уже есть в базовом классе . Функции нашей библиотек и могут работать с объектами вновь с о зданных типов , для них это ва рианты геометрической фигуры . Следует отметить , что в производных классах могут (и , как правило , должны ) появляться данные и функ ции , которых нет в базовом классе . Однако ни одна из функций , обрабатывающих "геоме трические фигу р ы ", никогда не узна ет о специфических свойствах многоугольника и ли эллипса , кроме того , что они по-своему рисуются , увеличиваются и поворачиваются . Произ водный класс сам может быть базовым для других классов , а поздние версии С ++ позв оляют сделать один кл а сс производ ным от нескольких других. При написании программы часто допускаются досадные оплошности , обнаруживающиеся только на стадии выполнения и , увы , слишком поздн о . Например , если переменная по смыслу - зна менатель дроби , хотелось бы получить сообщени е об ошибке тогда , когда ей присваив ается ноль , а не тогда , когда на этот ноль что-нибудь делится . Или , скажем , функц ия рисования точки . Невозможно удержаться от соблазна вызвать ее хотя бы раз без проверки выхода за границы экрана . В то же время , если мы пишем про грамму рисования линии , обязательно нужна фун кция , которая тупо ставит точку - и как можно быстрее . Существует много ситуаций , когд а функции и данные следует разрешить испо льзовать только привилегированным функциям , над которыми ва "хорошо подума л и ". В С ++ этого можно добиться , сделав "опасные " данные и функции защищенными членами каког о-нибудь класса . К ним имеют доступ только функции-члены этого же класса , а так ж е друзья класса . Напротив , если данные или функции-члены объявлены public, они явля ю тся общедоступными. С ++ предоставляет в распоряжение программи ста сложные типы данных . Однако ни аппарат классов , ни перегрузка операций не влияют на эффективность . То , что класс - это к ласс , известно только компилятору . Если функци и-члены классов объявлен ы inline, на их вызо в не требуется время . Фактически это не функции , а подстановки . Лишь виртуальные фун кции оставляют относительно небольшой след в оперативной памяти. Из всего выше сказанного вытекает лог ичный вывод : С ++ наиболее удобный , универсальный и необходимый язык . Но все же в озникает вопрос , что же было написано на этом языке , используя принципы ООП , что можно было бы "потрогать " любому программист у или пользователю . Ответ очевиден - это Microsoft Windows. MS Windows и новый метод разработки прог рамм. Одним из наиболее важных механизмов взаимодействия программ является обмен данными . В MS Windows существует несколько способов взаимодей ствия приложений : - почтовый ящик ; - динамический обмен данными ; - встраивание объектов. Специальный почтовый ящ ик (clipboard) Windows поз воляет пользователю переносить информацию из одного приложения в другое , не заботясь об ее форматах и представлении. В отличие от профессиональных операцио нальных операционных систем , где механизм обм ена данными между программами доступен только программисту , в Windows это делается очень просто и наглядно для пользователя. Механизм обмена данных между приложени ями - жизненно важное свойство многозадачной с реды . И в настоящее время производители пр ограммного обеспечения пришли уже к выв оду , что для переноса данных из одного приложения в другое почтового ящика уже недостаточно . Появился новый , более универсальн ый механизм - OLE ( Object Linking and Embedding ) - Встроенная объектная связь , который поз воляет переносить из одного прил ожения в другое разнородные данные . Например , с помощью этого механизма данные , подготовленные в системе сетевого планирования Time Line for Windows ( Symantec ), мож но переносить в текстовый процессор Just Write ( Symantec ), а затем , скажем , в генератор приложе ний Object Vision (Borland). Правда , это уже нестандартное средс тво Microsoft Windows, но тем не менее реализация OLE стал а возможной именно в Windows. Кроме механизма почтового ящика , предна значенного , в основном , для пользователя , прогр аммисту в Windows доступны специальные средства обмена данными между приложениями. Программным путем можно установить пря мую связь между задачами , например , принимая данные из последовательного порта , автоматическ и помещать их , скажем , в ячейки электронно й таблицы Excel, средствами которой можно тут же отображать сложные зависимости в в иде графиков или осуществлять их обработку в реальном режиме времени (этот механизм носит название динамического обмена данными - Dynamic Data Exchange, DDE ). Основные термины Клие нтское приложение DDE - приложение , которому необходимо установить диалог с серв ером и получить данные от сервера в п роцессе диалога. DDE-диалог - взаимосвязь между клиентским и серверным приложениями. Сервер-приложение - DDE приложение , которое переда ет д анные клиенту в процессе диалога. DDE-Транзакция -обмен сообщениями или данн ыми между клиентом и сервером. Item имя - строка , идентифицирующая некоторое множество данных , которое сервер в состояни и передать клиенту в процессе диалога. Service имя - строка, генерируемая сервером и используемая клиентом для установления д иалога. Строковый указатель - двойное слово , генери руемое операционной системой , идентифицирующее ст року , передающуюся в процессе динамического о бмена данными. Topic имя - строка , которая иде нтифицируе т тип данных , необходимых клиентскому приложе нию при динамическом обмене данных. Фильтр транзакции - флаг , который препятств ует передаче нежелательных типов транзакций в функцию обратного вызова. В Microsoft Windows динамический обмен данных явл яется формой связи , которая использует общие области памяти для обмена данными между приложениями . Приложение может использова ть DDE в некоторый момент времени для переда чи и получения новых данных от сервера. Механизм DDE схож с механизмом почтового ящика , который является частью операционн ой системы WINDOWS. Существует лишь незначительная разница в том , что почтовый ящик , в бол ьшинстве случае , используется как буфер време нного хранения информации . DDE может быть инициа лизирован пользователем и в большинс т ве случаев продолжать работать без ег о вмешательства. Библиотека DDEML обеспечивает пользователя наборо м средств , которые упрощают использование мех анизма DDE в WINDOWS приложениях . Вместо того , чтобы обрабатывать , получать и передавать DDE сообщения напря мую , приложения используют функции DDEML библиотеки . Библиотека DDEML также обеспечивает работу со строками и разделяемыми данными , генерируемыми DDE приложениями . Вместо того , чтобы использовать указатели на общие области памяти , DDE приложения создают и обменива ются строковыми указателями , которые идентифициру ют строки и данные. Уже существующие приложения , использующие протокол DDE, основанный на сообщениях полностью совместимы с теми , которые используют библи отеку DDEML. Вот почему приложение , использую ще е DDE-протокол могут установить диалог и вып олнять транзакции с приложениями , использующими библиотеку DDEML. Взаимосвязь между клиентом и сервером. DDE возникает всегда между клиентским при ложением и серверным . Клиентское приложение и нициализирует обме н данными путем установ ления диалога с сервером и передачи транз акции . Транзакция необходима для данных и обслуживания . Сервер отвечает на транзакцию и обеспечивает клиента данными . Сервер может иметь сразу несколько клиентов в одно и тоже время , в свою о ч ередь , клиент может получать данные сразу от нескольких серверов . Некоторое приложение одновре менно может быть и клиентом и сервером . В добавок к вышесказанному , клиент и се рвер могут оборвать диалог в любое удобно е для них время. DDE сервер использует три зарезервирован ных типа имен , расположенных иерархично : service, topic item - уникально идентифицируют некоторое множество дан ных , которое сервер может передать клиенту в процессе диалога. Service имя - это строка , которую генерирует сервер в те промежутки времени , в которые клиент может установить диалог с сервером. Topic имя - это строка , которая идентифицируе т логический контекст данных . Для сервера , который манипулирует файлами , topic имена это про сто названия файлов ; для других серверов - это специфиче ские имена конкретного прило жения . Клиент обязательно должен указывать topic и мя вместе с service именем , когда он хочет у становить диалог с сервером. Item имя - это строка , которая идентифицируе т некоторое множество данных , которое сервер может передать к лиенту в процессе транзакции . Например , item имя может идентифицирова ть ЦЕЛОЕ ( int, integer ), СТРОКУ ( string, char * ), несколько параграфов текста , или BITMAP образ. Все вышеуказанные имена позволяют клиенту установить диалог с сервером и получить от н его данные. Системный режим Системный режим работы обеспечивает клиен та всей необходимой информацией о сервере. Для того , чтобы определить , какие серв еры доступны в данный момент времени , а также какой информацией они могут обеспечи ть клиента , последний , находясь в начальн ом режиме работы , должен установить имя ус тройства , равное NULL. Такой шаблон диалога максим ально увеличивает эффективность работы , а так же работу с сервером в системном режиме . Сервер , в свою очередь , должен поддерживать нижеописанные i t em имена , а также другие , часто используемые клиентом : SZDDESYS ITEM TOPICS - список item имен , с которыми может работать сервер в данный момент времени . Этот список может изменяться время от времени. SZDDESYS ITEM SYSITEMS - список item имен , с которыми м ожет работать сервер в системном режи ме. SZDDDESYS ITEM STATUS - запросить текущий статус сервера . Обычно , данный запрос поддерживается только в формате CF_TEXT и содержит строку типа Готов /Занят. SZDDE ITEM ITEMLIST - список item имен , поддерживаемых серв ером в несистемном режиме работы . Этот список может меняться время от времени. SZDDESYS ITEM FORMATS - список строк , представляющий собой список всех форматов почтового ящика , подде рживаемых сервером в данном диалоге . Например , CF_TEXT формат представлен с трокой TEXT. Основное назначение и работа функции обратного вызова Приложение , которое использует DDEML, должно со держать функцию обратного вызова , которая обр абатывает события , полученные приложением . DDEML уведо мляет приложение о таких событиях путем п о сылки транзакций в функцию обратного вызова данного приложения. В зависимости от флага фильтра транза кции , сформированного при вызове функции DdeInitialize, ф ункция обратного вызова получает отсортированные транзакции вне зависимости от того , являе тся ли д анное приложение клиентом , сер вером или тем и другим одновременно . Следу ющий пример демонстрирует наиболее типичное и спользование функции обратного вызова. HDDEDATA CALLBACK DdeCallback( uType, uFmt, hconv, hsz1, hsz2, hdata, dwData1, dwData2 ) UINT uType; // Тип транзакции UINT uFmt; // Формат почтого ящика HCONV hconv; // Идентификатор диалога HSZ hsz1; // Идентификатор строки #1 HSZ hsz2; // Идентификатор строки #2 HDDEDATA hdata; // Идентификатор глобального объек та памяти DWORD dwData1; // Данные теку щей транзакции #1 DWORD dwData2; // Данные текущей транзакции #2 switch (uType) case XTYP_REGISTER: case XTYP_UNREGISTER: . . . return (HDDEDATA) NULL; case XTYP_ADVDATA: . . . return (HDDEDATA) DDE_FACK; case XTYP_XACT_COMPLETE: . . . return (HDDEDA TA) NULL; case XTYP_DISCONNECT: . . . return (HDDEDATA) NULL; default: return (HDDEDATA) NULL; Параметр uType идентифицирует тип посланной транзакции в функцию обратного вызова при помощи DDEML. Значения оставшихся параметров зави сят от типов транза кции . Типы транзакц ий будут обсуждены нами в разделе "Обработ ка Транзакций ". Диалог между приложениями Диалог между клиентом и сервером всег да устанавливается по требованию клиента . Ког да диалог установлен , оба партнера получают идентификатор , который опи сывает данный диалог. Партнеры используют этот идентификатор в большинстве функций DDEML для посылки транзакций и для их обработки . Клиенту может пот ребоваться диалог как с одним сервером , та к и с несколькими. Рассмотрим подробно как приложение устана влива ет диалог и получает информацию о уже существующих каналах связи. Простой Диалог Клиентское приложение устанавливает простой диалог с сервером путем вызова функции DdeConnect и определяет идентификаторы строк , которые содержат всю необходимую информацию о service имени текущего сервера и интересующем кл иента в данный момент topic имени. DDEML отвечает на вызов этой функции по сылкой соответствующей транзакции XTYP_CONNECT в функцию обратного вызова каждого доступного в данн ый момент времени сервера , зарегис трирова нное имя которого совпадает с именем , пере данным при помощи функции DdeConnect при условии , что сервер не отключал фильтр service имени выз овом функции DdeServiceName. Сервер может также установить фильтр на XTYP_CONNECT транзакцию заданием соответс твующего флага CBF_FAIL_CONNECTIONS при вызове функции DdeInitialize. В процессе обработки транзакции типа XTYP_CONNECT DDEML передает полученные от клиента service и topic име на серверу . Сервер должен проверить эти им ена и возвратить TRUE, если он в состо янии работать с такими именами , и FALSE в противном случае . Если ни один из существу ющих серверов не отвечает на CONNECT-запрос кли ента , функция DDeConnect возвращает ему NULL с информацие й о том , что в данный момент времени НЕ возможно установить диалог. Однако , если сервер возвратил TRUE, то диа лог был успешно установлен и клиент получ ает идентификатор диалога - двойное слово , посредством которого и ведется обмен данными с сервером. Затем сервер получает транзакцию вида XTYP_CONNECT_CONFIRM (в случае , есл и он НЕ описывал флаг фильтра CBF_FAIL_CONFIRMS при вызове соответствующей функции ). В нижеприведенном примере производится по пытка установить диалог с сервером , который в состоянии работать с service именем 'My Server' в с истемном режиме . Считаем , что пар аметры hszSysTopic и hszServName уже предварительно созданы нами ра нее. HCONV hConv; HWND hwndParent; HSZ hszServName; HSZ hszSysTopic; . . . hConv = DdeConnect( idInst, // Копия приложения hszServName, // Идентификатор service- имени handle hszSysTopic,/ / Идентификатор system-topic- имени (PCONVCONTEXT) NULL); // Используем контекст по умолчанию if( hConv == NULL ) MessageBox( hwndParent, "MyServer НЕ доступен !", (LPSTR) NULL, MB_OK ); return FALSE; . . . В этом примере функция DdeConnect заставляет DDEML посылать транзакцию вида XTYP_CONNECT в функци ю обратного вызова сервера MyServer. А теперь приведем пример функции обра тного вызова сервера , который обрабатывает тр анзакцию XTYP_CONNECT и сравнивает свое зарегистрированное имя с именем , полученным от клиента . Как уже было отмечено ранее , если они совпадают , то сервер в состоянии установи ть диалог с клиентом. #define CTOPICS 5 HSZ hsz1; // Идентификатор строки, полученный от DDEML. HSZ ahszTopics[CTOPICS]; // Массив поддреживаемых topic имен int i ; // Счетчик цикла . . // Для обработки транзакций используем с тандартную ANSI C . // конструкцию switch --> case --> default. . case XTYP_CONNECT: for (i = 0; i < CTOPICS; i++) if (hsz1 == ahszTopics[i]) return TRUE; // Установка диалога return FALSE; // Topic имя НЕ поддерживается, диалог запрещен. . . // Обработка других типов транзакций. . Если сервер возвращает TRUE в ответ на транзакцию XTYP_CONNECT, DDEML посылает транзакцию вида XTYP_CONNECT_CONFIRM в функцию обратного вызова данн ого сервера . Обработав эту транзакцию , сервер может получить идендификатор диалога. Вместо конкретного имени сервера клиент может установить шаблон диалога путем ус тановки идентификаторов service и topic имен в NULL при вызове функции DdeConnect. Если хотя бы один из вышеперечи сленных идентификаторов равен NULL, DDEML посылает транза кцию типа XTYP_WILDCONNECT в функцию обратного вызова всех активных в данный момент DDE-приложений (исключения составляют лишь те , кто при вызове соответствующей функции указал флаг фильтрации XTYP_WILDCONNECT). Любое сервер-приложение должно ответить н а данную транзакцию и возвратить указатель на массив структур типа HSZPAIR, оканчивающийся н улем. Если сервер-приложение НЕ вызывает функци ю DDeNameService для регистрации собствен ного service имен и в системе и фильтр обработки транзакций включен , то сервер НЕ получит транзакцию вида XTYP_WILDCONNECT. Вышеописанный массив должен содержать одн у структуру для каждого service и topic имен . DDEML выбир ает одну пару из массива для устано вления диалога и возвращает его идент ификатор клиенту . Затем DDEML посылает серверу тра нзакцию вида XTYP_CONNECT_CONFIRM (исключения составляют лишь те серверы , которые при инициализации устан овили фильтр обработки транзакций ). Продемонстируем использовани е транзакции вида XTYP_CONNECT. #define CTOPICS 2 UINT uType; HSZPAIR ahszp[(CTOPICS + 1)]; HSZ ahszTopicList[CTOPICS]; HSZ hszServ, hszTopic; WORD i, j; if (uType == XTYP_WILDCONNECT) // Сканируем список topic имен и создаем мас сив структур типа HSZ PAIR j = 0; for (i = 0; i < CTOPICS; i++) if (hszTopic == (HSZ) NULL || hszTopic == ahszTopicList[i]) ahszp[j].hszSvc = hszServ; ahszp[j++].hszTopic = ahszTopicList[i]; // // Последний элемент массива всегда NULL. // ahszp[j].hszSvc = NULL; ahszp[j++].hszTopic = NULL; // // Возвращаем дискриптор глобального объекта // памяти,содержащий структуры типа HSZPAIR. // return DdeCreateDataHandle( idInst, // Копия приложения (LPBYTE) &ahszp, // Указатель на массив типа HSZPAIR sizeof(HSZ) * j, // Длина массива 0, // Начальное смещение (HSZ) NULL, // item-имя не существует 0, // формат item-имени также // не существует 0); // Возлагаем все работу // с массивом на систему Любой сервер или клиент может обор вать диалог в любое время путем вызова фун кции DdeDisconnect. Это означает , что партнер по обмену данными получает транзакцию типа XTYP_DISCONNECT в функции обратного вызова (если , кон ечно , партнер не установил фильтр обработки транзакций вида CBF_SKIP_DISCONNECTIONS). Обычно приложение реагирует на тран закцию XTYP_DISCONNECT вызовом функции DdeQueryInfo для получения информации о прекращенном диалоге . После того , как функция обратного вызова обработала транзакцию типа XTYP_DISCONNECT, идентификатор диалога больше не существует. Клиентское приложен ие , которое получа ет транзакцию типа XTYP_DISCONNECT в своей функции об ратного вызова может попытаться возобновить д иалог при помощи вызова функции DdeReconnect. Клиентско е приложение может вызывать эту функцию т олько находясь внутри своей собственной фун к ции обратного вызова. Сложный диалог Клиентское приложение может использовать функцию DdeConnectList для того , чтобы определить какие сервер-приложения существуют в системе в данный момент времени. Клиент обязательно должен описывать service и topic имена , когда он вызывает эту функц ию ; это означает , что DDEML должна послать тран закцию вида XTYP_CONNECT все функции обратного вызова всех имеющихся в данный момент сервер-при ложений , чьи зарегистрированные имена совпадают с именами , указанными клиентом (искл ю чение составляют лишь те серверы , кото рые фильтруют получаемые транзакции ). В добавление к вышесказанному , можно о тметить , что клиент , при вызове функции DdeConnectList, может указать NULL в качестве service или topic имени , либо же сразу для обоих . Все до ступные в системе серверы , чьи зарегис трированные имена совпадают с именами , указан ными клиентом , отвечают на его запрос . Диа лог устанавливается со всеми такими серверами , даже если в системе запущено одно и тоже сервер-приложение несколько раз. Клиент мож ет использовать функции DdeQueryNextServer и DdeQueryConvInfo для того , чтобы понять , какой сервер находится в списке , полученный при вызове функции DdeConnectList. DdeQueryNextServer возвращает идентификатор диалога для следующего сервера , находящегося в списке ; DdeQueryConvInfo заполняет структуру CONVINFO информацией о диалоге. Клиент может сохранить полученные идентиф икаторы диалогов и отказаться от просмотра оставшихся серверов в списке. Приведем пример использования функции DdeConnectList для установл ения диалога со всеми серверами , которые поддерживают имя 'system topic', затем будем использовать функции DdeQueryConvInfo и DdeQueryNextServer для получения их идентификаторов service имен , одновремен но не забывая сохранить последние во врем енном буфере. HCONVLIST hconvList; // Список диалогов DWORD idInst; // Дискриптор приложения HSZ hszSystem; // System topic HCONV hconv = NULL; // Идентификатор диалога CONVINFO ci; // Информация о диалоге UINT cConv = 0; // Количество идентификаторов диалогов HSZ *pH sz, *aHsz; // Указатель на идентификатор строки // Присоединяемся ко всем серверам , подде рживающим // System topic. hconvList = DdeConnectList(idInst, NULL, hszSystem, NULL, NULL); // Вычисляем количество серверов в списк е. while((hconv = DdeQueryNextSe rver(hconvList,hconv)) != NULL) cConv++; // Выделяем буфер для сохранения идентиф икаторов строк. hconv = NULL; aHsz = (HSZ *) LocalAlloc(LMEM_FIXED, cConv * sizeof(HSZ)); // Копируем идентификатор строки в буфер. pHsz = aHsz; ile((hconv = DdeQueryNextServer(hconvList,hconv)) != NULL) DdeQueryConvInfo(hconv, QID_SYNC, (PCONVINFO) &ci); DdeKeepStringHandle(idInst, ci.hszSvcPartner); *pHsz++ = ci.hszSvcPartner; . . // Используем идентификатор : 'общаемся ' с сервером. . // Осв обождаем память и прекращаем диалог. LocalFree((HANDLE) aHsz); DdeDisconnectList(hconvList); Приложение может оборвать индивидуальный диалог , находящийся в списке диалогов путем вызова функции DdeDisconnect; приложение может оборвать все диалоги , находящ иеся в списке путем вызова функции DdeDisconnectList. Обе вышеуказанные функции указывают DDEML о необходимости посылки транзакции вида XTYP_DISCONNECT во все функции партнеров по диалогу данного приложения (в случае использования функции DdeDisconnectList будет посылаться транзакция XTYP_DISCONNECT для каждого элемента в списке диалогов ). Обмен данными между приложениями Так как DDE использует области памяти дл я передачи данных из одного приложения в другое , DDEML обеспечивает конечного программиста функц иями , при помощи которых DDE-приложен ия могут создавать и обрабатывать DDE-объекты. Весь спектр транзакций , который вызывает обмен данными , требует от приложения , экс портирующего их , создания некоторого буфера , с одержащего эти данные , а затем вызова функ ци и DdeCreateDataHandle. Эта функция создает DDE-объект , копирует данные из буфера в этот объект и возв ращает идентификатор данных для данного прило жения. Идентификатор данных-это двойное слово , ко торое использует DDEML для обеспечения доступа к данным в DDE -объекте. Для того , чтобы разделять данные в DDE-объекте , приложение передает идентификатор дан ных DDEML, а затем DDEML передает его в функцию обратного вызова приложения , получающего данные . В нижеприведенном примере показано , как создать DDE-объект и пол учить его иде нтификатор . В процессе обработки транзакции т ипа XTYP_ADVREQ, функция обратного вызова конвертирует текущее время в ASCII строку , копирует строку в вспомогательный буфер , а затем создает DDE- объект , содержащий вышеуказанную строку . Функция об р атного вызова возвращает иденти фикатор DDE-объекта DDEML, которая передает этот иден тификатор клиентскому приложению. typedef struct tagTIME INT hour; // 0 - 11 формат времени для часов. INT hour12; // 12-ой формат. INT hour24; // 24-ой формат. INT minute; INT second; INT ampm; // 0 --> AM , 1 --> PM TIME; HDDEDATA EXPENTRY DdeCallback (uType, uFmt, hconv, hsz1, hsz2, hdata, dwData1, dwData2) UINT uType; UINT uFmt; HCONV hconv; HSZ hsz1; HSZ hsz2; HDDEDATA hdata; DWORD dwData1; DWORD dwData2; CHAR szBuf[32]; switch (uType) case XTYP_ADVREQ: case XTYP_REQUEST: if ((hsz1 == hszTime && hsz2 == hszNow) && (uFmt == CF_TEXT)) // Копируем строку в буфер. itoa(tmTime.hour, szBuf, 10); lstrcat(szBuf, ":"); if (tmTime.minute < 10) lstrcat(szBuf, "0"); itoa(tmTime.minute, &szBuf[lstrlen(szBuf)], 10); lstrcat(szBuf, ":"); if (tmTime.second < 10) strcat(szBuf, "0"); itoa(tmTime.second, &szBuf[lstrlen(szBuf)], 10); szBuf[lstrlen(szBuf)] = '\0'; // Создаем глобальный объект и // возвращ аем его идентификатор return (DdeCreateDataHandle( idInst, // копия приложения (LPBYTE) szBuf, // исходный буфер lstrlen(szBuf) + 1, 0, // смещение от его начала hszNow, // item-имя CF_TEXT, // формат почтого ящика 0)); else return (HDDEDATA) NULL; . . // Обработка других типов транзакций. . Клиентское приложение получает указатель на DDE-объект путем передачи идентификатора д анных функции DdeAccessData. Указатель , возвращаемый этой функцией , обеспечивает доступ к данным в формате 'ТОЛЬКО НА ЧТЕНИ Е '. Клиент до лжен просмотреть полученные данные при помощи этого указателя и вызвать функцию DdeUnaccessData дл я его уничтожения . Клиент может скопировать полученные данные в заранее приготовленный буфер посредством вызова функции DdeGetData. В следующем п римере мы получим указатель на DDE-объект , сохраним его в па раметре hData, скопируем содержимое во временный б уфер и уничтожим указатель : HDDEDATA hdata; LPBYTE lpszAdviseData; DWORD cbDataLen; DWORD i; char szData[32]; . . . case XTYP_ADVDATA: lpszAdvi seData = DdeAccessData(hdata, &cbDataLen); for (i = 0; i < cbDataLen; i++) szData[i] = *lpszAdviseData++; DdeUnaccessData(hdata); return (HDDEDATA) TRUE; . . . Обычно , когда приложение , создающее иден тификатор данных , передает его DDEML, этот идентифи като р портится внутри вышеуказанного прил ожения . В этом нет ничего страшного , если сервер должен разделять данные только с одним клиентом . Если же сервер должен разделять данные сразу с несколькими клиен тами одновременно , ему придется указывать фла г HDATA_APP O WNED при вызове функции DdeCreateDataHandle. Это делает возможным получение прав с обственности на DDE-объект сервер-приложения и п редотвращает порчу идентификатора данных DDEML. Прилож ение может передавать DDEML идентификатор данных любое количество раз , о днако вызывать функцию DdeCreateDataHandle можно лишь однажды. Если приложение указывает флаг HDATA_APPOWNED в параметре atCmd при вызове функции DdeCreateDataHandle, оно обяза тельно должно вызывать функцию DdeFreeDataHandle для очист ки памяти вне зависимо сти от того , передавался ли идентификатор данных DDEML или нет . Перед тем как оборвать диалог , прилож ение должно вызывать функцию DdeFreeDataHandle для очистки всех созданных идентификаторов , но которые так и не были переданы DDEML. Если приложение еще не передало идентификатор DDE-объекта DDEML, то оно может добавит ь данные к уже существующему объекту или полностью заменить их в нем . Все эти сервисные функции обслуживаются функцией DdeAddData. Обычно приложение использует эту функцию для новой инициализаци и старых не уничтоженных DDE-объектов . После того , как прил ожение передает идентификатор данных DDEML, DDE-объект , идентифицирующий этот идентификатор НЕ может быть изменен , однако он может быть ун ичтожен. OLE-технология Как видно из описанного выше прот окола DDE, приложения должны обязательно зна ть типы передаваемых данных , уметь их обра батывать , а в основном даже могут работать только с символьными строками . Это , конеч но , не очень удобно , когда необходимо , напр имер , создать небольшой текст с различными картинками , пиктограммами и другими наглядными или не очень иллюстрациями . В этом случае на помощь программисту происхо дит OLE - встраивание объектов . Вместе с данными мы получаем машинный код , который эти д анные может обрабатывать. Способы упорядочивания , источники и целевые документы При использовании OLE-технологии пользователь всегда имеет дело с одним ведущим прил ожением (главным ) и одним ведомым (подчиненным ), а точнее , с одним ведомым. Приложение , с помощью которого получен объект для встраивания вс егда играет роль подчиненного . Это особенно характерно для случаев передачи объектов при встраивании и связывании через буфер промежуточного обмена. Часто используемые термины Приложение-источни к и Целевое приложение касаются не подчин ения приложений , а оп ределяют генеалогию объектов. Некоторые Windows-приложения могут выступать то лько в роли подчиненных , а некоторые тольк о в роли ведущих . Например , Paintbrush в OLE технологи и может играть только роль подчиненного п риложения , служащего для создания и модифи кации отдельных объектов . Другие приложен ия , например , Write или Cardfile можно считать оправданны м с точки зрения , что гораздо чаще при ходится вставлять иллюстрации в сложные по структуре текст , чем текст в иллюстрации . Новые приложения , такие как Word, м огу т выполнять в рамках OLE обе эти функции. Употребление термина объект считается пре стижным в кругах программистов , хотя часто он употребляется и не к месту . Всякий разработчик почитает своим долгом применить в своем продукте ООП без особой на то необход имости . В среде Windows в термин объект вкладывается несколько специфический смысл . Пользователя не приглашают постигать а зы ООП , или заняться конструированием объекто в на С ++. Когда об объектах говорят в рамках Windows, то имеют в виду возможность встраив ания в некоторый документ фрагмента , п орожденного другим приложением . Вот это "иноро дное тело " и называется объектом. В таком подходе нет ничего нового . Когда в текст , подготавливаемый Write, вставляется рисунок из Paintbrush посредством Clipboard или табл иц Exс el, в документ , подготавливаемый в Word, то результатом действия будет как раз появл ения объекта. Традиционные объекты всегда представляют собой копии . Работа с ними основывается на том , что все Windows приложения поддерживают не только свой собствен ный формат , но и некоторый обобщенный , стандартный , играющий роль общеизвестного международного языка . Если , например , в текстовый документ вставляется таблица из табличного процессора , то буфер промежуточного обмена преобразует ее в ф ормат к стандартном у , и тем самы м обеспечивает вставку . Такая копия в текс товом редакторе по виду не отличается от оригиналу , но она недоступна для внесения изменений . Невозможно , вставив таким способом копию из Paintbrush в Write документ , изменить цвет , толщину линий или м а сштаб. Новые объекты , доступные в рамках Windows 3.1 о чень похожи на традиционные , но они не являются копиями - это оригиналы . Они имеютс я в единственном экземпляре и находятся н епосредственно в целевых документах . Там они существуют одновременно в двух фо рма тах - в стандартном и в формате приложения- источника. Благодаря стандартному формату объект мож ет индицироваться и сохранять в рамках це левого документа . Имеется возможность обработки объекта также , как и любого файла ориги нала . Ситуация выглядит так , с ловно вн утри объекта встроен другой . Это обеспечивает доступ к средствам обработки нового объе кта (приложению-источнику ) посредством простого дво йного щелчка на объекте. Встроенные объекты Информация , вставленная в документ целево го приложения , представля ет собой объект . Такой объект встраивается в документ , об рабатываемый ведущим приложением . Это значит , что он рассматривается как составная часть данного документа , может распечатываться и сохраняться вместе с ним . Такие объекты мо гут содержать информацию любого типа : текст , таблицы , графики и др. Встроенные объекты существуют только в единственном экземпляре и только там , где они встроены - в целевом документе . Обрабаты ваются они своими "родительскими " программами , вызываемыми весьма эффективным способом , в отличие от традиционного. Связывание с родительским приложением Следующей весьма удобной особенностью вст роенных объектов является то , что они оста ются связанными с породившим их приложениями . Благодаря этому пользователь избавляется от необходимости по мнить имена и директ ории файлов-источников . Достаточно двойного щелчка на объекте - и родительская программа зап ускается. Важным достоинством подобного связывания встроенных объектов является мобильность докумен тов . Можно легко перенести такой документ с о дной машины на другую (необходимо только чтобы на них обеих была устан овлена оболочка и были необходимые приложения или динамические библиотеки от них ). Для обработки встроенных объектов достаточно буд ет щелкнуть по ней дважды и на другой машине произойде т тоже самое , ч то и на вашей : вызовется соответствующее п риложение . В этом случае необходимым условием переноса является наличие на другой маши не текстового редактора Write и графического реда ктора Paintbrush. При работе в рамках DDE такой перенос не возмож ен , точнее он будет включа ть в себя не только перенос самого фа йла-документа , но и связанных с данным фай лом файлов-источников и целевых файлов - всей структуры. Перспективы развития OLE Технология OLE делает только первые шаги . Пока только некоторые Wind ows приложения явл яются OLE совместимыми . Среди утилит группы Accessories в ерсии 3.1 такими на сегодняшний день являются только Write, Paintbrush и Cardfile. Но даже они "в своем кругу " не допускают вставки в произвольном направлении (т.е . из любой в любу ю другую ). В настоящее время речь идет о поддержке наиболее оправданного с прак тической точки зрения "направления встраивания " - из Paintbrush в Write и С ardfile документа. Чтобы определить какие из приложений поддерживаю OLE интерфейс , необходимо из OLE-со вместимого приложения выполнить директиву "ВСТАВИ ТЬ ОБЪЕКТ " в меню "Edit". В отрывшемся окне будет продемонстрирован список доступных встраив аемых объектов. В настоящий момент многие компиляторы уже ввели поддержку OLE в свои библиотеки : Borland C++ ver4.5 . Пример использования OLE технологии прив еден в приложении 1. Данная программа используе т созданный рисунок Paintbrush в виде файла или копирует его из Clipboard. Заключение В заключении хотелось бы отметить , что существующие способы обмена информации возникали вместе с развитием Windows. Как сама суть Windows, они являются продолжением зало женной в нее цель : способность работать с файлами любых форматов , на любом оборудов ании . В отличие от стандартного решения , к огда фирма-производитель оболочки (тип а Windows) пыталась сама написать различные дра йверы для поддержки устройств и различные библиотеки для поддержки форматов многочисленн ых файлов других пакетов , фирма Microsoft возложила эту обязанность на производителей оборудования и программного обеспеч е ния . Таким образом , последовательное развитие Clipboard-->DDE-->OLE является продолжением воплощения идеи "сам изобрел - сам внедряй ". Естественно , наибольшие надежды сейчас возлагаются на OLE (ее новый стандарт OLE.2), так как этот стандарт позволяет вкл ю чать в себя очень мощные сре дства , такие как Multimedia. В одном файле может находится не только текст , рисунок , а и даже целый фильм , полностью озвученный и готовый к показу . Приложение 1. Пример использования OLE технологии // ObjectWindows - (C) Copyright 1992 by Borland International // // oleclnt.cpp // Пример Ole Client программы , испльзующей OWL. Она показывает // пример использования Ole functions, и C++ классов . // Основное окно позволяет пользователю с оздать paint br ush // object, или копировать его из clipboard. #include #include #include #include #include #include #include #include #pragma hdrstop #include "oleclnte.h" #include "olecl ntr.h" #include "oleclnt.h" // статические данные класса LPOLECLIENTVTBL TOwlClient::lpClientVtbl = NULL; int TOleDocWindow::nNextObjectNum = 0; void TOleApp::InitInstance() TApplication::InitInstance(); vcfLink = RegisterClipboardFormat( "ObjectLink" ) ; vcfNative = RegisterClipboardFormat( "Native" ); vcfOwnerLink = RegisterClipboardFormat( "OwnerLink" ); // comments in owlole.h mention these ole clipboard formats // описание функций OWL Object, которые // позволяют хранить описание Ole Object int FA R PASCAL _export StdCallBack(LPOLECLIENT lpClient, OLE_NOTIFICATION notification, LPOLEOBJECT lpObject ) return (( PTOwlClient )lpClient)->TOleDocWindowThis-> CallBack( lpClient , notification, lpObject ); TOwlClient::TOwlClient( PTOleDocWindow owner , HINSTANCE hInst ) TOleDocWindowThis = owner; if ( !lpClientVtbl ) lpClientVtbl = new OLECLIENTVTBL; if ( hInst == 0 ) lpClientVtbl->CallBack = StdCallBack; else lpClientVtbl->CallBack = (TCallBack) MakeProcInstance( (FARPROC)StdCallBack, hInst ); lpvtbl = lpClientVtbl; void TOleDocWindow::WMURedraw( RTMessage ) bObjectLoaded = TRUE; InvalidateRect( HWindow, NULL, TRUE ); UpdateWindow( HWindow ); #pragma argsused int TOleDocWindow::CallBack( LPOLECLIENT lpOleClient , OLE_NOTIFICAT ION oleNot, LPOLEOBJECT lpOleObject ) switch ( oleNot ) case OLE_CHANGED: case OLE_SAVED: PostMessage( HWindow , WM_U_REDRAW, 0, 0L ); break; case OLE_CLOSED: break; case OLE_QUERY_PAINT: break; case OLE_RELEASE: break; case OLE_RENAMED: break; default : break; return TRUE; void TOleDocWindow::CMAbout( RTMessage ) MessageBox( HWindow , "OLE Client Program\n Written using ObjectWindows\nCopyright (c) 1992 Borland", GetApplication()->Name, MB_OK ); // создание новой paint brush void TOleDocWindow::CMPBrush( RTMessage ) BackupObject(); bObjectLoaded = FALSE; lstrcpy( lpszObjectName, GetNextObjectName() ); ret = OleCreate( "StdFileEditing", (LPOLECLIENT)pOwlClient, "PBRUSH", lhClientDoc, GetApplication()->Name, &lp Object, olerender_draw, 0 ); // Создание Ole Object - асинхронная операция. // Необходимо ожидать его создание , иначе // могут возникнуть ошибки при обработке // сообщений этого объекта. wait( ret , lpObject ); // OleSetHostNames устанавливает имя в сер вере OLE. ret = OleSetHostNames( lpObject, GetApplication()->Name, lpszObjectName ); wait( ret , lpObject ); void TOleDocWindow::CMUndo( RTMessage msg) if ( lpUndoObject ) if ( lpUndoObject != lpObject ) LPOLEOBJECT lpObjectToDelete = lpObject; lpObject = lpUndoObject; lpUndoObject = NULL; ret = OleDelete( lpObjectToDelete ); wait( ret , lpObjectToDelete ); bObjectLoaded = bUndoObjectLoaded; WMURedraw( msg ); void TOleDocWindow::CMCut( RTMessage msg) CMCopy( msg ); CloseCurrentOle(); void TOleDocWindow::CMCopy( RTMessage ) if ( OpenClipboard( HWindow ) && EmptyClipboard() ) ret = OleCopyToClipboard( lpObject ); check( ret ); CloseClipboard(); void TOleDocWindow::BackupObject() if ( lpObject ) ret = OleClone( lpObject, (LPOLECLI ENT)pOwlClient, lhClientDoc, GetApplication()->Name, &lpUndoObject ); wait( ret, lpObject ); lstrcpy( lpszLastObjectName, lpszObjectName ); lstrcpy( lpszObjectName , GetNextObjectName() ); bUndoObjectLoaded = bObjectLoaded; void TOleDocWindow::CMPaste( RTMessage ) if ( OpenClipboard( HWindow ) ) BackupObject(); lstrcpy( lpszObjectName, GetNextObjectName() ); ret = OleCreateFromClip( "StdFileEditing", (LPOLECLIENT)pOwlClient, lhClientDoc, lpszObjectName, &lpObject, oler ender_draw, 0 ); check( ret ); ret = OleSetHostNames( lpObject, GetApplication()->Name, lpszObjectName ); wait( ret , lpObject ); bObjectLoaded = TRUE; CloseClipboard(); PostMessage( HWindow , WM_U_REDRAW, 0, 0L ); LPSTR TOleDocWindow::GetNextObject Name() static char buffer[ MAXPATH ]; wsprintf( buffer, "object #%03d", nNextObjectNum++ ); return buffer; void TOleDocWindow::Paint( HDC hdc, PAINTSTRUCT _FAR &) LPOLEOBJECT lpObjectToDraw = NULL; if ( bObjectLoaded ) lpObjectToDraw = lpObject; else if ( lpUndoObject ) lpObjectToDraw = lpUndoObject; if ( lpObjectToDraw ) RECT rect; GetClientRect( HWindow, &rect ); // Замечание по OleDraw: // OleDraw должен возвращать OLE_ERROR_OBJECT, если // object был нарисован неверно. ret = OleDraw( lpObje ctToDraw , hdc, &rect , NULL, 0 ); wait( ret, lpObjectToDraw ); TOleDocWindow::TOleDocWindow( PTWindowsObject parent, LPSTR title ) : TWindow( parent, title ) ret = OLE_OK; lhClientDoc = 0; bObjectLoaded = FALSE; bUndoObjectLoaded = FALSE; bUndoObje ctLoaded = FALSE; pOwlClient = NULL; lpObject = NULL; lpUndoObject = NULL; strcpy( lpszDocName , "noname.ole" ); *lpszLastObjectName = 0; *lpszObjectName = 0; bDefDocName = TRUE; void TOleDocWindow::SetupWindow() TWindow::SetupWindow(); RegisterClientDoc(); pOwlClient = new TOwlClient( this ); void TOleDocWindow::RegisterClientDoc() ret = OleRegisterClientDoc( GetApplication()->Name, lpszDocName, 0, &lhClientDoc ); check( ret ); void TOleDocWindow::ShutDownWindow() CloseCurrent Ole(); if ( pOwlClient ) delete pOwlClient; TWindow::ShutDownWindow(); void TOleDocWindow::RegFileName( LPSTR FileName ) lstrcpy( lpszDocName , FileName ); ret = OleRegisterClientDoc( GetApplication()->Name, lpszDocName , 0, &lhClientDoc ); check ( re t ); void TOleDocWindow::CMActivate( RTMessage ) BackupObject(); RECT rect; GetClientRect( HWindow, &rect ); ret = OleActivate( lpObject , OLEVERB_PRIMARY, TRUE, TRUE , HWindow , &rect ); wait ( ret, lpObject ); PostMessage( HWindo w , WM_U_REDRAW, 0, 0L ); void TOleDocWindow::WMInitMenu( RTMessage msg ) HMENU hMenu = (HMENU)msg.WParam; WORD wEnableUndo; if ( (lpObject != lpUndoObject) && ( lpUndoObject != NULL )) wEnableUndo = MF_ENABLED; else wEnableUndo = MF_GRAYED; EnableMen uItem( hMenu, CM_UNDO , wEnableUndo ); EnableMenuItem( hMenu, CM_COPY , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED )); EnableMenuItem( hMenu, CM_CUT , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED )); ret = OleQueryCreateFromClip( "StdFileEditing", olerender_draw , 0 ); EnableMenuItem( hMenu, CM_PASTE , (( ret == OLE_OK ) ? MF_ENABLED : MF_GRAYED )); EnableMenuItem( hMenu, CM_ACTIVATE , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED )); EnableMenuItem( hMenu, CM_CLEAR , ( bObjectLoaded ? MF_ENABLED : MF_GRAYED )); DrawM enuBar( HWindow ); LPSTR TOleDocWindow::GetClassName() return "OLEDOCWINDOW"; void TOleDocWindow::GetWindowClass(WNDCLASS _FAR &wc ) TWindow::GetWindowClass( wc ); wc.lpszMenuName = "MENU_DOCWINDOW"; void TOleDocWindow::CMClear( RTMessage ) CloseCurrentOle(); void TOleDocWindow::CloseCurrentOle() // окончательное сохранение if ( lpObject ) ret = OleDelete( lpObject ); wait( ret , lpObject ); if ( lpUndoObject ) ret = OleDelete( lpUndoObject ); wait( ret , lpObject ); lpObject = lp UndoObject = NULL; bObjectLoaded = FALSE; InvalidateRect( HWindow , NULL, TRUE ); UpdateWindow( HWindow ); void TOleApp::InitMainWindow() MainWindow = new TOleDocWindow(NULL, "OWL OLE Application" ); int PASCAL WinMain(HINSTANCE hInstance, HINSTA NCE hPrevInstance, LPSTR lpCmd, int nCmdShow) TOleApp OleApp ("OleApp", hInstance, hPrevInstance, lpCmd, nCmdShow); OleApp.Run(); return (OleApp.Status);
1Архитектура и строительство
2Астрономия, авиация, космонавтика
 
3Безопасность жизнедеятельности
4Биология
 
5Военная кафедра, гражданская оборона
 
6География, экономическая география
7Геология и геодезия
8Государственное регулирование и налоги
 
9Естествознание
 
10Журналистика
 
11Законодательство и право
12Адвокатура
13Административное право
14Арбитражное процессуальное право
15Банковское право
16Государство и право
17Гражданское право и процесс
18Жилищное право
19Законодательство зарубежных стран
20Земельное право
21Конституционное право
22Конституционное право зарубежных стран
23Международное право
24Муниципальное право
25Налоговое право
26Римское право
27Семейное право
28Таможенное право
29Трудовое право
30Уголовное право и процесс
31Финансовое право
32Хозяйственное право
33Экологическое право
34Юриспруденция
 
35Иностранные языки
36Информатика, информационные технологии
37Базы данных
38Компьютерные сети
39Программирование
40Искусство и культура
41Краеведение
42Культурология
43Музыка
44История
45Биографии
46Историческая личность
47Литература
 
48Маркетинг и реклама
49Математика
50Медицина и здоровье
51Менеджмент
52Антикризисное управление
53Делопроизводство и документооборот
54Логистика
 
55Педагогика
56Политология
57Правоохранительные органы
58Криминалистика и криминология
59Прочее
60Психология
61Юридическая психология
 
62Радиоэлектроника
63Религия
 
64Сельское хозяйство и землепользование
65Социология
66Страхование
 
67Технологии
68Материаловедение
69Машиностроение
70Металлургия
71Транспорт
72Туризм
 
73Физика
74Физкультура и спорт
75Философия
 
76Химия
 
77Экология, охрана природы
78Экономика и финансы
79Анализ хозяйственной деятельности
80Банковское дело и кредитование
81Биржевое дело
82Бухгалтерский учет и аудит
83История экономических учений
84Международные отношения
85Предпринимательство, бизнес, микроэкономика
86Финансы
87Ценные бумаги и фондовый рынок
88Экономика предприятия
89Экономико-математическое моделирование
90Экономическая теория

 Анекдоты - это почти как рефераты, только короткие и смешные Следующий
Столько работы, заявление на увольнение некогда написать!
Anekdot.ru

Узнайте стоимость курсовой, диплома, реферата на заказ.

Обратите внимание, реферат по программированию "Протоколы и стандарты ООП", также как и все другие рефераты, курсовые, дипломные и другие работы вы можете скачать бесплатно.

Смотрите также:


Банк рефератов - РефератБанк.ру
© РефератБанк, 2002 - 2016
Рейтинг@Mail.ru