-new-tab
Statt -new-window. Steht im Kommentar daneben ![]()
Bzw. bei private sollte es vmtl. reichen, das -window wegzunehmen.
Moombas hat auch den Link gepostet, wo du die Infos findest.
-new-tab
Statt -new-window. Steht im Kommentar daneben ![]()
Bzw. bei private sollte es vmtl. reichen, das -window wegzunehmen.
Moombas hat auch den Link gepostet, wo du die Infos findest.
Ich konnte mir die ganzen sich wiederholenden Zeilen nicht mit anschauen, also hab ich es mal passend mit nem Array erstellt.
Arrays werden immer genutzt, wenn man das gleiche mehrmals machen würde und sich nur wenig ändert und vermeiden eine Menge Code, der eigentlich nur Copy-Pasted wird.
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global $iCurrentHoveredCtrl = 0, $iSC = 7 ; start of CtrlLabel in the array
Global $arLinks = [ _ ; Name, Link, NormalIconFile, NormalIconId, HoverIconFile, HoverIconId, CtrlLabel, CtrlIcon
["Test", "https://www.autoit.de", "shell32.dll", -12, "shell32.dll", -10, "_openInBrowser", 0, 0], _ ; This line can be removed
["Test Private", "https://www.autoit.de", "shell32.dll", -14, "shell32.dll", -15, "_openInPrivateBrowser", 0, 0], _ ; This line can be removed
["Intranet", "https://intranet.*****.com/", "shell32.dll", -14, "shell32.dll", -15, "_openInBrowser", 0, 0], _
["Schulungen", "https://unterweisung.*****.com:444", "shell32.dll", -14, "shell32.dll", -15, "_openInBrowser", 0, 0], _
["Zeus", "https://zeiterfassung.*****.com/(S(uf3fpljnpwj3zrubyeq1jx2l))/login.aspx", "shell32.dll", -14, "shell32.dll", -15, "_openInBrowser", 0, 0], _
["FAQ", "https://faq.*****.com/", "shell32.dll", -14, "shell32.dll", -15, "_openInBrowser", 0, 0], _
["IT-Ticket erstellen", "https://intranet.*****/it-ticket-eroeffnen", "shell32.dll", -14, "shell32.dll", -15, "_openInBrowser", 0, 0], _
["Idee einreichen", "https://idee.*****.de/welcomepage", "shell32.dll", -14, "shell32.dll", -15, "_openInBrowser", 0, 0], _
["Outlook", "https://outlook.office365.com/", "\\int\dfs\DE\PUBLIC\*****\Web-Outlook.ico", -1, "\\int\dfs\DE\PUBLIC\*****\Web-Outlook.ico", -1, "_openInBrowser", 0, 0], _
["Übersicht der BZ's", "https://plan.*****.com/BZ/BZ.htm", "shell32.dll", -14, "shell32.dll", -15, "_openInBrowser", 0, 0] _
]
Global $iWidth = 330, $iHeight = 60+UBound($arLinks)*40, $iSpace = 20
$hGui = GUICreate("Elkamet-Links", $iWidth, $iHeight, 800, 300)
$Pic1 = GUICtrlCreatePic("\\int\dfs\DE\PUBLIC\*****.gif", 64, 0, 217, 33)
; Create the Icons and Labels for all links
For $i = 0 To UBound($arLinks)-1 Step 1
$arLinks[$i][$iSC+1] = GUICtrlCreateIcon($arLinks[$i][2], $arLinks[$i][3], $iSpace, 46+$i*40, 32, 32)
$arLinks[$i][$iSC] = GUICtrlCreateLabel($arLinks[$i][0], $iSpace*3, 50+$i*40, $iWidth-4*$iSpace, 22)
GUICtrlSetFont($arLinks[$i][$iSC], 14, 400, 4, 'Arial', 5)
GUICtrlSetColor($arLinks[$i][$iSC], 0x0000CC)
GUICtrlSetCursor($arLinks[$i][$iSC], 0)
GUICtrlSetTip($arLinks[$i][$iSC], $arLinks[$i][1])
Next
GUISetState(@SW_SHOW, $hGui)
While 1
$iMsg = GUIGetMsg()
Switch $iMsg
Case $GUI_EVENT_CLOSE
Exit
Case $GUI_EVENT_MOUSEMOVE
$iId = GUIGetCursorInfo($hGui)[4]
If $iId <> $iCurrentHoveredCtrl Then
; Change the icon back to normal
If $iCurrentHoveredCtrl>0 Then
For $i = 0 To UBound($arLinks)-1 Step 1
If $iCurrentHoveredCtrl = $arLinks[$i][$iSC] Then GUICtrlSetImage($arLinks[$i][$iSC+1], $arLinks[$i][2], $arLinks[$i][3])
Next
EndIf
; Set the hover icon
$iCurrentHoveredCtrl = $iId
For $i = 0 To UBound($arLinks)-1 Step 1
If $iId = $arLinks[$i][$iSC] Then GUICtrlSetImage($arLinks[$i][$iSC+1], $arLinks[$i][4], $arLinks[$i][5])
Next
EndIf
EndSwitch
; Check if a Label/Link was pressed
For $i = 0 To UBound($arLinks)-1 Step 1
If $iMsg = $arLinks[$i][$iSC] Then Call($arLinks[$i][6], $i)
Next
WEnd
Func _openInBrowser($iIndex)
ShellExecute("firefox", "-new-window "&$arLinks[$iIndex][1]) ;requires firefox to be installed Other possible options: -new-tab
EndFunc
Func _openInPrivateBrowser($iIndex)
ShellExecute("firefox", "-private-window "&$arLinks[$iIndex][1]) ;requires firefox to be installed
EndFunc
Alles anzeigen
Wenn du links hinzufügen, Icons (und Hover-Icons) ändern willst und die Aktion beim klicken ändern willst (z.B. Excel statt firefox) musst du mit dieser Variante nur das Array verändern und ggf. eine neue Funktion unten hinzufügen.
Auf diese Weise ist alles dynamisch generiert und die Höhe des Fensters passt sich z.B. an die Anzahl der Links automatisch an.
Bei fragen meld dich gern wieder ![]()
MfG Kanashius.
Du kannst mit ShellExecute(@Scriptname) dein Programm neustarten und dann das aktuelle mit Exit beenden. (Funktioniert ggf. nur mit der .exe Anwendung, kommt drauf an, was Standartmäßig .au3 bei dir macht).
Wozu soll das gut sein?
Ich vermute mal, dass es gert_nrw_71 um das Problem im andern Thread geht, dass der Scanner nach einiger Zeit nicht mehr funktioniert und du dann das Script neustarten willst.
Ich würde empfehlen, stattdessen das eigentliche Problem zu beheben, sodass nicht neugestartet werden muss. Gerade wenn man nicht genau weiß, was das Problem ist, sollte man mit Debugging (z.b. ConsoleWrite) herausfinden, wo das Problem liegt und es beheben.
Solange man nicht weiß, wo genau das Problem ist, kann es passieren, dass der neustart z.B. nicht rechtzeitig ist, weil es auf einem anderen System viel schneller zu Problemen kommt,...
Und dann hat man ggf. komische Nebeneffekte und weiß nicht, wo sie herkommen.
Erstmal: Mehrere/Viele GUIs sind kein Grund, mehrere Scripte zu schreiben. Das kann alles in ein Script, bzw. auch eine Datei.
Der einzige Grund, warum man in AutoIt mehrere Anwendungen (.exe - Dateien) benötigt, bzw. eine Anwendung mehrmals ausführen muss ist multiprocessing. Wenn man mehrere Dinge gleichzeitig verarbeiten will, wobei Geschwindigkeit wichtig ist, sodass man mehrere Prozessorkerne nutzen muss.
Deshalb vermute ich gerade, dass du einen Design/Denk Fehler hast, weshalb du die ganzen Scripte eig. gar nicht benötigst. Macht also ggf. Sinn, wenn du uns deinen Code zeigst, bzw. deinen genauen Grund für mehrere Scripte.
Ansonsten zu deiner eigentlichen Frage: Wenn du eine mit AutoIt compilierte .exe hast kann die meines Wissens nach andere .au3 Dateien ausführen. Hab ich aber selbst noch nie gebraucht/gemacht, solltest du aber finden, wenn du danach suchst.
Alles was du hier mit verschlüsseln,... machst wird niemanden, der wirklich will, davon abhalten, dass er an den Code rankommt. AutoIt ist eine Scriptsprache, es ist also ohne Probleme möglich an den Code (auch von der .exe) zu kommen. Du betreibst also nur Obfuskation.
Probier dasselbe, was ich bei dem Beep vorgeschlagen hab auch fürs FileWrite. Also $sBuffer global machen und beim beep (in der hauptschleife) auch ins log schreiben.
Wenn du lang dauernde Codeteile (Abhängig von der Festplatte kann schreiben nen moment dauern, wobei es eig. von windows gebuffert werden sollte... ) aus den Funktionen rausnimmst, die direkt aus der _KeyProc aufgerufen werden und stattdessen nur eine Variable setzt und dann später in der Hauptschleife auf die geänderte Variable reagierst, blockierst du die _KeyProc Funktion nicht.
Ich vermute, dass das Betriebssystem bei FileClose die Daten tatsächlich auf die Festplatte schreibt und das Script darauf wartet. Es könnte also auch helfen, wenn du das FileOpen und FileClose woanders machst. Wird aber schwer, weil du ja den Code als Dateinamen nutzt...
Wenn du trotzdem die Beeps haben möchtest: Füg in der Hauptschleife (Zeile 39/40) nen If/Switch ein mit ner globalen $iState Variable. Die kannst du dann an stelle der Beeps auf 1 oder 2 setzen und in der Hauptschleife dann abhängig von $iState dann die entsprechende Anzahl Beeps ausführen.
Hi ![]()
Erstmal zum Stil:
Konsistenz bei Variablen/Funktionen Benennung: $hWH_Timer / $__chBTN_TimerStart / $g_iSecs / _Timer_WIN() / __TimerStart() / _Timer()
Du solltest einen Stil wählen und dann dabei bleiben.
In AutoIt wird bei Variablen und Funktionen normalerweise mit camelcase gearbeitet. Also am Anfang klein und dann jedes neue Wort mit nem Großbuchstaben.
z.B. $gTimerMainGui, $iTimerTimeLabel oder timerStart(), timerStop()
Bei Funktionen werden interne AutoIt-Funktionen am Anfang groß geschrieben z.B. GuiGetMsg(), GuiCtrlSetData(), ...
UDFs die von mit AutoIt ausgeliefert werden (in der Hilfe zu finden sind) fangen auch mit einem _ an und haben dann den UDF Namen, gefolgt von der Funktion.
z.B.: _GDIPlus_PenSetColor, _GDIPlus_RectFCreate, ...
UDFs, die nicht mit AutoIt selbst kommen fangen mit __ an und sonst wie eine normale UDF.
z.B. für meine Wallpaper UDF: __Wallpaper_InitDefaultTray(), __Wallpaper_Start, ...
Deshalb schreibt man eigene Funktionen am Anfang klein oder (wie ich meistens) mit einem _ am Anfang, um nicht ausversehen Funktionen gleich zu nennen und Konflikte zu vermeiden.
Also in deinem Fall: _timerStart(), _timerStop(),...
Für Variablen gelten die gleichn Regeln, nur dass man noch am Anfang das kürzel für den Dateityp hat. Also z.B. $hTimer, $iTimerLabel,...
Bei UDFs dann dementsprechend $__Wallpaper_bRunning, $__Wallpaper_bClear, ...
Ansonsten schaut das schon ganz gut aus (ich vermute mal die Formatierung wurde beim posten durcheinander geworfen).
In deiner Haupt-Scheife solltest du ein Sleep einbauen, um Resourcen zu sparen. Der Nutzer merkt es nicht, ob 10ms vergehen, bis auf den Buttonklick reagiert wird. Dafür ist die CPU nicht permanent damit ausgelastet die Schleife zu durchlaufen.
While Sleep(10) And Not $bEnd
Switch GUIGetMsg()
Case $iTimerExitButton
_timerExit()
Case $iTimerStartButton
_timerStart()
Case $iTimerPauseButton
_timerPause()
EndSwitch
WEnd
Wenn ich mehrere Controls (hier die buttons) habe, die die gleiche größe haben und sehr Strukturiert angeordnet sind nehm ich gerne nen Array (s. Beispiel), da ich jetzt ohne Probleme die größe des Fensters erhöhen könnte und einen Button ins Array hinzufügen kann, ohne dann alle anderen Werte anpassen zu müssen. Ich hab allgemein die Controls so erstellt, dass du einfach $iTimerGuiWidth ändern kannst und alle Controls werden passend mit skaliert.
Z.B. Local Static $iTimerCount = 0 ist nützlich, wenn man eine Variable nur in einer Funktion benutzt, die Funktion aber öfter verwendet wird. Sorgt für weniger globale Variablen.
Ansonsten evtl. drauf achten, dass Deutsch/Englisch einheitlich bleibt. (z.B. $Ende, wo auch der Typ (boolean) fehlte).
So etwa hätte ich das umgesetzt:
#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Date.au3>
Global $hTimerGui, $iTimerLabel, $iState = 0 ; 0=start, 1=running, 2=paused
Global $bEnd = False, $iTimer
Global $arTimerButtons = [["Start", -1], ["Pause", -1], ["Exit", -1]]
$hGuiSomeParent = GUICreate("",10,10)
_timerGuiCreate($hGuiSomeParent)
While Sleep(10) And Not $bEnd
Switch GUIGetMsg()
Case $arTimerButtons[2][1]
_timerExit()
Case $arTimerButtons[0][1]
_timerToggleStarted()
Case $arTimerButtons[1][1]
_timerTogglePaused()
EndSwitch
If $iState = 1 Then _timerUpdate()
WEnd
Func _timerGuiCreate($hParent, $sTitle = "Timer", $iBackgroundColor = 0x40E0D0)
Local Const $iTimerGuiWidth = 147, $iTimerGuiHeight = 80, $iTimerGuiSpace = 5
$hTimerGui = GUICreate($sTitle, $iTimerGuiWidth, $iTimerGuiHeight, Default, Default, BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW), Default, $hParent)
GUISetBkColor($iBackgroundColor, $hTimerGui)
Local $iBtnWidth = ($iTimerGuiWidth - (UBound($arTimerButtons)+1) * $iTimerGuiSpace) / UBound($arTimerButtons) ; (gui width - free space) / button amount
For $i=0 To UBound($arTimerButtons)-1 Step 1
$arTimerButtons[$i][1] = GUICtrlCreateButton($arTimerButtons[$i][0], ($i+1)*$iTimerGuiSpace + $i*$iBtnWidth - 2, $iTimerGuiHeight-$iTimerGuiSpace-46, $iBtnWidth, 20)
Next
GUICtrlSetState($arTimerButtons[1][1], $GUI_DISABLE)
$iTimerLabel = GUICtrlCreateLabel("00:00:00", $iTimerGuiSpace, 0, $iTimerGuiWidth-2*$iTimerGuiSpace, 25, BitOR($SS_NOTIFY, $SS_CENTER))
GUICtrlSetFont($iTimerLabel, 20, 500)
GUISetState(@SW_SHOW, $hTimerGui)
WinSetOnTop($hTimerGui, "", $WINDOWS_ONTOP)
EndFunc
Func _timerToggleStarted()
Local Static $iTimerCount = 0
If $iState = 0 Then
$iState = 1
GUICtrlSetData($arTimerButtons[0][1], "Stop")
GUICtrlSetState($arTimerButtons[1][1], $GUI_ENABLE)
$iTimerCount+=1
$iTimer = TimerInit()
; AdlibRegister("_timerUpdate")
Else
$iState = 0
GUICtrlSetData($arTimerButtons[0][1], $arTimerButtons[0][0])
GUICtrlSetData($arTimerButtons[1][1], $arTimerButtons[1][0])
GUICtrlSetState($arTimerButtons[1][1], $GUI_DISABLE)
If $iTimerCount>0 Then ConsoleWrite("Timer[" & $iTimerCount&"]: " & GUICtrlRead($iTimerLabel) & @CRLF& @CRLF)
GUICtrlSetData($iTimerLabel, "00:00:00")
; AdlibUnRegister("_timerUpdate")
EndIf
EndFunc
Func _timerTogglePaused()
If $iState = 1 Then
$iState = 2
GUICtrlSetData($arTimerButtons[1][1], "Resume")
; AdlibUnRegister("_timerUpdate")
ElseIf $iState = 2 Then
$iState = 1
GUICtrlSetData($arTimerButtons[1][1], $arTimerButtons[1][0])
; AdlibRegister("_timerUpdate")
EndIf
EndFunc
Func _timerUpdate()
Local Static $iHour, $iMins, $iSecs
_TicksToTime(TimerDiff($iTimer), $iHour, $iMins, $iSecs)
Local $sTime = StringFormat("%02i:%02i:%02i", $iHour, $iMins, $iSecs)
If GUICtrlRead($iTimerLabel) <> $sTime Then GUICtrlSetData($iTimerLabel, $sTime)
EndFunc ;==>Timer
Func _timerExit()
; AdlibUnRegister("_timerUpdate")
GUIDelete($hTimerGui)
$bEnd = True
EndFunc
Alles anzeigen
Ich hab statt dem Adlibregister einfach einen Call in der Hauptschleife genutzt.
Kann ggf. nicht so gut funktionieren, wenn in deinem größeren Programm dann mehrere Schleifen sind.
Hoffe, das hilft dir etwas weiter :).
MfG Kanashius.
Dein Rot (ich nehme mal RGB an) FF0000 würde somit Türkis 00FFFF werden (ob autoit das so abbilden kann und macht in diesem Fall kann ich nicht sagen)
Da NOT in Autoit ein boolean erwartet und das dann invertiert, wird die Zahl erst zu boolean konvertiert. Da alles außer 0 True ist, wird 0xFF0000 also zu True und dann negiert => Not 0xFF0000 ist also False.
warum gibt es kein XOR
XOR ist ein Fall, der sehr selten benötigt wird. Deshalb lohnt es sich nicht, dafür einen eigenen Operator einzuführen. Insbesondere, weil der nicht dem normalen Schema entsprechen würde, dass bei der ersten fehlgeschlagenen/zutreffenden Bedingung beendet werden kann.
=> Kurzschlussauswertung funktioniert nicht: Ist bei einer And Verknüpfung der erste boolean falsch muss der zweite nicht mehr überprüft werden. Selbiges bei Or, wenn der erste bool wahr ist.
Außerdem kann man XOR einfach mit Not a <> Not b darstellen.
Google => man curl: https://curl.se/docs/manpage.html#-d
-d ist also der data block in ascii form => String
Der Inhalt sieht auch nach JSON aus, das passt also.
_WinHttpSimpleRequest($hConnect, $sType = Default, $sPath = Default, $sReferrer = Default, $sData = Default, $sHeader = Default, $fGetHeaders = Default, $iMode = Default) hat ein $sData feld, dass dafür da sein dürfte.
Also würde ich das hier versuchen:
$sData = '[{"Feldname1": "Wert1", "Feldname2": "Wert2"}]'
$sHeader = 'header-1: The Header '&@crlf&"header-2: lines"
$sPath = "www.google.com/search"
$hHttp = _WinHttpOpen()
$hConn = _WinHttpConnect($hHttp, "http...") ; http... bis zum ersten / (exclusive) => die domain => (www.google.com)
$sResult = _WinHttpSimpleRequest($hConn, "POST", "/rest of the path", Default, $sData, $sHeader, Default, Default) ; Last one may be 0 -> Ascii; 1->UTF-8, 2->Binary
; /rest of the path after the first / (inclusive) => (/search)
_WinHttpCloseHandle($hConn)
_WinHttpCloseHandle($hHttp)
Ich habs nicht getestet und mir nur die UDF angesehen, aber es sollte so funktionieren.
Hi, ich hatte mir deinen Code gestern angesehen und fand es unglücklich, dass du jede Minute ein neues Bild erstellst, es als Datei speicherst und dann als Hintergrund setzt.
Das ist eine echt gute Methode, wie du sehr schnell deine Festplatte kaputt schreibst. Bei mir ist das Hintergrundbild (2x4K und 2xFHD Bildschirm) ca. 11MB groß...
Das wären ~15.840MB => ~16GB in 24 Stunden, die dort geschrieben werden...
Deshalb hab ich mir gestern ein paar Stunden angeschaut, wie genau die Fenster vom Desktop funktionieren und hab eine UDF geschrieben, mit der man auf den Desktop zeichnen kann.
Ich hab dein Script mal mit der UDF umgesetzt. Das würde dann so ausschauen:
;Author: Kanashius@autoitscript.com, Kanashius@autoit.de, https://www.kanashius.com
#include "WallpaperUDF.au3"
#include <StaticConstants.au3>
HotKeySet("^!o", "_openOptions")
HotKeySet("^!l", "_load")
Global $hFamily, $hFontTime, $hFontDate, $hFormat, $hBrush, $hPen, $iPosDate = 25, $iPosTime = 60, $arDays = StringSplit("SO.|MO.|DI.|MI.|DO.|FR.|SA.", "|")
Global $sOptionsFile = @AppDataDir & "\Clock_Wallpaper_Options.ini"
; initialize own tray
__Wallpaper_InitDefaultTray()
; start the wallpaper drawing loop
__Wallpaper_Start(_draw, _init, _shutdown)
If @error Then MsgBox(16, "Error", "Something went wrong starting initializing the wallpaper: "&@error)
Func _draw(ByRef $hGraphics, $iWidth, $iHeight, ByRef $arScreenInfo) ; will be called for each drawing cicle.
; Draw Date
Local $sDate = StringFormat("%s %02i.%02i.%04i", $arDays[@WDAY], @MDAY, @MON, @YEAR)
Local $tLayoutDate = _GDIPlus_RectFCreate($arScreenInfo[0][0] + 200, $arScreenInfo[0][1] + $iPosDate) ; Draw at the primary screen
Local $aInfoDate = _GDIPlus_GraphicsMeasureString($hGraphics, $sDate, $hFontDate, $tLayoutDate, $hFormat)
_GDIPlus_GraphicsDrawStringEx($hGraphics, $sDate, $hFontDate, $aInfoDate[0], $hFormat, $hBrush)
; Draw Time
Local $sTime = StringFormat("%02i:%02i:%02i", @HOUR, @MIN, @SEC)
$tLayoutTime = _GDIPlus_RectFCreate($arScreenInfo[0][0] + 200, $arScreenInfo[0][1] + $iPosTime) ; Draw at the primary screen
$aInfoTime = _GDIPlus_GraphicsMeasureString($hGraphics, $sTime, $hFontTime, $tLayoutTime, $hFormat)
_GDIPlus_GraphicsDrawStringEx($hGraphics, $sTime, $hFontTime, $aInfoTime[0], $hFormat, $hBrush)
; Return redraw areas
Local $arAreas[0][4]
_addRect($arAreas, $aInfoDate)
_addRect($arAreas, $aInfoTime)
return SetExtended(100, $arAreas) ; Change extended to the (min) time in ms to wait between each redraw. (This does not influence _process)
EndFunc
Func _addRect(ByRef $arAreas, $aTag)
ReDim $arAreas[UBound($arAreas)+1][4]
For $i = 1 To 4 Step 1
$arAreas[UBound($arAreas)-1][$i-1] = DllStructGetData($aTag[0], $i)
Next
EndFunc
Func _init($iWidth, $iHeight, ByRef $arScreenInfo) ; The initialization method is called once before the draw loop starts.
If UBound($arScreenInfo) = 0 Then
MsgBox(16, "Error", "It is difficult to draw a wallpaper without a screen.")
Exit
EndIf
_load()
$hFormat = _GDIPlus_StringFormatCreate(0x4000)
_GDIPlus_StringFormatSetAlign($hFormat, 1)
$hBrush = _GDIPlus_BrushCreateSolid(0xff000000)
$hPen = _GDIPlus_PenCreate(0xC4000000, 1)
EndFunc
Func _shutdown() ; The shutdown method is called at the end of the draw loop, after __Wallpaper_Exit was called.
_cleanUp()
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_PenDispose($hPen)
EndFunc
Func _load()
Local $bIsPaused = __Wallpaper_IsPause() ; pause drawing, while changing the fonts
if Not $bIsPaused Then __Wallpaper_PauseResume()
; Local $sBGFilePath = IniRead($sOptionsFile, "options", "image", 0)
$iPosDate = Int(IniRead($sOptionsFile, "options", "pos_date", $iPosDate))
$iPosTime = Int(IniRead($sOptionsFile, "options", "pos_time", $iPosTime))
_cleanUp()
$hFamily = _GDIPlus_FontFamilyCreate(IniRead($sOptionsFile, "options", "font", "Arial"))
$hFontDate = _GDIPlus_FontCreate($hFamily, IniRead($sOptionsFile, "options", "size_date", 25), 0)
$hFontTime = _GDIPlus_FontCreate($hFamily, IniRead($sOptionsFile, "options", "size_time", 25), 0)
if Not $bIsPaused Then __Wallpaper_PauseResume()
EndFunc
Func _cleanUp()
_GDIPlus_FontDispose($hFontTime)
_GDIPlus_FontDispose($hFontDate)
_GDIPlus_FontFamilyDispose($hFamily)
EndFunc
Func _openOptions()
Run("notepad.exe " & $sOptionsFile)
EndFunc
Alles anzeigen
Ich hab noch die Sekunden hinzugefügt, weil warum nicht ![]()
Edit: Link zur UDF: Wallpaper UDF
Edit2: _getMaxRect() removed
Hi, ich habe eine kleine Bibliothek geschrieben, mit der auf ein Fenster hinter den Desktop-Icons gezeichnet werden kann. Sie erlaubt das zeichnen auf das Wallpaper mit GDI+ ab Windows 8.
Da GDI+ genutzt wird, ist es nicht ganz so schnell, aber ich komme in meinem Beispiel Script immernoch auf 60-120fps.
Theoretisch kann man die Funktionen auch nutzen, um ein eigenes Child-Fenster mit Controls zu erzeugen (in __Wallpaper_Startup $hWorkerW ist das benötigte Fenster), falls das für jemanden interessant ist.
Viel Spaß damit
.
Beispiel:
;Author: Kanashius@autoitscript.com, Kanashius@autoit.de, https://www.kanashius.com
#include "WallpaperUDF.au3"
#include <StaticConstants.au3>
; initialize own tray
__Wallpaper_InitDefaultTray()
; animation variables
Global Const $fDeg = ACos(-1) / 180 ;ACos(-1) is nearly pi
Global Const $iDots = 7, $fAngelDist = 360 / $iDots, $iRadius = 250
Global $aCoordinates[$iDots][2], $bIsFirst = True
Global $iX_Center, $iY_Center, $fAngle = 0
; fps-counter variables
Global $iFPSTextWidth = 100, $iFPSTextSize = 16, $iTimer, $iFrames = 0, $sFps = "FPS: 0"
Global $hPen, $hFamily, $hFont, $hFormat, $hBrush
; create gui
Global $iWidth = 180, $iHeight = 125
$hGui = GUICreate("Wallpaper UDF example", $iWidth, $iHeight, 10, 10)
$idLabelFps = GUICtrlCreateLabel($sFps, 10, 10, $iWidth-20, Default, $SS_CENTER)
$idBtnPR = GUICtrlCreateButton("Pause/Resume", 10, 30, $iWidth-20)
$idBtnClear = GUICtrlCreateButton("Clear", 10, 60, $iWidth-20)
$idBtnExit = GUICtrlCreateButton("Exit", 10, 90, $iWidth-20)
GUISetState(@SW_SHOW, $hGui)
; start the wallpaper drawing loop
__Wallpaper_Start(_draw, _init, _shutdown, _process)
If @error Then MsgBox(16, "Error", "Something went wrong starting initializing the wallpaper: "&@error)
Func _draw(ByRef $hGraphics, $iWidth, $iHeight, ByRef $arScreenInfo) ; will be called for each drawing cicle.
; Draw the animation
For $i = 0 To $iDots - 1
$aCoordinates[$i][0] = $iX_Center+Cos($fAngle*$fDeg)*$iRadius
$aCoordinates[$i][1] = $iY_Center+Sin($fAngle*$fDeg)*$iRadius
If Not $bIsFirst Then
_GDIPlus_PenSetColor($hPen, 0xFFFFFF00)
_GDIPlus_PenSetWidth($hPen, 2)
_GDIPlus_GraphicsDrawLine($hGraphics, $aCoordinates[$i][0], $aCoordinates[$i][1], _
$aCoordinates[Mod(($i + $iDots / 2), $iDots)][0], $aCoordinates[Mod(($i + $iDots / 2), $iDots)][1], $hPen)
_GDIPlus_PenSetColor($hPen, 0xFFFF8000)
_GDIPlus_PenSetWidth($hPen, 3)
If $i < $iDots - 1 Then _GDIPlus_GraphicsDrawLine($hGraphics, $aCoordinates[$i][0], $aCoordinates[$i][1], $aCoordinates[$i + 1][0], $aCoordinates[$i + 1][1], $hPen) ;;draw outer lines
EndIf
$fAngle += $fAngelDist
Next
If Not $bIsFirst Then _GDIPlus_GraphicsDrawLine($hGraphics, $aCoordinates[$i - 1][0], $aCoordinates[$i - 1][1], $aCoordinates[0][0], $aCoordinates[0][1], $hPen)
$bIsFirst = False
$fAngle -= 0.5
; update fps
If TimerDiff($iTimer)>1000 Then
_updateFps($iFrames)
$iFrames = 0
$iTimer = TimerInit()
EndIf
$iFrames += 1
; draw fps
$tLayout = _GDIPlus_RectFCreate($iX_Center - $iFPSTextWidth, $iY_Center - 4, $iFPSTextWidth*2, $iFPSTextSize+4)
$aInfo = _GDIPlus_GraphicsMeasureString($hGraphics, $sFps, $hFont, $tLayout, $hFormat)
_GDIPlus_GraphicsDrawStringEx($hGraphics, $sFps, $hFont, $aInfo[0], $hFormat, $hBrush)
; Return redraw areas
Local $arAreas = [[$iX_Center-$iRadius,$iY_Center-$iRadius,$iX_Center+$iRadius,$iY_Center+$iRadius]] ; Set the areas that were redrawn and should be replaced
return SetExtended(0, $arAreas) ; Change extended to the (min) time in ms to wait between each redraw. (This does not influence _process)
EndFunc
Func _updateFps($iFps)
$sFps = "FPS: "&$iFps
GUICtrlSetData($idLabelFps, $sFps)
EndFunc
Func _process()
$iMsg = GUIGetMsg()
Switch $iMsg
Case -3, $idBtnExit
GUIDelete($hGui)
__Wallpaper_Exit()
Case $idBtnPR
__Wallpaper_PauseResume()
_updateFps(0)
Case $idBtnClear
__Wallpaper_Clear()
_updateFps(0)
EndSwitch
EndFunc
Func _init($iWidth, $iHeight, ByRef $arScreenInfo) ; The initialization method is called once before the draw loop starts.
If UBound($arScreenInfo) = 0 Then
MsgBox(16, "Error", "It is difficult to draw a wallpaper without a screen.")
Exit
EndIf
$iTimer = TimerInit()
$iX_Center = $arScreenInfo[0][0]+$arScreenInfo[0][2]/2
$iY_Center = $arScreenInfo[0][1]+$arScreenInfo[0][3]/2
$hPen = _GDIPlus_PenCreate(0xFFFF0000, 4)
$hFamily = _GDIPlus_FontFamilyCreate("Arial")
$hFont = _GDIPlus_FontCreate($hFamily, $iFPSTextSize)
$hFormat = _GDIPlus_StringFormatCreate(0x4000)
_GDIPlus_StringFormatSetAlign($hFormat, 1)
$hBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)
EndFunc
Func _shutdown() ; The shutdown method is called at the end of the draw loop, after __Wallpaper_Exit was called.
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFamily)
_GDIPlus_PenDispose($hPen)
EndFunc
Alles anzeigen
Und ich selber versuche so wenig wie möglich Global zu setzen, alles was man nur Lokal braucht, gehört für mich nur in einen Lokalen Kontext.
Da würde ich definitiv wiedersprechen. Konstanten gehören niemals lokal. Außerdem sollte GDIPlus beim Programmstart gestartet und beim beenden geschlossen werden, wenn die Funktionen öfter benutzt werden. Es erzeugt performance mäßig einfach viel zu viel overhead, ständig zu laden und wieder freizugeben.
Ich würde immer die Performance als erstes sehen, weil das vom Nutzer am ehesten bemerkt wird. Dann den Speicherverbrauch. Ist heutzutage nicht mehr ein ganz so großes Problem, deshalb wirds nicht allzu schnell auffallen. Und später kommt irgendwann Stil, also wenn möglich lokal,... (Natürlich alles im Rahmen, wenn es nicht anders geht muss man kompromisse eingehen.) Wenn es zu viele Globale Variablen werden, sodass es unübersichtlich wird, muss man halt auf mehrere Scripte aufteilen.
Lokal gehören nur alle temporären Variablen, die nur während eines Funktionsdurchlaufes verwendet werden. Bei denen macht es keinen Sinn, sie Global anzulegen.
Hier wüde ich sagen hängt es davon ab, wie oft das Wallpaper geändert werden soll. Wenn es manuell hin und wieder gewechselt wird würde für mich der Speicher evtl. wichtiger sein, weils eh nur alle paar Tage aufgerufen wird => Performance ist weniger wichtig (sollte aber auch nicht wenige Sekunden überschreiten). => Lokal anlegen und wieder freigeben.
Wenn es automatisch alle X Sekunden/Minuten wechselt sollte für Performance optimiert werden. => Global anlegen
Wobei ich vmtl. hier einfach nur auf Performance gehen würde und eher Global allokieren würde, weil der Speicherverbrauch so gering ist, dass er nicht ins gewicht fällt. Bei GBs an RAM sind nen paar KB egal.
Da du versuchst json zu verarbeiten, könnte es sinnvoll sein, wenn du dir die JSON-UDF mal anschaust:
Wenn ich mir den Code bisher so ansehe, hast du glaub ich, noch nicht ganz verstanden, was Variablen sind.
Variablen sind ausschließlich dazu da, Daten zu speichern. Sie verändern nichts. Zum Verändern sind Funktionen da.
Wenn du also z.B. GUICtrlSetColor($acLabel, $col) aufrufst, wird mit den Werten gearbeitet, die zu dem Zeitpunkt in den Variablen stehen und übergeben werden. Zum Zeitpunkt des Funktionsaufrufs bezieht sich $acLabel auf das Control und $col enthält die Farbe.
Wenn du aber z.B. $col = "0xFFFFFF" ausführst, wird nur ein anderer Wert in die Variable gespeichert. Dadurch verändert sich nichts. Erst wenn du die Funktion GuiCtrlSetColor erneut mit $col aufrufst, wird die Farbe verändert, da nun ein anderer Wert in $col steht.
Variablen sind also reine Speicher für Daten/Informationen, die man dann an Funktionen übergibt, die damit weiterarbeiten.
Das Ändern einer Variable löst aber keine andere Aktion aus, außer, dass in dem Datenfeld jetzt etwas anderes steht.
Solange die Variable nicht woanders ausgelesen/verwendet wird, ändert sich auch nichts.
Dein Problem ist ein anderes...
Du erstellst alle 5 Sekunden ein Label mit dem Inhalt $fslabel...
Dementsprechend hast du eine riesige Menge an Controls, die dort übereinander erstellt werden. Versuch mal, einen weiteren Text zu setzen.
Dadurch wird dein Programm irgendwann abstürzen, da du unendlich viele Labels erstellst.
Du musst das Label zusammen mit der GUI EINMAL erstellen und später nur den Inhalt mit GuiCtrlSetData ändern.
Ich würde das Fenster ähnlich erstellen, wie ich es in diesem Post RE: mehrere Zeiten wenn abgelaufen für OBS gemacht habe.
Dann musst du nur $iWidth und $iHeight am Anfang anpassen.
Wenn du dabei dann @DesktopWidth und @DesktopHeight verwendest kannst du einfach z.B. $iWidth = @DesktopWidth * 0.6 und schon hast du ein Fenster, das 60% der Bildschirmbreite füllt.
Es wäre dann auch einfach, z.b. die CTRL-Größe mit $iCtrlHeight anzupassen um z.b. auch Schriftgrößen Änderungen zu machen. Alle Control-Width Variablen mit nem Faktor für die Schriftgröße zu multiplizieren wäre auch kein Problem.
Es macht dann halt sinn, einige Variablen als "Stellschrauben" einzuführen, die Überall verwendet werden.
Ich erstell all meine Fenster schon länger auf diese Weise, weil dann einfache Anpassungen möglich sind.
Als Beispiel wäre hier eine Alarmfunktion. Das könnte dir weiterhelfen. Du musst nur anpassen, was beim alarm passieren soll.
#include <DateTimeConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <Array.au3>
Global $iWidth=250, $iHeight=300, $iCtrlHeight=25, $iCtrlSpace = 10, $iWidthMid=$iWidth/2, $iHeightMid=$iHeight/2, $bAlarm = False
$hGui = GUICreate("Timer", $iWidth, $iHeight)
Local $iWidthCtrlTime = 70, $iWidthBtnAddTime = 40, $iAddWidth = $iWidthCtrlTime + $iCtrlSpace + $iWidthBtnAddTime
ConsoleWrite($iWidthMid&"-"&$iAddWidth&"/"&2&@crlf)
$iCtrlTime = GUICtrlCreateDate("", $iWidthMid-$iAddWidth/2, $iCtrlHeight/2, $iWidthCtrlTime, $iCtrlHeight, $DTS_TIMEFORMAT)
$iCtrlTimeAddBtn = GUICtrlCreateButton("Add", $iWidthMid-$iAddWidth/2+$iWidthCtrlTime+$iCtrlSpace, $iCtrlHeight/2, $iWidthBtnAddTime, $iCtrlHeight)
$iCtrlTimers = GUICtrlCreateListView("Timer", $iCtrlSpace, $iCtrlHeight*2, $iWidth-2*$iCtrlSpace, $iHeight-2.5*$iCtrlHeight)
_GUICtrlListView_SetColumnWidth($iCtrlTimers,0, $iWidth-2*$iCtrlSpace-4)
$iCtrlTimersMenu = GUICtrlCreateContextMenu($iCtrlTimers)
$iCtrlTimersRemove = GUICtrlCreateMenuItem("Remove", $iCtrlTimersMenu)
Local $iWidthCtrlAlarm = 50, $iWidthBtnStopAlarm = 80, $iAlarmWidth = $iWidthCtrlAlarm + $iCtrlSpace + $iWidthBtnStopAlarm
$iCtrlAlarm = GUICtrlCreateLabel("", $iWidthMid-$iAlarmWidth/2, $iHeightMid - $iCtrlHeight/2 + $iCtrlHeight/4, $iWidthCtrlAlarm, $iCtrlHeight)
$iCtrlStopAlarm = GUICtrlCreateButton("Stop Alarm", $iWidthMid-$iAlarmWidth/2+$iWidthCtrlAlarm+$iCtrlSpace, $iHeightMid - $iCtrlHeight/2, $iWidthBtnStopAlarm, $iCtrlHeight)
GUICtrlSetState($iCtrlAlarm, $GUI_HIDE)
GUICtrlSetState($iCtrlStopAlarm, $GUI_HIDE)
GUISetState(@SW_SHOW, $hGui)
Local $iCount = 0
Local $iTimer = TimerInit()
While Sleep(10)
Switch GUIGetMsg()
Case -3
Exit
Case $iCtrlTimeAddBtn
_addTimer()
Case $iCtrlTimersRemove
_removeSelTimer()
Case $iCtrlStopAlarm
_stopAlarm()
EndSwitch
If $bAlarm Then
Switch $iCount
Case 0
Beep(500, 200)
Case 1
Beep(1000, 200)
$iCount = 0
EndSwitch
EndIf
If TimerDiff($iTimer) > 200 Then
$iTimer = TimerInit()
_checkTimers()
EndIf
WEnd
Func _startAlarm($sTime)
GUICtrlSetData($iCtrlAlarm, $sTime)
$bAlarm = True
GUICtrlSetState($iCtrlAlarm, $GUI_SHOW)
GUICtrlSetState($iCtrlStopAlarm, $GUI_SHOW)
GUICtrlSetState($iCtrlTimers, $GUI_HIDE)
EndFunc
Func _stopAlarm()
$bAlarm = False
GUICtrlSetState($iCtrlAlarm, $GUI_HIDE)
GUICtrlSetState($iCtrlStopAlarm, $GUI_HIDE)
GUICtrlSetState($iCtrlTimers, $GUI_SHOW)
EndFunc
Func _addTimer()
Local $sTime = GUICtrlRead($iCtrlTime)
GUICtrlCreateListViewItem($sTime, $iCtrlTimers)
Local $bAsc = False
_GUICtrlListView_SimpleSort($iCtrlTimers, $bAsc, 0)
EndFunc
Func _removeSelTimer()
_GUICtrlListView_DeleteItemsSelected($iCtrlTimers)
EndFunc
Func _checkTimers()
While _GUICtrlListView_GetItemCount($iCtrlTimers) > 0
$sTime = _GUICtrlListView_GetItem($iCtrlTimers, 0, 0)[3]
Local $arTime = StringSplit($sTime, ":", 3)
Local $arCTime = [@HOUR, @MIN, @SEC]
Local $iDiff = _timeDiffCurr($arTime, $arCTime)
If $iDiff < 1 or $iDiff > 86398 Then
_startAlarm($sTime)
_GUICtrlListView_DeleteItem($iCtrlTimers, 0)
Else
ExitLoop
EndIf
WEnd
EndFunc
Func _timeDiffCurr($arTime, $arTimeS)
return ((Abs($arTimeS[0]-$arTime[0]) * 60) + Abs($arTimeS[1]-$arTime[1])) * 60 + Abs($arTimeS[2]-$arTime[2])
EndFunc
Alles anzeigen
Hi ![]()
Das hängt natürlich davon ab, wie genau das Muster aussieht, bzw. was das Ziel ist.
So wie ich es aus deinem Beispiel sehe (Bei den Inputs sind die Zahlen manchmal glaub ich falsch => Copy and Paste fehler vermut ich mal) wäre meine Lösung so:
ConsoleWrite(V_test("01234567891011121314151617181920")&@crlf)
ConsoleWrite(V_test_loop("01234567891011121314151617181920")&@crlf)
Func V_test($sInput, $iAmount=5, $iStart=10, $iReplaceStart = "A")
$sText = StringRegExpReplace($sInput, ""&$iStart, $iReplaceStart)
if $iAmount=0 Then return $sText
return V_test($sText, $iAmount-1, $iStart+1, ChrW(AscW($iReplaceStart)+1))
EndFunc
Func V_test_loop($sInput, $iAmount=5, $iStart=10, $iReplaceStart = "A")
Local $sText = $sInput
While $iAmount>=0
$sText = StringRegExpReplace($sText, ""&$iStart, $iReplaceStart)
$iReplaceStart = ChrW(AscW($iReplaceStart)+1)
$iStart+=1
$iAmount-=1
WEnd
return $sText
EndFunc
Alles anzeigen
Einmal Rekursiv und einmal als Schleife.
Die Schleife solltest bevorzugt werden, da Rekursion begrenzt ist (Anzahl verschachtelter Funktionsausrufe ist begrenzt).
MfG, Kanashius.
Hi, ich würde davon abraten, über alle Daten einen Hash zu erzeugen. Das ist sehr Rechenintensiv und unnötig.
Deshalb meine Vorschläge:
Zu 1.:
MariaDB speichert, wann eine Tabelle zuletzt geändert wurde, also kannst du dort prüfen, ob sich deine Tabelle seit dem letzten check geändert hat. https://www.tutorialspoint.com/get-the-date-t…-mysql-database
Um dann nur geänderte Daten anzuzeigen ist es am sinnvollsten, wenn du in der Datenbank eine neue Spalte anlegst mit einem Timestamp, der bei jeder Änderung der Zeile aktualisiert wird.
In deinem Programm kannst du dann immer nur die eine kleine Abfrage machen, ob sich die Tabelle(n) geändert haben und wenn ja, alle Zeilen abfragen, bei denen der Timestamp >= deiner letzten Abfrage ist.
Ich würde aber max. alle paar Sekunden abfragen, ob sich etwas geändert hat. Kommt aber natürlich auf den Anwendungsfall an. Wenn es aber so oft Änderungen gibt, solltest du darüber nachdenken, ob nur eine Datenbank das Richtige ist, oder ob es sinnvoll ist, der Datenbank eine Messagequeue o.ä. vorzuschalten.
Zu 2.:
Es macht vmtl. Sinn, die Aktualisierung nur laufen zu lassen, wenn das Fenster im Fokus ist, bzw. wenn es nicht im Fokus ist, zu checken, ob es sichtbar ist (Ansätze dafür: https://www.autoitscript.com/forum/topic/15…ndow-is-on-top/). Ggf. dann noch ein check auf IDLE.
Das wären meine Ideen, um das ganze zumindest halbwegs Performant zu gestalten.
MfG Kanashius.
Ich würde empfehlen, dass ganze in eine Funktion auszulagern. Das macht es übersichtlicher und einfacher zu nutzen.
;check for ips and get them
$arIps = _activeIPs()
If @error Then
MsgBox(16, "Error", "IP Information could not be received: "&@error)
Else
If UBound($arIps) > 0 Then
ConsoleWrite($arIps[0][0]&" - "&$arIps[0][0]&@crlf) ; Or the guictrlsetdata
EndIf
EndIf
; only check
Local $check = _activeIPs(Default, True)
If @error Then
MsgBox(16, "Error", "IP Information could not be received: "&@error)
ElseIf $check Then
MsgBox(48, "", "Online")
Else
MsgBox(48, "", "Offline")
EndIf
Func _activeIPs($sHost = "127.0.0.1", $checkOnly = False)
Local $arIPs[1][2], $count = 0
Local $objAdapter
Static $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $sHost & "\root\cimv2")
If Not IsObj($objWMIService) Then return SetError(1)
Local $colAdapter = $objWMIService.ExecQuery("Select * From Win32_NetworkAdapterConfiguration WHERE IPEnabled = True", "WQL", 0x30)
If Not IsObj($colAdapter) Then return SetError(2)
For $objAdapter In $colAdapter
$sIp = $objAdapter.IPAddress(0)
$sGW = $objAdapter.DefaultIPGateway(0)
If $sIp or $sGW and IsString($sIp) or IsString($sGW) Then
If $checkOnly Then return True
ReDim $arIPs[$count+1][2]
$arIPs[$count][0] = $sIp
$arIPs[$count][1] = $sGW
$count+=1
EndIf
Next
If $checkOnly Then return False
return $arIPs
EndFunc
Alles anzeigen
Es kann also ein Array mit IP/Gateway gesucht werden oder nur getestet werden, ob eines vorhanden ist.
Ich hab auch das WMI-Object static gemacht (Static $objWMIService), da das Objekt nur beim ersten mal erfolgreich erstellt wurde und ab dem zweiten Call fehlschlug.
Scheinbar kann man nicht mehrere Objekte davon in einem Programm erstellen/nutzen, dementsprechend hab ich mit static dafür gesorgt, dass es nur einmal erstellt wird und nicht öfter (vmtl. muss man eigentlich nen close call an dem Objekt machen oder so).