Всем привет!
Мне очень нужно сохранять документы компаса ТОЛЬКО в определенном, заданным программно, местоположении. При работе, пользователь компаса нажимает в меню "Сохранить" или "Сохранить как", показывается нестандартная форма (разработанная), где уже жестко задан путь (область) сохранения и от пользователя нужено лишь задать имя файла (наименование и обозначение - опционально).
Вот в чем проблема: Создаем документ, он (документ) существует лишь в памяти, пока не сохранил. При его сохранении (если документ сохраняется впервые, то отрабатывается событие - 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.
но при создании документа (например детали) и последующем его сохранении вызывается событие BeginSaveAsDocument(). или вы имели в виду другое?
Суть Вашего Result := False; - скрыть стандартный диалог выбора имени файла, поэтому после Вам необходимо задать имя файла и сохранить через функцию Save, тут уже должно по идеи идти через kdBeginSaveDocument.
PS. Хотя если, Вы говорите, что файл по данному пути сохраняется, то можно закрыть файл без сохранения и открыть записанный по известному Вам пути.
Вариант 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;
скопированный документ открывается в компасе, а дальше происходит ошибка -
тут я вообще ничего не понимаю, из-за чего и что это такое
pss. заметил, что ошибка выскакивает как только исходный документ (тот который создал и сохранил) я закрываю, то есть
docOriginal.Close(kdDoNotSaveChanges);
также пробывал изврапщаться: скопированить еще не закрытый документ (создаваемый) под другим названием и открыть его до закпрытия (создаваемого документа). Те же яйца, только в профиль.
Всё это лучше, делать после прохождения события, скорее всего пытается прорисовать то, чего уже нет, да и документ подписан на события, Вы его закрыли, но не отписали от событий.
Здесь в обработчике нужно установить только флаг, что нужно сохранить, а потом при следующем цикле простоя выполнить docOriginal.SaveAs(saveFileName);.
м, что значит при следующем цикле простоя? - когда событие BeginSaveAsDocument() завершилось и следующее за ним событие или цикл (например function LibCommandState(Command: Integer; var Enable: Integer; var Checked: Integer): Integer; stdcall; для отработки состояний кнопок иструментальной панели - здесь постоянно работает цикл (рантайим режим)), в нем?
Можно в нём, можно пользовательское событие передать, через PostMessage, дело хозяйское.
"можно пользовательское событие передать, через PostMessage", а можно простенький примерчик?)
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)
спасибо, буду разбираться.
Запутался. Поправте, где ошибка: в событии 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.
форму сохранения пока не трогаю, использую абсолютный путь сохранения для теста
в объявлении:
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 (https://yadi.sk/d/RfHKDfrQqT5ar)
спасибо огромнешее!!!