Что нового

[Мышь, клавиатура] Как опросить спец. клавиши

gora

Знающий
Сообщения
315
Репутация
19
При запуске скрипта требуется опросить спец. клавиши (Shift, Ctrl, Alt) и записать состояние этих клавиш в переменную в виде суммы флагов:
1 = Shift
2 = Ctrl
4 = Alt
Возможно ли это сделать и как?

Спасибо.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
gora [?]
При запуске скрипта требуется опросить спец. клавиши
Если я правильно понял, что надо проверить нажаты эти клавиши или нет, то, можно так попробовать:
Код:
#include <Misc.au3>

Global $iShift = 1, $iCtrl = 10, $iAlt = 100 ; не нажаты

$hDll = DllOpen('user32.dll')

If _IsPressed('10', $hDll) Then
	$iShift = 2 ;нажата
EndIf
If _IsPressed('11', $hDll) Then
	$iCtrl = 20 ;нажата
EndIf
If _IsPressed('12', $hDll) Then
	$iAlt = 200 ;нажата
EndIf
DllClose($hDll)

MsgBox(64, 'Info', 'Shift: ' & $iShift & @LF & 'Ctrl: ' & $iCtrl & @LF & _
		'Alt: ' & $iAlt)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
gora сказал(а):
...и записать состояние этих клавиш в переменную в виде суммы флагов...

Код:
$Flag = BitOR(_IsPressed('10'), 2 * _IsPressed('11'), 4 * _IsPressed('12'))
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
madmasles, Yashied замечательно, оба способа работают, спасибо.
Может еще подскажете как победить "побочный" эффект нажатия спец. клавиш? Окно сообщения, например, MsgBox выводится на "втором" плане, т.е., под окном программы из которой был произведен запуск скрипта. Например, запускаю скрипт из текстового редактора (EmEditor), и сообщение оказывается под окном редактора.
Это можно победить?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
madmasles, нет смысла вызывать DllOpen() и DllClose() перед использованием _IsPressed(), т.к. user32.dll и многие другие библиотеки, AutoIt загружает автоматически при старте скрипта. Это все было актуально в более старых версиях AutoIt. Проверить, загружена ли DLL или нет, можно так:

Код:
#Include <WinAPI.au3>

ConsoleWrite('gdi32.dll: ' & _WinAPI_GetModuleHandle('gdi32.dll') & @CR)
ConsoleWrite('kernel32.dll: ' & _WinAPI_GetModuleHandle('kernel32.dll') & @CR)
ConsoleWrite('user32.dll: ' & _WinAPI_GetModuleHandle('user32.dll') & @CR)
ConsoleWrite('' & @CR)
ConsoleWrite('gdiplus.dll: ' & _WinAPI_GetModuleHandle('gdiplus.dll') & @CR)
ConsoleWrite('iphlpapi.dll: ' & _WinAPI_GetModuleHandle('iphlpapi.dll') & @CR)


gora сказал(а):
Окно сообщения, например, MsgBox выводится на "втором" плане, т.е., под окном программы из которой был произведен запуск скрипта.

Используй флаг 0x40000 в функции MsgBox().
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied [?]
нет смысла вызывать DllOpen() и DllClose()
Спасибо, не знал. Я в качестве образца брал пример к _IsPressed() из справки. Может надо в справке это как-то исправить?
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
Yashied [?]
Используй флаг 0x40000 в функции MsgBox().
К сожалению это не решает всех проблем "побочного" действия нажатия спец. клавиш...
Я вывожу собственное окно и в нем устанавливаю кнопку по умолчанию и устанавливаю на нее фокус. Курсор мыши у меня автоматически перемещается на указанную кнопку. Задание окну режима "поверх всех" выводит его выше других окон, но вот курсор мыши не перемещается на нужную кнопку, хотя она и выделена как кнопка по умолчанию. Как бы это еще исправить, заставить курсор устанавливаться как и без нажатия спец. клавиш?
Код:
#include <Misc.au3>
$Flag = BitOR(_IsPressed('10'), 2 * _IsPressed('11'), 4 * _IsPressed('12'))
MsgBox(64+0x40000+1+256, 'Info', '$Flag: ' & $Flag)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Ничего не понимаю. Нужно, чтобы при появлении MsgBox(), курсор автоматически перемещался на кнопку "OK"? Лучше приведи рабочий пример, демонстрирующий то, что необходимо в результате получить...
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
Yashied [?]
приведи рабочий пример, демонстрирующий то, что необходимо в результате получить...
Я привел в посте выше. Кнопка, на которую перемещается курсор - "Отмена". При запуске с нажатой спец. клавишей курсор на нее не перемещается. Если точнее, то это зависит от времени удерживания спец. клавиш. Если их удерживать более некоторого времени, то не перемещается, а если менее, то перемещается.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
:wacko:

Ммм... Курсор (курсор мыши) никуда не перемещается, да и не должен.
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
Yashied сказал(а):
никуда не перемещается, да и не должен.
У меня перемещается! :smile: В настройках мыши у меня стоит галка "На кнопке выбранной по умолчанию" (win XP SP3). И курсор выполняет это предписанное ему действие.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied,
Может в Windows 7 такой опции нет?
gora
У меня тоже такая опция стоит. Так, вроде, перемещается мышка:
Код:
#include <Misc.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Sleep(2000); чтобы нажать клавиши

Opt('MouseCoordMode', 2)

