Поиск дочернего окна

Обсуждение программ nnCron и nnCron LITE

Re: Поиск дочернего окна

Postby Burunduk » Mon, 11 Nov 2013, 12:25

Написал задачку по поиску статик-окна

Code: Select all
#( FIND_Static
RunOnce
NoDel
Time: 0 11 14 10 * 2013
VARIABLE CountStatic
Action:
WIN-EXIST: "GPSCockpit*"
IF
   WIN-ACTIVATE: "GPSCockpit*"   \  активируем главное окно GPSCockpit*
   WIN-ACTIVE: "GPSCockpit*"     \  проверяем, активировалось ли?
   IF
     0 CountStatic !
     FOR-CHILD-WINDOWS: "*"
         \ ... выполняем работу с дочерними окнами
         \ WIN-CHILD-HWND GET-WCLASS S" #32770" COMPARE 0=
          WIN-CHILD-HWND GET-WCLASS S" Static" COMPARE 0=
          IF
            CountStatic @ 1 + CountStatic !
            MSG: "Имя окна %FOUND-CHILD-WINDOW% Счётчик %CountStatic @ N>S%"
          THEN
      ;FOR-CHILD-WINDOWS
   ELSE
      MSG: "Не удалось активировать окно GPS Information"   
   THEN
ELSE
   MSG: "GPSCockpit* не найден."
THEN

MSG: "Конец задачи."
)#


Как и ожидалось, у моего статик окошка значение счётчика( у меня 7) совпадает с параметром INSTANCE=7, который показывает анализатор окон AutoIt WindowInfo. Параметр ControlID=1007 в программе WinSPY++ тоже похож.
Очевидно, что цикл перебора дочерних окон обычно идёт в одном и том же порядке, поэтому нужный статик можно просто определять по счёту. Правда у меня статики есть только в одной формочке, иначе пришлось бы еще проверять в начале какая дочерняя форма со статиками просматривается в текущий момент.

Может имеет смысл добавить функцию, которая возвращала бы хэндл окна по трем параметрам "имя_родительского_окна", "имя_класса", "номер_экземпляра" ? Тогда удобство работы с окнами вырастет.
Burunduk
 
Posts: 73
Joined: Thu, 03 Oct 2013, 06:57

Re: Поиск дочернего окна

Postby Burunduk » Mon, 11 Nov 2013, 12:30

Morituruz wrote:
Burunduk wrote:Network Time Protocol (NTP) — сетевой протокол для синхронизации внутренних часов компьютера

Я рад, что вы знаете, что такое NTP, но если бы не только прочитали заголовок ссылки, но и проследовали бы по ней, то увидели бы всю статью =-)
Это всё к тому к тому, что существует специальный софт для этих целей:
http://en.wikipedia.org/wiki/Ntpd
и очень даже возможно, что одна из реализаций его вполне себе будет работать с вашей железкой. Это должно быть надёжнее, чем по окошкам шариться, да и точнее, хотя высокая точность синхронизации под виндой я так понимаю в принципе недостижима, но раз вы говорите, что интернета нет, то деваться некуда.
Burunduk
 
Posts: 73
Joined: Thu, 03 Oct 2013, 06:57

Re: Поиск дочернего окна

Postby Burunduk » Mon, 11 Nov 2013, 12:35

Morituruz wrote:
Burunduk wrote:Network Time Protocol (NTP) — сетевой протокол для синхронизации внутренних часов компьютера

Я рад, что вы знаете, что такое NTP, но если бы не только прочитали заголовок ссылки, но и проследовали бы по ней, то увидели бы всю статью =-)
Это всё к тому к тому, что существует специальный софт для этих целей:
http://en.wikipedia.org/wiki/Ntpd
и очень даже возможно, что одна из реализаций его вполне себе будет работать с вашей железкой. Это должно быть надёжнее, чем по окошкам шариться, да и точнее, хотя высокая точность синхронизации под виндой я так понимаю в принципе недостижима, но раз вы говорите, что интернета нет, то деваться некуда.


