Что нового

альтернативный способ переключения окон в windows

Автор
A

Alexey

Новичок
Сообщения
171
Репутация
0
окна по ctrl+win+1/2 теперь переключаются нормально

что касается комбинации ctrl+win+3, то она ведёт себя странно - должна всегда переключать с текущего на следующее (и затем наоборот), а она переключает по-разному. иногда - правильно, иной раз - на предыдущее окно
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Alexey [?]
что касается комбинации ctrl+win+3, то она ведёт себя странно - должна всегда переключать с текущего на следующее (и затем наоборот), а она переключает по-разному. иногда - правильно, иной раз - на предыдущее окно
Это из за сложности(?) индикации текущего окна. Ведь когда пользователь (я, вы) перключает окна вручную, то сбивается последовательность окон, тогда следующее может стать предыдущим. Решение есть, но оно подразумивает установку хука на окна, ну или циклический мониторинг активных окон... позже попробую сделать.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Мда, как иногда всё бывает просто :D - решение оказалось намного проще и элегантнее чем я думал, ведь можно просто сравнивать активное окно с последним в "цикле" переключения, и если не совпадает, то аннулируем "цикл" чтобы начать переключение с текущего.

Поправил.
 
Автор
A

Alexey

Новичок
Сообщения
171
Репутация
0
CreatoR
большое спасибо, всё работает

с помощью одного менеджера быстрых клавиш уже назначил предыдущее окно на num 7, следующее - на num 1, а переключение между двумя - на клавишу \ (та из четырёх кнопок \ и /, которая рядом с левым shift). мега-удобно
:IL_AutoIt_1:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Alexey [?]
Ctrl + Win + 1/2 я привёл вот почему: запускать каждую из двух команд всё равно буду исключительно одной кнопкой (это максимально удобно, ради этого, по сути, всё и затевается). у меня это будут num 7 (previous window) и num 1 (next window). но если именно их прописать в скрипте, то будут конфликты с другими клавишами, поскольку num 7 - это также и home (а num 1 - end)
Ничего подобного, назначить можно их без проблем:

Код:
Global $sSwitchBack_HT 			= "{NUMPAD7}"
Global $sSwitchNext_HT 			= "{NUMPAD1}"
 
Автор
A

Alexey

Новичок
Сообщения
171
Репутация
0
CreatoR
попробовал назначить num 1 и num 7 напрямую - теперь окна переключаются исключительно при включённом num lock. без горящего индикатора num lock просто выполняются действия home и end
мне этот вариант абсолютно не подходит, поскольку я не использую num lock вообще (равно как и caps lock, и scroll lock), у меня они все всегда погашены

но в принципе, конечно, было бы неплохо обойтись в данном случае прямой привязкой к клавишам num 1 и num 7, без использования менеджера быстрых клавиш
(у меня была даже мысль полностью все необходимые мне действия из этого менеджера прописать в одном скрипте для Auto It, а от самого менеджера избавиться, ибо глючный он несколько. но сам я не справлюсь, ведь нюансов там немало, а как на данном форуме об этом просить помочь толком не придумал. ну не в столе же заказов создавать топик ?)

по поводу данной темы всё-таки ещё появился вопрос. я заметил, что в случаях, когда окно (имеющее кнопку на панели задач) содержит под-окно, то переключение окон на панели задач происходит с учётом этого под-окна (в случае, если в нём, допустим, набирается текст, т.е., курсор активен), причём, оно чуть ли не всегда не имеет своей кнопки на панели задач
это не удобно, поскольку не очевидно, на какое окно скрипт будет переключать

примеры: 1) fire-fox и его под-окно "сохранить объект как"..., 2) adobe audition и его под-окна "open", "reading...data"..., 3) u-torrent и его под-окно "открыть торрэнт" ...
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Alexey
Я даже виндовые комбинации клавиш отключил...
А все необходимые "горячие клавиши" создал при помощи одного скрипта на AutoIt...

Однако, также встречался с проблемой NumLock, которую не нашел способа решить...
 
Автор
A

Alexey

