23.07.2004, 05:58 | #1 |
Участник
|
Еще раз о подключении сканнера штрих кодов
Начало темы лежит на http://forum.mazzy.ru/index.php?showtopic=962
Очень похожая тема есть здесь http://www.axforum.info/forums/showt...EA%E0%ED%E5%F0 Но к сожалению ответа на главный вопрос "как отловить внешнее событие из другого процесса/потока в аксапте" никто не знает, создаётся впечатление что это невозможно сделать . Одно из реальных решений - опрашивать драйвер сканнера из самой аксапты по таймеру (напр. 1 сек) на предмет наличия новых данных (благо OPOS драйвер хорошо поддерживает такой подход). Видимо придется остановится на этом варианте, но хотелось бы еще подолбить эту тему, может появились уже свежие идеи. Есть еще одно решение - использовать сканнеры подключаемые в разьем клавиатуры. Необходимость в дровах и синхронизации с внешними событиями отпадает, но появляется новый вопрос: Как в аксапте удобным образом перехватить поступаемые со сканнера подключаемого в разьем клавиатуры данные? Опять же, как и в случае с COM драйвером я уже имею прекрасно работающее готовое решение в 1С - это "горячие клавиши". Я программирую сканнеры таким образом, чтобы они перед подачей самого сосканированного штрих-кода засылают в буфер клавиатуры код нажатия функциональной клавиши (в моём случае - F3), а в 1С в формах которые предполагают использование сканнера делаю невидимую кнопку, которой присваюваю hotkey F3. При нажатии на эту кнопку 1С открывает модальный диалог "введите штрих код". Поступившие из сканнера данные преспокойненько туда забиваются и последним символом поступает ENTER, который соответственно закрывает диалог и далее код в программе уже решает что делать с этим штрих-кодом. Т.о. где бы на форме не находился фокус ввода, сканирование штрих-кода приводит к корректному поступлению его в программу и автоматическому запуску самых разнообразных процедур. Столкнувшись с трудностью отлавливания внешнего события из Axapta я начал прорабатывать этот вариант и... столкнулся с опять же непреодолимой трудностью. Оказывается (судя из этого же форума) в Axapta практически нельзя назначить горячие клавиши кнопкам! Вариант с task не предлагать, ибо все task-и по функиональным клавишам нужны в самой Axapta. Вариант когда пользователь вынужден сперва спозиционироваться на нужное поле в форме и потом только сканировать тоже не пройдет вследствии своей жуткой неудобности. Есть ли у кого нибудь реальные наработки и решения в данной области? Что то я совсем перестал понимать как в самой Axapta разработчики предполагали подключать сканнеры (как COM, так и разьем с клавиатуры). Не верю что никто и никогда не подключал к Axapta сканнеры штрих-кодов. |
|
23.07.2004, 09:24 | #2 |
Участник
|
Я подключал через ActiveX. Обрабатываю события по таймеру. Работает без нареканий.
|
|
23.07.2004, 10:21 | #3 |
Модератор
|
Недавно на сайте у бывших "заклятых друзей" Компании "Атол" (http://www.atol.ru/ru/download/ Драйвер сканера шк) нашел фразу про совместимость с Axapta. Попробуйте их расспросить, как да что.
|
|
23.07.2004, 10:32 | #4 |
Злыдни
|
На мой взгляд, два наиболее оптимальных пути решения уже были детально разобраны на форуме:
1) через ActiveX. Наименее трудозатратный в плане разработки. В сочетании с SysFileDeployer дает неплохие результаты. Кстати, MSComm прекрасно отлавливает события - не совсем понимаю, при чем здесь таймер? Или имелась в виду задержка чтения (sleep())? 2) Работа с Com-портами из Аксы через API. Более детального ее описания, чем у George Nordic, найти сложно :-). Также обсуждение можно посмотреть на technet. Там, кстати, лежит ссылка на msdn, где описаны основные алгоритмы работы с COM на примере создания ActiveX, альтернативного MSComm. Принципиальных трудностей с реализацией также не вижу - у самого не хватило времени сделать такой механизм |
|
23.07.2004, 11:45 | #5 |
Участник
|
Спасибо всем за внимание, Я РЕШИЛ ПРОБЛЕМУ.
Счастья полные штаны. Перехватывать асинхронные события изве в Axapta - реально! Цитата:
SComm прекрасно отлавливает события - не совсем понимаю, при чем здесь таймер? Или имелась в виду задержка чтения (sleep())?
Цитата:
...Спасибо огромное за совет! Действительно я еще ломал голову как внедрить COM-объект в аксапту так чтобы и аксапта могла вызывать его методы, и объект мог вызывать события в ней - интеграция с ActiveX это решает.
Однако основная проблема всё равно остаётся открытой. Дело в том что обычные ActiveX контролы запускаются и целиком и полносью работают в рамках того же процесса и потока, в котором выполняется основная программа и поэтому никаких проблем не возникает - при возникновении Event-а метод его обработки работает как надо. Например, если я делаю ActiveX-control, который активирует внутри себя WinAPI-шный таймер (который выполняется в рамках очереди сообщений основного потока процесса), и в Event-е пишу print "Event" - всё работает замечательно - с периодичностью 1секунда в print window выводится эта строка. Тут же трудность состоит в том что объект драйвера выполняется в отдельном потоке и Event соответственно срабатывает в нём. А так как в это время сама аксапта может уже (и как правило так и происходит) заниматсься своими делами (реакцией на ввод, какие то внутренние циклы), то получается событие "вклинивается" в нормальный ход вещей совсем ненормальным образом. Например если я пишу в своём ActiveX контроле инициализацию thread-а, в котором периодически пытаюсь активировать Event - приложение рушится без лишних вопросов. Тут нужно сработать таким образом, чтобы активация событий была синхронизирована с работой основного кода аксапты. В 1С для этого специально был предусмотрен механизм внешних сообщений, вот я и подумал - а нет ли такого в аксапте тоже? Может можно хотя бы в основной поток GetMessage/DispatchMessage ложить свои сообщения? ИТАК, данную проблему можно прекрасно разрешить если вспомнить про т.н. "apartment model". Если кого то интересует могу поподробнее объяснить. |
|
23.07.2004, 11:49 | #6 |
Участник
|
конечно же интересует
с нетерпением ждем объяснений. |
|
23.07.2004, 11:59 | #7 |
Злыдни
|
Туплю, наверное.... Большинство ActiveX для работы с портами так и делают - создают отдельный поток и через APIшную функцию WaitCommEvent() обрабатывают прерывания от порта, генерируя СВОЕ событие. А ты уж его обрабатывай из Аксапта как хочешь... Зачем таймер-то?
Про apartment model - плиз, плиз. Очень интересно |
|
23.07.2004, 12:22 | #8 |
Участник
|
Позвольте спросить, как в Аксапте обработать событие от СОМ сервера? Дайте ссылочку плз на пример кода на X++.
А про apartment threading model скорее всего имеется ввиду это |
|
23.07.2004, 12:26 | #9 |
Участник
|
Упс... похоже я поторопился... Хотя и приложение перестало рушится в случае если событие вызывается когда аксапта крутится в цикле GetMessage/DispatchMessage и даже регулярно обновляется окно infolog, если в обработке события писать info( "...." ), но если событие случается в момент обновления таблиц или другой какой нибудь активности, всё подвисает странным образом...
В общем любой кто когда нибудь создавал проекты ActiveX-control-ов (да и вообще COM-объектов) в средах программирования (VC++ / C++Buidler / Delphi) с первых же шагов стандарных Wizard-ов имеет возможность выбрать так называемую Threading model (можно перевести как "модель управления многопоточностью") - по умолчанию данная опция обычно стоит в Apartment режиме из 4 возможных: Single, Apartment, Free, Both. Обычно с многопоточностью программисты разбираются сами и игнорируют этот параметр (многие даже не знают что это такое). Инфраструктура COM-объектов обеспечивает то, что для объектов с моделью многопоточности SINGLE, вызов их методов (invocation) произойдет в основном потоке программы, даже если они были вызваны из другого потока, ЧТО МНЕ И ТРЕБОВАЛОСЬ. Насколько я понимаю Windows просто складывает вызовы методов таких объектов с главную очередь сообщений программы и по в ProcessMessage вызывает их. По идее это должно было сработать, но сработало как то наполовину... сейчас еще покопаю в этом направлени... |
|
23.07.2004, 12:34 | #10 |
Участник
|
Цитата:
А ты уж его обрабатывай из Аксапта как хочешь...
Цитата:
Зачем таймер-то?
|
|
23.07.2004, 12:49 | #11 |
Злыдни
|
2 Alks
Так, давайте определимся, что мы обсуждаем: 1) Работу с COM-портами из Аксапта или 2) Создание АктивИкса, который может работать с портами |
|
23.07.2004, 13:08 | #12 |
Участник
|
О йес... Я добил его... Просто неправильно работал с SINGLE threading model - не передавал интерфейсы между потоками через ф-ии CoMarshalInterThreadInterfaceInStream и CoGetInterfaceAndReleaseStream. Теперь всё работает. Если кого то интересует - могу выложить исходные коды этого ActiveX-контрола на Delphi куда пожелаете.
P.S. Кстати саму threading model как оказалось менять вовсе и не обязательно - главное самому насильно принудить программу работать в single режиме вызовом вышеупомянутых функций. |
|
23.07.2004, 13:16 | #13 |
Участник
|
Цитата:
2 Alks
Так, давайте определимся, что мы обсуждаем: 1) Работу с COM-портами из Аксапта или Цитата:
2) Создание АктивИкса, который может работать с портами
|
|
23.07.2004, 13:27 | #14 |
Злыдни
|
Да понял, понял, не ругайся так
Супер, что получилось. Я все-таки хочу попробовать научить Аксапту работать с комами напрямую. |
|
23.07.2004, 13:35 | #15 |
Участник
|
2 Yprit
Цитата:
Да понял, понял, не ругайся так
Супер, что получилось. Я все-таки хочу попробовать научить Аксапту работать с комами напрямую. 2 Diman Цитата:
Позвольте спросить, как в Аксапте обработать событие от СОМ сервера? Дайте ссылочку плз на пример кода на X++.
|
|
23.07.2004, 13:44 | #16 |
Модератор
|
Цитата:
Изначально опубликовано Alks
Если кого то интересует - могу выложить исходные коды этого ActiveX-контрола на Delphi куда пожелаете. 2 Yprit: Вряд ли получиться... я бы не рекомендовал эксперементировать. |
|
23.07.2004, 13:49 | #17 |
Участник
|
Выложу завтра, с комментариями. Сегодня уже раб. день закончился, выгоняют.
|
|
23.07.2004, 13:50 | #18 |
Злыдни
|
Цитата:
Да и разве можно в X++ реализовать многопоточность, которая желательна для работы с COM-портом в такой манере?
А зачем - по нескольким причинам. Во-первых, мне не кажется оптимальным шлепать на все формы, где мне понадобится читать из/писать в Ком-порт, АктивХ. Субъективное ИМХО - не красиво это.... Во-вторых, у меня не для всех клиентов почему-то срабатывает скачивание файлов с сервера и регистрация этого АктивХ-а на клиенте через SysFileDeployer(). Причем никакой закономерности поймать пока не могу - а ручками копировать и регистрить лень... В-третьих, мне просто интересно |
|
23.07.2004, 13:53 | #19 |
Участник
|
2 Alks
Немного переформулирую вопрос: Как подключить COM сервер в Axapta и использовать его source интерфейс? Код обработчика события на X++ я не нашел. |
|
24.07.2004, 14:57 | #20 |
Участник
|
Короче намучился я с этой хренью вдоволь, и решил что лучше не морочить себе голову и делать через таймер.
Привожу исходный код двух основных модулей моего ActiveX-а, который запускает поток из которого совершенно безопасно генерируется событие для Axapta. Казалось бы всё пучком, но возникли две непреодолимые для меня сейчас проблемы: 1. создание и передача "safe" указателя на интерфейс IAxBarScanner драйверу сканнера (который разумеется сам не делает CoGetInterfaceAndReleaseStream, а если пытаться сделать его в основном потоке программы сразу после CoMarshalInterThreadInterfaceInStream, то черезчур умная ф-я возвращает прямой указатель, а не маршализированный). 2. вследствии непонятной мешанины с AddRef/Relese ActiveX застревает в памяти (откуда то берутся целых 5 ссылок на него и он не уничтожается как должен был бы), в результате объекты плодятся безконтрольно и ахапта при выходе остаётся в списке задач Думаю что всё это вопросы разрешимые, но заниматься ими уже надоело, да и сроки поджимают, времени распылятся по мелочам, когда менее элегантное решение всё таки существует нет. PHP код:
PHP код:
|
|
|
Похожие темы | ||||
Тема | Ответов | |||
«Обрезание» длинных штрих-кодов | 7 | |||
Подвисает сканер штрих-кодов | 0 | |||
AX 4.0 + сканеры штрих кодов | 11 | |||
Еще раз про сканеры штрих кодов | 14 | |||
Нужен совет по сканеру штрих-кодов | 5 |
|