Mach dir ein AutoIt-Skript, dass alle 10 Minuten
aufruft:
_MenuCmd($IDM_SAVE)
[/autoit]
aus der SciTE-Interface UDF
Mach dir ein AutoIt-Skript, dass alle 10 Minuten
aufruft:
_MenuCmd($IDM_SAVE)
[/autoit]
aus der SciTE-Interface UDF
Ich stehe hier vor einem sehr seltsamen Verhalten beim Setzen von Selektionen.
Das folgende Skript bewirkt, dass das unter dem Cursor stehende Wort selektiert wird. Dies kann entweder für die Wordcharacter gelten (mit Strg+Shift+E) oder zusätzlich mit führendem "$" für Variablen (mit Strg+E).
Das funktioniert auch tadellos - solange rechts neben dem Begriff ein Leerzeichen steht. Ist dies jedoch nicht so, Dann werden Bereiche selektiert, die nicht mit den Markern übereinstimmen.
Es spielt übrigens keine Rolle, wie ich die Selektion ausführe ( SelectionStart/-Stop; SetSel(); CharRightExtend() ), immer dasselbe Verhalten.
Vielleicht hat jemand eine Idee..
[Ich habe das Problem auch im EN-Forum gepostet.]
Edit: Problem gelöst! Ursache war, dass SciTe als Standard den HotKey "Strg+E" nutzt um die nächste Klammer zu finden.
-------------------------------------------------------------------------
EditKey = EventClass:new(Common)
-------------------------------------------------------------------------
-------------------------------------------------------------------------
-- expand selection to full variable ($variable) or only the word characters (variable)
---------------- SetSelection( ) -----------------------------------------
function SetSelection(_part)
local isWordChar = function(_char)
if string.char(_char):find('[a-zA-Z0-9_]') then return true end
return false
end
local iStart = editor.CurrentPos
local iEnd = iStart
while isWordChar(editor.CharAt[iStart-1]) do
iStart = iStart - 1
end
if string.char(editor.CharAt[iStart-1]) == "$" and _part == false then iStart = iStart - 1 end
while isWordChar(editor.CharAt[iEnd]) do
iEnd = iEnd + 1
end
if iStart ~= iEnd then
editor.SelectionStart = iStart
editor.SelectionEnd = iEnd
end
end -->SetSelection
-------------------------------------------------------------------------
----------------- Event: OnKey -----------------------------------------
function EditKey:OnKey(_keycode, _shift, _ctrl, _alt)
if _ctrl and _shift and not _alt and _keycode == 69 then SetSelection(true) end --- expand selection to full word with only Wordcharacters
if _ctrl and not _shift and not _alt and _keycode == 69 then SetSelection(false) end --- expand selection to full word with Wordcharacters and leading "$"
return nil
end --> EditKey
-------------------------------------------------------------------------
Alles anzeigen
Naja, Variablen wie $i verwende ich zum Beispiel für fast jede For-Schleife...
Zählervariablen gehören natürlich nicht in die Betrachtung und haben i.A. nur die geplante Lebensdauer des Schleifendurchlaufs. Leider bestehen sie in AutoIt auch ausserhalb der jeweiligen Schleife weiter, was ich als wenig sinnvoll betrachte. Mir würde eine Scopeabgrenzung für jeden Scriptblock (If..EndIf; Do..Until, For..Next usw.) wesentlich besser gefallen.
Man könnte zum Beispiel in Funktionen die selben Variablennamen verwenden, da man in Funktionen keinen Zugriff auf die Variablen hätte.
Das kannst du doch. Wenn du eine Globale Variable $X hast und deklarierst in einer Funktion ebenfalls $X aber als Local, dann verwendet die Funktion die lokale Variable. Ich persönlich halte es für nicht sehr glücklich identische Variablennamen in unterschiedlichen Scopes zu nutzen. Dann muß man beim Lesen des Codes gerade in größeren Funktionen zwingend drauf achten was wurde wo deklariert und zum Anderen hat man dann innerhalb der Funktion keinen Zugriff auf eine gleichnamige Globale Variable.
Test-Text:
Zeilen: 6452
Zeichen gesamt: 876133
Matches: 3752
Text und Pattern in Variablen eingelesen, dann in einer Schleife 50-mal abwechselnd alle Funktionen aufgerufen. (von eukalyptus habe ich die allgemeingültige Variante getestet)
Hier das Ergebnis:
Minimum Maximum Durchschnitt
BugFix 15.69 18.87 17.60
James 16.66 19.11 17.95
eukalyptus 0.07 0.15 0.11
Taz77 0.06 0.12 0.09
Taz77: Du liegst mit deiner Funktion einen Hauch vor eukalyptus.
( und nur 0,5% Zeitaufwand im Vergleich zu meiner Funktion :wacko: )
Dass James Variante langsamer ist als meine hatte ich vom reinen Anschauen her nicht erwartet, da ich ja 2-mal eine Schleife über alle Matches laufen lasse und er nur einmal. Aber hier wird wohl StringReplace die Bremse sein, da dort jedes mal der gesamte String dupliziert werden muss.
Also vielen Dank nochmal für eure Mitwirkung.
Und Taz77 - wäre schick, wenn du solche Funktionen im Skripte-Forum publizierst. Damit brauchst du wirklich nicht hinterm Berg halten. ![]()
Edit: Jetzt als AddOn!!
!! DEMO ANGUCKEN !!
Hi,
ich bin ja ein Tastaturfreak und somit versuche ich natürlich die Maus möglichst nicht zu benutzen.
In Sublime Text haben mir viele der möglichen Editoroperationen sehr gut gefallen. Ich versuche mal soviel, wie möglich davon in SciTE umzusetzen.
Für den Anfang:
• (markierte) Zeile(n) auf/ab bewegen mit Strg+Shift+PfeilAuf /+PfeilAb
• Markierung aufheben mit Strg+U
• Benachbarte Zeichen (li. u. re. vom Cursor) tauschen mit Strg+Shift+T
Die Datei bei euren Lua-Dateien speichern, Pfadaufruf anpassen. Hier ist mein persönlicher Lua-Pfad als Propertie hinterlegt.
Den Programmaufruf in der SciTEStartup.lua hinter "EventClass:BeginEvents()" einfügen:
--------------------------------------------------------------------------------
-- SciTE startup script.
--------------------------------------------------------------------------------
-- A table listing all loaded files.
LoadLuaFileList = { }
--------------------------------------------------------------------------------
-- LoadLuaFile(file, directory)
--
-- Helper function for easily loading Lua files.
--
-- Parameters:
-- file - The name of a Lua file to load.
-- directory - If specified, file is looked for in that directory. By default,
-- this directory is $(SciTEDefaultHome)\Lua.
--------------------------------------------------------------------------------
function LoadLuaFile(file, directory)
if directory == nil then
directory = props["SciteDefaultHome"] .. "\\Lua\"
end
table.insert(LoadLuaFileList, directory .. file)
dofile(directory .. file)
end -- LoadLuaFile()
-- Load all the Lua files.
LoadLuaFile("Class.lua") -- Always load first.
LoadLuaFile("Common.lua") -- Always load second.
LoadLuaFile("AutoItPixmap.lua")
LoadLuaFile("AutoHScroll.lua")
LoadLuaFile("AutoItAutoComplete.lua")
LoadLuaFile("LoadSession.lua")
LoadLuaFile("AutoItIndentFix.lua")
LoadLuaFile("EdgeMode.lua")
LoadLuaFile("SmartAutoCompleteHide.lua")
LoadLuaFile("Tools.lua")
LoadLuaFile("AutoItTools.lua")
LoadLuaFile("AutoItGotoDefinition.lua")
LoadLuaFile("SciTE_extras.lua")
-- Start up the events (Calls OnStartup()).
EventClass:BeginEvents()
LoadLuaFile("EditProcessing.lua", props["Lua.User.Scripts.Path"].."\") ---- Move (selected) lines, Unselect, Toggle chars <===== HIER EUREN PFAD ANGEBEN!
Alles anzeigen
NEUE VERSION in Post #2
In Planung:
- zeitgleiches Editieren an Mehrfachvorkommen einer Auswahl (z.B. eine Variable selektieren, Auswahl auf alle od. Schritt-für-Schritt weitere Vorkommen erweitern, Änderung Inhalt in allen Selektionen)
- Alignment bei Zuweisungen (mehrere Zuweisungen untereinander, markieren und am "=" ausrichten)
Hi,
folgende Problemstellung als Bsp.:
Ein Text enthält unbekannt viele Werte eines bestimmten Musters (z.B. ZAHLENWERT-SPACE-EINHEIT_KG) jetzt möchte ich alle diese Kg-Angaben in Gramm umwandeln.
Die Matches per RegExp zu finden ist kein Problem.
Mein Gedanke war nun, kann ich mit StringRegExpReplace während des Parsens den Match manipulieren und Replace mit dem geänderten Wert durchführen? Jein. Ich kann das führ den ersten Match durchführen, muß dann aber wieder den kpl. String weiterparsen, bis alle Vorkommen bearbeitet und ersetzt sind. Und zusätzlich muß ich das Pattern so aufbauen, dass auch immer der kpl. Text in Backreferenzen gecaptured wird damit ich den zu manipulierenden Wert auch abgreifen kann ohne dass der Rest verloren geht. Bei Texten mit einigen 1000 Zeilen ist mir diese Methode deutlich zu aufwändig (Ressourcen-verbratend).
Nächster Gedanke: Per Offset-Parsing die Fundstellen und Matches ermitteln und zwischenspeichern. Mit den Offset-Infos die Teilstrings selektieren, den Match manipulieren und einen neuen Ergebnisstring zusammensetzen. Das funktioniert auch - allerdings bei größeren Dimensionen (Text auf 6500 Zeilen mit 3800 Matches) werden bei mir ca. 30 s benötigt (inkl. Konsolenausgabe).
Vielleicht habt ihr eine Idee, wie man das performanter gestalten kann.
Bei ein paar hundert Zeilen Text ist das kein Problem, somit in der überwiegenden Zahl der Anwendungsfälle ausreichend. Ich muß aber z.B. öfter Maschinen-Logs abgrasen und da wäre es durchaus schick, wenns auch schneller geht.
Hier mal meine Lösung, in dem Bsp-String ersetze ich Zahlenwerte in eckigen Klammern mit dem Wert*1000:
$s = "abc[1] gjj66 h [20]j4l7l3 l[3]-g9 j[80lh[444][5]k21k]kq" ; alle Zahlen in eckigen Klammern sollen mit ihrem Wert*1000 ersetzt werden
$p = "(\[\d+\])" ; Search-Pattern
$sRet = _StrReplaceIterated($s, $p, '_GetManipulatedMatch') ; Funktionsaufruf mit Angabe der Funktion zur Manipulation der Matches
ConsoleWrite('Anzahl Ersetzungen:' & @extended & @LF)
ConsoleWrite($sRet & @LF)
Func _StrReplaceIterated($_s, $_sPatt, $_sReplFunc)
Local $aMatch, $iOff = 1, $sMatch = '', $sOff = '', $aPos, $sPart, $iStart = 1, $sOut = ''
While 1
$aMatch = StringRegExp($_s, $_sPatt, 1, $iOff)
If Not @error Then
$iOff = @extended
$sMatch &= $aMatch[0] & Chr(0)
$sOff &= $iOff & ','
Else
ExitLoop
EndIf
WEnd
If $sOff <> '' Then
$aPos = StringSplit(StringTrimRight($sOff, 1), ',')
$aMatch = StringSplit(StringTrimRight($sMatch, 1), Chr(0))
EndIf
If Not IsArray($aPos) Then Return SetError(1,0,0)
For $i = 1 To $aPos[0]
$sPart = StringTrimRight( StringMid($_s, $iStart, $aPos[$i]-$iStart), StringLen($aMatch[$i]) )
$sOut &= $sPart & Call($_sReplFunc, $aMatch[$i])
$iStart = $aPos[$i]
Next
$sOut &= StringRight($_s, StringLen($_s)-$aPos[$aPos[0]])
Return SetError(0, $aPos[0], $sOut)
EndFunc ;==> _StrReplaceIterated
; Funktion zur Manipulation der Matches
Func _GetManipulatedMatch($_s)
Local $i = StringTrimRight(StringTrimLeft($_s, 1), 1) *1000
Return "[" & $i & "]"
EndFunc
Du mußt diese in ein Array auslagern ( $arrayChild = $arrayParent[$x][$y] ). Ein direkter Zugriff ist nicht möglich.
Nach Manipulationen mußt du das Child-Array dann wieder in das Parent zurückschreiben.
Darkhunter566:
Versuche dir erst mal klar zu werden, was du eigentlich vorhast. Bis jetzt hast du davon noch nicht die geringste Ahnung. Wie sollen wir dir dann helfen?
Also bevor du hier noch irgendwas postest, schreib dir selbst als Pseudoprogramm (in Stichworten) auf, WAS genau WANN passieren soll.
2 Dinge:
- ArrayAdd ist eine "Spaß"bremse
da es für jeden Eintrag ein ReDim ausführt. Viel besser, wie bereits erwähnt, ein großes Array deklarieren und nach dem Befüllen auf die Zahl der Einträge mit nur einem ReDim schrumpfen.
- Eval ist so etwas wie "Es gibt wirklich keine Möglichkeit durch sauberes Programmieren das Problem zu lösen - dann kommt Eval zum Einsatz". ---- Also im Regelfall nie! Und wenn du es meiden kannst, dann tu es. Gewöhne dir das nicht erst an.
Noch was: Ich halte es für wenig wahrscheinlich, dass du allein mit einem Pattern die Ergebnisse rausziehen kannst.
Mein Tipp:
1. Datei als ganzes Einlesen
2. Zeilenfortschreibungen löschen (" _CRLF"), damit was in eine Zeile gehört auch in einer Zeile steht.
3. Inhalt an CRLF in ein Zeilen-Array splitten
4. Lies aus allen verwendeten Includes die Konstantendeklarationen aus (in ein Dictionry od. Arraylist).
Nun kannst du Zeile für Zeile parsen. Arbeite mit mehreren Dictionary/Arraylist ($Var nicht deklariert, $Var Global/Dim, $Var Local). Füge gefundene Variable dem jeweiligen Dict. zu, wenn noch nicht enthalten und nicht in Konstanten. Somit hast du nach Durchlauf aller Zeilen eine Übersicht, welche Variablen in welchem Scope verwendet werden.
gibt es von autoit eine möglichkeit dies einzustellen, damit der laptop zuerst von cd bootet?
Meines Wissens ist es nicht möglich mit Third Party Programmen Zugriff auf das BIOS zu erlangen. Aber evtl. bietet ja der Hersteller des Laptops ein Tool für derartige Zwecke. Zumindest läßt sich mit Herstellertools ein BIOS-Upgrade auch aus der Windows-Umgebung heraus durchführen.
Und als Tipp für die Zukunft: Es ist die schlechteste aller Einstellungen, wenn in der Bootreihenfolge das Festplattenlaufwerk an erster Stelle steht. Dort sollte immer der Zugriff auf einen externen Datenträger sein. Warum - das spürst du gerade am eigenen Leib.
Wenn die Auswahl kommt, bist du schon an der Stelle des BIOS-Aufrufs vorbei. Also PC ausschalten. Und nach Einschalten fleißig die Tastenkombination für BIOS-Aufruf betätigen.
Vielleicht findest du ja Inspiration in einem alten Skript von mir: https://autoit.de/index.php?page…50991#post50991
Du möchtest ein Projekt in Auftrag geben? Dann gib uns bitte folgende Informationen:
Je konkreter deine Angaben sind, so größer ist die Chance, daß sich jemand meldet.
Mit:
"Ich habe ein Projekt, suche Programmierer, weiteres per PN"
wirst du niemanden hinter'm Ofen vorlocken.
Sensible Daten brauchst du hier natürlich nicht offenlegen, eine allgemeine Beschreibung, die die Thematik verdeutlicht reicht uns.
Wie gehe ich denn sicher, dass alle released sind?
Das Hantieren mit Hooks greift direkt in das System ein. Wenn man damit arbeitet, wird erwartet, dass du weißt, was du tust.
Ist wie bei ASM, da gibts keine Syntaxfehler Warnung - da gibts den Crash.
Die beste Methode ist es, den Ablauf in wirklich alle Teilschritte zu zerlegen. Jedes Down, Hold-Down, Up muß vollkommen klar sein. Das ist nicht zu vergleichen mit Send(), wo im Standardfall Hit und Release automatisch erfolgen.
Also immer sauber mitzählen - Hit - jetzt muß ein Release kommen oder es wird z.B. für eine Kombination noch ein zweiter Hit erwartet. Danach müssen dann eben zwei Release erfolgen (und in der richtigen Reihenfolge!).
Eine automatische Anmeldung ist m.W. nicht zulässig und wiederspricht auch dem Grundgedanken des Dienstes.
Ich habe auch kein Verständnis für die "Ich will alles umsonst"-Mentalität, zumal der Dienst dich nichts kostet außer einem monatlich einmaligen Einloggens in deinen Account.
Aus diesem Grunde: [CLOSED]
Na klar kannst du mit Shift eine Mehrfachauswahl machen. Aber nicht in einem Abwasch.
Wie gehst du vor?
- Shift gedrückt halten
- 1. Klick 'pfeil ab' - erzeugt Key-Event
- 2. Klick 'pfeil ab' - erzeugt Key-Event
- 3. Klick 'pfeil ab' - erzeugt Key-Event
Du markierst drei Einträge, aber das passiert in 3 Schritten. In einem Rutsch geht das nur mit Maus (Klick erster Eintrag, Shift+Klick letzter zu markierender Eintrag).
Wenn du jetzt tatsächlich die Mehrfachauswahl berücksichtigen möchtest ist das Abfragen von Shift erforderlich - oder auch von Strg, bei selektiver Auswahl.
DAS ist dann etwas umfangreicher. Ich poste dir zwei Bsp., denen du das nötige entnehmen kannst:
#cs
Bsp. Auto-Ersetzen mit Hook
Umlaute und ß
linke Shift ergibt z.B. Ä-Ae, rechte Shift und CapsLock ergibt Ä-AE (RShift wir nicht per Hook gelöst)
Ä - Ae (AE) ä - ae
Ö - Oe (OE) ö - oe
Ü - Ue (UE) ü - ue
ß - ss
Hook ist nur wirksam für die GUI (Statusabfrage in der Schleife) und das benannte Ctrl.
#ce
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
OnAutoItExitRegister('OnAutoItExit')
Opt('MustDeclareVars', 1)
Global $hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
Global $hmod = _WinAPI_GetModuleHandle(0)
Global $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hStub_KeyProc), $hmod)
Global $active = False, $isShift = False
_Main()
[/autoit] [autoit][/autoit] [autoit]Func _Main()
Local $gui = GUICreate('Auto Ersetzen: Umlaute und "ß"', 400, 300)
GUICtrlCreateLabel('Im Input keine Ersetzung', 10, 10, 380)
GUICtrlCreateInput('', 10, 30, 380)
GUICtrlCreateLabel('Im Edit werden ersetzt: ä ==> ae ö ==> oe ü ==> ue ß ==> ss', 10, 60, 380)
Local $edit = GUICtrlCreateEdit('', 10, 80, 380, 210)
GUISetState()
Do
If BitAND(WinGetState($gui),
And _
_WinAPI_GetDlgCtrlID(ControlGetHandle($gui, '', ControlGetFocus($gui))) = $edit Then
$active = True
Else
$active = False
EndIf
Until GUIGetMsg() = -3
EndFunc
Func _Exit()
Exit
EndFunc
;===========================================================
; callback function
;===========================================================
Func _KeyProc($nCode, $wParam, $lParam)
Local $tKEYHOOKS, $vkCode, $ret, $isCapsLock = 0
$ret = DllCall("user32.dll","long","GetKeyState","long", 0x14)
If $ret[0] Then $isCapsLock = 1
$tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam)
If $nCode < 0 Or Not $active Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
$vkCode = DllStructGetData($tKEYHOOKS, "vkCode")
If $wParam = $WM_KEYDOWN Then
ConsoleWrite('$vkCode ' & $vkCode & @CRLF)
If $vkCode = 0xA0 Or $vkCode = 0xA1 Then
$isShift = True
EndIf
Switch $vkCode
Case 0xBA ; ü ==> ue
_keybd_event(0x55) ; Zeichen 'u'
If $isShift Then _keybd_event(0xA0, 0x2) ; Flag 0x2=KEYUP (LShift nach Senden Ersatzbuchstaben lösen)
_keybd_event(0x45) ; Zeichen 'e'
Return -1
Case 0xC0 ; ö ==>oe
_keybd_event(0x4F)
If $isShift Then _keybd_event(0xA0, 0x2)
_keybd_event(0x45)
Return -1
Case 0xDB ; ß ==> ss - nicht ausführen, wenn Shift/Capslock aktiv
If $isShift Or $isCapsLock Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
_keybd_event(0x53)
_keybd_event(0x53)
Return -1
Case 0xDE ; ä ==> ae
_keybd_event(0x41)
If $isShift Then _keybd_event(0xA0, 0x2)
_keybd_event(0x45)
Return -1
EndSwitch
Else
;~ ConsoleWrite('flags ' & DllStructGetData($tKEYHOOKS, "flags") & @CRLF)
Switch DllStructGetData($tKEYHOOKS, "flags")
Case 0x80, 0x81 ; 0x80= UP für 'normale' Tasten u. li. paarige, 0x81= UP für re. paarige
If $vkCode = 0xA0 Or $vkCode = 0xA1 Then $isShift = False ; LShift, RShift
EndSwitch
EndIf
Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc
Func _keybd_event($vkCode, $Flag=0)
DllCall('user32.dll', 'int', 'keybd_event', 'int', $vkCode, 'int', 0, 'int', $Flag, 'ptr', 0)
EndFunc
Func OnAutoItExit()
_WinAPI_UnhookWindowsHookEx($hHook)
DllCallbackFree($hStub_KeyProc)
EndFunc
#cs
Hook ENTER in einem Edit-Ctrl
- ENTER für Funktionsaufruf (Auslesen Inhalt Edit-Ctrl)
- SHIFT + ENTER für Zeilenumbruch im Edit-Ctrl
#ce
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
Opt("GUIOnEventMode", 1)
OnAutoItExitRegister('OnAutoItExit')
Global $hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
Global $hmod = _WinAPI_GetModuleHandle(0)
Global $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hStub_KeyProc), $hmod)
Global $gui, $edit, $active = False ; <== to allow hook only on this gui
Global $isShift = False
$gui = GUICreate('CRLF = <Shift>+<Enter>', 300, 170)
GUISetOnEvent(-3, '_end')
$edit = GUICtrlCreateEdit('', 10, 10, 280, 150)
GUISetState()
[/autoit] [autoit][/autoit] [autoit]While 1
_checkWinState()
Sleep(100)
WEnd
Func _checkWinState()
If Not $active And BitAND(WinGetState($gui),
Then
$active = True
ElseIf $active And Not BitAND(WinGetState($gui),
Then
$active = False
EndIf
EndFunc
Func _end()
Exit
EndFunc
Func _send() ; for example only
ConsoleWrite('_send(' & @CRLF & _
GUICtrlRead($edit) & @CRLF & _
') was called' & @CRLF)
EndFunc
;===========================================================
; callback function
;===========================================================
Func _KeyProc($nCode, $wParam, $lParam)
Local $tKEYHOOKS, $vkCode, $ID
$tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam)
If $nCode < 0 Or Not $active Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
$vkCode = DllStructGetData($tKEYHOOKS, "vkCode")
If $wParam = $WM_KEYDOWN Then
$ID = _WinAPI_GetDlgCtrlID(ControlGetHandle($gui, '', ControlGetFocus($gui))) ; get focus-ID from your gui
If $ID <> $edit Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) ; Edit has not focus
If $vkCode = 0xA0 Or $vkCode = 0xA1 Then ; left or right shift-button pressed
$isShift = True
EndIf
If ( $vkCode = 13 ) And ( Not $isShift ) Then
_send()
Return -1 ; so the system get not the $vkCode 13
ElseIf ( $vkCode = 13 ) And $isShift Then
GUICtrlSetData($ID, GUICtrlRead($ID)) ; if not using style $ES_WANTRETURN, use "GUICtrlRead($ID) & @CRLF"
EndIf
Else
Switch DllStructGetData($tKEYHOOKS, "flags")
Case 0x80, 0x81 ; 0x80= UP for 'normal' keys and left pairs, 0x81= UP for right pairs
If $vkCode = 0xA0 Or $vkCode = 0xA1 Then $isShift = False ; LShift, RShift
EndSwitch
EndIf
Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc
Func OnAutoItExit()
_WinAPI_UnhookWindowsHookEx($hHook)
DllCallbackFree($hStub_KeyProc)
EndFunc
Aber Vorsicht, falls du mit "_keybd_event()" arbeiten möchtest! Ein Tastendruck besteht aus zwei Phasen: Hit und Release. Du mußt am Ende deines Programmes sicherstellen, dass alle Tasten released sind - sinst hast du ein sehr merkwürdiges Verhalten deines PC.
Läßt sich aber schlimmstenfalls mit Neustart beheben.