Вывод пользовательских сообщений по ходу выполнения программы

Автор Тема: Вывод пользовательских сообщений по ходу выполнения программы  (Прочитано 8942 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн UraАвтор темы

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Здравствуйте

При запуске функции, пользователю необходимо выводить предупреждающее сообщение, что функция начала выполняться.
Например

Код - C++ [Выбрать]
  1. acutPrintf(_T("\n\rФункция выполняется. Пожалуйста подождите...\n\r"));

Затем, по ходу выполнения функции, необходимо выполнять вывод промежуточных значений.
В прошлых версиях AutoCAD это прекрасно отрабатывало и строки выводились в консоль AutoCAD.

Сейчас, в AutoCAD 2015 - AutoCAD 2016, эти строки выводятся только по завершении команды
Что необходимо сделать, чтобы строки выводились по ходу выполнения программы, а не в самом конце, когда программа завершена???

Перед началом выполнения функции необходимо уведомить пользователя, что функция начала выполняться.
Программа может выполняться достаточно долго.
Если не выводить никаких сообщений - пользователь будет думать, что программа висит.
Кроме этого вывод промежуточные результатов тоже важен.

Как это можно реализовать в AutoCAD2015 - AutoCAD2016?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А если убрать "\r" из твоей строки?
Хотя по хорошему нужно бы использовать для долгих операций ProgressBar.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Debalance

  • ADN Club
  • ****
  • Сообщений: 421
  • Карма: 16
    • Advanced software for AutoCAD
  • Skype: Debalance
Что необходимо сделать, чтобы строки выводились по ходу выполнения программы, а не в самом конце, когда программа завершена???
А может пойти другим путём, ну например, вывести кастомное диалоговое окошко в которое и вываливать всё необходимое: сообщения, прогрессбары и т.п.? Ведь в принципе командная строка стала вещью опциональной... её пользователь может вообще закрыть...

Оффлайн UraАвтор темы

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Цитировать
А если убрать "\r" из твоей строки?

Если убрать "\r" ничего не меняется - весь накопившейся, за время выполнения программы, текст выводится только после завершения команды.

Хотелось бы использовать Системное консольное меню AutoCAD а не создавать дополнительные окна.
Для каждой функции городить окно - нехорошо...

Создавать свое собственное диалоговое окно конечно решит проблему, но это неправильно.
Если мы делаем программу в среде AutoCAD, программа должна использовать ресурсы AutoCAD, а не создавать
дополнительные окна, которые фактически дублируют системные.

Раньше все работало без всяких проблем.
Может появились, для этой цели, другие функции или поможет изменение системных настроек?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Попробуй добавить вызов acedPrompt(L"");
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Вообще проблема связана с тем, что твоё приложение не даёт AutoCAD'у обработать свою очередь сообщений. Поэтому нужно каким-то образом дать ему такую возможность. Можешь попробовать воспользоваться следующей функцией:
Код - C++ [Выбрать]
  1. //////////////////////////////////////////////////////////////////////////
  2. // Эта функция при длительных вычислениях в lisp-функциях
  3. // позволяет AutoCAD обработать свою очередь сообщений (например, обновить
  4. // содержимое окна редактора, отреагировать на движения мыши и т.д.)
  5. //////////////////////////////////////////////////////////////////////////
  6.  
  7. int OnIdleAcadInternal(void) {
  8.   CWinApp *app = acedGetAcadWinApp();
  9.   // Это главное окно приложения AutoCAD
  10.   CWnd *wnd = app->GetMainWnd ();
  11.   // Создадим свой собственный диспетчерский цикл для обработки
  12.   // сообщений, переданных в AutoCAD. Если появились новые собщения -
  13.   // заставим AutoCAD их обработать.
  14.   MSG msg;  
  15.   // Выкачиваем сообщения из очереди сообщений AutoCAD
  16.   while (::PeekMessage(&msg, wnd->m_hWnd, 0, 0, PM_NOREMOVE))  {
  17.     // Если в очереди сообщений был запрос
  18.     // на завершение AutoCAD - выполним его.
  19.     if (!app->PumpMessage())  {
  20.       ::PostQuitMessage(0);
  21.       break;
  22.     }
  23.   }
  24.  
  25.   LONG lIdle = 0;
  26.   // Позволим MFC выполнить обработку состояния ожидания
  27.   //while (app->OnIdle(lIdle++)&& lIdle < 1000);
  28.   return RSRSLT;
  29. }

Вызов этой функции организуй после вызова acutPrintf, но не слишком часто - будет потеря производительности.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн UraАвтор темы

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Блокировался текст выводимый в самом начале программы, без циклов.
Эти же функции всегда правильно работали в AutoCAD2005-2012.


Похоже, что разработчики блокируют вывод на консоль и текст обновляется только
по завершении команды или при выполнении функции ввода пользовательских данных.



Добавил ваш код в программу - помогло. Спасибо.

Текст стал выводиться, правда несколько странно, но хорошо, что уже хоть так работает.

Попробовал добавить задержку после вывода текста, но перед функцией обработки сообщений - текст стал иногда выводиться.

Чтобы не ставить задержки в программе - вынужден был поставить функцию обработки очереди сообщений в цикле функции, где выполняются вычисления.
В большинстве случаев текст стал выводиться, но были случаи когда функция выполнялась порядка 40 сек., но текст выводился не всегда.
При этом функция OnIdleAcadInternal() выполнялась несколько тысяч раз.


Для проведения экспериментов добавил в самом начале программы следующий код

Код - C++ [Выбрать]
  1. for (int i=0; i < 900; i++) {
  2.         acutPrintf(_T("\n>>> Sleep = %i"), i*10);  //строка отображает пройденное время в миллисекундах
  3.         Sleep(10);                       //задержка 10 миллисекунд
  4.         OnIdleAcadInternal();
  5. }
  6.  

Выгрузил все лишние приложения, оставил только AutoCAD
При запуске функции - экран обновлялся в разное время
Ниже показан номер теста и время [миллисекунды], в которое выводился текст (первые 2 значения)
1) 270, 1110
2) 890, 1710
3) 880, 2100
4) 580, 1450

