19/12/2015
Чтение свойств чертежа (SummaryInfo) из внешнего приложения.
Вопрос:
Средствами ObjectARX и AutoCAD .NET API можно получить информацию о dwg-файле, которую записывает команда DWGPROPS. А можно ли прочитать эту информацию из внешнего C++ приложения без запуска AutoCAD?
Ответ:
Это возможно. Пример кода, который позволяет это сделать ниже:
Код - C++: [Выделить]
- //////////////////////////////////////////////////////////////////////////
- // Реализация чтения DwgProps для AutoCAD 2004...2016 (возможно и дальше,
- // если сохранится структура dwg-файла).
- //////////////////////////////////////////////////////////////////////////
- #include <io.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <malloc.h>
- #include <stdlib.h>
- #include <vector>
- #include <string>
- //
- // Имена стандартных свойств чертежа
- //
- const char *stdPropNames[] = {
- "title",
- "subject",
- "author",
- "keywords",
- "comments",
- "lastSavedBy",
- "revisionNumber",
- "hyperlinkBase"
- };
- class DwgProps
- {
- struct record {
- WORD len;
- union {
- char c[32767];
- wchar_t w[32767];
- };
- };
- public:
- DwgProps() {
- for (int i=0; i < sizeof(stdPropNames)/sizeof(stdPropNames[0]); i++) {
- m_stdProps.push_back("");
- }
- memset(bTotalEditingTime,0,sizeof(bTotalEditingTime));
- memset(bCreateDateTime,0,sizeof(bCreateDateTime));
- memset(bModifiedDateTime,0,sizeof(bModifiedDateTime));
- };
- ~DwgProps() {}
- // data items
- const char *title() const {return m_stdProps[0].c_str(); }
- const char *subject() const {return m_stdProps[1].c_str(); }
- const char *author() const {return m_stdProps[2].c_str(); }
- const char *keywords() const {return m_stdProps[3].c_str(); }
- const char *comments() const {return m_stdProps[4].c_str(); }
- const char *lastSavedBy() const {return m_stdProps[5].c_str(); }
- const char *revisionNumber() const {return m_stdProps[6].c_str(); }
- const char *hyperlinkBase() const {return m_stdProps[7].c_str(); }
- const char *customName(int idx) const {
- return ((idx >= 0 && idx < (int)m_custPropNames.size())?m_custPropNames[idx].c_str():0);
- }
- const char *customValue(int idx) const {
- return ((idx >= 0 && idx < (int)m_custPropValues.size())?m_custPropValues[idx].c_str():0);
- }
- const char *customValue(const char *name) const {
- for (int i=0; i < (int)m_custPropNames.size(); i++) {
- if (m_custPropNames[i] == name) return m_custPropValues[i].c_str();
- }
- return 0;
- }
- int customNumber() const { return (int) m_custPropNames.size(); }
- ULONG inDwg() { return ReadDiffDate(bTotalEditingTime); }
- SYSTEMTIME created() { return ReadDate(bCreateDateTime); }
- SYSTEMTIME updated() { return ReadDate(bModifiedDateTime); }
- const void DateToString(char *buf, SYSTEMTIME tm)
- {
- sprintf( buf,
- "%d-%02d-%02d %02d:%02d:%02d.%03d",
- tm.wYear, tm.wMonth, tm.wDay,
- tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds);
- }
- const void DiffDateToString(char *buf, ULONG tDiff)
- {
- int days = tDiff / (24*60*60*1000);
- tDiff -= days * (24*60*60*1000);
- int hours = tDiff / (60*60*1000);
- tDiff -= hours * (60*60*1000);
- int minutes = tDiff / (60*1000);
- tDiff -= minutes * (60*1000);
- int seconds = tDiff / 1000;
- tDiff -= seconds * (1000);
- int mseconds = tDiff;
- sprintf( buf,
- "Days:%d Hours:%d Minutes:%d Seconds:%d Milliseconds:%d",
- days, hours, minutes, seconds, mseconds);
- }
- int load(const char * fname)
- {
- bool unicode = false;
- int h;
- char buf[32767]; memset(buf,0,sizeof(buf));
- if ((h = _open(fname,_O_BINARY|_O_RDONLY)) == -1)
- return 0;
- char ACADVER[7];
- if (_read(h,ACADVER,sizeof(ACADVER)) <= 0) {
- _close(h); return 0;
- }
- if (atoi(ACADVER+2) < 1018) { // AutoCAD R14,2000...2002 обрабатывать не будем
- _close(h); return 0;
- }
- if (atoi(ACADVER+2) >= 1021) { // AutoCAD 2007... строки в Unicode
- unicode = true;
- }
- // Указатель перемещаем на WORD, содержащий смещение DwgProps
- if (_lseek(h,0x20,SEEK_SET) == -1) {
- _close(h); return 0;
- }
- // Считываем смещение DwgProps
- WORD offset_dwgprops = 0;
- if (_read(h,&offset_dwgprops,sizeof(offset_dwgprops)) <= 0) {
- _close(h); return 0;
- }
- long begin_offset = offset_dwgprops, cur_offset = offset_dwgprops;
- // Устанавливаем указатель на начало DwgProps
- if (_lseek(h,offset_dwgprops,SEEK_SET) == -1) {
- _close(h); return 0;
- }
- // Теперь можно читать длины и сами строки:
- record rec;
- for (int i=0; i < sizeof(stdPropNames)/sizeof(stdPropNames[0]); i++) {
- if (_read(h,&rec,sizeof(record)) == -1) {
- _close(h); return 0;
- }
- if (unicode) {
- WideCharToMultiByte(CP_ACP,0,rec.w,rec.len,buf,rec.len,0,NULL);
- m_stdProps[i] = buf;
- } else {
- m_stdProps[i] = rec.c;
- }
- cur_offset += (rec.len*((unicode)?2:1) + sizeof(rec.len));
- if (_lseek(h,cur_offset,SEEK_SET) == -1) {
- _close(h); return 0;
- }
- }
- if (_read(h,&bTotalEditingTime,sizeof(bTotalEditingTime)) == -1) {
- _close(h); return 0;
- }
- if (_read(h,&bCreateDateTime,sizeof(bCreateDateTime)) == -1) {
- _close(h); return 0;
- }
- if (_read(h,&bModifiedDateTime,sizeof(bModifiedDateTime)) == -1) {
- _close(h); return 0;
- }
- cur_offset += (sizeof(bTotalEditingTime)+ sizeof(bCreateDateTime) + sizeof(bModifiedDateTime));
- if (_lseek(h,cur_offset,SEEK_SET) == -1) {
- _close(h); return 0;
- }
- // Читаем количество собственных (custom) переменных
- WORD nCust = 0;
- if (_read(h,&nCust,sizeof(nCust)) <= 0) { _close(h); return 0; }
- cur_offset += sizeof(WORD);
- for (int i=0; i < nCust; i++) {
- // Считываем имя переменной
- if (_read(h,&rec,sizeof(record)) == -1) {_close(h); return 0;}
- if (unicode) {
- WideCharToMultiByte(CP_ACP,0,rec.w,rec.len,buf,rec.len,0,NULL);
- m_custPropNames.push_back(buf);
- } else {
- m_custPropNames.push_back(rec.c);
- }
- cur_offset += (rec.len*((unicode)?2:1) + sizeof(rec.len));
- if (_lseek(h,cur_offset,SEEK_SET) == -1) {
- _close(h); return 0;
- }
- if (_read(h,&rec,sizeof(record)) == -1) {_close(h); return 0;}
- if (unicode) {
- WideCharToMultiByte(CP_ACP,0,rec.w,rec.len,buf,rec.len,0,NULL);
- m_custPropValues.push_back(buf);
- } else {
- m_custPropValues.push_back(rec.c);
- }
- cur_offset += (rec.len*((unicode)?2:1) + sizeof(rec.len));
- if (_lseek(h,cur_offset,SEEK_SET) == -1) {_close(h); return 0;}
- }
- _close(h);
- return 1;
- }
- private:
- // data
- std::vector<std::string> m_stdProps;
- std::vector<std::string> m_custPropNames;
- std::vector<std::string> m_custPropValues;
- byte bTotalEditingTime[8];
- byte bCreateDateTime[8];
- byte bModifiedDateTime[8];
- SYSTEMTIME minDate, maxDate;
- //
- // Преобразование даты/времени из юлианского календаря
- //
- SYSTEMTIME FromJulian(ULONG days)
- {
- FILETIME fmin = {0, 0} , fmax = {0x7fffffff, 0xffffffff} ;
- FileTimeToSystemTime(&fmin, &minDate); FileTimeToSystemTime(&fmax, &maxDate);
- SYSTEMTIME s; memset(&s,0,sizeof(s));
- if (days < 0x1a4452) return minDate;
- if (days > 0x51fe2c) return maxDate;
- int j = days + 32044;
- int g = j / 146097;
- int dg = j % 146097;
- int c = (((dg / 36524) + 1) * 3) / 4;
- int dc = dg - (c * 36524);
- int b = dc / 1461;
- int db = dc % 1461;
- int a = (((db / 365) + 1) * 3) / 4;
- int da = db - (a * 365);
- int y = (((g * 400) + (c * 100)) + (b * 4)) + a;
- int m = (((da * 5) + 308) / 153) - 2;
- int d = (da - (((m + 4) * 153) / 5)) + 0x7a;
- int year = (y - 4800) + ((m + 2) / 12);
- int month = ((m + 2) % 12) + 1;
- int day = d + 1;
- s.wYear = year;
- s.wMonth = month;
- s.wDay = day;
- s.wHour = 2;
- s.wMinute = 0;
- s.wSecond = 0;
- s.wDayOfWeek = 0;
- s.wMilliseconds = 0;
- return s;
- }
- //
- // Добавление дробной части (миллисекунд)
- //
- SYSTEMTIME addMilliSecs(SYSTEMTIME s, double mseconds) {
- FILETIME f; SystemTimeToFileTime(&s, &f);
- ULARGE_INTEGER u;
- memcpy(&u, &f, sizeof(u));
- ULONGLONG mmsec = mseconds * 10000;
- u.QuadPart += mmsec;
- memcpy(&f, &u, sizeof(f));
- FileTimeToSystemTime(&f, &s);
- return s;
- }
- //
- // Чтение даты/времени
- //
- const SYSTEMTIME ReadDate(byte *src)
- {
- ULONG days = *((ULONG *)(src)); src += 4;
- ULONG fraction = *((ULONG *)(src)); src += 4;
- SYSTEMTIME tm = FromJulian(days);
- if (tm.wYear == maxDate.wYear)
- return tm;
- return addMilliSecs(tm,fraction);
- }
- //
- // Чтение интервала редактирования
- //
- const ULONG ReadDiffDate(byte* src)
- {
- ULONG days = *((ULONG *)(src)); src += 4;
- ULONG fraction = *((ULONG *)(src)); src += 4;
- ULONG diff = days * 24 * 60 * 60 * 1000 + fraction;
- return diff;
- }
- };
- ////-----------------------------------------
- //// Пример использования класса DwgProps
- ////-----------------------------------------
- //#include "stdafx.h"
- //#include <conio.h>
- //#include <stdio.h>
- //#include <string.h>
- //#include <wtypes.h>
- //#include <time.h>
- //#include "DwgProps.h"
- //
- //
- //const char * valid(const char *s)
- //{
- // return s ? s : "";
- //}
- //
- //void main(int argc, char *argv[])
- //{
- // DwgProps p;
- //
- // if ( argc < 2 )
- // {
- // fprintf(stderr, "Usage: dwgprops file [file ...]\n");
- // return;
- // }
- //
- // // loop over files
- // for ( int f = 1; f < argc; f++ )
- // {
- // printf("%s\n", argv[f]);
- //
- // if ( p.load(argv[f]) )
- // {
- // // print list of tags
- // printf(" Title: [%s]\n", valid(p.title()));
- // printf(" Subject: [%s]\n", valid(p.subject()));
- // printf(" Author: [%s]\n", valid(p.author()));
- // printf(" Comments: [%s]\n", valid(p.comments()));
- // printf(" Keywords: [%s]\n", valid(p.keywords()));
- // printf(" HyperlinkBase: [%s]\n", valid(p.hyperlinkBase()));
- // printf(" LastSavedBy: [%s]\n", valid(p.lastSavedBy()));
- // printf(" RevisionNo.: [%s]\n", valid(p.revisionNumber()));
- // char buffer[ 256 ];
- // p.DiffDateToString(buffer, p.inDwg());
- // printf(" Edit time: %s\n", buffer);
- // p.DateToString(buffer, p.created());
- // printf(" Created: [%s]\n", buffer);
- // p.DateToString(buffer, p.updated());
- // printf(" Updated: [%s]\n", buffer);
- // for ( int i = 0; i < p.customNumber(); i++ ) {
- // printf(" Custom Name[%d]: [%s]\n", i, valid(p.customName(i)));
- // printf(" Custom Value[%d]: [%s]\n", i, valid(p.customValue(i)));
- // }
- // }
- // }
- //}
Автор: Александр Ривилис
Отредактировано 19.12.2015 в 03:41:53
Обсуждение: http://adn-cis.org/forum/index.php?topic=3291
Опубликовано 19.12.2015Отредактировано 19.12.2015 в 03:41:53