Тема: Где Windows запоминает последнее активное окно AutoCAD?

Допустим у меня открыты окна AutoCAD2002 и AutoCAD2006. Моя программа обращается к приложению AutoCAD с помощью метода GetObject. Если я выделю на панели задач AutoCAD2002 а потом Excel то моя программа обратится к AutoCAD2002, если выделю AutoCAD2006 а потом Excel то моя программа обратится к AutoCAD2006. Где Winodows запоминает какое окно AutoCAD было выделено последним и не обращается например во втором случае к AutoCAD2002 а обращается к AutoCAD2006? Мне важно разобраться откуда можно прочитать название последней активной версии AutoCAD и каким способом. Помогите это сделать пожалуйста.

Re: Где Windows запоминает последнее активное окно AutoCAD?

Вам надо прочитать названия всех открытых окон (это можно сделать с помощью Win API) и сдалать активным нужное окно с помощью инструкции

AppActivate Caption

где Caption - имя окна.
После этого Excel найдет активное окно сам.

Re: Где Windows запоминает последнее активное окно AutoCAD?

> brigval
Уважаемый brigval! Спасибо за ответ!
Мне надо чтобы компьютер сам определял какое окно было активным, ставил для этого окна необходимые библиотеки и обращался затем без ошибок к программе этого окна. В каком месте надо указать моей программе прочитать версию программы последнего активного окна AutoCAD, чтобы она поставила правильные библиотеки в References для безопасной работы макросов?

Re: Где Windows запоминает последнее активное окно AutoCAD?

1 На сколько я в курсе, активное окно можно определить с помощью WinAPI.
2 Возможно, для решения вашей задачи удобнее использовать позднее связывание. Далее определять версию AutoCAD и для каждой версии использовать присущие ей объекты. По моему это здесь уже обсуждалось.
3 Может быть есть и другие способы.

Re: Где Windows запоминает последнее активное окно AutoCAD?

> Миша
Вам необходимо считывать значение Z Order окна либо устанавливать это значение самому. Z order это если образно сказать, это координата окна в системе Z. Можно это реализовать через SetWindowPos

Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Long, _
      ByVal hWndInsertAfter As Long, _
      ByVal x As Long, _
      ByVal y As Long, _
      ByVal cx As Long, _
      ByVal cy As Long, _
      ByVal wFlags As Long) As Long

Re: Где Windows запоминает последнее активное окно AutoCAD?

чуть раньше времени опубликовал. идея в том чтоб в качестве парметра
hWndInsertAfter подставлять hWnd не интересующего нас AutoCAD -а.Тогда система найдет AutoCAD который мы пропустим через SetWindowPos быстрее.

Re: Где Windows запоминает последнее активное окно AutoCAD?

> SmeL
Спасибо большое Smel! Обязательно попробую разобраться!

Re: Где Windows запоминает последнее активное окно AutoCAD?

> SmeL
Уважаемый Smel!

hWndInsertAfter подставлять hWnd не интересующего нас AutoCAD -а

может быть лучше без "не" и без пробела:

hWndInsertAfter подставлять hWnd интересующего нас AutoCAD-а

Но пока я понял что в какой-то момент времени мне надо запомнить порядковый номер определённого окна AutoCAD. Или наверное все окна находятся в определённой "стэковой" памяти или лучше сказать отсортированы по порядку вызова или активизиции. Надо просто определить какое окно в этом отсортированном списке имеет минимальный или максимальный номер? Правильно ли я Вас понял SmeL? Можно дополнительно спросить: какой номер окна надо искать минимальный или максимальный?

Re: Где Windows запоминает последнее активное окно AutoCAD?

Миша пишет:

Но пока я понял что в какой-то момент времени мне надо запомнить порядковый номер определённого окна AutoCAD

не правы.
Z order значение переменное если вы активировали окно автокада, то его Z order на данный момент максимальное, пока не появилось окно выше него. про hWndInsertAfter я пологаю, что правильно выразился. для того чтоб найти hWnd Вам понадобится FindWindow * если известен Caption окна заранее, что мало вероятно. Тогда вам нужно узнать весь список окон при помощи EnumWindows ** и в нем выбрать интересующее.

//*
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
      ByVal lpWindowName As String) As Long
//**
Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, _
      ByVal lParam As Long) As Long