$hGui = GUICreate('', 260, 100)
$nButtonOK = GUICtrlCreateButton('OK', 20, 30, 100, 40)
$nButtonDefault = GUICtrlCreateButton('No OK', 140, 30, 100, 40, $BS_DEFPUSHBUTTON)
GUICtrlSetState(-1, $GUI_FOCUS)
GUISetState()

$Flag = BitOR(_IsPressed('10'), 2 * _IsPressed('11'), 4 * _IsPressed('12'))

If $Flag Then
	;WinSetOnTop($hGui, '', 1)
	MouseMove(190, 50, 0)
EndIf

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nButtonDefault
			MsgBox(0, '', 'No OK')
		Case $nButtonOK
			MsgBox(0, '', 'OK')
	EndSwitch
WEnd
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
:smile:

Я, если честно, вообще про эту опцию только сейчас вспомнил. Ну, не пользуюсь я ей. Вот немного измененный пример madmasles'а:

Код:
#Include <GUIConstantsEx.au3>
#Include <WinAPI.au3>

$hGui = GUICreate('', 260, 100)
$nButtonOK = GUICtrlCreateButton('OK', 20, 30, 100, 40)
$nButtonDefault = GUICtrlCreateButton('No OK', 140, 30, 100, 40)
GUICtrlSetState(-1, BitOR($GUI_FOCUS, $GUI_DEFBUTTON))
GUISetState()

_SnapCursor()

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nButtonDefault
			MsgBox(0, '', 'No OK')
		Case $nButtonOK
			MsgBox(0, '', 'OK')
	EndSwitch
WEnd

Func _SnapCursor($hWnd = 0)

	Local $aPos, $iOpt

	If $hWnd Then
		$iOpt = Opt('WinWaitDelay', 0)
		$hWnd = WinActivate($hWnd)
		Opt('WinWaitDelay', $iOpt)
		If Not $hWnd Then
			Return 0
		EndIf
	EndIf
	$aPos = ControlGetPos('', '', _WinAPI_GetFocus())
	If Not IsArray($aPos) Then
		Return 0
	EndIf
	$iOpt = Opt('MouseCoordMode', 2)
	MouseMove($aPos[0] + $aPos[2] / 2, $aPos[1] + $aPos[3] / 2, 0)
	Opt('MouseCoordMode', $iOpt)
	Return 1
EndFunc   ;==>_SnapCursor
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied
Я, надеюсь, Вы не против, немного изменил Вашу функцию:
Код:
#include <GUIConstantsEx.au3>

Dim $aButton[11][2] = [[10]]
$hGui = GUICreate('', 200, 265)
For $i = 1 To $aButton[0][0]
	$aButton[$i][1] = 'Button ' & $i
	$aButton[$i][0] = GUICtrlCreateButton($aButton[$i][1], 50, 10 + 25 * ($i - 1), 100, 20)
	GUICtrlSetState($aButton[$i][0], $GUI_DISABLE)
Next
GUISetState()
BlockInput(1)
For $i = $aButton[0][0] To 1 Step -1
	_SnapCursor($aButton[$i][0])
	GUICtrlSetState($aButton[$i][0], $GUI_ENABLE)
	Beep(500 + $i * 100, 100)
	Sleep(500)
Next
BlockInput(0)
While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case Else
			For $i = 1 To $aButton[0][0]
				If $nMsg = $aButton[$i][0] Then
					MsgBox(0, '', $aButton[$i][1])
				EndIf
			Next

	EndSwitch
WEnd

Func _SnapCursor($nCtrlID)
	Local $aPos, $iOpt

	$aPos = ControlGetPos($hGui, '', $nCtrlID)
	If Not IsArray($aPos) Then
		Return 0
	EndIf
	$iOpt = Opt('MouseCoordMode', 2)
	MouseMove($aPos[0] + $aPos[2] / 2, $aPos[1] + $aPos[3] / 2, 0)
	Opt('MouseCoordMode', $iOpt)
	Return 1
EndFunc   ;==>_SnapCursor
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Я вот тут как раз написал универсальную функцию ControlSnapCursor(), аналогично другим Control... функциям. Теперь она может работать с любыми окнами (не только с AutoIt'овскими).

Код:
#Include <GUIConstantsEx.au3>

$hForm = GUICreate('', 260, 100)
$Button1 = GUICtrlCreateButton('OK', 20, 30, 100, 40)
$Button2 = GUICtrlCreateButton('Cancel', 140, 30, 100, 40)
GUICtrlSetState(-1, BitOR($GUI_FOCUS, $GUI_DEFBUTTON))
GUISetState()

;~ControlSnapCursor($hForm, '', $Button1)
;~ControlSnapCursor($hForm, '', $Button2)
;~ControlSnapCursor('[ACTIVE]')
ControlSnapCursor('')

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func ControlSnapCursor($sTitle, $sText = '', $sID = '')

	Local $hWnd, $aPos, $iOpt

	$iOpt = Opt('WinWaitDelay', 0)
	$hWnd = WinActivate($sTitle, $sText)
	Opt('WinWaitDelay', $iOpt)
	If Not $hWnd Then
		Return 0
	EndIf
	$aPos = ControlGetPos($hWnd, '', $sID)
	If @error Then
		Return 0
	EndIf
	$iOpt = Opt('MouseCoordMode', 2)
	MouseMove($aPos[0] + $aPos[2] / 2, $aPos[1] + $aPos[3] / 2, 0)
	Opt('MouseCoordMode', $iOpt)
	Return 1
EndFunc   ;==>ControlSnapCursor
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied
В полезняшки! :ok: :IL_AutoIt_1:
 
Верх