Форум: "Основная";
Текущий архив: 2006.08.27;
Скачать: [xml.tar.bz2];
ВнизКак узнать что пользователь только-что закрыл AutoCAD Найти похожие ветки
← →
Calibr2 (2006-07-11 06:37) [0]У меня проблема в том, что нужно отловить момент, когда пользователь закроет приложение AutoCAD. Приложение AutoCAD у меня хранится в переменной типа IAcadApplication из модуля AutoCAD_TLB. Как это возможно сделать подскажите, буду очень признателен!!!
← →
Elen © (2006-07-11 08:00) [1]
> Calibr2
Уточни свой вопрос - для чего?
ИМХО попробуй в таймере что нибудь типа
try
caption:=AcadApplication1.caption;
except
Messagebox("","Все закрыто")
end;
Это не самый лучший вариант но работает.
Или ставь хук на закрытие приложения
← →
AbrosimovA © (2006-07-11 08:39) [2]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleServer, AutoCAD_TLB;
type
TForm1 = class(TForm)
AcadDocument1: TAcadDocument;
procedure AcadDocument1BeginClose(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.AcadDocument1BeginClose(Sender: TObject);
begin
ShowMessage("AutoCAD закрывается")
end;
end.
← →
Elen © (2006-07-11 08:57) [3]
> AbrosimovA ©
У автора речь идет не о документе а о приложении. Акад не факт что закроют а на документе это сработает но при закрытии дока Акад не сам закрывается если конечно автор это не пропишет
← →
Calibr2 (2006-07-11 09:57) [4]Я уточняю! Мне нужно перехватить закрытие AutoCADа, чтобы перед закрытием вывести сообщение типа MessageBox, а если AutoCAD уже закроется уже будет поздно. Мне нужно именно перехватить закрытие, а когда ответят на MessageBox, то пожалуйста пусть дальше закрывается. Говорите написать Хук, а какие комбинации клавиш мне в нем отлавливать? Приведите пример кода please...
← →
Elen © (2006-07-11 10:22) [5]
> Calibr2
Попробуй на VBA написать скрипт который будет выполнятся с Акадом и помести его как стандартный шаблон и там ты сможеш проконтролировать все. Это будет гораздо эффективнее и безопаснее чем ставить Хуки.
Если все же хочеш хук то рой в сторону SetWindowhookEx в SDK хелпе. И на этом форуме много про это веток в WinAPI и основной
← →
Elen © (2006-07-11 10:31) [6]P.S.
//Это DLL
uses
SysUtils,
windows,
Dialogs,
Classes;
var hook:HHOOK;
{$R *.res}
function _(code:Integer;w:WPARAM;l:LPARAM):word;stdcall;
var
begin
beep(100,100);
//Будет пикать при закрытии и открытии приложения и в других случаях
result:=CallNextHookEx(hook,code,w,l) ;
end;
//********** FUNCTION **********
function hh:hhook ;
begin
result:=SetWindowsHookEx(WH_CBT,@_,HInstance,0);
end;
//********** END FUNCTION ******
//********** FUNCTION **********
function uh(hhh:hhook):LongBool;
begin
result:=UnhookWindowsHookEx(hhh);
end;
//********** END FUNCTION ******
exports hh, uh;
begin
end.
Создай проект и загружай в нем эту ДЛЛ и пусть висит
Вызовеш hh в проекте и она вернет тебе хендл на хук, который потом нужно закрывать в uh
Почитай еще про WH_CBT и иже с ними в SDK
← →
Calibr2 (2006-07-11 11:02) [7]Да хук на данный момент не надежный помощник. Ну неужели никак нельзя отловить закрытие AutoCADa. А если узнать его Handle, потом задать для него новую оконну процедуру и отлавливать сообщение WM_DESTROY или WM_QUIT, как вы думаете выйдет так или нет
← →
Elen © (2006-07-11 11:07) [8]
> задать для него новую оконну процедуру
А это как в твоем понимании?
← →
Calibr2 (2006-07-11 11:21) [9]В моем понимании это так:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
OldWinProc, NewWinProc: Pointer;
procedure NewWinProcedure(var Msg: TMessage);
public
{ Public declarations }
end;
var
Form1: TForm1;
h: hWnd;
implementation
{$R *.dfm}
procedure TForm1.NewWinProcedure(var Msg: TMessage);
begin
if Msg.Msg = WM_DESTROY then
Application.MessageBox("Сохранит изменения в документе?",
"AutoCAD", MB_YESNO + MB_ICONWARNING);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
//Ну Handle я найду конечно иным способом чем этот
//просто допустим Handle уже у меня есть
h := FindWindow(nil, "AutoCAD 2004");
NewWinProc := MakeObjectInstance(NewWinProcedure);
OldWinProc := Pointer(SetWindowLong(h, GWL_WNDPROC, Cardinal
(NewWinProc)));
end;
end.
← →
Elen © (2006-07-11 11:30) [10]И что мешает попробовать прямо сейчас?
← →
AbrosimovA © (2006-07-11 11:30) [11]Смотри здесь:
http://66.249.93.104/search?q=cache:4LIqHO1_xaIJ:www.autocad.ru/cgi-bin/f1/board.cgi%3Ft%3D6915Ah+TAcadApplicationEvents&hl=ru&gl=ru&ct=clnk&cd=1
← →
Elen © (2006-07-11 11:42) [12]
> AbrosimovA ©
ИМХО Автор имеет в виду не СОМ объект а стороннее приложение где это не пройдет Пусть лучше изучит VBA, хоть это и гадость но это лучше
← →
Calibr2 (2006-07-11 11:55) [13]AbrosimovA
а где можно скачать компонент TAcadApplicationEvents?
← →
Calibr2 (2006-07-11 12:32) [14]Ладно ответте мне пожалуйста на такой вопрос. Если в AutoCADе запущено несколько документов и они абсолютно все хранятся у меня в массиве и для них всех назначен метод OnClose, почему он срабатывает не для всех документов. При тестировании я запустил 3 документа, затем закрыл AutoCAD и MessageBox вышел только 2 раза, а 3-ий документ проигнорировал, помогите исправить проблему, подскажите, что у меня не так:
var
Acad: OleVariant;
AcadApp: IAcadApplication;
AcadDocs: array[0..50] of TAcadDocument;
procedure TForm1.Timer1Timer(Sender: TObject);
var
i: Integer;//Счетчик, вспомогат. переменная
iCol: Integer;//Количество документов в AutoCADе
begin
try
{пытаемся подключиться к уже запущенному AutoCADу}
Acad := GetActiveOleObject("AutoCAD.Application");
AcadApp := IDispatch(Acad) as IAcadApplication;
Caption := "AutoCAD запущен";// пишем, что AutoCAD запущен
except
{если не получилось, то пишем, что AutoCAD закрыт}
Caption := "AutoCAD сейчас закрыт...";
ListBox1.Clear;// очищаем список
iCol := 0;
exit;// выходим
end;
try
{пытаемся подключиться к активному документу}
iCol := AcadApp.Documents.Count;//Определяем кол-во документов
{Цикл перебора всех запущенных документов}
for i := 0 to iCol - 1 do
begin
AcadDocs[i].Free;
AcadDocs[i] := nil;
AcadDocs[i] := TAcadDocument.Create(Self);//Создаем документ
AcadDocs[i].ConnectTo(AcadApp.Documents.Item(i));//Соединяем его с
//i-тым в AutoCadе
AcadDocs[i].OnBeginClose := BeginClose;//Закрытие
end;
except
{если не получилось, то пишем Чертёж не запущен}
Caption := "Чертеж не запущен...";
exit;// выходим
end;
end;
(******* ПРОЦЕДУРА ЗАКРЫТИЯ ДОКУМЕНТОВ *******)
procedure TForm1.BeginClose(Sender: TObject);
var
i : Integer;//Счётчик
Name: String; //Имя закрывающегося файла
begin
Timer1.Enabled := false;
Name := (Sender as TAcadDocument).Name;//Определяем имя закрывающегося файла
{Выводим диалог сохранения}
if Application.MessageBox(pChar("Сохранить изменения в документе " + Name + "?"), "AutoCAD", mb_YESNO + MB_ICONWARNING) = idYES then
{Если отвечают "ДА"}
Caption := "Yes";
else
Caption := "No";
Timer1.Enabled := true;
end;
← →
umbra © (2006-07-11 12:32) [15]http://www.autocad.ru/cgi-bin/f1/board.cgi?t=6915Ah
← →
Elen © (2006-07-11 12:49) [16]
> Calibr2
У меня твой пример работает на ура. Но окно сообщения появляется только если ты перейдеш на свою форму после клика по закрыть. Ты наверное пропустил одно сообщение (Не заметил). Вместо этого ставь свою форму на перед типа SetForegroundWindow
← →
Calibr2 (2006-07-11 13:14) [17]Спасибо тебе Elen за твое терпение, но все таки иногда одно сообщение не отображается!!! Но все равно спасибо всем за советы!!!
← →
AbrosimovA © (2006-07-11 13:24) [18]
> а где можно скачать компонент TAcadApplicationEvents?
Если ты внимательно смотрел по ссылке, там приведён юнит :unit SinkAcadEvents;
interface
Uses
ComObj, AutoCAD_TLB, Classes;
Type
TAcadApplicationEvents = class(TInterfacedObject, IUnknown, IDispatch)
← →
Calibr2 (2006-07-11 14:00) [19]
> AbrosimovA
Какой модуль нужно прописать в uses чтобы использовать тип IConnectionPointContainer или IConnectionPoint
← →
AbrosimovA © (2006-07-11 14:34) [20]ActiveX
← →
jack128 © (2006-07-11 14:49) [21]Calibr2 (11.07.06 14:00) [19]
Какой модуль нужно прописать в uses чтобы использовать тип IConnectionPointContainer или IConnectionPoint
Наверно для тебя это большая новость, но Explorer встроена возможность поиска по содержимому файла...
← →
AbrosimovA © (2006-07-11 14:51) [22]Delphi: Search->Find in files...
← →
Calibr2 (2006-07-11 17:31) [23]
> Elen
Ты не могла бы протестировать мой пример несколько раз потому-что у меня сообщение иногда срабатывает иногда нет. Именно это меня и смущает. Я уже вывел свое окно наверх, все равно 1 раз из 5-10 не срабатывает.
← →
AbrosimovA © (2006-07-12 08:14) [24]Я бы вместо этого
> Acad := GetActiveOleObject("AutoCAD.Application"); AcadApp
> := IDispatch(Acad) as IAcadApplication;
написал бы так
AcadApp := GetActiveOleObject("AutoCAD.Application") as IAcadApplication;
тогда не требовалось бы создавать промежуточную переменную Acad, которая у тебя нигде не используется.
← →
Elen © (2006-07-12 08:16) [25]
> Calibr2
Значит слухай сюдыть : В твоей проге нет ошибки но в определенные моменты таймер не успевает за Акадом. Протестируй в дебугере и увидишь
Привожу тебе мое решение :
unit Unit1;
interface
uses comobj,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, OleServer, AutoCAD_TLB;
type
TForm1 = class(TForm)
AcadDocument1: TAcadDocument;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var Acad: OleVariant;
AcadApp: IAcadApplication;
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject);
begin
try
Acad := GetActiveOleObject("AutoCAD.Application");
Application.Title:="yes";
//АКАД запущен
except
Application.Title:="no";
//Акад закрыт
end;
end;
end.
На будущее просьба Приводи код полностью от unit до последнего end
Неудобно тестировать.
Удачи! ;-)
← →
Elen © (2006-07-12 08:17) [26]P.S. При запуске из Делфи будет ругаться. Не обращай внимание и нажимай F9 в экзешнике все пойдет как по маслу
← →
AbrosimovA © (2006-07-12 08:28) [27]
> Acad := GetActiveOleObject("AutoCAD.Application");
Зачем это делать в таймере?
← →
Elen © (2006-07-12 08:50) [28]
> AbrosimovA ©
Это не лучшее решение это пример
> Calibr2
Лучще все таки если ты напишеш скрипт на VBA для Акада
← →
Calibr2 (2006-07-12 09:15) [29]
> Elen
VBA это вообще, что новый язык и вообще где можно ему научиться?
← →
Elen © (2006-07-12 09:50) [30]
> где можно ему научиться?
Методом тыка. Запускаеш акад и пробуеш написать скрипт сам. Недельку помучаешся зато с пользой т.к. в любом офиссе сможеш решать такие задачи без всяких хуков.
← →
Elen © (2006-07-12 10:11) [31]
> Calibr2
Значит так : Вот тебе макрос-скрипт решающий твою задачу на VBA Acad
Public WithEvents ACADApp As AcadApplication " Use with Application Event Examples
Sub Example_AcadApplication_Events()
Set ACADApp = GetObject(, "AutoCAD.Application")
End Sub
Private Sub ACADApp_BeginQuit(Cancel As Boolean)
If MsgBox("AutoCAD Хочет закрыться Ладушки или нет?", vbYesNoCancel + vbQuestion) <> vbYes Then
Cancel = True
End If
End Sub
Запускаеш Акад в меню Assist->Macro->Macros создаеш макрос как Global и в редакторе VBA на ветке ThisDrawing вписываеш этот код.
и запускаеш его. Он должен срабатывать при каждом запуске Акада
Удачи и да простят меня Мастера за VBA мазню на этом чистейшем форуме!
если можно сообщи результат сюда же ;-)
← →
Calibr2 (2006-07-12 10:50) [32]
> Elen
Я не знаком с VBA не могла бы ты по подробнее объяснить. И в Акаде такого меню у меня нет Assist -> Macro-> Macros. И VBA редактор не пойму где взять.
← →
Calibr2 (2006-07-12 11:00) [33]
> Elen
А вот вроде получается я еще напишу.
← →
Calibr2 (2006-07-12 11:46) [34]
> Elen
Я сохранил Макрос в формате *.dvb а как сделать чтоб он запускался вместе с Acadom, я пока сам его не запущу он не запускается
← →
Elen © (2006-07-12 15:55) [35]
> Calibr2
Задай этот вопрос на форум AutoCAD (по ссылке AbrosimovA)
← →
Calibr2 (2006-07-13 08:14) [36]Спасибо всем!!!! Вы меня очень выручили!!! Особенное спасибо Elen!!!:):):):)
← →
Elen © (2006-07-13 09:13) [37]
> Calibr2
Wellcome
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.08.27;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.097 c