Форум пользователей ПО АСКОН

Профессиональные вопросы => Программирование приложений => Delphi => Тема начата: SerGoVec от 22.03.16, 15:24:39

Название: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 22.03.16, 15:24:39
Всем привет!

Мне очень нужно сохранять документы компаса ТОЛЬКО в определенном, заданным программно, местоположении. При работе, пользователь компаса нажимает в меню "Сохранить" или "Сохранить как", показывается нестандартная форма (разработанная), где уже жестко задан путь (область) сохранения и от пользователя нужено лишь задать имя файла (наименование и обозначение - опционально).

Вот в чем проблема: Создаем документ, он (документ) существует лишь в памяти, пока не сохранил. При его сохранении (если документ сохраняется впервые, то отрабатывается событие - BeginSaveAsDocument (см. файл DocumentEvent - SDK\Pascal\Delphi\step12), через мою форму, документ физически сохраняется на диске компа, в заданном месте, НО при этом окно документа в компасе имеет заголовок - "Деталь БЕЗ ИМЕНИ"  (в случае m3d или a3d) и при нажатии в меню компаса "Сохранить" вызывается событие BeginSaveAsDocument (см. файл DocumentEvent - SDK\Pascal\Delphi\step12) вместо события BeginSaveDocument (см. файл DocumentEvent - SDK\Pascal\Delphi\step12), что говорит, что компас знать ничего не знает о ранее проведенном сохранении документа, для компаса данный документ как бы сохраняется впервые и поэтому идет вызов события "Сохранить как". (BeginSaveAsDocument).

Как побороть?

ps. Интересная особенность: в процессе отработки кода логики, написанной в событии BeginSaveAsDocument() , при исполнении строки KompasAPI.ActiveDocument.SaveAs( 'путь сохранения' ), где KompasAPI:IApplication  - заголовок окна документа соответствует имени  файла, вводимого пользователем в форму. Но после отработки события BeginSaveAsDocument(), заголовок окна документа меняется на "Деталь БЕЗ ИМЕНИ".

Код:

Логика в событии BeginSaveAsDocument (см. файл DocumentEvent - SDK\Pascal\Delphi\step12)

//kdBeginSaveAsDocument - Начало сохранения документа - показ диалога (save)компаса.
function DocumentEvent.BeginSaveAsDocument() : WORDBOOL;
var
  SaveCreatedDocumentDialog:  TSaveLocalCreatedDocumentDialog; //форма сохранения
  KompasAPI: IApplication; //Api7
  Kompas: KompasObject; //Api5
begin
  ////////////////проверка - есть ли в атрибуте документа путь к файлу
  GetNewKompasAPI();
  if KompasAPI <> nil then
  begin
    if KompasAPI.ActiveDocument.PathName = '' then
    begin
        //своя форма для сохранения вновь созданных документов
      Kompas := KompasObject(CreateKompasObject);
      Application.Handle := kompas.ksGetHWindow;
      Kompas.ksEnableTaskAccess(0);

      SaveCreatedDocumentDialog := TSaveLocalCreatedDocumentDialog.Create(Application);

      SaveCreatedDocumentDialog.ShowModal;
      FreeAndNil(SaveCreatedDocumentDialog);

      kompas.ksEnableTaskAccess(1);
      Application.Handle := 0;
      kompas := nil;

      Result := False;
    end
    else begin
      ...
      Result := True;
    end;
  end;
end;

форма сохранения (событие нажатие на кнопку сохранить)
procedure TSaveLocalCreatedDocumentDialog.btnSaveClick(Sender: TObject);
var
  docOriginal: KompasDocument;
begin
    //получение вводимого имени файла в форму
  saveFileName := labEditFileName.Text;

  GetNewKompasAPI();
  if KompasAPI <> nil then
  begin
      //GetExtendFileType - получение символьного обозначения типа документа по его цифровому коду
    saveFileName := Share_GetPathToWorkSpace() + saveFileName + '.' + GetExtendFileType(KompasAPI.ActiveDocument.Type_);

    if FileExists(saveFileName) then
      ShowMessage('Файл уже существует!') //...
    else begin
        // какой-то косяк в отображении имени файла сох.документа - без имени на каком-то этапе

      docOriginal := KompasAPI.ActiveDocument;
      docOriginal.SaveAs(saveFileName);

      Close;  //закрыть форму
    end;
  end;
end;

получение интерфейса компаса IApplication

procedure GetNewKompasAPI();
var
  disp: IDispatch;
begin
  if KompasAPI = nil then
  begin
    disp := IDispatch(CreateKompasApplication);
    KompasAPI := disp as IApplication;
  end
end;
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: Sabahs от 22.03.16, 15:41:55
Result := False; - фактически прерывает сохранение и Компас думает, что ничего не сохранял.
Попробуйте использовать вместо SaveAs, функцию Save.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 22.03.16, 16:03:14
но при создании документа (например детали) и последующем его сохранении вызывается событие BeginSaveAsDocument(). или вы имели в виду другое?
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: Sabahs от 22.03.16, 16:15:17
Суть Вашего Result := False; - скрыть стандартный диалог выбора имени файла, поэтому после Вам необходимо задать имя файла и сохранить через функцию Save, тут уже должно по идеи идти через kdBeginSaveDocument.
PS. Хотя если, Вы говорите, что файл по данному пути сохраняется, то можно закрыть файл без сохранения и открыть записанный по известному Вам пути.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 22.03.16, 17:11:44
Вариант ps =) не прокатил. Это первое, что я попролбыл еще до публикавания поста.

