Ich warte SICHER noch etwas...und zwar idR bis zur nächsten Version. ....
So handhabe ich das auch. Und wenn mich in der neuen Version wirklich was interessiert, dann wird in der VM installiert - das tut keinem weh. ![]()
Ich warte SICHER noch etwas...und zwar idR bis zur nächsten Version. ....
So handhabe ich das auch. Und wenn mich in der neuen Version wirklich was interessiert, dann wird in der VM installiert - das tut keinem weh. ![]()
Neue Version im #Startpost
v 0.8
NEU: gekapseltes Modul: StringOr ( .find() / .gmatch() / .gsub() / .match() )
Lua-Stringpattern ermöglichen keine ODER-Pattern. In diesen Funktionen können dafür mehrere Pattern als Table übergeben werden.
NEU: LineTabReplace() - Ersetzen von TAB mit Leerzeichen in einer Textzeile
NEU: EditorTabReplace() - Ersetzen aller TAB in der aktuell in SciTE geöffneten Datei
GEÄNDERT: Optionale Parameter ASCIIcompare(), (in)sensitiver Vergleich / Reihenfolge auf-/absteigend. Standard: sensitiv aufsteigend (nil, nil)
v0.7
NEU: ASCIIcompare() - Vergleich zweier ASCII-Strings
Ich habe noch ergänzt um ein Lua-Skript, mit dem in der aktuell in SciTE geöffneten Datei on-the-fly die Tab-Ersetzung durchgeführt wird. #Start-Post
Als Ergänzung TabReplace (au3- und lua-Skript):
In vorhandenen Dateien alle TAB durch die der Position (und der vorgegebenen TAB-Weite) entsprechende Anzahl von Leerzeichen ersetzen.
Die globale Constante $__LISTVIEWCONSTANT_GUI_RUNDEFMSG war in der GuiListView.au3 in der AutoIt-Version 3.3.14.5 noch enthalten, in der V. 3.3.16.0 nicht mehr
Ein Grund, warum ich die sogenannten "Stables" wegen oft vorhandener Instabilität frühestens nach einem Jahr installiere. ![]()
Übrigens hat das keinen Eingang gefunden in den Script Breaking Chances.
Diese UDF ist nicht gedacht, um in ein fertiges Skript eingebunden zu werden. Sie dient nur zur Unterstützung bei der Entwicklung.
Funktionen:
Das angefügte Beispiel bringt folgende Ergebnisse:
;-- TIME_STAMP 2022-03-10 13:58:40
#include "ErrorList.au3"
#include <File.au3>
_Test_1()
_Clear()
_Test_2()
_Clear()
_Test_3()
_Clear()
_Test_4()
_Clear()
Func _Test_1()
Local $aFile = _FileListToArray('C:\Gibt-Es-Nicht\Pfad', 1) ; FLTA_FILES
_ErrorList_Add()
If @error Then ConsoleWrite(@CRLF & '>> Fehlerwert wird durchgeleitet, @error: ' & @error & @CRLF)
; einige Operationen um den Fehlerspeicher neu zu belegen
ClipPut('irgendwas')
Local $clip = ClipGet() ; fehlerfrei
ConsoleWrite('>> ClipGet @error: ' & @error & @CRLF)
; Abfrage des letzten registrierten Fehlers als String: "@error|@extended|@ScriptLineNumber|Funktionsaufruf"
ConsoleWrite('-> ' & _ErrorList_LastError(3) & @CRLF & @CRLF)
MsgBox(0, 'Test 1', 'Weiter zu Test 2.')
EndFunc
Func _Test_2()
; alle Funktionsaufrufe werden der ErrorList hinzugefügt
; zuerst fehlerfreie Operationen
Local $iSizeMyDocs = DirGetSize(@MyDocumentsDir)
_ErrorList_Add()
Local $FileTime = FileGetTime(@AutoItExe)
_ErrorList_Add()
; jetzt ein Fehler
_MakeError()
_ErrorList_Add()
; weiter fehlerfrei
Local $FileVersion = FileGetVersion(@AutoItExe)
_ErrorList_Add()
Local $Attrib = FileGetAttrib(@AutoItExe)
_ErrorList_Add()
; Ausgabe ALLER Aufrufe als Liste in die Console
_ErrorList_List(False)
MsgBox(0, 'Test 2', 'Weiter zu Test 3.')
EndFunc
Func _Test_3()
; wie Test_2 - aber nur Auflistung der Fehler
; alle Funktionsaufrufe werden der ErrorList hinzugefügt
; zuerst fehlerfreie Operationen
Local $iSizeMyDocs = DirGetSize(@MyDocumentsDir)
_ErrorList_Add()
Local $FileTime = FileGetTime(@AutoItExe)
_ErrorList_Add()
; jetzt ein Fehler
_MakeError()
_ErrorList_Add()
; weiter fehlerfrei
Local $FileVersion = FileGetVersion(@AutoItExe)
_ErrorList_Add()
Local $Attrib = FileGetAttrib(@AutoItExe)
_ErrorList_Add()
; Ausgabe NUR FEHLERHAFTER Aufrufe als Liste in die Console (Standard)
_ErrorList_List()
MsgBox(0, 'Test 3', 'Weiter zu Test 4.')
EndFunc
Func _Test_4()
MsgBox(0, 'Test 4', 'ACHTUNG!' & @CRLF & _
'Jetzt werden alle "_ErrorList_" -Funktionen aus dem Skript gelöscht!' & @CRLF & _
'Nach Beendigung mit (mehrfachem) Ctrl+Z wieder das Original herstellen.' & @CRLF & _
'Dann "_ErrorList_Remove" mit dem Parameter "True" versehen und erneut ausführen.' & @CRLF & _
'Jetzt wird auch die Includezeile aus dem Skript entfernt. - Wiederherstellen, wie vorab.')
; Entfernen ALLER Funktionsaufrufe "_ErrorList_..."
; mit Parameter "(True)" wird auch die Includezeile gelöscht
_ErrorList_Remove(True)
EndFunc
Func _Clear()
$g_aErrList[0][0] = 0
ReDim $g_aErrList[1][4]
EndFunc
; Generieren von @error- und @extended Werten
Func _MakeError()
Local $a[] = [-9,-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8,9]
Return SetError($a[Random(0,17,1)], $a[Random(9,17,1)])
EndFunc
Alles anzeigen
_ErrorList_LastError(3)
_ErrorList_List(False) - alle Einträge
_ErrorList_List() - Nur Einträge mit Fehlern
Das Fenster enthält "komplizierte" Controls, daher auch die ISN Nutzung, mit der das fehlerfreier geht.
Nicht falsch verstehen, aber hier zeigt sich m.M. nach der Nachteil von IDE's, die dir versuchen das Denken abzunehmen.
Wenn du dir z.B. nicht bewusst bist, welche Flags oder Flagkombinationen du setzen musst, um ein bestimmtes Aussehen / Verhalten deiner Controls zu erreichen, dann geht dir hier auch ein Lerneffekt verloren. weil du es beim nächsten mal wieder nicht weißt.
Um erstmalig eine GUI zu erstellen ist das für einen Anfänger durchaus eine gute Hilfe. Aber auch da ist derjenige gefordert hinterher zu schauen: Welcher Code wurde mir generiert und was passiert dabei?
Und früher oder später verabschiedest du dich sicher auch von GUI-Erstellungs-Tools. Ich gehe nach jahrelanger Forumserfahrung davon aus, dass 95% der wirklich aktiven AutoIt-Nutzer ihre GUI händisch erstellen. Denn selbst wenn ich nur mal eben eine Test-GUI benötige, ist diese per Hand deutlich schneller erstellt, als mit einem Tool.
Bei diesem CAD System z.B. ändert sich das Menüband, sobald man gewisse Objekte anklickt bzw. Optionen auswählt.
Dieses will ich gerne "mitschneiden" oder wie auch immer, so dass ich die Buttons auf dem Streamdeck mittels PlugIn entsprechend umschalten/freischalten/etc. kann. Somit hätte man eine Interaktion zwischen Streamdeck und Programm, obwohl für dieses Programm keine native Schnittstelle existiert.
Somit ist der Hinweis auf StreamDeck in der Fragestellung leider völlig irreführend. Dein Problem ist das CAD-Programm, dessen Messages du gerne verwerten möchtest.
Also benenne mal, mit welchem CAD-Proggi du arbeitest, evtl. hat ja bereits jemand dafür Lösungen parat (kann mich schwach erinnern, dass hier im Forum schon mehrfach das Thema CAD-Automatisierung ein Thema war).
Hast du schon probiert mit dem AutoItWindowInfo-Tool Infos zu deinem CAD zu bekommen um mit den Control-Funktionen zu reagieren?
Wenn das nicht möglich ist, musst du erst mal selbst die Nachrichten, die beim Aktivieren der jeweiligen Menüpunkte gesendet werden herausfinden. Dazu kannst du z.B. Winspector nutzen. (In diesem Thread hatten wir mal nützliche Tools zur Fenster- und Controlbestimmung aufgelistet).
Wenn also der "normale" Zugriff mittels ControlSend / ControlCommand etc. nicht möglich ist, musst du dich in den Windows-Nachrichtenstrom einklinken und auf die jeweiligen Messages reagieren. Du brauchst diese, wenn ich das richtig verstanden habe, ja nicht manipulieren, sondern musst nur wissen: Aha, MSG_XYZ wurde an Fenster-HWND 0x123456 gesendet, lParam /wParam enthielten den Wert "n" --> jetzt ist das Menü scharf.
In dieser Richtung musst du also weiter machen.
Edit:
Um Fensterinformationen von fremden Fenstern in einem AutoIt-Programm auswerten zu können ist Subclassing erforderlich. Dazu benötigst du eine extra dll (DSSUBCLS.DLL).
Bsp. und DL-Info für die DLL findest du hier. (Eventuell sind inzwischen auch andere Vorgehensweisen möglich, hatte mir den Link vor Jahren gespeichert.)
Edit_2:
Habe gerade gesehen, dass der DL der DSSUBCLS.DLL leider tot ist. Vielleicht hat ja jemand die DLL zur Hand.
Wie auch in der Lua-Doku beschrieben, kann bei string.gmatch kein Caret als Anker verwendet werden, da dies die Iteration verhindern würde.
(Habe ich anfangs überlesen und wie blöd nach dem Fehler gesucht. Solche extrem wichtigen Infos hätte ich in fetter Rotschrift erwartet.
)
Hier mal ein fiktives Beispiel. Es sollen aus einem String alle alleinstehenden Ziffern(-gruppen) (getrennt durch Leerzeichen) gefunden werden.
Da die reinen Stringpattern kein Oder ermöglichen, sind mehrere Pattern nacheinander anzuwenden um alle Möglichkeiten zu berücksichtigen.
Um die letzte Bedingung zu erfüllen und keine Matches auf bereits durch die vorigen Pattern gefundenen Gruppen zu haben muss ich als Anker Stringanfang und -ende mit angeben. Aber, wie oben angeführt, ist das mit string.gmatch nicht möglich.
Ich zeige das mal hier im Bsp.
local tStr = {
"007 0xFF 123 777cd 456 0x0011AB 789", --> 007 123 456 789
" 007", --> 007
"007"} --> 007
local tPatt = {
"(%d+)%s", --> alle Zifferngruppen, denen ein Leerzeichen folgt
"%s(%d+)$", --> Zifferngruppe nach Leerzeichen am Stringende
"^(%d+)$"} --> String besteht nur aus Zifferngruppe
local tExpect = {
{"007 123 456","789",""},
{"","007",""},
{"","","007"}}
for i=1, #tStr do
print('>> STRING "'..tStr[i]..'"')
for j=1, #tPatt do
local m = ''
print('->\tPATTERN "'..tPatt[j]..'", erwartet: "'..tExpect[i][j]..'"')
for match in tStr[i]:gmatch(tPatt[j]) do
m = m..match..' '
end
m = m:gsub('%s+$','')
local pm = '+'
if tExpect[i][j] ~= m then pm = '!' end
print(pm..'>\tMATCH "'..m..'"')
end
end
Alles anzeigen
>> STRING "007 0xFF 123 777cd 456 0x0011AB 789"
-> PATTERN "(%d+)%s", erwartet: "007 123 456"
+> MATCH "007 123 456"
-> PATTERN "%s(%d+)$", erwartet: "789"
+> MATCH "789"
-> PATTERN "^(%d+)$", erwartet: ""
+> MATCH ""
>> STRING " 007"
-> PATTERN "(%d+)%s", erwartet: ""
+> MATCH ""
-> PATTERN "%s(%d+)$", erwartet: "007"
+> MATCH "007"
-> PATTERN "^(%d+)$", erwartet: ""
+> MATCH ""
>> STRING "007"
-> PATTERN "(%d+)%s", erwartet: ""
+> MATCH ""
-> PATTERN "%s(%d+)$", erwartet: ""
+> MATCH ""
-> PATTERN "^(%d+)$", erwartet: "007"
!> MATCH ""
Wie kann man das umgehen? - Durch Verwendung einer String-Funktion, die Anker im Pattern nutzen kann, string.match.
Als Lösung prüfe ich vor Ausführung von gmatch, ob nur die letzte (durch gmatch nicht erkennbare) Bedingung erfüllt ist mit match.
Somit wird gmatch nur auf Strings angewendet, die mit den möglichen Pattern auch verarbeitbar sind.
local tRes = {}
table.insert(tRes, strTest:match('^(%d+)$')) -- fügt Treffer ein oder nil
if #tRes == 0 then
-- weiter mit :gmatch
end
Das ist etwas Code mehr, aber erfüllt den Zweck. ![]()
Neu: v 0.3, s. Startpost
Excel unterstützt standardmäßig keine RegEx Ausdrücke
Da VBA standardmäßig dazu gehört - eigentlich doch. ![]()
Das ist unabhängig von SetColor.
Das erste auf der GUI erstellte Control, dass einen Fokus erhalten kann, bekommt diesen automatisch. (Button, Input, Edit).
Ich umgehe das, indem ich einen Button 1x1 Pixel groß außerhalb des sichtbaren GUI Bereiches (x: -2, y: -2) als erstes Control erstelle.
Ist das fehlende Leerzeichen bei "\nAt" Absicht oder ein Fehler im Text?
Dort fehlt kein Leerzeichen, das ist ein Format-String. "\n" ist ein Zeilenumbruch und die neue Zeile beginnt mit "At". ![]()
Funktioniert denn dein PS Skript in der PS-Shell?
Hier ein Bsp. aus einem anderen Thread, wie man PS in AutoIt ausführen kann.
Global $sProcess = 'chrome.exe'
Global $sPathOutFile = 'C:\Code\chrome_processlist.txt'
Global $sCmdPS = _
'Get-WmiObject Win32_Process -Filter "name = ''' & $sProcess & '''" | Select-Object CommandLine | ' & _
'Format-Table -Property * -AutoSize | Out-String -Width 4096 | Out-File -FilePath ' & $sPathOutFile
_PowerShell_Run($sCmdPS)
Func _PowerShell_Run($_sCmd, $_iOutput=0)
Local Const $sKey32 = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell"
Local Const $sKey64 = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell"
Local Static $sKey = @CPUArch = 'X64' ? $sKey64 : $sKey32
Local Static $sPSexe = RegRead($sKey, 'Path')
Local $sPathTMP = StringFormat('%s\__%s%s%s%s%s%s%s.ps1', @TempDir, @YEAR, @MON, @MDAY, @HOUR, @MIN, @SEC, @MSEC)
Local $fH = FileOpen($sPathTMP, 2+8+128)
FileWrite($fH, $_sCmd)
FileClose($fH)
Local $sRun = StringFormat('%s -ExecutionPolicy UnRestricted -File %s', $sPSexe, $sPathTMP)
Local $sOut = '', $iPID = Run($sRun, @ScriptDir, @SW_HIDE, 0x2)
If $_iOutput = 1 Then
Do
$sOut &= StdoutRead($iPID)
Until @error
StdioClose($iPID)
Else
While ProcessExists($iPID)
Sleep(350)
WEnd
EndIf
FileDelete($sPathTMP)
Return ($_iOutput = 1 ? $sOut : 1)
EndFunc
Alles anzeigen
Auslöser ist sehr wahrscheinlich ein PAINT-Event, müsste man mal mitloggen welches bei Änderung Inhalt und welches bei Empfang ENTER ausgelöst wird.
ist das von unserem BugFIX ??
Alles andere auf meiner Seite ja, aber das habe ich nur gehosted. Es stammt von prog@ndy - einem ehemaligen Forumsmitglied. Er ist aber nicht mehr mit AutoIt aktiv.
Neue Version, v 0.2 im Startpost.
Neue Version 0.6, s. Startpost