Разработка интегрированных прикладных программ (Меньшикова К. Г.). Разработка интегрированных прикладных программ (Меньшикова К. Г.. Методическое пособие по курсу Проектирование программного обеспечения автоматизированных систем для студентов, обучающихся по направлению Прикладная математика и информатика
Скачать 313.5 Kb.
|
2.OLE-автоматизацияЛюбое приложение, которое хочет сделать доступными для других программ свои внутренние функции, (т.н. программируемое приложение), может осуществить это, предоставив клиентам объекты, реализующие интерфейс IDispatch. Это обычный COM-интерфейс, который реализован с помощью виртуальной таблицы указателей на его методы, но в его состав входит метод Invoke, который используется для вызова других (диспетчерских) методов. Клиент, которого в данном случае принято называть контроллером автоматизации, может посредством Invoke обращаться к необходимому методу и передавать параметры. Конечно, современные программные инструментарии предоставляют в распоряжение программистов достаточно удобные средства для создания серверов и контроллеров. Рассмотрим примеры их создания. 2.1.Создание сервера автоматизации в Builder C++Для создания сервера можно разработать обычное приложение и затем добавить к нему описание класса COM-объекта, создаваемого этим приложением. Через этот объект будет осуществляться доступ к функциональности, которую нужно автоматизировать. На рис. 1 представлено главное окно приложения-сервера «День недели». Рис. 1 Приложение должно выводить на экран текущую дату (в Label2) и день недели (в Label3). В поле ввода (Edit1) можно ввести любую дату, а по щелчку на кнопке (Button1) получить день недели, соответствующий введенной дате. В класс формы (Form1) главного окна приложения были добавлены следующие функции: void __fastcall TForm1::day_this(int& n); void __fastcall TForm1::day_date(AnsiString str,int& n); void __fastcall TForm1::day_week(int n, AnsiString& str); В модуль формы следует также добавить строку #include Функция day_this возвращает номер дня недели (1 – воскресенье): void __fastcall TForm1::day_this(int& n) { n=DayOfWeek(Date()); } Функция day_date по заданной дате возвращает номер дня недели: void __fastcall TForm1::day_date(AnsiString str,int& n) { TDateTime dtDate = StrToDate(str); n=dtDate.DayOfWeek(); } Функция day_week по заданному номеру дня недели возвращает его название: void __fastcall TForm1::day_week(int n, AnsiString& str) { char days[7][12] = {"Воскресенье","Понедельник", "Вторник","Среда", "Четверг","Пятница","Суббота"}; str=(AnsiString)(days[n-1]); } Пусть при создании формы Form1 в окне появляется текущая дата: void __fastcall TForm1::FormCreate(TObject *Sender) { int i; AnsiString str; str = DateToStr(Date()); Label2->Caption=str; day_this(i); day_week(i,str); Label3->Caption=str; } При щелчке на кнопке Button1, по дате, введенной в Edit1, определяется день недели: void __fastcall TForm1::Button1Click(TObject *Sender) {int i; AnsiString str; str=Edit1->Text; try { day_date(str,i); day_week(i,str); Label5->Caption=str; } catch(Exception &e) { Application->MessageBoxA (e.Message.c_str(), "Ошибка",MB_OK); } Label4->Caption=Edit1->Text; } Сохранив проект, как обычное Windows-приложение, затем можно превратить его в сервер автоматизации. Для этого следует:
Обычно описания интерфейсов создаются на языке IDL (Interface Definition Language), а затем по ним строится библиотека типов. При работе в среде Builder C++ и Delphi достаточно в окне редактора библиотеки указать свойства и методы создаваемого COM-объекта. Объект (рис. 2) имеет диспетчерский интерфейс IDayWeek, в состав которого входят два метода (Today, Data_Day) и свойство Visible. Выбрав кнопку Export To IDL, можно получить описание на языке IDL интерфейса IDayWeek, входящего в состав библиотеки типов “Project_DayWeek Library”: Project_DayWeek.idl [ uuid(C55ED6A4-5583-4E88-8317-0539445A5F6E), version(1.0), helpstring("Project_DayWeek Library") ] library Project_DayWeek { importlib("stdole2.tlb"); [ uuid(C13BFB8F-C655-43CA-80D9-C53B659E5C85), version(1.0), helpstring("Dispatch interface for DayWeek Object"), dual, oleautomation ] interface IDayWeek: IDispatch { [ id(0x00000001) ] HRESULT _stdcall Today([out] BSTR * str ); [ id(0x00000002) ] HRESULT _stdcall Data_Day([in] BSTR dat, [out] int * n, [out] BSTR * week ); [ propget, id(0x00000003) ] HRESULT _stdcall Visible([out, retval] VARIANT_BOOL * Value ); [ propput, id(0x00000003) ] HRESULT _stdcall Visible([in] VARIANT_BOOL Value ); }; [uuid(3E979810-8A64-4EAE-9F1E-8C582079F4AF), version(1.0), helpstring("DayWeek Object") ] coclass DayWeek { [default] interface IDayWeek; }; }; Рис. 2 Заготовки модуля DayWeekImpl заполняются соответствующим кодом. Метод Data_Day возвращает номер и название дня недели для заданной даты: STDMETHODIMP TDayWeekImpl::Data_Day(BSTR dat, int* n, BSTR* week) { int i; AnsiString str; str=(AnsiString)dat; Form1->day_date(str,i); Form1->day_week(i,str); *n =i; *week= WideString(str.c_str()).c_bstr(); return S_OK; } Метод Today возвращает текущую дату и название дня недели: STDMETHODIMP TDayWeekImpl::Today(BSTR* str) { AnsiString s; s=Form1->Label2->Caption + " " + Form1-> Label3->Caption; *str= WideString(s.c_str()).c_bstr(); return S_OK; } Два следующих метода get_Visible и set_Visible отвечают за чтение и установку свойства Visible, которое позволяет сделать видимым или невидимым приложение-сервер: STDMETHODIMP TDayWeekImpl::get_Visible(VARIANT_BOOL* Value) { try { *Value=Form1->Visible; } catch(Exception &e) { return Error(e.Message.c_str(), IID_IDayWeek); } return S_OK; }; STDMETHODIMP TDayWeekImpl::set_Visible(VARIANT_BOOL Value) {try { Form1->Visible=Value; } catch(Exception &e) { return Error(e.Message.c_str(), IID_IDayWeek); } return S_OK; }; При описании параметров методов сервера автоматизации используются типы данных, принятые в IDL. Часто используются типы данных, которым легко можно найти аналог в языке программирования (short - двухбайтовое целое число со знаком, long - четырехбайтовое целое число со знаком, single - четырехбайтовое действительное число, double - восьмибайтовое действительное число, BSTR - двоичная строка, VARIANT_BOOL - true= 1, false = 0). Можно использовать также и другие типы данных. После компиляции и запуска сервера на выполнение он зарегистрируется в реестре. При необходимости удаления записей рекомендуется запустить его с ключом /unregserver. При переносе сервера автоматизации в другой каталог, можно запустить его снова, при этом записи в реестре обновятся. Записи делаются в разделах реестра HKEY_LOCAL_MASHINE\SOFTWARE и HKEY_CLASSES. После создания сервера автоматизации, основываясь на информации, содержащейся в библиотеке типов, можно создавать приложения, управляющие этим сервером, т.е. контроллеры автоматизации. Это можно сделать с помощью различных инструментариев, включая Visual C++, Delphi, C++Builder, VBA и т.д. |