Новичок
Сообщения
171
Репутация
0
благодарствую ;) с исправлениями теперь всё стало максимально удобно
 
Автор
A

Alexey

Новичок
Сообщения
171
Репутация
0
просьба к CreatoR'у дополнить скрипт следующим функционалом:

1. переключение (по ctrl-win-5) на 2 окн? назад (то есть, к примеру, находясь в пятом окне, переключаешь сразу на третье, без какого-либо отображения четвёртого)
(находясь на первом, переключаешь сразу на предпоследнее)

2. переключение (по ctrl-win-6) на 2 окн? вперёд
(находясь на последнем, переключаешь сразу на второе)

3. переключение (по ctrl-win-7) сразу к с?мому первому окну
4. переключение (по ctrl-win-8) сразу к с?мому последнему окну
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Alexey
Ок, добавил.
А также добавил диалог выбора горячих клавиш с последующим сохранением в ini-файл. Пришлось немного попотеть чтобы подключить библиотеки Yashied'а к скрипту (точнее заставить работать), но оно того стоило, я теперь в новых проектах только эти либы и буду использовать :beer:



Скачать
 
Автор
A

Alexey

Новичок
Сообщения
171
Репутация
0
CreatoR, спасибо за очередные улучшения :smile:

впрочем, промучившись вчера пару часов и сегодня ещё больше и не добившись надёжного и нужного результата, я всё-таки вынужден попросить выложить ещё один вариант последнего скрипта
в нём не должно быть:
- диалога выбора горячих клавиш
- сохранения в ini-файл

в нём должно быть:
- всё как и раньше, но только с добавлением тех функций, о которых говорилось вчера

и поскольку комбинации теперь прописываются по-другому, прошу вместо меня в скрипте их прописать, используя эти сочетания клавиш:
Global $sDef_Exit_HT ctrl + shift + R
Global $sDef_SwitchBack_HT ctrl + win + 1
Global $sDef_SwitchNext_HT ctrl + win + 2
Global $sDef_SwitchDblBack_HT ctrl + win + 8
Global $sDef_SwitchDblNext_HT ctrl + win + 9
Global $sDef_SwitchNextBack_HT ctrl + win + 3
Global $sDef_SwitchBackNext_HT ctrl + win + 7
Global $sDef_SwitchFirst_HT ctrl + win + 0
Global $sDef_SwitchLast_HT ctrl + win + 5

по возможности безо всяких zip-файлов, просто как и прежде в тэге Auto It

ещё вопрос по трём дополнительным файлам в zip-архиве (HotKey.au3, HotKeyInput.au3, vkArray.au3)
правильно ли я сделал, что закинул эти 3 файла в папку Include и при этом имевшийся HotKey.au3 был заменён новым из этого архива ?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Alexey [?]
в нём не должно быть:
Ок:
Код:
;<TaskBar Windows Switcher> program by G.Sandler, v1.1
;http://autoit-script.ru/index.php/topic,203.0.html

#NoTrayIcon
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <GUIToolbar.au3>
#include <WinAPI.au3>
#include <Array.au3>
#include <Misc.au3>
#include <HotKey.au3>

_Singleton("TaskBar_Windows_Switcher")

#Region Variables & Options
Opt("WinWaitDelay", 1)

Global $sLast_NextBack_Window 		= ""
Global $sLast_BackNext_Window 		= ""        

Global $sExit_HT 					= 0x0352 ;ctrl + shift + R
Global $sSwitchBack_HT 				= 0x0A31 ;ctrl + win + 1
Global $sSwitchNext_HT 				= 0x0A32 ;ctrl + win + 2
Global $sSwitchDblBack_HT 			= 0x0A38 ;ctrl + win + 8
Global $sSwitchDblNext_HT 			= 0x0A39 ;ctrl + win + 9
Global $sSwitchNextBack_HT 			= 0x0A33 ;ctrl + win + 3
Global $sSwitchBackNext_HT 			= 0x0A37 ;ctrl + win + 7
Global $sSwitchFirst_HT 			= 0x0A30 ;ctrl + win + 0
Global $sSwitchLast_HT 				= 0x0A35 ;ctrl + win + 5
Global $sSwitchAsAltTab_HT 			= 0x0409 ;alt + tab