Поэтому выполнение функции OnIdleAcadInternal() сразу после вывода текста, без задержки,
отрабатывать не будет никогда, а если ставить задержку - то как повезет, текст может и не появиться.

Интересно почему при выполнении команд ввода пользовательских данных задержку вводить не требуется? При этом все сразу выводится.
Может имеется другой механизм обновления данных? Например функция вывода в консоль данных, которые где-то
накапливаются и ждут указания программы, об их обновлении?
По результатам теста видно - что данные уже выведены (выполнено несколько функций acutPrintf) , но в очередь сообщений данные еще не попали.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Интересно почему при выполнении команд ввода пользовательских данных задержку вводить не требуется? При этом все сразу выводится.
Потому что в этот момент:
1. Управление от твоей программы передаётся AutoCAD.
2. AutoCAD обрабатывает всю свою очередь сообщений перед тем как запросить ввод пользователя.
Короче говоря бросай возится с acutPrintf - идеала ты не добьешься. Делай так, как делает сам AutoCAD при длительных вычислениях - используй ProgressBar: http://adndevblog.typepad.com/autocad/2012/05/progress-and-cancellation-of-long-objectarx-tasks.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Debalance

  • ADN Club
  • ****
  • Сообщений: 421
  • Карма: 16
    • Advanced software for AutoCAD
  • Skype: Debalance
Если мы делаем программу в среде AutoCAD, программа должна использовать ресурсы AutoCAD, а не создавать
дополнительные окна, которые фактически дублируют системные.
Но это, безусловно, не догма. Возможно у этого варианта есть свои минусы. Но и плюсы тоже очевидны. Один из них самый и весомый это - окончательный уход от капризов разработчиков AutoCAD. Сами же видите, что идеология работы тех или иных контролов меняется от версии к версии, а это означает постоянное "приспосабливание" портируемого на новую версию AutoCAD Вашего исходного кода. Стоит ли игра свеч решать, конечно, Вам.

Оффлайн UraАвтор темы

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Короче говоря бросай возится с acutPrintf - идеала ты не добьешься. Делай так, как делает сам AutoCAD при длительных вычислениях - используй ProgressBar: http://adndevblog.typepad.com/autocad/2012/05/progress-and-cancellation-of-long-objectarx-tasks.html

Спасибо. Сейчас пока все работает, посмотрю немного позже.

Но это, безусловно, не догма. Возможно у этого варианта есть свои минусы. Но и плюсы тоже очевидны. Один из них самый и весомый это - окончательный уход от капризов разработчиков AutoCAD. Сами же видите, что идеология работы тех или иных контролов меняется от версии к версии, а это означает постоянное "приспосабливание" портируемого на новую версию AutoCAD Вашего исходного кода. Стоит ли игра свеч решать, конечно, Вам.