Спасибо за советы! Пару лет назад рассматривали вариант приобретения специализированного тайм-сервера, но пока не позволяет бюджет обсерватории. Еще не хотелось загружать процессор задачами, которые могут конкурировать с программой регистрации данных. Windows увы не ОС реального времени.
Burunduk
 
Posts: 73
Joined: Thu, 03 Oct 2013, 06:57

Re: Поиск дочернего окна

Postby Morituruz » Mon, 11 Nov 2013, 15:04

Не знаю, какой бюджет, но иногда можно купить плату по довольно неплохой цене, пусть и б/у:
http://www.ebay.com/itm/BC635PCI-DATUM- ... 1c38b3a8ba

К сожалению, самый популярный производитель не пишет цены открытым текстом:
http://www.meinbergglobal.com/english/p ... -clock.htm
зато купив эту штуку вы сами себе будете стратум 0 сервером с полным набором софта для работы под виндой, причём безо всяких неконтролируемых джиттеров USB или чем вы сейчас с GPS соединены и прочих негарантируемых системой задержек.
User avatar
Morituruz
 
Posts: 725
Joined: Sun, 14 Oct 2007, 01:51

Re: Поиск дочернего окна

Postby VoidVolker » Mon, 11 Nov 2013, 16:44

Burunduk wrote:Т.е. можно определить хэндл окна по его координатам?

Да. В данном случае, проще пройтись по всем статик-окнам и проверяя координаты каждого окна, выбрать то окно, чьи координаты нас устраивают.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Поиск дочернего окна

Postby AlikasS » Tue, 12 Nov 2013, 03:01

Burunduk wrote:Написал задачку по поиску статик-окна
Spoiler: show
Code: Select all
#( FIND_Static
RunOnce
NoDel
Time: 0 11 14 10 * 2013
VARIABLE CountStatic
Action:
WIN-EXIST: "GPSCockpit*"
IF
   WIN-ACTIVATE: "GPSCockpit*"   \  активируем главное окно GPSCockpit*
   WIN-ACTIVE: "GPSCockpit*"     \  проверяем, активировалось ли?
   IF
     0 CountStatic !
     FOR-CHILD-WINDOWS: "*"
         \ ... выполняем работу с дочерними окнами
         \ WIN-CHILD-HWND GET-WCLASS S" #32770" COMPARE 0=
          WIN-CHILD-HWND GET-WCLASS S" Static" COMPARE 0=
          IF
            CountStatic @ 1 + CountStatic !
            MSG: "Имя окна %FOUND-CHILD-WINDOW% Счётчик %CountStatic @ N>S%"
          THEN
      ;FOR-CHILD-WINDOWS
   ELSE
      MSG: "Не удалось активировать окно GPS Information"   
   THEN
ELSE
   MSG: "GPSCockpit* не найден."
THEN

MSG: "Конец задачи."
)#

Как и ожидалось, у моего статик окошка значение счётчика( у меня 7) совпадает с параметром INSTANCE=7, который показывает анализатор окон AutoIt WindowInfo. Параметр ControlID=1007 в программе WinSPY++ тоже похож.
Очевидно, что цикл перебора дочерних окон обычно идёт в одном и том же порядке, поэтому нужный статик можно просто определять по счёту. Правда у меня статики есть только в одной формочке, иначе пришлось бы еще проверять в начале какая дочерняя форма со статиками просматривается в текущий момент.

Может имеет смысл добавить функцию, которая возвращала бы хэндл окна по трем параметрам "имя_родительского_окна", "имя_класса", "номер_экземпляра" ? Тогда удобство работы с окнами вырастет.

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

а можно и ControlID поюзать...
Code: Select all
WINAPI: GetDlgCtrlID User32.dll
использовать так
на входе хендл элемента (WIN-HWND/WIN-CHILD-HWND ), на выходе ID
Code: Select all
0x140E58 GetDlgCtrlID .
у элемента где время ID - 1007 (у меня. проверь это значение у себя, его показывает AutoIt Window Info)
User avatar
AlikasS
 
