Сохранение файлов (документов) в определенном местоположении.

Автор SerGoVec, 22.03.16, 15:24:39

« назад - далее »

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

SerGoVec

Всем привет!

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

Вот в чем проблема: Создаем документ, он (документ) существует лишь в памяти, пока не сохранил. При его сохранении (если документ сохраняется впервые, то отрабатывается событие - 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;

Result := False; - фактически прерывает сохранение и Компас думает, что ничего не сохранял.
Попробуйте использовать вместо SaveAs, функцию Save.

SerGoVec

но при создании документа (например детали) и последующем его сохранении вызывается событие BeginSaveAsDocument(). или вы имели в виду другое?

Суть Вашего Result := False; - скрыть стандартный диалог выбора имени файла, поэтому после Вам необходимо задать имя файла и сохранить через функцию Save, тут уже должно по идеи идти через kdBeginSaveDocument.
PS. Хотя если, Вы говорите, что файл по данному пути сохраняется, то можно закрыть файл без сохранения и открыть записанный по известному Вам пути.

SerGoVec

Вариант 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;

скопированный документ открывается в компасе, а дальше происходит ошибка -
тут я вообще ничего не понимаю, из-за чего и что это такое

SerGoVec

pss. заметил, что ошибка выскакивает как только исходный документ (тот который создал и сохранил) я закрываю, то есть

docOriginal.Close(kdDoNotSaveChanges);

также пробывал изврапщаться: скопированить еще не закрытый документ (создаваемый) под другим названием и открыть его до закпрытия (создаваемого документа). Те же яйца, только в профиль.

Всё это лучше, делать после прохождения события, скорее всего пытается прорисовать то, чего уже нет, да и документ подписан на события, Вы его закрыли, но не отписали от событий.
Здесь в обработчике нужно установить только флаг, что нужно сохранить, а потом при следующем цикле простоя  выполнить docOriginal.SaveAs(saveFileName);.

SerGoVec

м, что значит при следующем цикле простоя? - когда событие BeginSaveAsDocument() завершилось и следующее за ним событие или цикл (например  function LibCommandState(Command: Integer; var Enable: Integer; var Checked: Integer): Integer; stdcall; для отработки состояний кнопок иструментальной панели - здесь постоянно работает цикл (рантайим режим)), в нем?

Можно в нём, можно пользовательское событие передать, через PostMessage, дело хозяйское.

SerGoVec

"можно пользовательское событие передать, через PostMessage", а можно простенький примерчик?)



SerGoVec

Запутался. Поправте, где ошибка: в событии 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.

SerGoVec

форму сохранения пока не трогаю, использую абсолютный путь сохранения для теста

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

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;


результат ничего.

Называется отослали письмо, куда - на деревню дедушке.
Судя по коду, у Вас AddIn библиотека, без формы?
PS. Можно, но класс нужно создавать от TWinControl.

Лучше один раз посмотреть, тут без WinApi, берём Step12 и немного - рихтуем.
Видео - exe, https://yadi.sk/d/RfHKDfrQqT5ar
+ Благодарностей: 1