DWG превью

Автор Тема: DWG превью  (Прочитано 20550 раз)

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

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
DWG превью
« : 14-11-2013, 12:34:23 »
пользуюсь функцией
Код - C++ [Выбрать]
  1. Acad::ErrorStatus open_save_close(const ACHAR *DWGFileName)
  2. {
  3.         struct resbuf DWGMode;
  4.         int nRetVal = acedGetVar(_T("SDI"), &DWGMode);
  5.         if ( RTNORM != nRetVal) return Acad::eKeyNotFound;
  6.         if (DWGMode.resval.rint != 0)
  7.                 return Acad::eCantOpenFile;
  8.                        
  9.         Acad::ErrorStatus es = Acad::eOk;
  10.         CComPtr<AutoCAD::IAcadDocument> IDoc;
  11.                        
  12.         CComPtr<AutoCAD::IAcadApplication> IApp;
  13.         CComPtr<AutoCAD::IAcadDocuments> IDocs;
  14.         CComPtr<IDispatch> pDisp = acedGetAcadWinApp()->GetIDispatch(TRUE);
  15.         if(!pDisp) return Acad::eCantOpenFile;
  16.         HRESULT hr = pDisp->QueryInterface(AutoCAD::IID_IAcadApplication,(void**)&IApp);
  17.         if (FAILED(hr)) return Acad::eCantOpenFile;    
  18.  
  19.         hr = IApp->get_Documents(&IDocs);
  20.         if(FAILED(hr)) return Acad::eCantOpenFile;
  21.  
  22.         _variant_t b(VARIANT_FALSE);
  23.         hr = IDocs->Open(_bstr_t(DWGFileName),b,b,&IDoc);
  24.         if(FAILED(hr)) return Acad::eCantOpenFile;
  25.  
  26.         hr = IApp->ZoomExtents();
  27.         if(FAILED(hr)) return Acad::eCantOpenFile;
  28.  
  29.         VARIANT saveChanges, fileName;
  30.         saveChanges.vt = VT_BOOL;
  31.         saveChanges.boolVal = VARIANT_FALSE;
  32.         fileName.vt = VT_ERROR;
  33.         fileName.scode = DISP_E_PARAMNOTFOUND;
  34.         IDoc->Save();
  35.         IDoc->Close(saveChanges, fileName);
  36.         return Acad::eOk;
  37. }
чтоб заставить автокад сгенирироватьт превьюшку к чертежу по имени DWGFileName.
все было замечательно. функция работала с автокадами 2008-2014 (32\64bit). Но, появились 2 компьютера с установленными автокадами 2013 (32bit) на которых эта функция не генерирует превьюху.

последовательность работы такая. создается программно AcDbDatabase, в которую я добавляю объекты (отрезки, штриховки и т.д. это не суть важно). потом database сохраняется в файл. после этого отрабатывает функция  open_save_close и у dwg появляется картинка.

а на этих двух автокадах картинка не генерируется, хотя и происходит и открытие и зуммирование и сохранение чертежа. думал, дело в системной переменной, отвечающей за генерацию картинки (THUMBSAVE). нет. с ней все в порядке. значение = 1.
кстати, если результат сохранения database (программно созданный чертеж без превьюшки) открыть, прозуммировать и сохранить ВРУЧНУЮ (пользуясь командами автокада), то превьюха генерируется.
так вот вопрос, почему команда автокада SAVE делает превьюшку чертежа всегда, если системная переменная говорит ей, что делать превьюху надо, а IDoc->Save() делает это под настроение?
« Последнее редактирование: 15-11-2013, 02:17:27 от Александр Ривилис »

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DWG превью
« Ответ #1 : 15-11-2013, 02:34:40 »
Привет, Николай!
1. Я хотел бы уточнить уверен ли ты что в этой ситуации чертеж сохраняется?
2. Если сохраняется, то в той ли версии AutoCAD, что и на других PC?
3. Одинаковы ли значения ISAVEPERCENT на этих PC?
4. Экспериментировал ли ты с разными значениями THUMBSIZE?
В письме, которое ты мне направил, ты указал что обошёл эту ситуацию путём удаления ветки реестра в HKCU, что соответствует второй стадии установки AutoCAD.
Интересно всё-таки посмотреть на ветки реестров в "нормальной" и "ненормальной" ситуации. У тебя осталась возможность экспериментировать или теперь у тебя не осталось "полигона" для тестов?
 
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: DWG превью
« Ответ #2 : 15-11-2013, 16:16:15 »
1. уверен. когда чертеж создается программно, то объекты чертежа находятся за пределами видимости экрана. после функции open_save_close() происходит зуммирование и сохранение. т.е если открыть чертеж, просто программно созданный, то получим чистый экран и за пределами видимости экрана - объекты и превью у чертежа нет. если открыть чертеж после open_save_close(), объекты видны в рабочей части чертежа (был же зум). и на всех компьютерах, кроме двух проблемных у чертежа уже есть превью.
2. поддерживаем сейчас от 2010 вверх, так что всё сохраняетс в формате 2010 акада
3. да, везде стоят данные по умолчанию (50)
4. да, только результат тот же. по умолчанию стоит везде 3 (512x512)
5. ветки есть. http://yadi.sk/d/KAsIeKxSCjQiz

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DWG превью
« Ответ #3 : 15-11-2013, 16:40:12 »
Если восстановить "ненормальную" ветку реестра, то превью снова перестанет сохраняться?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: DWG превью
« Ответ #4 : 18-11-2013, 11:58:09 »
увы, после переустановки акада под текущего пользователя начинает работать и со старой (восстановленной) и с новой веткой реестра :(

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DWG превью
« Ответ #5 : 18-11-2013, 12:00:28 »
Тогда действительно увы... Так как воспроизвести баг не представляется возможным, то будем считать что его и нет...  ::)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: DWG превью
« Ответ #6 : 25-06-2015, 11:32:45 »
и снова вылезла эта проблема. правда теперь уже на моем компьютере ))), так что экспериментировать можно сколько угодно

проблема все-таки в странном поведении именно Save (просто нет превьюхи, хоть сохранение происходит нормально, т.к. после открытия чертежа объекты отзуммированы на всё окно)
Код - C++ [Выбрать]
  1. IDoc->Save();
возврат из неё идет S_OK, но превьюхи у чертежа нет.
а вот если вместо этой строки поставить
Код - C++ [Выбрать]
  1. CString strCommand = _T("_QSAVE\n");
  2. BSTR bstCommand = strCommand.AllocSysString();
  3. hr = IDoc->SendCommand(bstCommand);
  4. ::SysFreeString(bstCommand);
  5. if(FAILED(hr)) return Acad::eUnrecoverableErrors;
то превью у чертежа присутствует в той же самой ситуации (без изменения акадовских переменных, отвечающих за генерацию превью)
PS: Я так понимаю, что из здесь присутствующих ни у кого нет доступа к исходникам автокада), так что этот пост можно рассматривать в качестве "обходного маневра" для генерации превью у чертежа.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DWG превью
« Ответ #7 : 25-06-2015, 11:36:53 »
В порядке эксперимента. Попробуй IDoc->SaveAs()
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DWG превью
« Ответ #8 : 25-06-2015, 11:40:52 »
и снова вылезла эта проблема. правда теперь уже на моем компьютере ))), так что экспериментировать можно сколько угодно
Забыл уточнить - это происходит во всех поддерживаемых версиях AutoCAD?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: DWG превью
« Ответ #9 : 25-06-2015, 12:10:39 »
Цитировать
это происходит во всех поддерживаемых версиях AutoCAD?
было на разных компьютерах в 2010, 2012, 2014 и 2015. Так что думаю во всех версиях (даже не поддерживаемых) картина та же. кстати в 32bit и 64bit картина одинаковая. у меня сейчас 64bit.
Причем конкретно сейчас на 2014x64 у меня Save() не дает картинку, а в 2015 - все ок. Такое чувство, что где-то что-то разрегистрировалось для конкретного автокада ))) (переустановка профиля акада под текущим пользователем решит проблему на 100%, ну а там то как-раз и должны обновляться все регистрации)