Posts: 1434
Joined: Wed, 28 Jun 2006, 05:39
Location: Khabarovsk

Re: Поиск дочернего окна

Postby Burunduk » Tue, 12 Nov 2013, 08:54

AlikasS wrote:INSTANCE показывает в каком порядке созданы дочерние окна (порядок определяется автором проги) мне такая информация попалась


Изучая первоисточник
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633574(v=vs.85).aspx

при первой кавалерийской атаке, параметр INSTANCE не нашел. Поэтому решил, что это изобретение авторов AutoIt WindowInfo. Думаю, что получают они его
аналогичным перебором списка окон. А список окон все очевидно получают одним и тем же вызывом функции API. Поэтому последовательность окон и в AutoIt WindowInfo, и в Кроне
одинакова. Другое дело, что теоретически порядок создания дочерних окон может зависить от поведения пользователя, открывающего окна в том или ином порядке.
Но вот в самой дочерней форме последовательность создания статик-окон естественно неизменна. Как папа-программист выстругал...

Попробую сейчас покопать на тему ControlID ...

AlikasS wrote:у элемента где время ID - 1007

У меня тоже 1007
Burunduk
 
Posts: 73
Joined: Thu, 03 Oct 2013, 06:57

Re: Поиск дочернего окна

Postby AlikasS » Tue, 12 Nov 2013, 09:11

Burunduk wrote:при первой кавалерийской атаке, параметр INSTANCE не нашел. Поэтому решил, что это изобретение авторов AutoIt WindowInfo.
ага. есть такое подозрение :)
User avatar
AlikasS
 
Posts: 1434
Joined: Wed, 28 Jun 2006, 05:39
Location: Khabarovsk

Re: Поиск дочернего окна

Postby Burunduk » Tue, 12 Nov 2013, 10:10

AlikasS wrote:а можно и ControlID поюзать...Код: Выделить всёWINAPI: GetDlgCtrlID User32.dllиспользовать такна входе хендл элемента (WIN-HWND/WIN-CHILD-HWND ), на выходе ID



Заглянул в SDK Help:

The GetDlgCtrlID function returns the identifier of the specified control.

int GetDlgCtrlID(
HWND hwndCtl // handle of control
);

Parameters hwndCtl Identifies the control.

Return Values

If the function succeeds, the return value is the identifier of the control.
If the function fails, the return value is NULL. An invalid value for the hwndCtl parameter, for example, will cause the function to fail.

Remarks

GetDlgCtrlID accepts child window handles as well as handles of controls in dialog boxes. An application sets the identifier for a child window when it creates the window by assigning the identifier value to the hmenu parameter when calling the CreateWindow or CreateWindowEx function.
Although GetDlgCtrlID may return a value if hwndCtl identifies a top-level window, top-level windows cannot have identifiers and such a return value is never valid.

Итак, ControlID применим только для дочерних окон.

Там же нашёл еще одну функцию, которая похоже еще лучше подходит к данной задаче.
The GetDlgItem function retrieves the handle of a control in the specified dialog box.

HWND GetDlgItem(
HWND hDlg, // handle of dialog box
int nIDDlgItem // identifier of control
);

Parameters hDlg Identifies the dialog box that contains the control.

nIDDlgItem Specifies the identifier of the control to be retrieved. ЭТО ВРОДЕ и ЕСТЬ ControlID !

Return Values

If the function succeeds, the return value is the window handle of the given control. ТО, ЧТО НАДО ДЛЯ ПРЯМОГО ДОСТУПА К СТАТИК-ОКНАМ
If the function fails, the return value is NULL, indicating an invalid dialog box handle or a nonexistent control.

Remarks

You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes. As long as the hDlg parameter specifies a parent window and the child window has a unique identifier (as specified by the hMenu parameter in the CreateWindow or CreateWindowEx function that created the child window), GetDlgItem returns a valid handle to the child window.