В форме дописал следующее:

procedure TSaveLocalCreatedDocumentDialog.btnSaveClick(Sender: TObject);
var
  docOriginal: KompasDocument;
begin
    //получение вводимого имени файла в форму
  saveFileName := labEditFileName.Text;

  GetNewKompasAPI();
  if KompasAPI <> nil then
  begin
      //GetExtendFileType - получение символьного обозначения типа документа по его цифровому коду
    saveFileName := Share_GetPathToWorkSpace() + saveFileName + '.' + GetExtendFileType(KompasAPI.ActiveDocument.Type_);

    if FileExists(saveFileName) then
      ShowMessage('Файл уже существует!') //...
    else begin
        // какой-то косяк в отображении имени файла сох.документа - без имени на каком-то этапе

      docOriginal := KompasAPI.ActiveDocument;
      docOriginal.SaveAs(saveFileName); //попадаем в событие компаса SaveDocument(), где Result := True //документ сохранен
     
     
      /////////////////////////////////////////////////////
      docOriginal.Close(kdDoNotSaveChanges);
      docOriginal := nil;

      KompasAPI.Documents.Open(saveFileName, True, False);
      ////////////////////////////////////////////////////

      Close;  //закрыть форму
    end;
  end;
end;

скопированный документ открывается в компасе, а дальше происходит ошибка -
тут я вообще ничего не понимаю, из-за чего и что это такое
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 22.03.16, 17:18:20
pss. заметил, что ошибка выскакивает как только исходный документ (тот который создал и сохранил) я закрываю, то есть

docOriginal.Close(kdDoNotSaveChanges);

также пробывал изврапщаться: скопированить еще не закрытый документ (создаваемый) под другим названием и открыть его до закпрытия (создаваемого документа). Те же яйца, только в профиль.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: Sabahs от 22.03.16, 17:25:18
Всё это лучше, делать после прохождения события, скорее всего пытается прорисовать то, чего уже нет, да и документ подписан на события, Вы его закрыли, но не отписали от событий.
Здесь в обработчике нужно установить только флаг, что нужно сохранить, а потом при следующем цикле простоя  выполнить docOriginal.SaveAs(saveFileName);.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 23.03.16, 17:03:18
м, что значит при следующем цикле простоя? - когда событие BeginSaveAsDocument() завершилось и следующее за ним событие или цикл (например  function LibCommandState(Command: Integer; var Enable: Integer; var Checked: Integer): Integer; stdcall; для отработки состояний кнопок иструментальной панели - здесь постоянно работает цикл (рантайим режим)), в нем?
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: Sabahs от 23.03.16, 17:07:01
Можно в нём, можно пользовательское событие передать, через PostMessage, дело хозяйское.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 24.03.16, 09:51:02
"можно пользовательское событие передать, через PostMessage", а можно простенький примерчик?)
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: Sabahs от 24.03.16, 10:06:10
https://books.google.com.ua/books?id=Abk7DaKvEcUC&pg=PA119&lpg=PA119&dq=своё+сообщение+PostMessage+делфи&source=bl&ots=HPR9caliSB&sig=0_XPqpwLacz_9p3GVi2_K4lvDGY&hl=ru&sa=X&ved=0ahUKEwjDqPjs39jLAhUB1hoKHRhiCq0Q6AEIVzAH#v=onepage&q=%D1%81%D0%B2%D0%BE%D1%91%20%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5%20PostMessage%20%D0%B4%D0%B5%D0%BB%D1%84%D0%B8&f=false (https://books.google.com.ua/books?id=Abk7DaKvEcUC&pg=PA119&lpg=PA119&dq=%D1%81%D0%B2%D0%BE%D1%91+%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5+PostMessage+%D0%B4%D0%B5%D0%BB%D1%84%D0%B8&source=bl&ots=HPR9caliSB&sig=0_XPqpwLacz_9p3GVi2_K4lvDGY&hl=ru&sa=X&ved=0ahUKEwjDqPjs39jLAhUB1hoKHRhiCq0Q6AEIVzAH#v=onepage&q=%D1%81%D0%B2%D0%BE%D1%91%20%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5%20PostMessage%20%D0%B4%D0%B5%D0%BB%D1%84%D0%B8&f=false)
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 24.03.16, 10:12:30
спасибо, буду разбираться.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 24.03.16, 17:36:45
Запутался. Поправте, где ошибка: в событии BeginSaveAsDocument(), как я понял нужно прописать postmessage, (например, PostMessage(Application.Handle, WM_SAVEDOC, 0, LParam(KompasAPI.ActiveDocument));) с тем рассчетом чтобы после отработки этого события ( BeginSaveAsDocument() ), с помощью postmessage перейти к обработке собственной процедуры (назовем ее procedure a, которая должна быть объявлена так - procedure a(var Msg: TMessage); message WM_SAVEDOC;, где WM_SAVEDOC это константа WM_SAVEDOC = WM_USER +1;). Ключевом здесь является директива message, которая будет указывать, что процедура (procedure a)  будет ловить сообщение WM_SAVEDOC от PostMessage.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 24.03.16, 17:59:42
форму сохранения пока не трогаю, использую абсолютный путь сохранения для теста

в объявлении:

const
  WM_SAVEDOC = WM_USER + 1;

DocumentEvent = class ( cBaseEvent, IDocumentFileNotify)
public
...
protected
...
   function BeginSaveDocument( fileName : PAnsiChar ) : WORDBOOL; virtual; stdcall;
..
  procedure a(var Msg: TMessage); message WM_SAVEDOC;
end;

реализация:

//kdBeginSaveAsDocument - Начало сохранения документа - показ диалога (save)компаса.
function DocumentEvent.BeginSaveAsDocument() : WORDBOOL;
var
  SaveCreatedDocumentDialog:  TSaveLocalCreatedDocumentDialog; //форма сохранения
  KompasAPI: IApplication; //Api7
  Kompas: KompasObject; //Api5
begin
  ////////////////проверка - есть ли в атрибуте документа путь к файлу
  GetNewKompasAPI();
  if KompasAPI <> nil then
  begin
    if KompasAPI.ActiveDocument.PathName = '' then
    begin
        //своя форма для сохранения вновь созданных документов
      Kompas := KompasObject(CreateKompasObject);
      Application.Handle := kompas.ksGetHWindow;
      Kompas.ksEnableTaskAccess(0);

      SaveCreatedDocumentDialog := TSaveLocalCreatedDocumentDialog.Create(Application);

      SaveCreatedDocumentDialog.ShowModal;
      ////////////////////////
        PostMessage(Application.Handle,
                                    WM_SAVEDOC, 0, LParam(KompasAPI.ActiveDocument));
      ////////////////////////
      FreeAndNil(SaveCreatedDocumentDialog);

      kompas.ksEnableTaskAccess(1);
      kompas := nil;

      Result := False;
    end
    else begin
      ...
      Result := True;
    end;
  end;
end;


procedure DocumentEvent.a(var Msg: TMessage);
begin
  KompasDocument(Msg.LParam).SaveAs('....testpost.m3d');
end;


результат ничего.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: Sabahs от 24.03.16, 18:32:55
Называется отослали письмо, куда - на деревню дедушке.
Судя по коду, у Вас AddIn библиотека, без формы?
PS. Можно, но класс нужно создавать от TWinControl.
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: Sabahs от 24.03.16, 20:33:39
Лучше один раз посмотреть, тут без WinApi, берём Step12 и немного - рихтуем.
Видео - exe, https://yadi.sk/d/RfHKDfrQqT5ar (https://yadi.sk/d/RfHKDfrQqT5ar)
Название: Re: Сохранение файлов (документов) в определенном местоположении.
Отправлено: SerGoVec от 25.03.16, 10:00:59
спасибо огромнешее!!!