телевизори. Конзоли. Проектори и аксесоари. Технологии. Цифрова телевизия

Обектът не може да бъде създаден от контейнера на ActiveX v82 comconnector. Създаване на ActiveX контролни контейнери. Скрипт за създаване на контрол

Александър Костарев
програмист в технологичния отдел на R-Style Software Lab.

Създаване на елементи ActiveX контролие широко застъпен в специализираната литература. Но методите за писане на ActiveX контейнери се обсъждат много по-рядко, главно само по отношение на тяхното взаимодействие с ActiveX обекти. Още по-малко публикации са посветени на процедурите за разработване на контейнери, които поддържат собствените си софтуерен интерфейс(API), което ви позволява да работите с тях и обектите, които съдържат от други приложения или скриптови езици. Примери за такива контейнери са софтуерни продукти като Microsoft Visual Basic, Borland Delphi и др.

Въпреки това не е възможно да се решат редица проблеми с помощта на съществуващи контейнери; това изисква специализирани контролни контейнери. Една от тези задачи е да създадете разширяемо приложение, което ви позволява да автоматизирате често възникващи операции, които не могат да бъдат предвидени по време на разработката. Автоматизацията изисква приложението да показва обектите си външно и да бъде интегрирано с инструмент за разработка на разширения. Строителство потребителски интерфейссе основава в повечето случаи на вмъкване на различни контроли във форма - контейнер от ActiveX обекти. По този начин създаването на инструмент изисква създаване на ActiveX контейнер.

Ще разгледаме някои проблеми, които възникват при въвеждането на компонентна архитектура в набор от инструменти, както и методи за тяхното решаване. Това може да представлява интерес както за разработчиците на контролни контейнери, така и за самите разработчици на ActiveX обекти, тъй като статията демонстрира целта и използването на различни методи на стандартни контролни интерфейси от страна на контейнера.

Предложените решения се основават на опита от разработването на инструментариума RS-Forms - нов софтуерен продукт R-Style Software Lab компания. RS-Forms включва инструмент за разработка на графичен потребителски интерфейс за Windows платформа, среда за изпълнение на програми, създадени с помощта на езиците RSL*, C и C++, както и система за отстраняване на грешки в RSL програми.

*Object RSL - език за програмиране високо ниво, създаден от R-Style Software Lab. За повече подробности вижте http://www.softlab.ru/products/rsl/. - Забележка изд.

Като част от проекта беше внедрена първата версия на дизайнера на формуляри (фиг. 1), която ви позволява да създавате формуляри, да внедрявате както стандартни контроли, така и произволни ActiveX обекти в тях, да запазвате готови формуляри в хранилището на постоянно хранилище среден и ги заредете от него. С помощта на дизайнера можете да преглеждате свойствата, методите и събитията на всеки контролен елемент, вграден във формуляра, и да променяте стойностите на свойствата.

Дизайнерът е изграден върху ActiveX контролен контейнер (формуляр), който предоставя описаната по-горе функционалност. В допълнение, формата поддържа различни опциинастройки за неговото представяне, включително процентно обвързване на вградените елементи с граници, контрол на последователността на преминаването им от клавиатурата, тяхната видимост, шрифт и размер на шрифта, цвят на фона, текст и др.

В допълнение към разработването на графичен потребителски интерфейс, дизайнерът включва механизъм за автоматично генериране на код в C++ и RSL. Важно е да се отбележи, че всички операции, извършвани върху формуляра в дизайнера, са достъпни и в режим на изпълнение от програмния код.

Ориз. 1. Дизайнер на формуляри.

Създаден в дизайнер графични формиможе да се използва във всяко C/C++ приложение, както и от всеки скриптов език, като Visual Basic или RSL. Когато използвате формуляри в C++ приложения, разработени с библиотеката MFC, можете да използвате дизайнера като диалогов редактор на ресурси.

Сега нека обсъдим концепцията за изграждане на контейнер и принципите на работа с ActiveX контроли.

Основни функции на контейнера

Всеки контейнер с контроли трябва да има функционалност, която ви позволява да създавате ActiveX обекти, да гарантирате правилната им работа и да ги премахвате от оперативна памет, както и да записвате елементи в обектното хранилище на постоянен носител и да ги зареждате от него*. Контейнерът включва редица компоненти (фиг. 2), които осигуряват стандарт (в съответствие с Технология на Microsoft ActiveX) функционалност, необходима за правилната работа на контролите.

* Общите въпроси на изграждането на контейнери и сървъри на COM обекти са разгледани в книгата на D. Chappel „ActiveX и OLE технологии“ - М.: „Руско издание“, 1997 г.

Контейнерът поддържа колекция (например списък) от комуникационни обекти с ActiveX елементи- един комуникационен обект за всеки управляващ елемент. В допълнение, програмируемият контейнер трябва да осигури стандартен механизъм за манипулиране на елементи от тази колекция.

Контролният обект отговаря за правилното взаимодействие на съответния елемент с контейнера. Всеки комуникационен обект съдържа подобект, който разширява контрола със стандартни специфични за контейнера набори от свойства, методи и събития. Този подобект се нарича разширен контрол. Пример за разширени свойства е името (Name), местоположението в контейнера (Width, Left) и др. Посочените набори са свойства на контейнера, а не на някакъв индивидуален контрол, въпреки че е точно това, което изглежда на потребителя на системата. Има няколко варианта за прилагане на разширен контрол. Например, това може да бъде подобект на комуникационен обект (вижте Фигура 2) или действителен COM обект, който агрегира оригиналния контрол. Всеки вариант има своите предимства и недостатъци. В тази статия разглеждаме само първия метод.

Всяка разширена контрола съдържа като подобект обект за поглъщане на събитие от свързаната с нея контрола (фиг. 2). Неговите задачи включват първична идентификация на получените събития (независимо дали е необходима персонализирана обработка на събития или не) и, ако е необходимо, прехвърлянето им към неговия обект собственик (разширен контрол), което гарантира маршрутизиране на събитията през йерархията на контейнерните обекти.

Скрипт за създаване на контрол

Включването на контрола в контейнер се състои от три фази: създаване на ActiveX обект, инициализиране и активиране.

Контролите се създават в адресното пространство на контейнера с помощта на стандартни COM функции като CoCreateInstance. Съответният глобално уникален идентификатор на клас CLSID се предава на функцията като контролен идентификатор. Трябва да се отбележи, че контейнерът трябва да поддържа различни опции за идентифициране на COM обекти в системата - като програмен идентификатор ProgID, уникален идентификатор на клас под формата на низ и др.

Основната цел на фазата на инициализация е да прехвърли към контрола, чрез функцията IOleObject::SetClientSite, указател към интерфейса IOleClientSite на комуникационния обект и да извика функцията IPersistStreamInit::InitNew или IPersistStreamInit::Load (в зависимост от това дали обектът е зареден от хранилището или не). Предаването на указател към интерфейса IOleClientSite към обекта може да се случи преди зареждане/инициализация или след това; моментът на предаване се определя от наличието на атрибута OLEMISC_SETCLIENTSITEFIRST (IOleObject::GetMiscStatus). Това е важно, тъй като моментът на преминаване на показалеца определя в кой момент от време контролата ще получи стойностите на свойствата на околната среда от контейнера. Ако този знак бъде игнориран, тогава по-нататъшното функциониране на ActiveX обекта може да е неправилно.

След това тази фаза включва първоначална инициализация на свойствата на разширения контрол, който допълва създавания ActiveX обект. Например, трябва да зададете правилно името на обекта (инициализирайте свойството Name, което гарантира идентифицирането на контролите в контейнера). Всяка контрола, вградена в програмируем контейнер, трябва да поддържа това свойство, но все още е свойство на контейнера. Често по подразбиране на обектите се дава краткото име на класа, към който принадлежат (това име се връща от метода IOleObject::GetUserType за параметъра USERCLASSTYPE_SHORT), последвано от цифров индекс, който гарантира, че имената на контролите в контейнера е уникален. Ако получите посочено имене успее или ако не отговаря на логиката на контейнера, тогава можете да посочите някакво предварително дефинирано име с подходящ индекс.