Да уж, пришлось с этим столкнуться. Даже стоял вопрос, чтобы вообще уйти от AutoCAD...
Мне еще повезло, что использую функции, не особо меняющиеся от версии к версии.
У меня один исходный текст программы, который компилируется для разных версий AutoCAD 2005-2012
Созданы только разные проекты для разных версий  Visual Studio.

Это сделано для упрощения поддержки программы.
Если разные исходные коды нужно править в разных местах и можно не везде поменять.

Меняющуюся часть определяю, для разных версий AutoCAD, в директивах компилятора.
Т.е. для одной версии использовался один кусок кода, для другой версии - другой.
Помогало до AutoCAd2012 включительно.
Но для  AutoCAD 2015-2016 это не получается сделать. Код сильно отличается...

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Но для  AutoCAD 2015-2016 это не получается сделать. Код сильно отличается...
Потому что он использует командные методы?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн UraАвтор темы

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Самая большая проблема была в изменении логики acedCommand с пользовательским вводом. Меняется много текста.
Директивами можно заменить часть кода, но если его много - потом сложно будет самому разобраться.
Поэтому решено сделать отдельные исходники для AutoCAD2015-2016
Надеюсь, что этот же код адаптирую и для 2017, но я пока не смотрел. Сначала этот нужно до конца доделать.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Самая большая проблема была в изменении логики acedCommand с пользовательским вводом. Меняется много текста.
Эх. Если бы сразу писал код без использования командных методов, то переход на AutoCAD 2015 перешёл бы безболезненно...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн UraАвтор темы

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Эх. Если бы сразу писал код без использования командных методов, то переход на AutoCAD 2015 перешёл бы безболезненно...

Вы имеете ввиду заменить на функции acedCmd? Или имеются другие возможности?

Я сначала заменил все функции acedCommand на acedCmd, везде, где это было возможно,
а уже потом начал переводить исходник для AutoCAD 2015-2016.
Да, код стал гораздо лучше переноситься. Но получилось не везде, часть команд осталось,
в которых необходим пользовательский ввод.

Уже в исходнике для AutoCAD 2015-2016 пришлось заменить acedCommandC на вставку объекта
и сразу после этого его перемещение с помощью AcEdJig
В прошлых версиях этого кажется не было.

Спасибо вам за помощь!!! Самому пришлось бы очень долго разбираться.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Вы имеете ввиду заменить на функции acedCmd? Или имеются другие возможности?
Я имел в виду не использовать готовые команды AutoCAD. Вот вместо команды вставки блока вы же воспользовались AcEdJig. Аналогично и в других моментах можно было бы поступить. Не так много есть мест, где нельзя заменить стандартную команду своим кодом, который будет работать не хуже, но зато гораздо более управляемый.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн UraАвтор темы

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
К сожалению - это вынужденная мера. Это показатель качества библиотеки.
Наверное это не совсем правильно, писать функции полностью повторяющие имеющимся в системе, но если без этого нельзя - то куда деваться, придется писать.

Программист должен пользоваться предлагаемой ему библиотекой.
В свою очередь в библиотеке должны присутствовать функции, которые нужны пользователю для работы. и только по особым случаям пользователем должны создаваться свои функции, которых нет в имеющейся библиотеке.
Кроме этого функции должны быть удобные в использовании.
Это если библиотека хорошая.

А сейчас получается, что все без исключения программисты создают свою дополнительную библиотеку, поскольку имеющейся пользоваться или сложно или невозможно...
Это неправильно, но это единственный реальный выход из положения.

В прочем это наверное не реализуемая мечта...
Разработчик делает функции для себя (а не для всех), как ему удобней и предоставляет библиотеку пользователю.
А пользователю уже остается пользоваться тем, что есть.

Это пожалуй касается API всех систем, а не только AutoCAD...
Как правило, все API достаточно сложные в использовании и не имеют 100 процентного доступа к данным.
Особенно это касается систем проектирования в 3D.
Немного приходилось писать для Pro/Engineer (Creo), есть с чем сравнивать...

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Вы путаете команды AutoCAD и API (SDK). Просто в AutoCAD одно и тоже можно получить разными способами. Командные методы (т.е. использование acedCommand и ему подобных функций) - это самый нижний уровень, который зависит от множества системных переменных и категорически не рекомендуется для использования. Только если не существует альтернативного API следует прибегать к этому методу.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение