Что нового

Почему WinGetState возвращает неверное значение статуса окна?

agikon

Знающий
Сообщения
789
Репутация
17
Подскажите пожалуйста в чём дело.
У меня WinGetState возвращает неверные значение статусов окон. Например окно развернуто, но WinGetState возвращает значение не 32, а 47. Если окно сверну то возврщает не 16, а 15.

Вот самый простой пример, создал файл 1.txt и открыл блокнотом, и на рабочем столе это окно отображается, но WinGetState возвращает значеник 47.
WinXp

Код:
sleep(3000) ; 3 секунды чтобы скрипт успел свернутся и удостовериться что окно "1.txt - Блокнот" развёрнуто
	$status = WinGetState("1.txt - Блокнот", "")
	
    If BitAnd($status, 32) Then
        MsgBox(64,'окно развёрнуто',$status, '')
    Else
		MsgBox(64,'по данным скрипта окно не развёрнуто',$status, '')
    EndIf
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
agikon [?]
WinGetState возвращает значение 47
Окно одновременно имеет несколько состояний. 47 - это сумма значений: 32+8+4+2+1. Чтобы получить конкретное значение (состояние) вы и применяете BitAnd().
Разве у вас при выполнении скрипта заголовок сообщения не "окно развёрнуто"?
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
InnI [?]
Разве у вас при выполнении скрипта заголовок сообщения не "окно развёрнуто"?
нет.
в том то и дело что выбивает
Код:
MsgBox(64,'по данным скрипта окно не развёрнуто',$status, '')

я ж говорю что BitAnd возвращает значение 47, а не 32.

Ах да.
47 это когда окно развёрнуто на весь экран и отображается.
А если отображается, но не на весь экран (а маленьким окошком), то возвращает значение 7.
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
InnI [?]
Всё правильно. А если за 3 секунды вы его активируете, то будет ещё +8. И т.д.
активирую.
47 это с активированым на весь экран.
А если не активиравное то возвращает 39.
но никак не 32.

кстати
если окно не активировано то должно выдавать 2 (2 = окно отображается)
исходя из справки по WinGetState


В справке вот какие возвраты
Код:
Возвращаемое значение

Параметры состояния указанного окна. Для выделения перечисленных ниже параметров требуется использовать совместно с BitAND():
    1 = окно имеется 
    2 = окно отображается
    4 = окно доступно
    8 = окно активно
    16 = окно свернуто
    32 = окно развернуто
При ошибке возвращается 0 и величина @error равна 1, если окно не найдено.

47,7,15,39 в справке вообще нет таких возвращений.
У меня есть всё что угодно, но не 1,2,4,8,16,32.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Ещё раз объясняю. Возвращается СУММА значений. А функция BitAnd() определяет, есть ли в данной сумме запрашиваемое вами значение. В сумме 47 будет 32 - значит окно развёрнуто. А в сумме 7 не будет 32 - значит окно НЕ развёрнуто. Но в обоих случаях окно есть, отображается и доступно (1+2+4). Значение 32 не будет никогда, т.к. развёрнутое окно должно быть, а это уже +1.
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
InnI [?]
Ещё раз объясняю. Возвращается СУММА значений. А функция BitAnd() определяет, есть ли в данной сумме запрашиваемое вами значение. В сумме 47 будет 32 - значит окно развёрнуто. А в сумме 7 не будет 32 - значит окно НЕ развёрнуто. Но в обоих случаях окно есть, отображается и доступно (1+2+4). Значение 32 не будет никогда, т.к. развёрнутое окно должно быть, а это уже +1.
А почему тогда у меня функция BitAnd() не определяет 32 (хотя ж в 47 есть 32 как вы говорите) ?
Окно развёрнуто, активно, возвращает 47, но пишет что
Код:
MsgBox(64,'по данным скрипта окно не развёрнуто',$status, '')



Вы же видите что я в скрипте запрашиваю есть 32 или нет.
И BitAnd()говорит что 32 нет, хотя при этом возвращает 47.

