Что нового

Как определить нажатие клавиши в GUICtrlCreateEdit ?

agikon

Знающий
Сообщения
789
Репутация
17
Помогите пожалуйста как при печатании текста в элементе GUICtrlCreateEdit была нажата клавиша "а" то при этом выскочило сообщение.

Я вот написал как я понимаю но оно не работает, вернее даже ошибку при компиляции выдаёт.
Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>

$GUI = GUICreate("", 100, 100)
GUISetState(@SW_SHOW, $GUI)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)

While 1
    Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch

	Switch GUICtrlCreateEdit($forma1)
		If _IsPressed(41) Then ; 41 клавиша А
			MsgBox(64,'','нажата кл. А', '')
		else
		endif
	EndSwitch
WEnd
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Ну как вариант можно использовать AdlibRegister

Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>

$GUI = GUICreate("", 300, 300)
$forma1 = GUICtrlCreateEdit("", 10, 10, 280, 280, $ES_WANTRETURN)
GUISetState(@SW_SHOW, $GUI)

AdlibRegister('Test')

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
	EndSwitch
WEnd

Func test()
	Local $text = GUICtrlRead($forma1)
	If (StringRight($text, 1) == 'a') Then
		GUICtrlSetData($forma1, StringTrimRight($text, 1))
		MsgBox(0, '', 'Нажали a')
	EndIf
EndFunc
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Для _IsPressed() требуется библиотека Misc.au3
Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>
#include <Misc.au3>

$GUI = GUICreate("", 100, 100)
GUISetState(@SW_SHOW, $GUI)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)

While 1
	
	If WinActive($GUI) and _IsPressed(41) Then MsgBox(64,'','нажата кл. А', '')
	
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd


или можно так:
Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>

HotKeySet('a', 'msg')

$GUI = GUICreate("", 100, 100)
GUISetState(@SW_SHOW, $GUI)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func msg()
	MsgBox(64,'','нажата кл. А', '')
EndFunc
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
Спасибо за примеры.
Но вот каждый пример имеет свои ньюансы.
От скрипт от Viktor1703 реагирует именно на GUICtrlCreateEdit и это хорошо, но зато проверка идёт на символы а не на коды. Поэтому такую клавишу как TAB отследить как?

А скрипт от Zaramot реагирует именно на коды, но не именно в элементе GUICtrlCreateEdit "$forma1" , а по всему окну GUI , поэтому отследить в каком GUICtrlCreateEdit произошло нажатие не получается. И это плоховато.

Кстати, подскажите пожалуйста а почему от так выдаёт ошибку?
Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>
#include <Misc.au3>

$GUI = GUICreate("", 100, 100)
GUISetState(@SW_SHOW, $GUI)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)

While 1
   
    If WinActive($GUI) and _IsPressed(1B) Then MsgBox(64,'','нажата кл. TAB', '')
   
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Код:
_IsPressed('1B')


Пример с TAB, но с помощью простого ввода мне не удалось отправить TAB в Edit

Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>

$GUI = GUICreate("", 300, 300)
$forma1 = GUICtrlCreateEdit(@TAB, 10, 10, 280, 280)
GUISetState()

AdlibRegister('Test')

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func test()
    Local $text = GUICtrlRead($forma1)
    If StringRegExp($text, @TAB) Then
        GUICtrlSetData($forma1, StringReplace($text, @TAB, ''))
        MsgBox(0, '', 'Нажали TAB')
    EndIf
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,487
Как то так:

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIEdit.au3>

$GUI = GUICreate("", 100, 100)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)
$iDummy = GUICtrlCreateDummy()

GUISetState(@SW_SHOW, $GUI)
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
		Case $iDummy
			MsgBox(64, 'Title', GUICtrlRead($iDummy))
    EndSwitch
WEnd

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $nNotifyCode = BitShift($wParam, 16)
    $nID = BitAnd($wParam, 0x0000FFFF)
    $hCtrl = $lParam
	
    Switch $nNotifyCode
		Case $EN_UPDATE
            $aSel = _GUICtrlEdit_GetSel($hCtrl)
			_GUICtrlEdit_SetSel($hCtrl, $aSel[0]-1, $aSel[0])
			$sChar = ControlCommand($GUI, '', $nID, "GetSelected")
			_GUICtrlEdit_SetSel($hCtrl, $aSel[0], $aSel[0])
			
			GUICtrlSendToDummy($iDummy, $sChar)
	EndSwitch
	
    Return $GUI_RUNDEFMSG
EndFunc
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
CreatoR
скрипт работает но после 3-4 нажатий на кнопку "а" почемуто ошибка выскакивает 'память не может быть прочитана". у меня XP. Ну это скорее всего у меня что-то с ОС.

Viktor1703
а не знаете почему не посылается кодом?
а как же быть с другими клавишами которые на код не реагируют?
я так понял только макрос на @TAB есть, а на ESC/PRINT/ EXECUTE / PRINT SCREEN и др. на эти есть макросы?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,323
CreatoR,
На Win 7x86 (AutoIt 3.3.6.1) скрипт у меня тоже вылетает после второго-третьего нажатия
!>22:40:46 AutoIT3.exe ended.rc:-1073741819
>Exit code: -1073741819 Time: 7.134

PS
Так вроде работает.
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>

$GUI = GUICreate("", 100, 100)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)
$iDummy = GUICtrlCreateDummy()

GUISetState(@SW_SHOW, $GUI)
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $iDummy
			ToolTip('Last char pressed: >' & GUICtrlRead($iDummy) & '<', 0, 0)
			;ConsoleWrite(GUICtrlRead($iDummy) & @LF)
			;MsgBox(64, 'Title', GUICtrlRead($iDummy))
	EndSwitch
WEnd

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
	$nNotifyCode = BitShift($wParam, 16)
	$nID = BitAND($wParam, 0x0000FFFF)
	$hCtrl = $lParam

	Switch $nNotifyCode
		;Case $EN_UPDATE
		Case $EN_CHANGE
			$sSel = GUICtrlRead($nID)
			If $sSel Then
				$sChar = StringRight($sSel, 1)
				GUICtrlSendToDummy($iDummy, $sChar)
			EndIf
	EndSwitch

	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
madmasles
и ваш код ошибку выдает на XP.
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Так может просто проблема в GUICtrlCreateDummy() ?!

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>

$GUI = GUICreate("", 100, 100)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)
GUISetState(@SW_SHOW, $GUI)
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $nNotifyCode = BitShift($wParam, 16)
    $nID = BitAND($wParam, 0x0000FFFF)
    $hCtrl = $lParam

    Switch $nNotifyCode
        ;Case $EN_UPDATE
        Case $EN_CHANGE
            $sSel = GUICtrlRead($nID)
            If $sSel Then
                ToolTip('Last char pressed: >' & StringRight($sSel, 1) & '<', 0, 0)
            EndIf
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,323
Viktor1703 [?]
Так может просто проблема в GUICtrlCreateDummy() ?!
Я много раз использовал Dummy в функциях GUIRegisterMsg() и никогда не было проблем. :shok:
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
madmasles, ну например у меня ни Ваш ни CreatoR'a пример не работает (Windows XP sp3) а вот без Dummy - всё отлично :smile:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,323
Viktor1703 [?]
ну например у меня ни Ваш ни CreatoR'a пример не работает
А если так?
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>

$GUI = GUICreate("", 100, 100)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)
$iDummy = GUICtrlCreateDummy()

GUISetState(@SW_SHOW, $GUI)
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $iDummy
			$sSel = GUICtrlRead($forma1)
			If Not $sSel Then ContinueLoop
			$sChar = StringRight($sSel, 1)
			ToolTip('Last char pressed: >' & $sChar & '<', 0, 0)
			;ConsoleWrite(GUICtrlRead($iDummy) & @LF)
			;MsgBox(64, 'Title', GUICtrlRead($iDummy))
	EndSwitch
WEnd

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
	$nNotifyCode = BitShift($wParam, 16)
	$nID = BitAND($wParam, 0x0000FFFF)
	;$hCtrl = $lParam

	Switch $nNotifyCode
		;Case $EN_UPDATE
		Case $EN_CHANGE
			GUICtrlSendToDummy($iDummy)
	EndSwitch

	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
и всё-таки, можно как-то отследить нажатие таких клавишь как ESC/PRINT/ ENTER / PRINT SCREEN ну если не в конкретном GUICtrlCreateEdit то в целом по GUI ?
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
и всё-таки, можно как-то отследить нажатие таких клавишь как ESC/PRINT/ ENTER / PRINT SCREEN ну если не в конкретном GUICtrlCreateEdit то в целом по GUI ?
Просто поменяй клавиши в моих примерах:
Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>
#include <Misc.au3>

$GUI = GUICreate("", 100, 100)
GUISetState(@SW_SHOW, $GUI)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)

While 1
    
    If WinActive($GUI) and _IsPressed("1B") Then MsgBox(64,'','нажата кл. ESC', '')
    
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd


Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>

HotKeySet('{ESC}', 'msg')

$GUI = GUICreate("", 100, 100)
GUISetState(@SW_SHOW, $GUI)

$forma1 = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func msg()
    MsgBox(64,'','нажата кл. ESC', '')
EndFunc
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,323
agikon [?]
и всё-таки, можно как-то отследить нажатие таких клавишь как ESC/PRINT/ ENTER / PRINT SCREEN
Попробуйте так.
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <IsPressedEx.au3>;CreatoR	http://autoit-script.ru/index.php/topic,1391.0.html

Opt('MustDeclareVars', 1)
Opt('GUICloseOnESC', 0)

Global $fEdit, $hGUI, $nEdit, $aRet[2], $nBtn

$hGUI = GUICreate('Test', 150, 150)
GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND')
$nEdit = GUICtrlCreateEdit('', 10, 10, 130, 100, $ES_WANTRETURN)
$nBtn = GUICtrlCreateButton('Kill focus Edit', 10, 115, 130)
GUISetState()