Этот код подобен варианту AppActivate с одним плюсом и минусом ;)
+ в том, что активное окно не меняется
- что нужно больше писать :)

Re: Где Windows запоминает последнее активное окно AutoCAD?

что то я тут разошелся :)
Выше я писал как можно выбрать с каким из запущенных версий автокада будет работать Ваше приложение. Что то вы долго молчали и подумал может достаточно узнать с каким из запущенных версий Вам придется работать. на это сможет ответить EnumWindows данная функция возвращает окна в Z order порядке.

Re: Где Windows запоминает последнее активное окно AutoCAD?

> SmeL
EnumWindows очень интересная функция, я даже нашёл для неё пример:

'Add this code to a form
Private Sub Form_Load()
    'KPD-Team 2000
    'URL: http://www.allapi.net/
    'E-Mail: KPDTeam@Allapi.net
    'Set the form's graphics mode to persistent
    Me.AutoRedraw = True
    'call the Enumwindows-function
    EnumWindows AddressOf EnumWindowsProc, ByVal 0&
End Sub
'Add this code to a module
Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Public Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Boolean
    Dim sSave As String, Ret As Long
    Ret = GetWindowTextLength(hwnd)
    sSave = Space(Ret)
    GetWindowText hwnd, sSave, Ret + 1
    Form1.Print Str$(hwnd) + " " + sSave
    'continue enumeration
    EnumWindowsProc = True
End Function

Но теперь передо мной стоит задача: получить GUID самого верхнего окна AutoCAD, по этому GUID найти в реестре название приложения и определить LIBID этого приложения и подсоединить соответствующую библиотеку к моей программе в Excel. Самое трудное из всего этого определить GUID из ответных параметров функции EnumWindows, если эта информация есть в ответных параметрах функции. Если GUID нет в ответных параметрах функции EnumWindows, то надо как-то используя ответные параметры функции EnumWindows выйти на GUID, помогите пожалуйста мне это сделать!
Жду ответа!

Re: Где Windows запоминает последнее активное окно AutoCAD?

Как плохо не читать документацию, я не знаю что такое GUID. Если сможете мне объяснить раньше чем дадут ответ, то может мы найдем выход.

Re: Где Windows запоминает последнее активное окно AutoCAD?

> SmeL
GUID это Глобальный Универсальный ID (идентификатор) приложения
LIBID это ID библиотеки, которую использует приложение
Выглядят эти ID следующим образом: "{851A4561-F4EC-4631-9B0C-E7DC407512C9}" (это LIBID).
Зная GUID приложения в реестре можно найти название этого приложения и LIBID, название библиотеки которую использует это приложение и название (полный путь) файла этой библиотеки, а зная название файла библиотеки, можно подключить эту библиотеку програмным способом в VBA.
Поэтому мне надо научиться получать GUID верхнего окна AutoCAD из ответных даных функции EnumWindows!
Посмотрите для дополнительной информации следующие страницы:
https://www.caduser.ru/forum/topic31130.html
https://www.caduser.ru/forum/topic30943.html
https://www.caduser.ru/forum/topic30948.html

Re: Где Windows запоминает последнее активное окно AutoCAD?

EnumWindows возвращает хэндлы. и вот через хэндл можно спрашивать у системы все что угодно. Функцию типо GetGUID я не встречал (которая возвращает GUID по хэндлу). Но думаю Вам чуть поможет функция которая вернет путь запущенного окна.

Private Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Long, _
        ByVal lpFileName As String, _
        ByVal nSize As Long) As Long
Private Declare Function GetWindowWord Lib "user32" (ByVal hwnd As Long, _
        ByVal nIndex As Long) As Integer
Const GWW_HINSTANCE = (-6)
Private Sub Form_Load()
    MsgBox GetPath(Me.hwnd)
End Sub
Public Function GetPath(hwnd As Long)
 Dim Path As String
 Dim hInst As Long
 Path = String$(128, Chr$(0))
 hInst = GetWindowWord(hwnd, GWW_HINSTANCE)
 GetPath = Left$(Path, GetModuleFileName(hInst, Path, Len(Path)))
End Function

Зная GUID приложения в реестре можно найти название этого приложения и LIBID

Как еще один вариант решения задачи можно создать таблицу путь к exe и соответствуюий LIBID, (соглашусь что вариант не универсальный но пока другово варианта не придумал).