Код:
sleep(3000) ; 3 секунды чтобы скрипт успел свернутся и удостовериться что окно "1.txt - Блокнот" развёрнуто
    $status = WinGetState("1.txt - Блокнот", "")
   
    If BitAnd($status, 32) Then
        MsgBox(64,'окно развёрнуто',$status, '')
    Else
        MsgBox(64,'по данным скрипта окно не развёрнуто',$status, '')
    EndIf


Так как же 32 вытянуть из этой СУММЫ 47?
Или что посоветуете?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
попробуй так
Код:
While 1
	$status = WinGetState('1 — Блокнот')
	If BitAND($status, 32) Then
		ConsoleWrite($status & @CRLF)
		;MsgBox(64, 'окно развёрнуто', $status, '')
	EndIf
	Sleep(100)
WEnd

увидишь только два значения - 39 и 47. это если окно развернуто и на переднем плане(47) или окно развернуто, но не на переднем плане (39). если не критично, то применяй класс окна вместо заголовка
так или иначе оба значения имеют в себе число 32, то есть - окно развернуто
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
agikon,
Так должно понятнее быть. Запускайте скрипт и меняйте вручную состояние окна.
Код:
Global Static $i__State
Global $iPID, $aWnd, $hWnd, $iTmp, $aState[6] = ['существует', 'отображается', 'доступно', 'активно', 'свёрнуто', 'развёрнуто'], $sMess

$iPID = Run('notepad.exe')
If Not $iPID Then Exit 13
$iTmp = TimerInit()
While TimerDiff($iTmp) < 3000
	$aWnd = WinList('[Class:Notepad]')
	For $i = 1 To $aWnd[0][0]
		If WinGetProcess($aWnd[$i][1]) <> $iPID Then ContinueLoop
		If Not BitAND(WinGetState($aWnd[$i][1]), 2) Then ContinueLoop
		$hWnd = $aWnd[$i][1]
		$aWnd = 0
		$iPID = 0
		$iTmp = 0
		ExitLoop 2
	Next
	Sleep(3)
WEnd
If Not $hWnd Then Exit 13

While WinExists($hWnd)
	Sleep(1000)
	$iTmp = WinGetState($hWnd)
	If $iTmp And $i__State <> $iTmp Then
		$i__State = $iTmp
		$sMess = 'WinGetState = ' & $i__State & ' -->  Окно:' & @LF
		For $i = 0 To 5
			If BitAND($i__State, 2 ^ $i) Then $sMess &= 2 ^ $i & ' --> ' & $aState[$i] & @LF
		Next
		ToolTip($sMess, 0, 0)
	EndIf
WEnd
Exit
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Вы же видите что я в скрипте запрашиваю есть 32 или нет.
И BitAnd()говорит что 32 нет, хотя при этом возвращает 47.

:shok: ГДЕ он такое говорит ?

Код:
sleep(3000) ; 3 секунды чтобы скрипт успел свернутся и удостовериться что окно "1.txt - Блокнот" развёрнуто
    $status = WinGetState("Безымянный", "")

    If BitAnd($status, 32) Then
        MsgBox(64,'окно развёрнуто',"Статус = "&$status&@CR&"BitAnd 32 = "&BitAnd($status, 32))
    Else
        MsgBox(64,'по данным скрипта окно не развёрнуто',"Статус = "&$status&@CR&"BitAnd 32 = "&BitAnd($status, 32))
    EndIf
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
agikon [?]
Вы же видите что я в скрипте запрашиваю
Вижу. И этот скрипт работает правильно. Но мне почему-то кажется, что у себя вы запускаете другой скрипт... или у вас AutoIt сломался :smile:
Сообщите результат выполнения следующего кода:
Код:
$status = 47
MsgBox(64, 'test_47', BitAnd($status, 32), '')
$status = 7
MsgBox(64, 'test_7 ', BitAnd($status, 32), '')
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
joiner
Ваш код такой же как и мой, только разница ваш в цикле. Результаты аналогичны, показывает неверные результаты, при развёернутом окне, пишет что окно свёрнуто.
C2H5OH
И ваш код тоже самое возврвщает.Результаты аналогичны, показывает неверные результаты, при развёернутом окне, пишет что окно свёрнуто.