$aHK_Vars = StringSplit("Exit|Back|Next|DblBack|DblNext|NextBack|BackNext|First|Last|AsAltTab", "|")

For $i = 1 To $aHK_Vars[0]
	If $aHK_Vars[$i] = "Exit" Then
		_HotKeyAssign($sExit_HT, "_Exit")
	Else
		_HotKeyAssign(Eval("sSwitch" & $aHK_Vars[$i] & "_HT"), "_SwitchTaskBarWindow_Proc", _
			BitOR($HK_FLAG_DEFAULT, $HK_FLAG_EXTENDEDCALL))
	EndIf
Next
#EndRegion Variables & Options

While 1
	Sleep(1000)
WEnd

Func _SwitchTaskBarWindow_Proc($iKey)
	Local $HotKeyPressed = "0x" & Hex($iKey, 4)
	_HotKeyAssign($HotKeyPressed)
	
	Local $sActivate_Window = "", $hParent_Active_Wnd = _WinAPI_GetAncestor(WinGetHandle(""), $GA_ROOTOWNER)
	Local $aTaskBarWindows = _WinListTaskBarWindowsEx(Number($HotKeyPressed <> $sSwitchAsAltTab_HT))
	
	If @error Then Return _HotKeyAssign($HotKeyPressed, "_SwitchTaskBarWindow_Proc", BitOR($HK_FLAG_DEFAULT, $HK_FLAG_EXTENDEDCALL))
	
	For $i = 1 To $aTaskBarWindows[0][0]
		If WinActive($aTaskBarWindows[$i][0]) Or $aTaskBarWindows[$i][0] = $hParent_Active_Wnd Then
			Switch $HotKeyPressed
				Case $sSwitchBack_HT, $sSwitchAsAltTab_HT ;Предыдущее окно (1-ое по счёту)
					If $i = 1 Then $i = $aTaskBarWindows[0][0] + 1
					$sActivate_Window = $aTaskBarWindows[$i - 1][0]
				Case $sSwitchNext_HT, $sSwitchAsAltTab_HT ;Следующее окно (1-ое по счёту)
					If $i = $aTaskBarWindows[0][0] Then $i = 0
					$sActivate_Window = $aTaskBarWindows[$i + 1][0]
				Case $sSwitchDblBack_HT ;Предыдущее окно (2-ое по счёту)
					If $i = 1 Then $i = $aTaskBarWindows[0][0] + 1
					If $i = 2 Then $i = $aTaskBarWindows[0][0] + 2
					$sActivate_Window = $aTaskBarWindows[$i - 2][0]
				Case $sSwitchDblNext_HT	;Следующее окно (2-ое по счёту)
					If $i = $aTaskBarWindows[0][0] Then $i = 0
					If $i + 2 <= $aTaskBarWindows[0][0] Then $sActivate_Window = $aTaskBarWindows[$i + 2][0]
				Case $sSwitchNextBack_HT ;Следующее <> Предыдущее окно
					If $sLast_NextBack_Window <> $aTaskBarWindows[$i][0] Then $sLast_NextBack_Window = ""
					
					If $sLast_NextBack_Window = "" Then
						If $i = $aTaskBarWindows[0][0] Then $i = 0
						$sActivate_Window = $aTaskBarWindows[$i + 1][0]
						$sLast_NextBack_Window = $sActivate_Window
					Else
						If $i = 1 Then $i = $aTaskBarWindows[0][0] + 1
						$sActivate_Window = $aTaskBarWindows[$i - 1][0]
						$sLast_NextBack_Window = ""
					EndIf
				Case $sSwitchBackNext_HT ;Предыдущее <> Следующее окно
					If $sLast_BackNext_Window <> $aTaskBarWindows[$i][0] Then $sLast_BackNext_Window = ""
					
					If $sLast_BackNext_Window = "" Then
						If $i = 1 Then $i = $aTaskBarWindows[0][0] + 1
						$sActivate_Window = $aTaskBarWindows[$i - 1][0]
						$sLast_BackNext_Window = $sActivate_Window
					Else
						If $i = $aTaskBarWindows[0][0] Then $i = 0
						$sActivate_Window = $aTaskBarWindows[$i + 1][0]
						$sLast_BackNext_Window = ""
					EndIf
				Case $sSwitchFirst_HT, $sSwitchLast_HT
					$sActivate_Window = ""
			EndSwitch
			
			ExitLoop
		EndIf
	Next
	
	;Не найдены активные окна...
	If $sActivate_Window = "" Then
		Switch $HotKeyPressed
			Case $sSwitchBack_HT, $sSwitchLast_HT
				;Активируем последнее окно
				$sActivate_Window = $aTaskBarWindows[$aTaskBarWindows[0][0]][0]
			Case Else
				;Активируем первое окно
				$sActivate_Window = $aTaskBarWindows[1][0]
		EndSwitch
	EndIf
	
	WinActivate($sActivate_Window)
	_HotKeyAssign($HotKeyPressed, "_SwitchTaskBarWindow_Proc", BitOR($HK_FLAG_DEFAULT, $HK_FLAG_EXTENDEDCALL))
EndFunc

Func _WinListTaskBarWindowsEx($iListSort=1)
	Local $hToolbar = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", "ToolbarWindow323")
	If @error Then $hToolbar = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", "ToolbarWindow322")
	If @error Then Return SetError(1, 0, 0)
	
	Local $aWinList = WinList()
	Local $aRet_List[$aWinList[0][0] + 1][2], $iToolbarButtonIndex
	
	For $i = 1 To $aWinList[0][0] Step 1
		If Not BitAND(WinGetState($aWinList[$i][1]), 2) Then ContinueLoop
		
		$iToolbarButtonIndex = _WinAPI_FindToolbarButton($aWinList[$i][1], $hToolbar)
		
		If $iToolbarButtonIndex > 0 Then
			$aRet_List[0][0] += 1
			$aRet_List[$aRet_List[0][0]][0] = $aWinList[$i][1]
			$aRet_List[$aRet_List[0][0]][1] = $iToolbarButtonIndex
		EndIf
	Next
	
	If $aRet_List[0][0] = 0 Then Return SetError(2, 0, 0)
	
	ReDim $aRet_List[$aRet_List[0][0] + 1][2]
	If $iListSort Then _ArraySort($aRet_List, 0, 1, $aRet_List[0][0], 1)
	
	Return $aRet_List
EndFunc

Func _WinAPI_FindWindowEx($hParent, $hChild, $sClass, $sWindow)
	; must create structs and use ptrs to account for passing a true NULL as classname or window title
	; simply using "wstr" and "" does NOT work
	Local $sStruct1, $sStruct2
	
	If $sClass = "" Then
		$sClass = 0
	Else
		$sStruct1 = DllStructCreate("wchar[256]")
		DllStructSetData($sStruct1, 1, $sClass)
		$sClass = DllStructGetPtr($sStruct1)
	EndIf
	
	If $sWindow = "" Then
		$sWindow = 0
	Else
		$sStruct2 = DllStructCreate("wchar[256]")
		DllStructSetData($sStruct2, 1, $sWindow)
		$sWindow = DllStructGetPtr($sStruct2)
	EndIf
	
	Local $aRet = DllCall("user32.dll", "hwnd", "FindWindowExW", "hwnd", $hParent, "hwnd", $hChild, "ptr", $sClass, "ptr", $sWindow)
	
	$sStruct1 = 0
	$sStruct2 = 0
	
	Return $aRet[0]
EndFunc

