Тема: превью чертежа

В общем если не вдаваться в подробности, то ситуация такая.
есть DWG файлы с кучей значков, мне нада для конкретного значка из конкретного файла сделать иконку, потом создать кнопочку и т.д.
Ну во-первых, стандартная иконка блока никуда не годится, т.к. размер у нее 32х32, а нада больше, чтоб пользователь гарантированно не промазал и чтоб у него не было нервного срыва, когда он смотрит на кучу мелких кнопочек :)
Но сейчас не об этом. Сделал я сначала вариант 32х32. Посмотрел на картинку внимательно и заметил, что если у полилинии есть глобальная ширина, то на картинке блочка только контурная часть этой самой полилинии рисуется. Не понравилось :)
Еще есть вариант делать превью чертежа (ну вернее базы чертежа), и для этих целей нужна пустая база в которую я копирую свой блочек. исходник этого ниже.

/*pBlockDatabase - это AcDbDatabase, где лежит блок
pBlock - это запись в AcDbBlockTable
pOut - это создаваемая мной база для получения скриншота значка.
setBitmap() - вычленяем картинку из мусора, переданного акадом :). если кому будет интересно, кину исходник
*/
//... тут всякие разные инициализации и поиск нужного блочка
AcDbDatabase* pOut;
if (pBlockDatabase->wblock(pOut,pBlock->objectId())!=Acad::eOk)
{
  delete [] pBlockDatabase;
  return NULL;
}
if (acrxLoadApp(_T("AcadBlock")))
{
  HINSTANCE hInst;
  if ((hInst = LoadLibrary(_T("acblock.arx")))!=NULL)
  {
    MakePreviewFuncType makePreviewFunc;
    if ((makePreviewFunc = (MakePreviewFuncType)GetProcAddress(hInst,(LPCSTR)"acdbMakeDrawingPreview"))!=NULL)
    if (makePreviewFunc(pOut,false)==Acad::eOk)
      setBitmap((BYTE*)pOut->thumbnailBitmap());
                            
    FreeLibrary(hInst);
  }
  acrxUnloadModule(_T("acblock.arx"));
}
delete pOut;
//... y и так далее

Но как ни смешно, и в этом случае получается только контурная отрисовка полилиний с глобальной шириной. НО, если вставить

if (pOut->saveAs(_T("C:\\test.dwg"))==Acad::eOk){ ; }

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

Re: превью чертежа

Это обычная ситуация, когда чертеж не загружен в редактор AutoCAD. IMHO с этим ничего поделать нельзя, разве что грузить в редактор.

Re: превью чертежа

:( м-да, нехорошо получается.
просто я не создаю даже файл, а получаю картинку напрямую из БД чертежа.
а теперь прийдется найти куда можно сохранить, сохранить, тихонько открыть, сохранить, получить картинку и грохнуть файл. ладно, попробую выкрутиться.

Re: превью чертежа

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

Вот исходники. Может кто знает, что я делаю неправильно?
Кстати, может поможет, я заметил, что до первого выполнения функции с диалога переключиться в чертеж нельзя, а после него фокус переходит на окно чертежа, но курсор там не появляется.

void openDocHelper(void *pData)
{
   if (acDocManager->isApplicationContext())
   {
      Acad::ErrorStatus es = Acad::eOk;
      if (!acDocManager->isDocumentActivationEnabled())
         es = acDocManager->enableDocumentActivation();
      es = acDocManager->appContextOpenDocument((const ACHAR *)pData);
      es = acDocManager->curDocument()->dat abase()->saveAs((const ACHAR *)pData);        
      acDocManager->curDocument()->dat abase()->disableUndoRecording(Adesk::kTrue);
      es = acDocManager->closeDocument(acDocManager->curDocument());
      es = acDocManager->disableDocumentActivation();
   }
}

HBITMAP getBlockHBitmap(ACHAR *pBlockName, ACHAR *pFileName)
{
   Acad::ErrorStatus es=Acad::eOk;
   std::wstring tmpDWG_filename = _T("c:\testout.dwg");
   // ... тут заполнение pOut
   
     if( (es = pOut->saveAs(tmpDWG_filename.c_str()))!=Acad::eOk )
     {
       delete pOut;
       delete pBlockDatabase;
       return NULL;
     }
     delete pOut;
   }
   
   delete pBlockDatabase;
   AcApDocument* pDoc = acDocManager->curDocument();
   if (pDoc)
   { 
     // при повторном запуске в дебаге выпадает окно с текстом "Деактивируемый контекст активации не является активным для данного потока исполнения." и акад умирает.
     acDocManager->executeInApplicationContext(openDocHelper, (void *)tmpDWG_filename.c_str());
   }

   HPALETTE hPal;
   acdbGetPreviewBitmapFromDwg(tmpDWG_filename.c_str(), &m_Bitmap, &hPal);
   DeleteObject(hPal);
   ::DeleteFile(tmpDWG_filename.c_str()); 
   return m_Bitmap;
}

Re: превью чертежа

А это правильно: std::wstring tmpDWG_filename = _T("c:\testout.dwg"); ?
Про двойной бэкслеш не забыл?

Re: превью чертежа

это просто опечатка. на самом деле это переменная класса, а тут когда писал не заметил :(

Re: превью чертежа

У меня похожая ситуация: мне нужно создать превьюшки 3Д объектов в цвете.
Все объекты находятся в одном чертеже. У меня была идея устанавливать нужный вид и визуальный стиль и выводить изображение в файл командой saveImg, но она выводит весь экран, а мне нужно часть экрана с нужным объектом. Это можно легко сделать с помощью программ захвата экрана, но хочеться получить автоматический метод, т.к. объектов несколько тысяч.
(Я в моём посте "Вывод части окна Автокада в графический файл из ARX" попытался описать проблему, да видно плохо описал то что не нужно, т.к. никто не откликнулся...)

У меня была идея высчитать в ARX нужные экранные координаты рамки в Автокаде по объекту и вызывать стороннюю программу на Delphi, которая копирует часть образа экрана (если из ARX это сделать затруднительно).

Подскажите, так можно сделать, или нужно идти по другому пути?

(изменено: Александр Ривилис, 12 февраля 2010г. 09:38:04)

Re: превью чертежа

В интернете есть масса исходников на C++, которые позволяют сохранить часть экрана в графический файл. Например: http://www.daniweb.com/forums/thread189901.html или http://www.codeproject.com/KB/cpp/Scree … in32_.aspx Конечно все они требуют доводки, но...

Re: превью чертежа

Александр Ривилис,
Спасибо, что откликнулись.

Да, с выводом части экрана проблем нет, есть куча исходников и готовых компонент.
Мне непонятно как преобразовать в ARX габариты объекта в координаты рабочего стола windows:
1.объект->getBoundingBox
2.преобразовать полученные точки из getBoundingBox в экранные координаты видового экрана.
3.Найти эти точки в координатах рабочего стола (сдвинуть относительно угла видового экрана).

1,2 пункт я представляю как, а с 3-м у меня проблема :)

Re: превью чертежа

acedCoordFromWorldToPixel должна тебе помочь.

Re: превью чертежа

Александр Ривилис,
Спасибо, буду разбираться.