Нові релізи "1С: Управління торгівлею": оновлення без розвитку. Вирішення проблем із реєстрацією зовнішніх компонентів у терміналі Розширення списку методів
23 жовтня вийшов новий реліз конфігурації «1С: Управління торгівлею». В черговий раз в оновлення увійшли зміни щодо ВетІС, ЄДАІС, і майже ніяк не торкнулася загальна функціональність конфігурації.
Що змінилося?
Якщо подивитися на структуру змін, які включені до останнього релізу конфігурації «1С: Управління торгівлею», то більше половини - це оновлення щодо ЄДАІС, ВетІС, і лише кілька рядків в описі релізу присвячено розширенню функціональних можливостей програмного продукту, які не обумовлені жодними законодавчими актами.
Розділи, у яких відбулися зміни:
у роздрібних продажах додано підтримку зчитування двомірного штрихового коду акцизних і федеральних спеціальних марок нового зразка, що містить цифровий ідентифікатор ЕДАІС;
доопрацьовано інтеграцію із системою ветеринарного контролю (ВетІС);
доопрацьовано обмін із системою ЄДАІС;
додано нові можливості сервісу обміну електронними документами;
виконано доопрацювання в частині сервісу 1С:Бізнес-мережа;
доопрацьовано інтеграцію з Яндекс.Касою.
Щодо загальної функціональності, тут було внесено кілька змін до блоку планування та казначейства. І традиційно постійні доповнення щодо обліку ПДВ.
При цьому останній актуальний реліз конфігурації «1С: Управління торгівлею»перестав бути винятком - сьогодні розвиток зміни для оперативного обліку йде переважно шляхом закриття завдань, що виникають внаслідок законодавчого регулювання у сфері торгівлі. Логічно, що підтримка вимог регуляторів стає пріоритетнішою, і, зрештою, визначає напрямок розвитку програмного рішення в цілому.
Чи оперативний облік стає регламентованим?
Зазвичай конфігурація «1С: Управління торгівлею»використовується для автоматизації оперативного обліку. При цьому у зв'язку з "1С: Бухгалтерією"прийнято було «завантажувати» всі вимоги щодо модифікації типового функціоналу "1С: УТ",щоб зберегти можливість поновлення бухгалтерської програми з мінімальними трудовитратами.
Враховуючи обсяг регламентуючих документів для оперативного обліку в торгівлі та відображення цих вимог у типовій конфігурації, є причини більш дбайливо підходити до внесення змін до типового функціоналу торгової конфігурації. Наприклад, проблеми з обміном із системою Меркурій можуть якщо не паралізувати діяльність цілої низки підприємств, то призвести до тривалих простоїв як мінімум.
Як один з варіантів рішення можна розглядати використання механізму розширень, тим більше що фірма «1С» активно цей функціонал. Безумовно, такий підхід вимагатиме додаткових трудовитрат від розробників. Але це оптимальний спосіб підтримки змін у сучасних конфігураціях.
Більш радикальним буде розподіл функціоналу між типовою конфігурацією «1С: Управління торгівлею»та якимись зовнішніми обліковими чи аналітичними системами. Тут з боку «1С» знову-таки зроблено достатньо для ефективного вирішення таких завдань на рівні платформи.
У будь-якому випадку, тепер при проектуванні корпоративних облікових систем та розподілі функціональних можливостей між конфігураціями потрібно мати на увазі: не виключено, що оновлювати «1С: Управління торгівлею»доведеться якщо не так часто, як "1С: Бухгалтерію", то вже точно не 1-2 рази на рік, як багато хто робив це раніше.
- Tutorial
Вступ
Ця стаття дає уявлення про роботу зовнішніх компонентів у системі «1С: Підприємство».Буде показаний процес розробки зовнішньої компоненти системи «1С: Підприємство» версії 8.2, що працює під управлінням ОС сімейства Windows з файловим варіантом роботи. Такий варіант роботи використовують у більшості рішень, призначених для підприємств малого бізнесу. ВК буде реалізована мовою програмування C++.
Зовнішні компоненти "1C: Підприємство"
«1С: Підприємство» є системою, що розширюється. Для розширення функціональних можливостей системи використовують зовнішні компоненти (ВК). З точки зору розробника ВК є деяким зовнішнім об'єктом, який має властивості та методи, а також може генерувати події для обробки системою «1С: Підприємство».Зовнішні компоненти можна використовувати для розв'язання класу завдань, які складно чи навіть неможливо реалізувати на вбудованій мові «1C: Підприємство» програмування. Зокрема, до такого класу можна віднести завдання, що вимагають низькорівневої взаємодії з операційною системою, наприклад, для роботи зі специфічним обладнанням.
У системі «1С: Підприємство» використовуються дві технології створення зовнішніх компонентів:
- з використанням Native API
- з використанням технології COM
Структура ВК
Зовнішній компонент системи «1С: Підприємство» представлений у вигляді DLL-бібліотеки. У коді бібліотеки описується клас-спадкоємець IComponentBase. У створюваному класі мають бути визначені методи, відповідальні за функцію зовнішньої компоненти. Більш детально перевизначені методи будуть описані нижче під час викладу матеріалу.Запуск демонстраційної ВК
Завдання:- Виконати складання зовнішньої компоненти, що постачається з підпискою ІТС і призначеної для демонстрації основних можливостей механізму зовнішніх компонентів у 1С
- Підключити демонстраційну компоненту до конфігурації 1С
- Переконатись у коректній працездатності заявлених функцій
Компіляція
Демонстраційна ВК розташована на диску підписки ІТС у каталозі "/VNCOMP82/example/NativeAPI".Для складання демонстраційної ВК будемо використовувати Microsoft Visual Studio 2008. Інші версії даного продукту не підтримують формат проекту Visual Studio, що використовується.
Відкриваємо проект AddInNative. У налаштуваннях проекту підключаємо каталог із заголовними файлами, необхідними для збирання проекту. За умовчанням вони розміщуються на диску ІТС у каталозі /VNCOMP82/include.
Результатом збирання є файл /bind/AddInNative.dll. Це і є скомпільована бібліотека для підключення до конфігурації 1С.
Підключення ВК до конфігурації 1С
Створимо порожню конфігурацію 1С.Нижче наведено код модуля керованої програми.
перем ДемоКомп; Процедура ПриПочаткуРоботиСистеми() ПідключитиЗовнішнюКомпоненту("...\bind\AddInNative.dll", "DemoVK", ТипЗовнішньоїКомпоненти.Native); ДемоКомп = Новий ("AddIn.DemoVK.AddInNativeExtension"); КінецьПроцедури
Якщо при запуску конфігурації 1С не було повідомлено про помилку, ВК була успішно підключена.
В результаті виконання наведеного коду у глобальній видимості конфігурації з'являється об'єкт ДемоКомп, що має властивості та методи, які визначені в коді зовнішньої компоненти
Демонстрація закладеного функціоналу
Перевіримо працездатність демонстраційної ВК. Для цього спробуємо встановити та прочитати деякі властивості, викликати деякі методи ВК, а також отримати та обробити повідомлення ВК.У документації, що поставляється на диску ІТС, заявлений наступний функціонал демонстраційної ВК:
- Управління станом об'єкта компоненти
Методи: увімкнути, Вимкнути
Властивості: Включено - Управлінням таймером
Кожну секунду компонента надсилає повідомлення системі «1C: Підприємство» з параметрами Component, Timerта рядком лічильника системного годинника.
Методи: СтартТаймер, СтопТаймер
Властивості: Є Таймер - Метод ПоказатиВрядкуСтатуса, який відображає у рядку статусу текст, переданий методом як параметри
- Метод ЗавантажитиКартинку. Завантажує зображення із зазначеного файлу та передає його в систему «1C: Підприємство» у вигляді двійкових даних.
перем ДемоКомп; Процедура ПриПочаткуРоботиСистеми() ПідключитиЗовнішнюКомпоненту(...); ДемоКомп = Новий ("AddIn.DemoVK.AddInNativeExtension"); ДемоКомп.Вимкнути(); Повідомити (ДемоКомп.Включен); ДемоКомп.Включити (); Повідомити (ДемоКомп.Включен); ДемоКомп.СтартТаймер(); КінецьПроцедури Процедура ОбробкаЗовнішньоїПодії(Джерело, Подія, Дані) Повідомити(Джерело + " " + Подія + " " + Дані); КінецьПроцедури
Результат запуску конфігурації наведено на зображенні
На панель «Повідомлення» виведено результати дзвінків методів ДемоКомп.Вимкнути()і Демо.Комп.Включити(). Наступні рядки на тій же панелі містять результати обробки отриманих від ВК повідомлень Джерело, Подіяі Данівідповідно.
Довільне ім'я зовнішньої компоненти
Завдання: Змінити ім'я зовнішньої частини довільне.У попередньому розділі використовувався ідентифікатор AddInNativeExtension, зміст якого був пояснений. В даному випадку AddInNativeExtension- це найменування розширення.
У коді ВК визначено метод RegisterExtensionAs, що повертає системі «1С: Підприємство» ім'я, яке необхідне для подальшої реєстрації ВК у системі. Рекомендується вказувати ідентифікатор, який певною мірою розкриває суть зовнішньої компоненти.
Наведемо повний код методу RegisterExtensionAsіз зміненим найменуванням розширення:
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* dest = 0; ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, wsExtension, iActualSize); return true; ) return false;
У наведеному прикладі ім'я ВК змінено на SomeName. Тоді при підключенні ВК необхідно вказувати нове ім'я:
ДемоКомп = Новий ("AddIn.DemoVK.SomeName");
Розширення списку властивостей ВК
Завдання:- Вивчити реалізацію властивостей ВК
- Додати властивість рядкового типу, доступна для читання та запису
- Додати властивість рядкового типу, доступна для читання та запису, яка зберігає тип даних останньої встановленої властивості. При встановленні значення властивості ніяких дій не провадиться
Для визначення властивостей створюваної компоненти розробнику необхідно реалізувати такі методи у коді бібліотеки AddInNative.cpp:
GetNProps
Повертає кількість властивостей даного розширення, 0 – за відсутності властивостей
FindProp
Повертає порядковий номер властивості, ім'я якого передається у параметрах
GetPropName
Повертає ім'я властивості за його порядковим номером та за переданим ідентифікатором мови
GetPropVal
Повертає значення властивості із зазначеним порядковим номером
SetPropVal
Встановлює значення властивості із зазначеним порядковим номером
IsPropReadable
Прапор повертає прапор можливості читання властивості із зазначеним порядковим номером
IsPropWritable
Повертає прапор прапора можливості запису властивості із зазначеним порядковим номером
Розглянемо реалізацію наведених методів класу CAddInNative.
У демонстраційній ВК визначено 2 властивості: Включеноі Є Таймер (IsEnabledі IsTimerPresent).
У глобальній області видимості коду бібліотеки визначено два масиви:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Увімкнено", L"ЄТаймер");
які зберігають російську та англійську назви властивостей. У заголовному файлі AddInNative.hвизначається перерахування:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Always last);
ePropIsEnabledі ePropIsTimerPresentвідповідно мають значення 0 і 1 використовуються для заміни порядкових номерів властивостей на осмислені ідентифікатори. ePropLast, має значення 2, використовується отримання кількості властивостей (методом GetNProps). Ці імена використовуються лише всередині коду компоненти та недоступні ззовні.
Методи FindProp та GetPropName здійснюють пошук за масивами g_PropNamesі g_PropNamesRu.
Для зберігання значення полів у модулі бібліотеки у класу CAddInNative визначені властивості, які зберігають значення властивостей компонентів. Методи GetPropValі SetPropValвідповідно повертають та встановлюють значення цих властивостей.
Методи IsPropReadableі IsPropWritableі повертають trureабо false, залежно від переданого порядкового номера властивості відповідно до логіки програми.
Для того щоб додати довільну властивість необхідно:
- Додати ім'я властивості, що додається в масиви g_PropNamesі g_PropNamesRu(файл AddInNative.cpp)
- У перелік Props(файл AddInNative.h) перед ePropLastдодати ім'я, що однозначно ідентифікує властивість, що додається
- Організувати пам'ять під збереження значень властивостей (завести поля модуля компоненти, що зберігають відповідні значення)
- Внести зміни до методів GetPropValі SetPropValдля взаємодії з виділеною на попередньому кроці пам'яттю
- Відповідно до логіки програми внести зміни до методів IsPropReadableі IsPropWritable
Дамо назви тестовим властивостям Тесті ПеревіркаТипувідповідно. Тоді в результаті виконання пункту 1 маємо:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Увімкнено", L"ЄТаймер", L"Тест", L"ПеревіркаТипу");
Перелік Propsматиме вигляд:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Always last);
Для значного спрощення коду використовуватимемо STL C++. Зокрема, для роботи з рядками WCHAR, підключимо бібліотеку wstring.
Для збереження значення методу Тест, визначимо у класі CAddInNativeв області видимості private поле:
string test1;
Для передачі рядкових параметрів між «1С:Підприємство» та зовнішньою компонентою використовується менеджер пам'яті «1С:Підприємство». Розглянемо його роботу докладніше. Для виділення та звільнення пам'яті відповідно використовуються функції AllocMemoryі FreeMemory, визначені у файлі ImemoryManager.h. При необхідності передати системі «1С: Підприємство» рядковий параметр, зовнішня компонента має виділити під неї пам'ять викликом функції AllocMemory. Її прототип виглядає так:
virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0;
де pMemory- адресу вказівника, в який буде вміщено адресу виділеної ділянки пам'яті,
ulCountByte- Розмір ділянки пам'яті, що виділяється.
Приклад виділення пам'яті під рядок:
WCHAR_T * t1 = NULL, * test = L "TEST_STRING"; int iActualSize = wcslen(test1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, test1, iActualSize);
Для зручності роботи з рядковими типами даних опишемо функцію wstring_to_p. Вона отримує як параметр wstring-рядок. Результатом функції є заповнена структура tVariant. Код функції:
bool CAddInNative::wstring_to_p(std::wstring str, tVariant* val) ( char* t1; TV_VT(val) = VTYPE_PWSTR; m_iMemory->AllocMemory((void**)&t1, (str.length()+1) * sizeof(WCHAR_T));memcpy(t1, str.c_str(), (str.length()+1) * sizeof(WCHAR_T));val -> pstrVal = t1;val -> strLen = str.length(); return true;
Тоді відповідна секція case оператора switch методу GetPropValнабуде вигляду:
case ePropTest1: wstring_to_p(test1, pvarPropVal); break;
Методу SetPropVal:
case ePropTest1: if (TV_VT(varPropVal) != VTYPE_PWSTR) return false; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); break;
Для реалізації другої властивості визначимо поле класу CaddInNative
uint8_t last_type;
в якому зберігатимемо тип останнього переданого значення. Для цього до методу CaddInNative::SetPropVal додамо команду:
last_type = TV_VT(varPropVal);
Тепер при запиті читання значення другої властивості повертатимемо значення last_type, Що вимагає зазначене завдання.
Перевіримо працездатність змін.
Для цього наведемо зовнішній вигляд конфігурації 1С до вигляду:
перем ДемоКомп; Процедура ПриПочаткуРоботиСистеми() ПідключитиЗовнішнюКомпоненту("...", "DemoVK", ТипЗовнішньоїКомпоненти.Native); ДемоКомп = Новий ("AddIn.DemoVK.SomeName"); ДемоКомп.ПеревіркаТіпа = 1; Повідомити(Рядок(ДемоКомп.ПеревіркаТипу)); ДемоКомп.Тест = "Вася"; Повідомити(Рядок(ДемоКомп.Тест)); ДемоКомп.Тест = "Петя"; Повідомити(Рядок(ДемоКомп.Тест)); Повідомити(Рядок(ДемоКомп.ПеревіркаТипу)); КінецьПроцедури
В результаті запуску отримаємо послідовність повідомлень:
3
Вася
Петро
22
Друге та третє повідомлення є результатом читання властивості, встановленого на попередньому кроці. Перше та друге повідомлення містять код типу останньої встановленої властивості. 3 відповідає цілісному значенню, 22 - рядковому. Відповідність типів та їх кодів встановлюється у файлі types.h, що знаходиться на диску ІТС.
Розширення списку методів
Завдання:- Розширити функціонал зовнішньої компоненти наступним функціоналом:
- Вивчити способи реалізації методів зовнішньої компоненти
- Додати метод-функцію Функц1, яка як параметр приймає два рядки («Параметр1» та «Параметр2»). Як результат повертається рядок виду: «Перевірка. Параметр1, Параметр2»
- Переконатися у працездатності здійснених змін
Для визначення методів створюваної компоненти розробнику необхідно реалізувати такі методи у коді бібліотеки AddInNative:
GetNMethods, FindMethod, GetMethodName
Призначені для отримання відповідно до кількості методів, пошуку номера та імені методу. Аналогічні відповідним методам для властивостей
GetNParams
Повертає кількість параметрів методу із зазначеним порядковим номером; якщо метод із таким номером відсутній або не має параметрів, повертає 0
GetParamDefValue
Повертає значення за промовчанням вказаного параметра вказаного методу
HasRetVal
Повертає прапор наявності у методу із зазначеним порядковим номером значення, що повертається: true для методів із повертаним значенням і falseв іншому випадку
CallAsProc
false, виникає помилка часу виконання та виконання модуля 1С: Підприємства припиняється. Пам'ять для масиву параметрів виділяється та звільняється 1С: Підприємством.
CallAsFunc
Виконує метод із зазначеним порядковим номером. Якщо метод повертає false, виникає помилка часу виконання та виконання модуля 1С: Підприємства припиняється. Пам'ять для масиву властивостей виділяється 1С: Підприємством. Якщо значення, що повертається, має тип рядок або двійкові дані, компонента виділяє пам'ять функцією AllocMemoryменеджер пам'яті, записує туди дані і зберігає цю адресу у відповідному полі структури. 1С: Підприємство звільнить цю пам'ять викликом FreeMemory.
Повний опис методів, включаючи список параметрів, докладно описаний у документації, що поставляється на диску ІТС.
Розглянемо реалізацію описаних вище методів.
У коді компоненти визначені два масиви:
static wchar_t *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Включити", L"Вимкнути", L"ПоказатиВ рядкуСтатусу", L"СтартТаймер", L"СтопТаймер", L"ЗавантажитиМалюнок");
та перерахування:
enum Methods (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Always last);
Вони використовуються у функціях GetNMethods, FindMethodі GetMethodName, За аналогією з описом властивостей.
Методи GetNParams, GetParamDefValue, HasRetValреалізують switch, залежно від переданих параметрів та логіки програми повертають необхідне значення. Метод HasRetValу своєму коді має лише список методів, які можуть повертати результат. Для них він повертає true. Для всіх сталевих методів повертається false.
Методи CallAsProcі CallAsFuncмістять безпосередньо виконуваний код методу.
Для додавання методу, який може викликатися лише як функція, необхідно зробити наступні зміни у вихідному коді зовнішньої компоненти:
- Додати ім'я методу до масивів g_MethodNamesі g_MethodNamesRu(файл AddInNative.cpp)
- Додати осмислений ідентефікатор методу до переліку Methods (файл AddInNative.h)
- Внести зміни до коду функції GetNParamsвідповідно до логіки програми
- При необхідності внести зміни до коду методу GetParamDefValue, якщо потрібно використовувати значення за промовчанням параметрів методу.
- Внести зміни до функції HasRetVal
- Внести зміни до логіки роботи функцій CallAsProcабо CallAsFunc, помістивши туди код методу, що безпосередньо виконується.
static wchar_t *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Включити", L"Вимкнути", L"ПоказатиВ рядкуСтатусу", L"СтартТаймер", L"СтопТаймер", L"ЗавантажитиМалюнок", L"Тест");
Enum Methods (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Always last);
Відредагуємо функцію GetNPropsщоб вона повертала кількість параметрів методу «Тест»:
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( case eMethShowInStatusLine: return 1; case eMethLoadPicture: return 1; case eMethTest: return 2; default:)
Внесемо зміни до функції :
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) ( TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) howInStatusLine: case eMethStartTimer: case eMethStopTimer: case eMethTest: / / There are no parameter values by default break; default: return false;) return false;
Завдяки доданому рядку
case eMethTest:
у разі відсутності одного чи кількох аргументів відповідні параметри матимуть порожнє значення ( VTYPE_EMPTY). Якщо необхідно значення за промовчанням для параметра, слід задати його в секції eMethTestоператора switch функції CAddInNative::GetParamDefValue.
Оскільки метод «Тест» може повертати значення, необхідно внести зміни до коду функції HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( case eMethLoadPicture: case eMethTest: return true; default: return false; ) return false; )
І додамо виконуваний код методу у функцію CallAsFunc:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch(LoMethodNum) ( case eMeMe if (!lSizeArray || !paParams) return false; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstrVal; break;) return ret;
Скомпілюємо компоненту і наведемо код конфігурації до виду:
перем ДемоКомп; Процедура ПриПочаткуРоботиСистеми() ПідключитиЗовнішнюКомпоненту("...", "DemoVK", ТипЗовнішньоїКомпоненти.Native); ДемоКомп = Новий ("AddIn.DemoVK.SomeName"); пер = ДемоКомп.Тест ("Привіт,", "Світ!"); Повідомити(пер); КінецьПроцедури
Після запуску конфігурації отримаємо повідомлення: «Привіт, Світ!», що свідчить, що метод відпрацював успішно.
Таймер
Завдання:- Вивчити реалізацію таймера у демонстраційній ВК
- Модифікувати метод "СтартТаймер", додавши можливість передавати в параметрах інтервал спрацьовування таймера (у мілісекундах)
- Переконатися у працездатності здійснених змін
У WinAPI для роботи з часом можна скористатися повідомленням WM_TIMER. Це повідомлення надсилатиметься вашій програмі через інтервал часу, який ви поставите під час створення таймера.
Для створення таймера використовується функція SetTimer:
UINT SetTimer(HWND hWnd, // описувач вікна UINT nIDevent, // ідентифікатор (номер) таймера UINT nElapse, // затримка TIMERPROC lpTimerFunc); // покажчик на функцію
Операційна система надсилатиме повідомлення WM_TIMERу програму з інтервалом зазначеним у аргументі nElapse(У мілісекундах). В останньому параметрі можна вказати функцію, яка виконуватиметься при кожному спрацюванні таймера. Заголовок цієї функції має виглядати так (ім'я може бути будь-яким):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Розглянемо реалізацію таймера у демонстраційній ВК.
Так як ми розглядаємо процес розробки зовнішньої компоненти для ОС сімейства Windows, не розглядатимемо реалізацію таймера в інших операційних системах. Для ОС GNU/Linux, зокрема, реалізація буде відрізнятися синтаксисом функції SetTimerі TimerProc.
У виконуваному коді викликається метод SetTimer, до якого передається функція MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
Ідентефікатор створеного таймера міститься у змінну m_uiTimerщоб його можна було відключити.
Функція MyTimerProcвиглядає наступним чином:
VOID CALLBACK MyTimerProc(HWND hwnd, // handle of window for timer messages UINT uMsg, // WM_TIMER message UINT idEvent, // timer identifier DWORD dwTime // current system time) ( if (!pAsyncEvent) return; w "ComponentNative", *what = L"Timer"; wchar_t *wstime = new wchar_t; if (wstime) ( wmemset(wstime, 0, TIME_LEN); , what, wstime); delete wstime; ) )
Суть функції зводиться до того, що викликається метод ExternalEvent, що посилає повідомлення системі «1С: Підприємство».
Для розширення функціоналу методу СтартТаймерзробимо такі дії:
Модифікуємо код методу GetNParamsтак, щоб він для методу eMethStartTimerповертав значення 1:
case eMethStartTimer: return 1;
Наведемо код методу CallAsProcдо вигляду:
case eMethStartTimer: if (!lSizeArray || TV_VT(paParams) != VTYPE_I4 || TV_I4(paParams)<= 0) return false; pAsyncEvent = m_iConnect; #ifndef __linux__ m_uiTimer = ::SetTimer(NULL,0,TV_I4(paParams),(TIMERPROC)MyTimerProc); #else // код для GNU/Linux #endif break;
Тепер перевіримо працездатність. Для цього в модулі керованого додатка конфігурації напишемо код:
перем ДемоКомп; Процедура ПриПочаткуРоботиСистеми() ПідключитиЗовнішнюКомпоненту("...", "DemoVK", ТипЗовнішньоїКомпоненти.Native); ДемоКомп = Новий ("AddIn.DemoVK.SomeName"); ДемоКомп.СтартТаймер(2000); КінецьПроцедури
Після запуску конфігурації до програми надходитимуть повідомлення з інтервалом у 2 секунди, що говорить про коректну роботу таймера.
Взаємодія із системою «1С: Підприємство»
Для взаємодії між зовнішньою компонентою та системою «1С: Підприємство» використовуються методи класу IAddInDefBase, описаного у файлі AddInDefBase.h. Перерахуємо найчастіше використовувані:Генерація повідомлення про помилку
віртуальний bool ADDIN_API AddError(unsigned short wcode, const WCHAR_T* source, const WCHAR_T* descr, long scode)
wcode, scode- коди помилки (список кодів помилок з описом можна знайти на диску ІТС)
source- джерело помилки
descr- Опис помилки
Надсилання повідомлення системі «1С: Підприємство»
virtual bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource- Джерело повідомлення
wszMessage- Текст повідомлення
wszData- дані, що передаються
Перехоплення повідомлення здійснюється процедурою Обробка Зовнішньої Події
Реєстрація зовнішньої компоненти у системі «1С: Підприємство»
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfileName- Ім'я компоненти.
Цих методів достатньо повноцінного взаємодії ВК і 1С. Для отримання даних зовнішньою компонентою від системи «1С: Підприємство» та навпаки зовнішня компонента відправляє спеціальне повідомлення, яке у свою чергу перехоплюється системою «1С» і, при необхідності, викликає методи зовнішньої компоненти для зворотної передачі даних.
Тип даних tVariant
При обміні даними між зовнішньою компонентою та системою «1С: Підприємство» використовується тип даних tVariant. Він описаний у файлі types.h, який можна знайти на диску з ІТС:struct _tVariant ( _ANONYMOUS_UNION union ( int8_t i8Val; int16_t shortVal; int32_t lVal; int intVal; unsigned int uintVal; int64_t llVal; uint8_t ui8Val; uint8_t ui8Val; uint64_t ullVal; int32_t errCode; long hRes; float fltVal; double dblVal; bool bVal; char chVal; wchar_t wchVal; DATE date; IID IDVal; struct _tVariant *pvarVal; struct tm tmVal; strVal;uint32_t strLen ; //count of bytes ) __VARIANT_NAME_3/*str*/; _ANONYMOUS_STRUCT struct ( WCHAR_T* pwstrVal; uint32_t wstrLen; //count of symbol ) __VARIANT_NAME_4/*wstr*/; ) __VARIANT_NAME_1; uint32_t cbElements; //Dimension for an one- dimensional array in pvarVal TYPEVAR vt;);
Тип tVariantявляє собою структуру, яка включає себе:
- суміш (union), призначену безпосередньо для зберігання даних
- ідентифікатор типу даних
- Визначення типу даних, які на даний момент зберігаються у змінній
- Звертання до відповідного поля суміші, для безпосереднього доступу до даних
додаток
Каталог examples містить приклади до статтіexamples/1 - запуск демонстраційної компоненти
examples/2 - демонстрація розширення списку властивостей
examples/3 - демонстрація розширення списку методів
Кожен каталог містить проект VS 2008 та готову конфігурацію 1C.
Варіант синтаксису: На ім'я та місцезнаходження
Синтаксис:
Підключити Зовнішню Компоненту (<Местоположение>, <Имя>, <Тип>)
Параметри:
<Местоположение>(обов'язковий)
Тип: Рядок.
Розташування зовнішнього компонента.
Як місце розташування може використовуватися:
шлях до файлу зовнішнього компонента у файловій системі (недоступно на веб-клієнті), не ZIP-архів;
повне ім'я макета, що зберігає двійкові дані або ZIP-архів;
URL до зовнішнього компонента, у вигляді двійкових даних або ZIP-архіву, в , аналогічному ОтриматиНавігаційнеПосилання.
<Имя>(обов'язковий)
Тип: Рядок.
Символічне ім'я зовнішнього компонента, що підключається.
Ім'я має задовольняти правила іменування вбудованої мови.
<Тип>(Необов'язковий)
Тип: Тип Зовнішньої Компоненти.
Тип зовнішнього компонента, що підключається.
Не використовується, якщо компонент упакований у ZIP-архів.
Опис варіанта методу:
Підключає компоненти, виконані за технологією Native та COM.
Компонент може зберігатися в інформаційній базі або макеті конфігурації у вигляді двійкових даних або ZIP-архіві.
Для режимів запуску "Тонкий клієнт" та "Веб-клієнт" компонент повинен бути попередньо встановлений методом Встановити Зовнішню Компоненту.
Варіант синтаксису: За ідентифікатором
Синтаксис:
Підключити Зовнішню Компоненту (<ИдентификаторОбъекта>)
Параметри:
<ИдентификаторОбъекта>(обов'язковий)
Тип: Рядок.
Ідентифікатор об'єкта зовнішнього компонента як ProgID (Programmatic Identifier) реєстру MS Windows (наприклад: "AddIn.Scanner").
Повинна відповідати інформації, що у реєстраційної базі даних системи (Registry).
Опис варіанта методу:
Компонент має бути виконаний за технологією COM та зареєстрований у реєстрі MS Windows.
Ці компоненти сумісні з компонентами 1С:Підприємства 7.7.
Увага! Варіант методу не працює на сервері та у зовнішньому з'єднанні.
Значення, що повертається:
Тип: Бульово.
Істина – підключення пройшло успішно.
Опис:
Підключає зовнішній компонент до 1С:Підприємству.
Зовнішні компоненти можуть зберігатися в інформаційній базі або макетах конфігурації як ZIP-архів або у вигляді двійкових даних, а також у файлі файлової системи.
При роботі на тонкому клієнті та веб-клієнті компонент має бути попередньо встановлений.
Доступність:
Тонкий клієнт, веб-клієнт, сервер, зовнішнє з'єднання.
Примітка:
Зовнішні компоненти можуть бути виконані за технологією Native API чи COM. Компоненти, виконані за технологією COM, сумісні з компонентами 1С: Підприємства 7.7.
Веб-клієнт може працювати лише з компонентами в інформаційній базі, запакованими в архів.
Тонкий клієнт може працювати з компонентами в інформаційній базі, запакованими в архів, та компонентами, які розташовані у файловій системі.
Товстий клієнт може працювати з усіма варіантами зберігання компонентів. При цьому якщо компонент встановлений методом Встановити Зовнішню Компоненту, то використовується встановлений компонент, а якщо не встановлений, то компонент буде отриманий в момент підключення.
Сервер може працювати з усіма компонентами. Компонент кешується на сеанс роботи сервера.
Приклад:
Якщо Підключити ЗовнішнюКомпоненту("AddinObject.Scanner") Тоді
Повідомити("Компонента для сканера штрих-кодів завантажена");
Інакше
Повідомити("Компонента для сканера штрих-кодів не завантажена");
КінецьЯкщо;
Запитання: Зовнішня компонента Native Api на C++ під Linux (Ubuntu x64) на 1С 8.3
Пишу ВК, не можу підключити до 1с на ubuntu. Навіть екзапл від 1с не підключається. Тому питання щодо нього:
1) Намагаюся підключи ВК із прикладу VNCOMPS, наведеним у статті
(Посилання можна знайти в самому кінці: «Копіювання»).
Усередині проекту NativeApi є makefile. За його допомогою я збираю.so бібліотеку на Ununtu.
Але при "Підключити Зовнішню Компоненту" 1с вилітає.
Аналогічно, якщо збираю за допомогою build.sh (в корені проекту).
У самому makefile змінюю прапор з m32 на m64, т.к. 1с та сама система x64. (З параметром m32 не підчіплюється все одно)
Ось приклад виклику ВК із 1С 8.3:
ПідключенняВиконано = Підключити Зовнішню Компоненту("/home/alexeyubuntux64-20 gb/Документи/VNCOMP83/example/NativeAPI/AddInNative.so", "AddInNative", ТипЗовнішньоїКомпоненти.Native); Є статейка на цю тему.
Але, наскільки я бачу, всі ці моменти вже враховані виправили у прикладі VNCOMPS.
Але, по суті, справа в параметрах компіляції. Мб 32-бітна зовнішня компонента підчіпляється до 32-х бітної 1с нормально, але я розгорнув на Ubuntu x64 1c enterprise83 8.3.5-1486 amd64. І хочу до неї підчепити ВК.
Чи є у кого думки, як вирішити це питання?)
VNCOMPS-приклад повинен працювати, але походу треба виправити параметри складання, або сама платформа, на якій я тестую - некоректна.
Відповідь:Цікаво, а насправді можна зовнішню компоненту написати?
Питання: Не підключається зовнішній компонент (Native)
Скомпілював приклад з ІТС для 64 і 32 бітної системи.
Підключаю так:
Результат Підключення = Підключити Зовнішню Компоненту (Шлях КДЛЛ, "Comp", Тип Зовнішньої Компоненти. Native); На одному ПК підключення відбувається, на іншому немає. Є різниця в ос. Де підключення проходить, там стоїть Win7, де немає Win10. При цьому на ПК, де моя компонента не працює, працюють типові компоненти.
Тестував на різних платформах (8.3.4.482, 8.3.6.2100, 8.3.11.2700, 8.3.12.1412).
Як зрозуміти, чому не підключається?
Відповідь: vc_redist не забув?
Питання: 1С8 та зовнішня компонента з типом Native