Цитировать
Попробуй IDoc->SaveAs()
попробовал. картина та же что и в Save

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DWG превью
« Ответ #10 : 25-06-2015, 12:16:50 »
А открытие/сохранение через стандартные ObjectARX методы (AcDbDatabase::saveAs(...)) ?
Кстати, насколько я понимаю Thumbnail нормально сохраняется, если документ является активным и текущим, а AcDbDatabase - рабочей, т.е. переключится на неё не мешало бы перед сохранением. Запуск команды это переключение выполняет сам.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: DWG превью
« Ответ #11 : 25-06-2015, 12:57:40 »
Код - C++ [Выбрать]
  1. Acad::ErrorStatus open_save_close(const ACHAR *DWGFileName)
  2. {
  3.         struct resbuf DWGMode;
  4.         int nRetVal = acedGetVar(_T("SDI"), &DWGMode);
  5.         if ( RTNORM != nRetVal) return Acad::eKeyNotFound;
  6.         if (DWGMode.resval.rint != 0)
  7.         {
  8.                 // это вариант SDI. сразу не подходит
  9.                 return Acad::eCantOpenFile;
  10.         }
  11.                        
  12.         Acad::ErrorStatus es = Acad::eUnrecoverableErrors;
  13.         CComPtr<AutoCAD::IAcadDocument> IDoc;
  14.                        
  15.         CComPtr<AutoCAD::IAcadApplication> IApp;
  16.         CComPtr<AutoCAD::IAcadDocuments> IDocs;
  17.         CComPtr<IDispatch> pDisp = acedGetAcadWinApp()->GetIDispatch(TRUE);
  18.         if(!pDisp) return Acad::eCantOpenFile;
  19.  
  20.         // взять начальное значение THUMBSAVE (RASTERPREVIEW для ACAD2010-2012)
  21.         CString acadVarName = _T("THUMBSAVE");
  22.         #if defined(_MSC_VER) && (_MSC_VER == 1500) /* ACAD2010/2011/2012 */
  23.                 acadVarName = _T("RASTERPREVIEW");
  24.         #endif
  25.  
  26.         struct resbuf previewSaveBefore;
  27.         nRetVal = acedGetVar(acadVarName.GetString(), &previewSaveBefore);
  28.         if ( RTNORM != nRetVal) return Acad::eKeyNotFound;
  29.  
  30.         bool bChanged = false;
  31.         if (previewSaveBefore.resval.rint != 1)
  32.         {
  33.                 struct resbuf previewForceSave;
  34.                 previewForceSave.restype = RTSHORT;
  35.                 previewForceSave.resval.rint = 1;
  36.                 nRetVal = acedSetVar(acadVarName.GetString(), &previewForceSave);
  37.                 if ( RTNORM != nRetVal) return Acad::eKeyNotFound;
  38.                 bChanged = true;
  39.         }
  40.         HRESULT hr = pDisp->QueryInterface(AutoCAD::IID_IAcadApplication,(void**)&IApp);
  41.         if (SUCCEEDED(hr))
  42.         {
  43.                 hr = IApp->get_Documents(&IDocs);
  44.                 if(SUCCEEDED(hr))
  45.                 {
  46.                         _variant_t b(VARIANT_FALSE);
  47.                         hr = IDocs->Open(_bstr_t(DWGFileName),b,b,&IDoc);
  48.                         if(SUCCEEDED(hr))
  49.                         {
  50.                                 hr = IApp->ZoomExtents();
  51.                                 if(SUCCEEDED(hr))
  52.                                 {
  53.                                         //hr = IDoc->Save();
  54.                                         CString strCommand = _T("_QSAVE\n");
  55.                                         BSTR bstCommand = strCommand.AllocSysString();
  56.                                         hr = IDoc->SendCommand(bstCommand);
  57.                                         ::SysFreeString(bstCommand);
  58.                                         if(SUCCEEDED(hr))
  59.                                         {
  60.                                                 VARIANT saveChanges, fileName;
  61.                                                 saveChanges.vt = VT_BOOL;
  62.                                                 saveChanges.boolVal = VARIANT_FALSE;
  63.                                                 fileName.vt = VT_ERROR;
  64.                                                 fileName.scode = DISP_E_PARAMNOTFOUND;
  65.                                                 hr = IDoc->Close(saveChanges, fileName);
  66.                                                 if(SUCCEEDED(hr))
  67.                                                         es = Acad::eOk;
  68.                                         }
  69.                                 }
  70.                         }
  71.                 }
  72.         }
  73.  
  74.         if (bChanged) acedSetVar(acadVarName.GetString(), &previewSaveBefore);
  75.         return es;
  76. }
  77.  

вот собственно полная функция на сегодняшний день. в неё нужно просто передать полный путь к программно созданному dwg файлу, который уже "выгружен" из автокада.

т.к. программное сохранение  файла гарантирует, что картинку мы НЕ получим, отсюда такие танцы с бубном. банально, нужна превьюха чертежа.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Re: DWG превью
« Ответ #12 : 25-06-2015, 15:34:02 »
Понимаю, что влезаю не в свое дело, но вспомнил, что где то читал о подобном...
Вот, нашел ссылку https://sites.google.com/site/bushmansnetlaboratory/moi-zametki/screens  Только там на C#, но вдруг пригодиться как идея.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DWG превью
« Ответ #13 : 25-06-2015, 16:06:32 »
Это совсем из другой оперы. Здесь Николай Горлов добивается того, чтобы внутри dwg-файла появилась привьюшка, а Андрей сохраняет во внешний файл.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: DWG превью
« Ответ #14 : 30-06-2015, 12:16:32 »
Boxa.Shu, C# не знаю, да и если честно, смысла не вижу разбираться, слишком много заморочек при работе с автокадом.
если я правильно понял тот пример, то к автокаду он относится слабо. там что-то типа принтскрина только не на всё окно, а на указанную область.
раз уж на то пошло, то
Код - C++ [Выбрать]
  1. #include <atlimage.h>
  2. ...
  3. HBITMAP m_Bitmap;
  4. std::auto_ptr<AcGsScreenShot> autoScreenShot(acgsGetScreenShot(0));
  5. AcGsScreenShot* screenShot = autoScreenShot.get();
  6. if (screenShot)
  7. {
  8.         int colorDepth, mWidth, mHeight;
  9.         screenShot->getSize(mWidth, mHeight, colorDepth);
  10.  
  11.         CBitmap * retBitmap = new CBitmap;
  12.         if(!retBitmap->CreateBitmap(mWidth,mHeight,1,colorDepth,NULL))return;
  13.  
  14.         BYTE * destination = new BYTE[mWidth * mHeight * (int)(colorDepth/8.0)];
  15.         for(int x = 0; x < mWidth; x++)
  16.         {
  17.                 for(int y = 0; y < mHeight; y++)
  18.                 {
  19.                         if(screenShot->getScanline(x,y) != NULL)
  20.                                 CopyMemory((void*)(&destination[(y*mWidth + x) * (int)(colorDepth/8.0)]),screenShot->getScanline(x,y),(int)(colorDepth/8.0));
  21.                 }
  22.         }
  23.  
  24.         if(retBitmap->SetBitmapBits(mWidth * mHeight * (int)(colorDepth/8.0),destination) != 0)
  25.         {
  26.                 CImage image;
  27.                 image.Attach(retBitmap->operator HBITMAP());   
  28.                 image.Save(_T("c:\\tempBitmap.bmp"), Gdiplus::ImageFormatBMP);
  29.         }
  30.  
  31.         delete retBitmap;
  32.         delete[] destination;
  33. }
  34.  

вот этот кусок кода делает чистый снимок с видимой части текущего чертежа и сохраняет его в файл "c:\tempBitmap.bmp". Это на мой взгляд проще и лучше, т.к. не нужно клацать мышкой, не мешают всплывающие окна и т.п. (на вкус и цвет фломастеры разные ))) )

PS: по поводу того, чего я добиваюсь. зайду из далека. есть файл, в котором находится куча блоков (только blocktablerecord-ы и причем превьюшек на блоки нет, т.к. файл собирался в кучу программно). образно, на этот файл завязан комбобоксик, в котором перечислены имена блоков этого файла. и вот когда пользователь меняет текущую позицию комбика, ему нужно увидеть, с каким блоком он собирается делать махинации (по простому, нужна картинка приемлемого качества для текущего выбора).
Получить картинку можно несколькими способами (где-то писал, даже уроки делал, но это было давно, и сайтик уже помер):
1. взять из блоктэйблрекорда самого блока  - увы, паршивая картинка, да и нет её по умолчанию. а создавать ерунду смысла нет

2.
Код - C++ [Выбрать]
  1. Acad::ErrorStatus MakeThumbnail(AcDbDatabase* pDb)
  2. {
  3.         CString moduleName = _T("acblock.crx");
  4.         #if defined(_MSC_VER) && (_MSC_VER == 1500) /* ACAD2010/2011/2012 */
  5.                 moduleName = _T("acblock.arx");
  6.         #endif
  7.  
  8.         Acad::ErrorStatus es = Acad::eAmbiguousInput;
  9.         if (acrxLoadModule(moduleName, FALSE))
  10.         {
  11.                 HINSTANCE hInst;
  12.  
  13.                 if ((hInst = LoadLibrary(moduleName)) !=NULL)
  14.                 {
  15.                         MakePreviewFuncType makePreviewFunc;
  16.                         if ((makePreviewFunc = (MakePreviewFuncType)GetProcAddress(hInst,"acdbMakeDrawingPreview")) != NULL)
  17.                         {
  18.                            es = makePreviewFunc(pDb,false);
  19.                         }
  20.                         FreeLibrary(hInst);
  21.                 }
  22.                 acrxUnloadModule(moduleName);
  23.         }
  24.         return es;
  25. }
  26.  
Эта штука создает превьюшку в программно созданном (через AcDbDatabase::saveAs)и сохраненном на диске dwg файле. качество картинки просто ужаааааасное, типы линий, их толщина, иногда даже цвет объектов мягко говоря не соответствуют содержимиму файла. В качестве эксперимента, можешь попробовать воспользоваться функицей, чтоб понять о чем я. Хоть достоинством этой штуки можно считать её работу в SDI формате.

3. есть компонент для просмотра блоков разработанный в автодеске на базе CStatic (причем сами они им не пользуются, это только для нас) ))). я б сказал - на тобi боже, шо менi не гоже (перевод думаю не нужен ))) ). ну и с этим компонентом от версии к версии происходят преинтереснейшие глюки ))).

4 и 5. все дальнейшие варианты требуют, чтоб чертеж был загружен визуально и был текущим. а оставшихся вариантов то всего два. один из них в начале ЭТОГО поста, второй был 25-06-2015, 12:57:40 в этой теме.

Разница в 4 и 5 состоит в том, что "4" дает сразу картинку, которую нужно подогнать под размер, а в "5" картинка лежит в dwg и её приходится вытаскивать функцией acdbGetPreviewBitmapFromDwg.
Вот собственно и всё, что я нарыл, воспроизвел и большую часть похоронил из-за не удовлетворительных результатов. А ну, еще, эта вся штука должна работать от 2010 автокада вверх до текущей версии. И желательно так работать, чтоб в каждом новом автокаде не нужен был шаман с бубном ))). Увы, создать картинку приемлемого качества, не открывая файл визуально, на данный момент не возможно (а значит для меня не возможно в принципе, т.к. под отдельно взятый автокад код переписываться не будет).