Активирането на контрола предполага определена последователност от действия. Първото нещо, което трябва да направите, е да настроите обратната връзка на ActiveX обекта към комуникационния обект в контейнера (контролен сайт). За целта се извиква методът IOleObject::Advise, на който като параметър се предава указател към стандартния интерфейс на комуникационния обект IAdviseSink. След това трябва да заявите правилно интерфейса на фамилията IViewObject (според спецификацията, ActiveX обект може да поддържа интерфейсите IViewObject, IViewObject2, IViewObjectEx, които са в йерархията на наследяване) и да зададете обратна връзка за него, като извикате IViewObject:: Метод SetAdvise, предаващ указател към IAdviseSink. Освен това трябва да кажете на контролата името на неговия контейнер (това се осъществява чрез извикване на метода IOleObject::SetHostName), да заявите и запазите всички интерфейси, необходими за правилна работа с ActiveX обекта (поне IOleInPlaceObject и IOleControl). Последното нещо, което трябва да направите, за да визуализирате контролата визуално, е да извикате функцията IOleObject::DoVerb* с параметъра OLEIVERB_INPLACEACTIVATE.

*В изпълнение на ATL определена функция, наред с други неща, отговаря за създаването на прозорец за редовни (с прозорци) контроли.

Контролен скрипт за изтриване

За да премахнете контрола, вградена в контейнер, от паметта, трябва да изключите съответния обект на асоцииране на контрола от колекцията и след това да изпълните две операции последователно: break обратна връзкаи освобождаване на съхранени указатели към интерфейси на ActiveX обекти.

За да прекъснете връзките за обратна връзка, първо трябва да информирате премахнатия елемент за необходимостта от освобождаване (чрез извикване на метода IUnknown::Release) указателите, които държи към интерфейса IAdviseSink на комуникационния обект. За целта се извикват методите IViewObject::SetAdvise (предавайки NULL като аргумент) и IOleObject::Unadvise, на които трябва да предоставите идентификатора на връзката, записан на етапа на активиране. След това трябва да активирате процедурата за деинициализация на ActiveX обект (чрез извикване на функцията IOleObject::Close). Следващата стъпка е да кажете на контролата да освободи указателя към интерфейса IOleClientSite, като извика IOleObject::SetClientSite с параметъра NULL.

Фазата на освобождаване на съхранени указатели към контролни интерфейси включва извикване на метода Release върху тях последователно. Веднага след като последният указател бъде освободен, обектът (в съответствие с COM технологията) ще бъде изтрит от RAM.

Запазване и зареждане на скрипт

Записването на контейнерен обект в хранилище, независимо от типа на последния, означава запазване на свойствата на контейнера (например свойства на околната среда) и колекцията от вградени контроли, тоест идентификаторите и свойствата (включително разширени) на всеки принадлежащ обект към колекцията. Идентификаторът на контролния елемент може да бъде глобален уникален идентификатор на клас (CLSID). Това ще ви позволи да създадете необходимия ActiveX обект на етапа на инициализация и да го заредите с данните, съдържащи се в хранилището след посочения идентификатор. За да запазите свойствата на контролен елемент, например в поток, се извиква методът Save на стандартния ActiveX обектен интерфейс IPersistStreamInit. За зареждане се извиква методът Load на същия интерфейс.

Тази процедура за запазване гарантира последващото възстановяване на контейнерния обект от съхранение. Описаният метод работи добре, при условие че от момента на запазване до момента на зареждане не е имало промяна във версията или премахване на контроли от системата. Такива ситуации често възникват при преместване на хранилище на данни от един компютър на друг, където запазените ActiveX обекти не са инсталирани или регистрирани. В този случай зареждането на контейнерен обект от хранилището или ще доведе до фатално прекратяване на програмата, или ще причини грешка при зареждането на целия контейнер като цяло. За да се предотвратят грешки, е необходимо ясно да се установи границата между данните на различните контроли, записвайки в хранилището след идентификатора на обекта размера на информацията, записана от него. Това ще позволи на етапа на зареждане да се позиционира точно в началото на данните на всеки ActiveX обект и също така ще пропусне контроли, които не са регистрирани в системата, но ще зареди контейнерния обект като цяло.

Интерфейси за събиране на ActiveX обекти

Съгласно стандарта контролният контейнер трябва да позволява на ActiveX обектите, вградени в него, да взаимодействат. За да направите това, трябва да поддържате интерфейса IOleContainer, който ви позволява да изброите всички контроли, вмъкнати в него. Ако има разширен контрол, изброяването трябва да се извърши върху неговите IUnknown интерфейси, а не през интерфейсите на основния обект.

Стандартен интерфейс за събиране на обекти се използва за предоставяне на достъп до колекцията на клиенти за автоматизация. Стандартната колекция включва методите Add, Remove, Clear и Item и свойствата _NewEnum и Count, които осигуряват цялостна итерация на елементи. Например Visual Basic за всяка конструкция използва свойството _NewEnum за изброяване на елементи, а конструкцията for next използва свойството Count и метода Item. В езика Object RSL свойството _NewEnum се използва при достъп стандартен метод ActiveX обект CreateEnum. Това е илюстрирано, например, от RSL програма, която отпечатва, използвайки посочения метод, имената на файловете, отворени в Microsoft приложение Excel (текстът му е даден по-долу).

импортиране на rslx; ob = ActiveX("Excel.Application", null, true); en = ob.Workbooks.CreateEnum; докато (en.next) println(en.item.Name) край;

Разгледаните сценарии ви позволяват да разработите функции за добавяне на контрола към контейнер и премахването й от него. В повечето случаи функцията add създава обект за връзка с контролата (който съхранява всички указатели към интерфейсите на ActiveX обекта, необходими за работа) и извиква подобна функция върху него. Последният, от своя страна, изпълнява описания по-горе сценарий на внедряване (възможно е без фазата на активиране). Ако формирането на ActiveX обект в RAM е успешно, функцията на контейнера добавя съответния комуникационен обект към колекцията. Често, поради сходството си, процедурите за вграждане и зареждане на контрола от хранилището се комбинират.

* * *

Тук разгледахме основните въпроси, свързани с изграждането на контролни контейнери: внедряване, визуално показване, запазване и зареждане на ActiveX обект, както и правилното му премахване от RAM. Въпреки това, в процеса на създаване на среда с графичен инструмент, трябваше да внедрим няколко контейнера, които да се различават един от друг по интерфейсите за автоматизация, които предоставят, подмножествата от ActiveX обекти, разрешени за внедряване, наборите от свойства, методи и събития на разширени контроли и др. За тази цел беше предложен модел, който позволява създаването на различни контейнерни елементи и се интегрира добре с ATL библиотеката. Независимостта от конкретни интерфейси се постига чрез използването на шаблонни класове, чиито параметри са тези интерфейси.

*Например, контрола Tab е контейнер от страници със свойства, които са контейнери с общо предназначение.

Този модел ви позволява бързо да създавате основни версии на различни ActiveX обекти, които имат "контейнерна логика". В допълнение, внедрената инфраструктура позволява създаването на контейнери, които не са контроли. Такъв контейнер може да бъде поставен като Windows прозорцивъв всяка част от разработваното приложение и след това чрез изпращане на подходящи съобщения внедрява различни контроли в него.

Резултатът е доста гъвкава архитектура за изграждане на контейнери, с която можете да създадете съветник, който се разширява функционалност Microsoft Visual Studio среда към механизма за генериране на скелет на контейнер.

Системи и всички свързани бяха налични. Тази грешка има следните причини и решения:

    Класът не е регистриран. Например, в системния регистър не се споменава клас или класът е споменат, но сочи към файл от грешен тип или към файл, който не може да бъде намерен. Ако е възможно, стартирайте обектното приложение. Ако информацията в регистъра е неправилна или остаряла, приложението ще провери регистъра и ще коригира информацията. Ако стартирането на приложението не разреши проблема, стартирайте отново програмата за инсталиране на приложението;

    Не може да се използва DLL, изискван от обекта, защото не е намерен или е намерен повреден. Уверете се, че всички свързани DLL файлове са налични. Например обект за достъп до данни (DAO) изисква поддръжка за DLL файлове, които се различават в зависимост от платформата. Ако това е причината за грешката, ще трябва да стартирате отново инсталационната програма за този елемент;

    Обектът е наличен на компютъра, но е лицензиран и не успява да провери наличността на лиценза, необходим за инстанциране на обекта.

    Екземпляри на някои обекти могат да бъдат създадени само след като компонентът намери лицензионен ключ, потвърждавайки регистрацията на този обект за създаване на екземпляр върху този компютър. Ако има препратка към обекта в правилно инсталиран или правилен ключ се предоставя автоматично.

    Ако опитът за създаване на екземпляр е резултат от извикване на функция CreateObjectили GetObject, обектът трябва да намери ключа. В този случай той може да търси в системния регистър или да търси специален файл, който създава по време на инсталацията (например с разширение .LIC). Ако ключът не може да бъде намерен, екземплярът на обекта не може да бъде създаден. Ако крайният потребител е конфигурирал неправилно обектното приложение, изтрито за постоянно необходим файлили промени системния регистър, обектът няма да може да намери своя ключ. Ако ключът не може да бъде намерен, обектът не може да бъде създаден. В този случай инстанцията може да работи в системата на разработчика, но не и в системата на потребителя. Потребителят трябва да преинсталира лицензирания елемент;

    Опитвате се да използвате функцията за получаване на обект GetObjectза да получите препратка към клас, създаден с помощта на Visual Basic. GetObjectне може да се използва за получаване на препратка към клас, създаден с помощта на Visual Basic;

    Достъпът до обекта е изрично отказан. Например, вие се опитвате да получите достъп до обект с данни, който в момента се използва и е заключен, за да предотврати блокиране. В този случай може да имате достъп до елемента по друго време.

За получаване Допълнителна информацияИзберете елемента, за който имате въпрос, и натиснете F1 (Windows) или ПОМОЩ (Macintosh).


Ръчното редактиране на системния регистър на Windows за премахване на ключове за грешки с грешка 800A01AD не се препоръчва, освен ако не сте професионалист по обслужване на компютри. Грешките, допуснати при редактиране на регистъра, могат да доведат до неработоспособност на вашия компютър и да причинят непоправими щети на вашия операционна система. Всъщност дори една запетая, поставена на грешното място, може да попречи на компютъра ви да се зареди!

Поради този риск силно препоръчваме да използвате доверен инструмент за почистване на регистър като WinThruster [Изтегляне] (разработен от Microsoft Gold Certified Partner), за да сканирате и поправите всякакви проблеми в регистъра, свързани с грешка 800A01AD. Използвайки Registry Cleaner [Изтегляне], можете да автоматизирате процеса на намиране на повредени записи в регистъра, липсващи препратки към файлове (като тези, причиняващи грешката %%error_name%%) и повредени връзки в регистъра. Преди всяко сканиране, a резервно копие, което ви позволява да отмените всички промени с едно щракване и ви предпазва от евентуална повреда на вашия компютър. Най-добрата част е, че коригирането на грешки в системния регистър [Изтегляне] може значително да подобри скоростта и производителността на системата.


Внимание:Ако не сте опитен потребител PC, ние НЕ препоръчваме ръчно редактиране на системния регистър на Windows. Неправилното използване на редактора на системния регистър може да причини сериозни проблеми и да изисква Преинсталиране на Windows. Ние не гарантираме, че проблемите, произтичащи от неправилно използване на редактора на регистъра, могат да бъдат коригирани. Вие използвате редактора на системния регистър на свой собствен риск.

Преди ръчно възстановяване Регистър на Windows, трябва да създадете резервно копие, като експортирате частта от системния регистър, свързана с грешка 800A01AD (например ActiveX):

  1. Кликнете върху бутона Започнете.
  2. Въведете " команда" В лента за търсене... ОЩЕ НЕ КЛИКАЙТЕ ENTER!
  3. Докато държите натиснати клавишите CTRL-Shiftна клавиатурата натиснете ENTER.
  4. Ще се покаже диалогов прозорец за достъп.
  5. Кликнете да.
  6. Черната кутия се отваря с мигащ курсор.
  7. Въведете " regedit" и натиснете ENTER.
  8. В редактора на системния регистър изберете ключа, свързан с грешка 800A01AD (например ActiveX), който искате да архивирате.
  9. В менюто Файлизберете Експортиране.
  10. В списъка Запази визберете папката, в която искате да запазите резервното копие на ActiveX ключа.
  11. В полето Име на файлВъведете име за архивния файл, например „ActiveX архивиране“.
  12. Уверете се, че полето Експортна гамаизбрана стойност Избран клон.
  13. Кликнете Запазване.
  14. Файлът ще бъде записан с разширение .рег.
  15. Вече имате резервно копие на свързания с ActiveX запис в системния регистър.

Следните стъпки за ръчно редактиране на системния регистър няма да бъдат описани в тази статия, тъй като има вероятност да повредят вашата система. Ако желаете повече информация относно ръчното редактиране на регистъра, моля, разгледайте връзките по-долу.



Свързани публикации