Func _WinAPI_FindToolbarButton($hWnd, $hTB)
	Local $iReturn = -1, $iPID, $hProcess, $sStruct = DllStructCreate("ptr")
	
	; open process owning toolbar control
	_WinAPI_GetWindowThreadProcessId($hTB, $iPID)
	
	$hProcess = _WinAPI_OpenProcess(0x410, False, $iPID)
	
	If $hProcess Then
		Local $iCount = _GUICtrlToolbar_ButtonCount($hTB)
		
		For $i = 0 To $iCount - 1
			Local $iID = _GUICtrlToolbar_IndexToCommand($hTB, $i)
			
			; button param is ptr to owner's window handle, stored in target process's memory space
			Local $dwData = _GUICtrlToolbar_GetButtonParam($hTB, $iID)
			
			; read the window handle from the explorer process
			Local $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", _
					$hProcess, "ptr", $dwData, "ptr", DllStructGetPtr($sStruct), "uint", 4, "uint*", 0)
			
			If $aRet[5] Then
				If $hWnd = DllStructGetData($sStruct, 1) Then
					$iReturn = $i
					ExitLoop
				EndIf
			EndIf
		Next
		
		_WinAPI_CloseHandle($hProcess)
	EndIf
	
	Return $iReturn
EndFunc

Func _Exit()
	Exit
EndFunc


правильно ли я сделал, что закинул эти 3 файла в папку Include и при этом имевшийся HotKey.au3 был заменён новым из этого архива ?
Многие скажут что да, я лично папку includ'ов стараюсь не трогать.
 
Автор
A

Alexey

Новичок
Сообщения
171
Репутация
0
сейчас вроде бы всё в порядке, большое спасибо за отзывчивость и оперативность. буду с удовольствием использовать этот Special Edition ;)
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
CreatoR сказал(а):
Задачка интересная, но как бы удивительно это не звучало, мне вот одно неясно - почему именно «Ctrl + Win + 1/2»? это же неудобно. Вообщем вот сделал через «Win + Left/Right»:

Код:
#NoTrayIcon
#include <GUIToolbar.au3>
#include <Array.au3>
;

Opt("WinWaitDelay", 1)

$sExit_HT = "^+e" ;Выход по <Ctrl + Shift + E>
$sSwitchBack_HT = "#{Left}"
$sSwitchNext_HT = "#{Right}"

HotKeySet($sExit_HT, "_Exit")
HotKeySet($sSwitchBack_HT, "_SwitchTaskBarWindow_Proc")
HotKeySet($sSwitchNext_HT, "_SwitchTaskBarWindow_Proc")

While 1
	Sleep(1000)
WEnd

Func _SwitchTaskBarWindow_Proc()
	HotKeySet(@HotKeyPressed)
	
	Local $sActivate_Window = ""
	Local $aTaskBarWindows = _WinListTaskBarWindowsEx()
	
	If @error Then Return HotKeySet(@HotKeyPressed, "_SwitchTaskBarWindow_Proc")
	
	For $i = 1 To $aTaskBarWindows[0][0]
		If WinActive($aTaskBarWindows[$i][0]) Then
			Switch @HotKeyPressed
				Case $sSwitchBack_HT ;Предыдущее окно
					If $i = 1 Then $i = $aTaskBarWindows[0][0] + 1
					$sActivate_Window = $aTaskBarWindows[$i - 1][0]
				Case $sSwitchNext_HT ;Следующее окно
					If $i = $aTaskBarWindows[0][0] Then $i = 0
					$sActivate_Window = $aTaskBarWindows[$i + 1][0]
			EndSwitch
			
			ExitLoop
		EndIf
	Next
	
	;Не найдены активные окна...
	If $sActivate_Window = "" Then
		Switch @HotKeyPressed
			Case $sSwitchBack_HT
				;Активируем последнее окно
				$sActivate_Window = $aTaskBarWindows[$aTaskBarWindows[0][0]][0]
			Case $sSwitchNext_HT
				;Активируем первое окно
				$sActivate_Window = $aTaskBarWindows[1][0]
		EndSwitch
	EndIf
	
	WinActivate($sActivate_Window)
	HotKeySet(@HotKeyPressed, "_SwitchTaskBarWindow_Proc")
EndFunc