Итак, до Статик-окна можно добраться зная хэндл родительского окна и ControlID самого статика.
Беда только в том, что статики лежат на системном диалоговом окне с именем класса #32770. А таких окон в приложении несколько. НО У НИХ ПОЧЕМУ-ТО ОДИНАКОВЫЙ ControlID !!!

А вот диалоговые окна класса #32770 с разными хэндлами и одинаковыми ID имеют разных родителей. Короче, совсем без перебора не получится.
Burunduk
 
Posts: 73
Joined: Thu, 03 Oct 2013, 06:57

Re: Поиск дочернего окна

Postby VoidVolker » Tue, 12 Nov 2013, 12:22

Омг, зачем такие сложности? Я же уже сказал, что проще всего просто выбрать нужное окно по его координатам на экране. Алгоритм простой: есть три окна в ряд, смотрим в менеджере окон, их позицию - 100, 200, 300. Далее просто проверяем координаты полученного окна:
Code: Select all
FOR-CHILD-WINDOWS: "<win>"
    WIN-HWND WIN-POS \ x1 y2 \ Получаем координаты родительского окна
    DROP  \ x1
    WIN-CHILD-HWND WIN-POS  \ x2 y2 \ Получаем координаты дочернего окна
    DROP \ x1 x2
    - 299 > IF
      \  Третье окно найдено
    THEN
;FOR-CHILD-WINDOWS
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Поиск дочернего окна

Postby AlikasS » Wed, 13 Nov 2013, 02:39

Burunduk wrote:Там же нашёл еще одну функцию, которая похоже еще лучше подходит к данной задаче.

каждый выбирает свои грабли :-D и что ими делать
эксперимент по твоему варианту
Code: Select all
WINAPI: GetDlgItem User32.dll
 Ok
1007 0xD08A2 GetDlgItem HEX . DECIMAL
C0860  Ok
где 0xD08A2 хэндл элемента без имени и с классом #32770 на котором лежит Static со временем
выдает правильный хэндл статика.
но проблема, что у этой проги куча элементов
без имени и с классом #32770

я вижу вариант только перебирать их всех (так же через FOR-CHILD-WINDOWS: .... ;FOR-CHILD-WINDOWS)
и ловить то на котором есть элемент nIDDlgItem 1007 т.е. которое на
Code: Select all
1007 WIN-CHILD-HWND GetDlgItem
даст не 0 ,
но таких вариантов по крайней мере 3 штуки
Spoiler: show
Code: Select all
<%
WINAPI: GetDlgItem User32.dll
%>
#( FIND_Static
NoActive
Action:
WIN-EXIST: "GPSCockpit*"
IF
   WIN-ACTIVATE: "GPSCockpit*"   \  активируем главное окно GPSCockpit*
   WIN-ACTIVE: "GPSCockpit*"     \  проверяем, активировалось ли?
   IF

     FOR-CHILD-WINDOWS: "#32770"

          1007 WIN-CHILD-HWND GetDlgItem DUP
          IF N>S
             S" - хендл элемента" S+ EVAL-SUBST MsgBox
     ELSE DROP
          THEN
      ;FOR-CHILD-WINDOWS
   ELSE
      MSG: "Не удалось активировать окно GPS Information"   
   THEN
ELSE
   MSG: "GPSCockpit* не найден."
THEN
MSG: "Конец задачи."
)#
и между ними придется то же как то выбирать
вариант выходит навороченее следующего.
User avatar
AlikasS
 
Posts: 1434
Joined: Wed, 28 Jun 2006, 05:39
Location: Khabarovsk

Re: Поиск дочернего окна

Postby AlikasS » Wed, 13 Nov 2013, 05:23

