Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
3-1150883161
312Kbps
2006-06-21 13:46
2006.08.27
Выбор записи в DBLookupComboBox !


2-1155065333
ronyn
2006-08-08 23:28
2006.08.27
Windows feat ShellApi


6-1144146711
WebSqlNeederr
2006-04-04 14:31
2006.08.27
Закрыть вылетающееся окошко ошибки ИЕ, вернее кликнуть на ОК


15-1154427261
lurce
2006-08-01 14:14
2006.08.27
Советский Энциклопедический Словарь в эл. виде


1-1152605075
Levin_610
2006-07-11 12:04
2006.08.27
активность пользователя





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский