Тема: Закрытие DXF-файла без запроса на сохранение.

Проблема следующая:
При закрытии DXF-файла AutoCAD выдает сообщение

"Файл ххх.dxf был сохранен в формате dxf-2000. Сохранить его в текущем формате AutoCAD?".

Т.е. AutoCAD хочет сохранить чертеж в DWG-формат.
Если создается DWG-файл все закрывается без вопросов, даже если в формате DWG-2000 сохранять.
А вот с DXF ни в какую.
Перепробовал разные варианты, которые нашел на форуме, но увы, все напрасно. Не могу найти место, где выходит запрос.
Как писал Леонид в форуме:
https://www.caduser.ru/forum/topic17005.html

Перехватить MessageBox удалось только на сообщении WM_SYSCOMMAND

А как это сделать для AutoCAD, подскажите, пожалуйста. Может этот вариант и сработает.
Заранее спасибо!

Re: Закрытие DXF-файла без запроса на сохранение.

> Serghei
А может его просто самому пересохранить в dwg и вопросов не будет?

Re: Закрытие DXF-файла без запроса на сохранение.

> Александр Ривилис
Хотелось бы пощупать перехватчик событий, например WM_SYSCOMMAND.
Как это можно сделать?

Re: Закрытие DXF-файла без запроса на сохранение.

> Александр Ривилис
Объясню причину.
У меня работает таймер, который выполняет некоторые действия в чертеже и сохраняет его по указанию в DXF или DWG. Если обрабатывается отдельно чертеж, то сохраняется без вопросов, как ты рекомендовал, дополнительно в DWG. Но, если начинается пакетная обработка, то тут причуды и начинаются. Поэтому мне и надо найти, где это все происходит.

Re: Закрытие DXF-файла без запроса на сохранение.

Посмотри функцию acedRegisterFilterWinMsg(), хотя я не уверен, что в ее calback-функцию попадает WM_SYSCOMMAND.
Еще вариант: ::SetWindowLongPtr(...,GWL_WNDPROC,...);

Re: Закрытие DXF-файла без запроса на сохранение.

> Александр Ривилис
Александр, спасибо за помощь.
Ты был прав WM_SYSCOMMAND не попадает в acedRegisterFilterWinMsg(), точнее в ее calback-функцию.
А можно поподробней о SetWindowLongPtr.
Спасибо.

Re: Закрытие DXF-файла без запроса на сохранение.

Привет всем!
Много времени прошло, хорошо что сохранился проект :)
Правда точно не помню, но кажись все работало
Для начала в реакторе я находил окошко документа по заголовку  pDocCreating->docTitle()

void DocReactor::documentCreated(AcApDocument * pDocCreating)
{
    // ищем окошко документа
    HWND wnd0 = adsw_acadMainWnd();
    HWND wnd1 = FindWindowEx(wnd0, NULL, "MDIClient", NULL);
    HWND wnd = FindWindowEx(wnd1, NULL, NULL, pDocCreating->docTitle());
    // оконная процедура !!!!!!!!!!!!!!!!
    WNDPROC wpProc = NULL;
    //==============================================================
    wpProc = (WNDPROC) SetWindowLong(wnd, GWL_WNDPROC, (LONG) EditSubclassProc);
    //==============================================================
    AcApDocManagerReactor::documentCreated (pDocCreating);
}

и в оконной процедуре делал свое черное дело

LRESULT APIENTRY EditSubclassProc(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam)
{
    // ищем индекс окна
    int intIndex = 0;
    bool bFound = false;
    for (intIndex; intIndex < vDocWnds.size(); intIndex++)
    {
        if (vDocWnds.at(intIndex) == hwnd)
        {
            bFound = true;
            break;
        }
    }
    // адреса процедур храню в массиве
    WNDPROC wp = vDocProcs.at(intIndex);
    switch(uMsg)
    {
        case WM_SYSCOMMAND:
            {
                if (wParam == 61536) // закрытие
                {
                    AcDbDatabase* db = vDocs.at(intIndex)->database();
                    long res = acdbSetDbmod(db, 0);
                }
                break;
            }
        case WM_DESTROY:
            {
                // возвращаем адрес окошку обратно
                SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wp);
                break;
            }
        default:
        ;
    }
    return CallWindowProc(wp, hwnd, uMsg, wParam, lParam);
}

Re: Закрытие DXF-файла без запроса на сохранение.

> Serghei

> Леонид
Я немного подумал над этим вопросом. Код предложенный Леонидом в данном случае не поможет, т.к. независимо от состояния DBMOD (т.е. от того модифицирован или нет чертеж) запрос на сохранение все равно появится. Поэтому нужно пойти другим путем. В момент, перед тем когда сообщение (MessageBox) должно появится, нужно перенаправить вызов MessageBox на свою функцию. Приблизительно так: http://rsdn.ru/article/baseserv/IntercetionAPI.xml Можно даже проанализировать тот ли вопрос задается, и если тот то вернуть код возврата, IDNO (если мне не изменяет память), а если нет передать управление в в исходную функцию.

Re: Закрытие DXF-файла без запроса на сохранение.

Мужики, еще раз вам огромное спасибо!
Буду пробовать оба варианта.
Немного дольше займет времени, зато наберусь еще опыта.

Re: Закрытие DXF-файла без запроса на сохранение.

Тогда на закуску тебе еще и третий вариант с SetWindowsHookEx (). Примеры ищи в гугле.

Re: Закрытие DXF-файла без запроса на сохранение.

Выдалась свободная минутка:

HHOOK hMsgBoxHook = NULL;
bool flag_dxf = false;
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
  TCHAR ach[40];
  HWND hwnd;
  HWND hwndButton;
  if(nCode < 0)
    return CallNextHookEx(hMsgBoxHook, nCode, wParam, lParam);
  switch(nCode)
  {
  case HCBT_CREATEWND:
    {
      // Get handle to the message box!
      hwnd = (HWND)wParam;
      CBT_CREATEWND *lstr = (CBT_CREATEWND *)lParam;
      if (lParam && lstr->lpcs->lpszName) {
        // Устанавливаем флаг если в тексте сообщения встречается DXF и 2000
        if (strstr(lstr->lpcs->lpszName,"2000") && strstr(lstr->lpcs->lpszName,"DXF"))
          flag_dxf = true; else flag_dxf = false;
      }
      break;
    }
    case HCBT_ACTIVATE:
      {
        // Get handle to the message box!
        hwnd = (HWND)wParam;
        hwndButton = GetDlgItem(hwnd, IDNO);
        if (hwndButton && flag_dxf) {
          SendMessage(hwndButton,WM_LBUTTONDOWN,0,0);
          SendMessage(hwndButton,WM_LBUTTONUP,0,0);
          flag_dxf = false;
        }
      }
  }
  return CallNextHookEx(hMsgBoxHook, nCode, wParam, lParam);
}
class CArxProjectApp : public AcRxArxApp {
public:
  CArxProjectApp () : AcRxArxApp () {}
  virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
    AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
    // Устанавливаем хук
    hMsgBoxHook = ::SetWindowsHookEx(WH_CBT,CBTProc,NULL,GetCurrentThreadId());
    return (retCode) ;
  }
  virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
    // Снимаем хук
    UnhookWindowsHookEx(hMsgBoxHook);
    return (retCode) ;
  }
  virtual void RegisterServerComponents () {
  }
}

В двух словах: если появляется сообщение о сохранении в формате DXF 2000 то автоматом нажимается кнопка Нет (No).