ты присмотрись внимательно что показывает nnCron WinSpy и AutoIt Window Info
у твоего элемента Static (со временем)
Main Windows: c именем "GPSCockpit - *" (часть названия меняется) и классом "Afx:400000:8:10011:0:460abd"
простой отладочный вариант такой:
Code: Select all
<%
WINAPI: GetDlgCtrlID User32.dll
%>
#( FIND_Static
NoActive
Action:
WIN-EXIST: "GPSCockpit*"
IF
   WIN-ACTIVATE: "GPSCockpit*"   \  активируем главное окно GPSCockpit*
   WIN-ACTIVE: "GPSCockpit*"     \  проверяем, активировалось ли?
   IF

     FOR-CHILD-WINDOWS: "Static"

          WIN-CHILD-HWND GetDlgCtrlID 1007 =
          IF
            HINT: "Имя окна %FOUND-CHILD-WINDOW%  хендл %WIN-CHILD-HWND%"
          THEN
      ;FOR-CHILD-WINDOWS
   ELSE
      MSG: "Не удалось активировать окно GPS Information"   
   THEN
ELSE
   MSG: "GPSCockpit* не найден."
THEN
MSG: "Конец задачи."
)#
выведет только один хинт :-)
элемент однозначно определяется
User avatar
AlikasS
 
Posts: 1434
Joined: Wed, 28 Jun 2006, 05:39
Location: Khabarovsk

Re: Поиск дочернего окна

Postby Burunduk » Wed, 13 Nov 2013, 07:32

VoidVolker wrote:Алгоритм простой: есть три окна в ряд, смотрим в менеджере окон, их позицию - 100, 200, 300. Далее просто проверяем координаты полученного окна:


В данной программе внутренние окна могут передвигаться оператором. Он может даже наложить одно окно на другое, так что координаты двух окон совпадут!(Это очень вредный оператор :) , вроде меня )
Еще главное окно может перемещаться по экрану. Нужно будет вычислять относительные координаты дочерних окон.

Хотя возможно Ваш метод придётся использовать для работы с кнопками на ToolbarWindow32.

Кстати, в Вашем примере проще использовать WIN-POS

Code: Select all
FOR-CHILD-WINDOWS: "<win>"
    WIN-HWND WIN-POS  \ x1 y1 \ Получаем координаты левого верхнего родительского окна
    DROP  \ x1
    WIN-CHILD-HWND WIN-POS  \ x1 x2 y2 \ Получаем координаты дочернего окна
    DROP \ x1 x2
    - 299 > IF
      \  Третье окно найдено
    THEN
;FOR-CHILD-WINDOWS
Burunduk
 
Posts: 73
Joined: Thu, 03 Oct 2013, 06:57

Re: Поиск дочернего окна

Postby Burunduk » Wed, 13 Nov 2013, 07:47

AlikasS wrote:выведет только один хинт элемент однозначно определяется


Да, я заметил, что статики есть только на одной дочерней форме. Хоть в этом повезло.
Ещё есть статики на впомогательных формах вроде About, Settings и т.п.
Но они модальные, и должны быть закрыты до момента синхронизации, и следовательно не попадут в список
перебора.

Теперь буду искать слова для работы со временем и строками.
Burunduk
 
Posts: 73
Joined: Thu, 03 Oct 2013, 06:57

Re: Поиск дочернего окна

Postby AlikasS » Wed, 13 Nov 2013, 08:46

Burunduk wrote:Теперь буду искать слова для работы со временем и строками.

для правильного вектора :-D
Code: Select all
FOUND-CHILD-WINDOW
из моего примера с HINT даст строку из Static

Code: Select all
3 - 0 MAX
обрежет сроку на 3 символа справа (отброс секунд, если не нужна такая точность)

Code: Select all
SH:M>Min
переведет строку в минуты
итого мы имеем на стеке количество минут из таймера в программе

предлагаю вычислить из текущего времени (из системы) аналогичное число
сравнить их и принять решение о синхронизации или не...
User avatar
AlikasS
 
Posts: 1434
Joined: Wed, 28 Jun 2006, 05:39
Location: Khabarovsk

PreviousNext

Return to nnCron forum (Russian)

Who is online

Users browsing this forum: No registered users and 3 guests