Func _WinListTaskBarWindowsEx()
	Local $hToolbar
	
	For $i = 2 To 4
		$hToolbar = ControlGetHandle("[CLASS:Shell_TrayWnd]", "", "ToolbarWindow32" & $i)
		If Not @error Then ExitLoop
	Next
	
	Local $aWinList = WinList()
	Local $aRet_List[$aWinList[0][0] + 1][2], $iToolbarButtonIndex
	
	For $i = $aWinList[0][0] To 1 Step -1
		If Not BitAND(WinGetState($aWinList[$i][1]), 2) Then ContinueLoop
		
		$iToolbarButtonIndex = _WinAPI_FindToolbarButton($aWinList[$i][1], $hToolbar)
		
		If $iToolbarButtonIndex > 0 Then
			$aRet_List[0][0] += 1
			$aRet_List[$aRet_List[0][0]][0] = $aWinList[$i][1]
			$aRet_List[$aRet_List[0][0]][1] = $iToolbarButtonIndex
		EndIf
	Next
	
	If $aRet_List[0][0] = 0 Then Return SetError(1, 0, 0)
	
	ReDim $aRet_List[$aRet_List[0][0] + 1][2]
	_ArraySort($aRet_List, 0, 1, $aRet_List[0][0], 1)
	
	Return $aRet_List
EndFunc

Func _WinAPI_FindWindowEx($hParent, $hChild, $sClass, $sWindow)
	; must create structs and use ptrs to account for passing a true NULL as classname or window title
	; simply using "wstr" and "" does NOT work
	Local $sStruct1, $sStruct2
	
	If $sClass = "" Then
		$sClass = 0
	Else
		$sStruct1 = DllStructCreate("wchar[256]")
		DllStructSetData($sStruct1, 1, $sClass)
		$sClass = DllStructGetPtr($sStruct1)
	EndIf
	
	If $sWindow = "" Then
		$sWindow = 0
	Else
		$sStruct2 = DllStructCreate("wchar[256]")
		DllStructSetData($sStruct2, 1, $sWindow)
		$sWindow = DllStructGetPtr($sStruct2)
	EndIf
	
	Local $aRet = DllCall("user32.dll", "hwnd", "FindWindowExW", "hwnd", $hParent, "hwnd", $hChild, "ptr", $sClass, "ptr", $sWindow)
	
	$sStruct1 = 0
	$sStruct2 = 0
	
	Return $aRet[0]
EndFunc

Func _WinAPI_FindToolbarButton($hWnd, $hTB)
	Local $iReturn = -1, $iPID, $hProcess, $sStruct = DllStructCreate("ptr")
	
	; open process owning toolbar control
	_WinAPI_GetWindowThreadProcessId($hTB, $iPID)
	
	$hProcess = _WinAPI_OpenProcess(0x410, False, $iPID)
	
	If $hProcess Then
		Local $iCount = _GUICtrlToolbar_ButtonCount($hTB)
		
		For $i = 0 To $iCount - 1
			Local $iID = _GUICtrlToolbar_IndexToCommand($hTB, $i)
			
			; button param is ptr to owner's window handle, stored in target process's memory space
			Local $dwData = _GUICtrlToolbar_GetButtonParam($hTB, $iID)
			
			; read the window handle from the explorer process
			Local $aRet = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", _
					$hProcess, "ptr", $dwData, "ptr", DllStructGetPtr($sStruct), "uint", 4, "uint*", 0)
			
			If $aRet[5] Then
				If $hWnd = DllStructGetData($sStruct, 1) Then
					$iReturn = $i
					ExitLoop
				EndIf
			EndIf
		Next
		
		_WinAPI_CloseHandle($hProcess)
	EndIf
	
	Return $iReturn
EndFunc

Func _Exit()
	Exit
EndFunc


А можно вместо Win + Left/Right зделать Mouse Right Click + Mouse Wheel Up/Down ???
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Creator, можешь написать код ???

Заранее спасибо.
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Спасибо за MouseSetOnEvent, я сделал чтобы прокручивать роликом (без правой кнопки мыши), но и за этого я не могу прокручивать страницы...по этому мне нужна правая кнопка мыши.
 
Верх