madmasles
Да, ваш скрипт явно правильно работает.
Возвращает вот такие значение:
-окно развёрнуто на весь экран, и активно - 47
-окно на весь экран, но не активно-39

-окно маленькое, активно -15
-окно маленькое, не активно-7

-окно маленькое, свернуто-23
-окно на весь экран, свёрнуто- 23
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
agikon
ну так код и показывает сумму в которой есть 32. а это число есть только в двух числах - 39 и 47. условие же срабатывает. ты запрашиваешь не число 32, а сумму. и если в сумме есть 32, то срабатывает условие. вот я и показал тебе в примере, что все работает
ну так такой же код и у madmasles. только уточняет. но в сумме дает то же.
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
joiner
Я понял что вы хотите сказать, но суть в том чтобы выдернуть эти 32 и 16 из этой всей суммы.
В примере от madmasles именно 16 и 32 выдернуты из суммы.
Уже сейчас я начинаю понимать что вообщето можно было привязаться к всей сумме, то есть к 47, 39, 15, и не ждать 1,2,4,8,16,32.
Но ведь я ориентировался на справку, а там вроде бы как 1,2,4,8,16,32 должны были возвращаться, и про сумму ни слова, вот я и не понимал откуда берутся 47и 39, а не 1,2,4,8,16,32.

Вот смотрите пример из справки
Код:
$state = WinGetState("Untitled", "")

; Is the "minimized" value set?
If BitAnd($state, 16) Then
    MsgBox(0, "Пример", "Window is minimized")
EndIf

Оказывается это не верный пример, 16 не вернётся из такого примера? а возвратится 23.

Всем спасибо за разьяснение, теперь остаточно всё понял.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
agikon
пример от madmasles просто конкретизирован. и все. но вычисление идет из возведения в степень и перебора.
что нужно? получить три состояния окна? 39 - развернуто, но не активно, 47 - развернуто и активно.
Код:
While 1
	$status = WinGetState('1 — Блокнот')
	If $status = 39 Then
		ToolTip('Окно развернуто - неактивно', 0, 0)
	ElseIf $status = 47 Then
		ToolTip('Окно развернуто - активно', 0, 0)
	ElseIf $status = 23 Then
		ToolTip('Окно свернуто', 0, 0)
	EndIf
	Sleep(100)
WEnd

и это то же самое, что я привел выше
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
joiner [?]
пример от madmasles просто конкретизирован. и все. но вычисление идет из возведения в степень и перебора. что нужно? получить три состояния окна? 39 - развернуто, но не активно, 47 - развернуто и активно.
Всё верно.
Но я ж говорю в справке ошибка.
От я и не понимал откуда берутся эти 47,39 и т.д.
Ведь в справке об этим ни слова.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
agikon [?]
Оказывается это не верный пример, 16 не вернётся из такого примера.
Это верный пример. И в этом примере не возвращается 16. Здесь определяется - есть ли 16 в $state. "да" или "нет".
Кликните по функции
Код:
WinGetState()
и прочитайте справку на этом сайте. Возможно, она будет более понятна.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
ошибки нет
Возвращает значение, указывающее состояние окна. Используйте BitAND(), чтобы проверить содержит ли сумма параметров интересующую вас составляющую:
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
agikon
Число представляет собой битовый флаг, например в бинарном виде это будет так:
47 = 101111

47 = 32 + 8 + 4 + 2 + 1

Видишь 0 красным помечен, а в сумме отсутствует 16? Так вот 0 стоит в позиции флага 16. Если добавишь 16, получишь число 63 и битовый флаг сменится на 1. Это такой способ хранить флаги в числе (хранить несколько триггеров в числе).

Лень мне фотошопить тебе картинку, просто смотри по цвету цифр в верхней и нижней строке. Цвет числа и его позиция битового флага того же цвета. Это двоичная математика.

Ещё такая строка поможет понять позицию по степеням.
47 = 2^5 + 2^3 + 2^2 + 2^1 + 2^0

Ещё пример, чтобы понять установку битового флага
1 = 000001
2 = 000010
4 = 000100
8 = 001000
16 = 010000
32 = 100000
------------------
12 = 001100 (8 + 4)
 
Верх