While 1
	If $fEdit Then
		$aRet[0] = _IsPressedEx('[:ALLKEYS:]')
		If $aRet[0] Then
			If $aRet[1] <> $aRet[0] Then
				$aRet[1] = $aRet[0]
				ToolTip('Last char pressed: >' & __KeyGetType($aRet[1], 0) & '<', 0, 0)
			EndIf
		EndIf
	EndIf
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nBtn
			ToolTip('')
	EndSwitch
WEnd

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
	Local $nNotifyCode = BitShift($wParam, 16)
	Local $nID = BitAND($wParam, 0x0000FFFF)
	Switch $hWnd
		Case $hGUI
			Switch $nID
				Case $nEdit
					Switch $nNotifyCode
						Case $EN_SETFOCUS
							If Not $fEdit Then $fEdit = True
						Case $EN_KILLFOCUS
							If $fEdit Then $fEdit = False
					EndSwitch
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND
 

AZJIO

Меценат
Меценат
Сообщения
2,903
Репутация
1,200
agikon
Да можно. Используй GUISetAccelerators, это не глобальные горячие клавиши в отличии от HotKeySet. Когда произойдёт вызов быстрой клавиши, то проверяешь какой элемент в фокусе. Если Edit, то соответственно делаешь событие.

Мне понравился вариант от funkey для определения элемента в фокусе по ID.
Код:
$nFocused = _WinAPI_GetDlgCtrlID(ControlGetHandle($hGui, "", ControlGetFocus($hGui)))
Switch $nFocused
	Case $Input0
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,487
madmasles [?]
Так вроде работает
Для последнего символа. А что если я введу символ в середину текста?

Вот так не вылетает:

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIEdit.au3>

$GUI = GUICreate("", 100, 100)

$iEdit = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)
$iDummy = GUICtrlCreateDummy()

GUISetState(@SW_SHOW, $GUI)
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
		Case $iDummy
			$aSel = _GUICtrlEdit_GetSel($iEdit)
			_GUICtrlEdit_SetSel($iEdit, $aSel[0]-1, $aSel[0])
			$sChar = ControlCommand($GUI, '', $iEdit, "GetSelected")
			_GUICtrlEdit_SetSel($iEdit, $aSel[0], $aSel[0])
			
			MsgBox(64, 'Title', $sChar)
    EndSwitch
WEnd

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $nNotifyCode = BitShift($wParam, 16)
    
    Switch $nNotifyCode
		Case $EN_UPDATE
            GUICtrlSendToDummy($iDummy, 1)
	EndSwitch
	
    Return $GUI_RUNDEFMSG
EndFunc
 

AZJIO

Меценат
Меценат
Сообщения
2,903
Репутация
1,200
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIEdit.au3>

$hGui = GUICreate("", 100, 100)

$iEdit = GUICtrlCreateEdit("", 10, 10, 80, 80, $ES_WANTRETURN)
$iKey_a = GUICtrlCreateDummy()
$iKey_Ctrl_n = GUICtrlCreateDummy()
$iKey_Ctrl_z = GUICtrlCreateDummy()

; если раскладка не совпадает с англ. яз. то временно переключаем в неё, чтобы зарегистрировать горячие клавиши
$tmp = 0
$KeyLayout = RegRead("HKCU\Keyboard Layout\Preload", 1)
If Not @error And $KeyLayout <> 00000409 Then
	_WinAPI_LoadKeyboardLayout(0x0409)
	$tmp = 1
EndIf

Local $aAccelKeys[3][2] = [["a", $iKey_a],["^n", $iKey_Ctrl_n],["^z", $iKey_Ctrl_z]]
GUISetAccelerators($aAccelKeys)

If $tmp = 1 Then _WinAPI_LoadKeyboardLayout(Dec($KeyLayout)) ; восстанавливаем раскладку по умолчанию

GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $iKey_a
			If _Focused($iEdit) Then MsgBox(0, 'Сообщение', 'Нажата a')
		Case $iKey_Ctrl_n
			If _Focused($iEdit) Then MsgBox(0, 'Сообщение', 'Нажата Ctrl + n')
		Case $iKey_Ctrl_z
			If _Focused($iEdit) Then MsgBox(0, 'Сообщение', 'Нажата Ctrl + z')
	EndSwitch
WEnd

Func _Focused($iID)
	Return _WinAPI_GetDlgCtrlID(ControlGetHandle($hGui, "", ControlGetFocus($hGui))) = $iID
EndFunc   ;==>_Focused

Func _WinAPI_LoadKeyboardLayout($sLayoutID, $hWnd = 0)
	Local Const $WM_INPUTLANGCHANGEREQUEST = 0x50
	Local $aRet = DllCall("user32.dll", "long", "LoadKeyboardLayoutW", "wstr", Hex($sLayoutID, 8), "int", 0)

	If Not @error And $aRet[0] Then
		If $hWnd = 0 Then
			$hWnd = WinGetHandle(AutoItWinGetTitle())
		EndIf

		DllCall("user32.dll", "ptr", "SendMessage", "hwnd", $hWnd, "int", $WM_INPUTLANGCHANGEREQUEST, "int", 1, "int", $aRet[0])
		Return 1
	EndIf

	Return SetError(1)
EndFunc   ;==>_WinAPI_LoadKeyboardLayout
 
Верх