1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Oscar

Beiträge von Oscar

  • Verschieben der Buttons einer Toolbar

    • Oscar
    • 1. September 2018 um 16:29

    Ich versuche mich gerade daran, bei einer Toolbar die Buttons verschiebbar zu machen, sodass man die Anordnung der Buttons selbst bestimmen kann.

    Bisher habe ich ein, einigermassen funktionierendes, Beispiel (siehe unten) hinbekommen. Allerdings mit zwei Einschränkungen:

    1. der Abstand zwischen den Buttons muss 0 Pixel betragen

    2. es dürfen keine Separator-Buttons vorhanden sein

    AutoIt
    #include <AutoItConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiImageList.au3>
    #include <GuiMenu.au3>
    #include <GuiReBar.au3>
    #include <GuiToolbar.au3>
    #include <RebarConstants.au3>
    #include <StructureConstants.au3>
    #include <ToolbarConstants.au3>
    #include <WinAPIGdi.au3>
    #include <WinAPIGdiInternals.au3>
    #include <WinAPIHObj.au3>
    #include <WinAPIIcons.au3>
    #include <WinAPIShellEx.au3>
    #include <WindowsConstants.au3>
    
    Opt('GUIOnEventMode', 1)
    
    Global Const $iUserIconSize = 32 ; die Icongroesse der User-Toolbar
    
    Global $hUserImgList = _GUIImageList_Create($iUserIconSize, $iUserIconSize, 5)
    Global $aIconIndices[] = [10, 18, 41, 54, 65, 85, 124, 94]
    For $iIndex In $aIconIndices
        _GUIImageList_AddIconEx($hUserImgList, 'imageres.dll', $iIndex)
    Next
    
    Global $hMainGui = GUICreate('Toolbar Drag and Drop', 800, 320, -1, -1, BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPCHILDREN))
    GUISetOnEvent($GUI_EVENT_CLOSE, '_CloseMainGui')
    GUISetFont(12, 400, 0, 'Verdana')
    Global $hDrivesRebar = _GUICtrlRebar_Create($hMainGui, BitOR($CCS_TOP, $CCS_NODIVIDER, $RBS_VARHEIGHT, $RBS_BANDBORDERS))
    Global $hUserToolbar = _GUICtrlToolbar_Create($hMainGui, BitOR($TBSTYLE_FLAT, $TBSTYLE_TOOLTIPS))
    _GUICtrlToolbar_SetMetrics($hUserToolbar, 10, 10, 0, 10) ; <- der Abstand zwischen den Buttons (4. Parameter) muss auf 0 stehen, sonst klappt das nicht
    _GUICtrlToolbar_SetImageList($hUserToolbar, $hUserImgList)
    _GUICtrlRebar_AddToolBarBand($hDrivesRebar, $hUserToolbar, '', 0, $RBBS_NOGRIPPER)
    _GUICtrlRebar_SetBandLength($hDrivesRebar, 0, 800)
    For $i = 0 To UBound($aIconIndices) - 1
        _GUICtrlToolbar_AddButton($hUserToolbar, 10000 + $i, $i)
    Next
    ;~ _GUICtrlToolbar_AddButtonSep($hUserToolbar) ; <- mit Separator klappt das verschieben nicht richtig
    GUISetState(@SW_SHOW)
    GUIRegisterMsg($WM_NOTIFY, '_WM_NOTIFY')
    GUIRegisterMsg($WM_SIZE, '_WM_SIZE')
    WinWaitClose($hMainGui)
    Exit
    
    Func _CloseMainGui()
        _GUIImageList_Destroy($hUserImgList)
        GUIDelete($hMainGui)
    EndFunc   ;==>_CloseMainGui
    
    Func _WM_SIZE($hWnd, $iMsg, $wParam, $lParam)
        #forceref $hWnd, $iMsg, $wParam
        Local $iWidth = BitAND($lParam, 0xFFFF)
        _GUICtrlRebar_SetBandLength($hDrivesRebar, 0, Int($iWidth / 2))
        Return $GUI_RUNDEFMSG
    EndFunc   ;==>_WM_SIZE
    
    Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
        #forceref $hWnd, $iMsg, $wParam
        Local Static $fDragButton = False
        Local $tNMHDR, $hWndFrom, $iCode, $tNMTBHOTITEM, $iOldPos, $iNewPos, $tNMMOUSE, $iCmdID
        $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
        $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
        $iCode = DllStructGetData($tNMHDR, 'Code')
        Switch $hWndFrom
            Case $hUserToolbar
                Switch $iCode
                    Case $TBN_HOTITEMCHANGE
                        If $fDragButton Then
                            $tNMTBHOTITEM = DllStructCreate($tagNMTBHOTITEM, $lParam)
                            $iOldPos = _GUICtrlToolbar_CommandToIndex($hUserToolbar, DllStructGetData($tNMTBHOTITEM, 'idOld'))
                            $iNewPos = _GUICtrlToolbar_CommandToIndex($hUserToolbar, DllStructGetData($tNMTBHOTITEM, 'idNew'))
                            If $iOldPos > -1 And $iNewPos > -1 Then _GUICtrlToolbar_MoveButton($hUserToolbar, $iOldPos, $iNewPos)
                        EndIf
                    Case $TBN_DRAGOUT ; sobald ein Button zur Seite bewegt wird
                        $fDragButton = True ; das als dragging Start markieren
                    Case $TBN_ENDDRAG ; sobald der Benutzer den Button loslaesst
                        $fDragButton = False ; das dragging als beendet markieren
                    Case $NM_LDOWN ; wenn der Benutzer einen linken Mausklick auf einen der Buttons macht
                        $tNMMOUSE = DllStructCreate($tagNMMOUSE, $lParam)
                        $iCmdID = DllStructGetData($tNMMOUSE, 'ItemSpec')
                        If $iCmdID <> 0xFFFFFFFF Then
                            ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iCmdID = ' & $iCmdID & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
                        EndIf
                EndSwitch
        EndSwitch
        Return $GUI_RUNDEFMSG
    EndFunc   ;==>_WM_NOTIFY
    
    Func _GUIImageList_AddIconEx(ByRef $hImgList, $sPath, $iIndex)
        Local $aIconSize, $hIcon, $hIcon32, $hDIB, $hAND, $iImgIndex
        $aIconSize = _GUIImageList_GetIconSize($hImgList)
        $hIcon = _WinAPI_ShellExtractIcon($sPath, $iIndex, $aIconSize[0], $aIconSize[1])
        $hDIB = _WinAPI_Create32BitHBITMAP($hIcon, False)
        $hAND = _WinAPI_CreateANDBitmap($hDIB)
        $iImgIndex = _GUIImageList_AddMasked($hImgList, $hDIB, $hAND)
        _WinAPI_DeleteObject($hAND)
        _WinAPI_DeleteObject($hDIB)
        _WinAPI_DestroyIcon($hIcon)
        Return $iImgIndex
    EndFunc   ;==>_GUIImageList_AddIconEx
    Alles anzeigen

    Meine Frage: Wie kriege ich das ohne die Einschränkungen hin?

  • Drag and Drop auf Toolbar

    • Oscar
    • 1. September 2018 um 15:56
    Zitat von chesstiger

    Das Drop-Event in WParam enthält einerseits alle Dateinamen, andererseits auch die Koordinaten des "Loslassens". Über ChildWindowFromPoint kannst du dir dann das entsprechende Control-Handle holen und schauen, ob es deine Toolbar ist.

    Ja, ich denke, das ist als Workaround noch besser, als das transparente Label.

    Vermutlich werde ich diese Variante benutzen. Danke schön!

    Die Toolbar wird unter AutoIt scheinbar nicht so oft benutzt. Man findet im Netz nur sehr wenig Scripte dazu.

  • Icon-Show

    • Oscar
    • 31. August 2018 um 19:10
    Zitat von bazii

    Funktioniert prima und ist vor allem sehr nützlich.

    Freut mich, das zu hören! :)

    Und es gibt auch noch eine neue Version mit einigen sinnvollen (IMHO) Erweiterungen. Siehe Post#1.

  • Drag and Drop auf Toolbar

    • Oscar
    • 30. August 2018 um 13:43
    Zitat von BugFix

    Hier mal ein Bsp. wie du aus dem Explorer auslesen kannst.

    Es ist nett von euch, mir Workaraounds vorzuschlagen, aber der einfachste Workaround ist ein transparentes Label unter der Toolbar (habe ich schon ausprobiert).

    Das funktioniert und vermutlich werde ich das wohl auch so machen. :/

    Ich hatte mich halt gefragt, warum es bei der Toolbar den Style "$TBSTYLE_REGISTERDROP" gibt und man bei WM_NOTIFY die Message "$TBN_GETOBJECT" bekommt, wenn man die "Quelle" (den Dateinamen) nicht ermitteln kann?

    Ich vermute, dass das irgendwie in dieser PIID (Pointer auf ein Object) steckt, aber ich konnte nicht herausbekommen, wie man das "dekodiert".

  • Drag and Drop auf Toolbar

    • Oscar
    • 30. August 2018 um 07:59
    Zitat von autoiter

    Falls aber auch $WM_DROPFILES in Ordnung wäre,

    Ja, die Funktion kenne ich bereits und das wäre evtl. eine Alternative, aber dabei wird die gesamte Gui als Ziel akzeptiert.

    Ich hätte aber gern nur die Toolbar. Eine Kombination aus beiden ist auch nicht so einfach, weil WM_NOTIFY vor WM_DROPFILES aufgerufen wird.

    Dann müsste ich das über globale Variablen anpassen.

    Da kann ich dann auch wieder ein transparentes Label benutzen. Damit klappt auch das interne @GUI_DragFile.

    Ich hatte halt die Hoffnung, dass man anhand der PIID irgendwie den Dateinamen herausbekommen könnte...

  • Drag and Drop auf Toolbar

    • Oscar
    • 29. August 2018 um 17:46
    Zitat von autoBert

    Funktioniert hier nicht das gleiche Schema, das du in deinem FileCommander angewendet hast?

    Im "alten" FileCommander habe ich keine echte Toolbar verwendet. Das sind "nur" normale Buttons und das Drag and Drop funktioniert über ein unsichtbares Label.

    Ich bin aber gerade dabei, den FileCommander von Grund auf neu zu schreiben und ich habe bereits die obere Toolbar und auch die Laufwerkbuttons als echte Toolbar.

  • Drag and Drop auf Toolbar

    • Oscar
    • 29. August 2018 um 17:00

    Ich habe ein kleines Problem.

    Und zwar möchte ich eine Datei vom Explorer auf die Toolbar in meinem Script ziehen. Im Prinzip klappt das auch.

    Ich habe als Extended-Style bei der GUI "$WS_EX_ACCEPTFILES" angegeben und bei der Toolbar "$TBSTYLE_REGISTERDROP".

    Somit erhalte ich bei $WM_NOTIFY einen Notification-Code "$TBN_GETOBJECT", wenn ich die Datei über der Toolbar bewege.

    Das Problem ist jetzt, wie bekomme ich den Dateinamen von der Datei heraus?

    Ich kriege eine piid, also wohl einen Pointer auf ein Objekt, aber was fange ich damit an? Wie kriege ich den Dateinamen raus?

    Hier mal ein Minimalbeispiel:

    AutoIt
    #include <AutoItConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiReBar.au3>
    #include <GuiToolbar.au3>
    #include <RebarConstants.au3>
    #include <StructureConstants.au3>
    #include <ToolbarConstants.au3>
    #include <WindowsConstants.au3>
    
    
    Opt('GUIOnEventMode', 1)
    
    Global $hMainGui = GUICreate('Test', 1020, 480, -1, -1, BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPCHILDREN), $WS_EX_WINDOWEDGE + $WS_EX_ACCEPTFILES)
    GUISetOnEvent($GUI_EVENT_CLOSE, '_CloseMainGui')
    Global $hDrivesRebar = _GUICtrlRebar_Create($hMainGui, BitOR($CCS_TOP, $CCS_NODIVIDER, $RBS_VARHEIGHT, $RBS_BANDBORDERS))
    Global $hUserToolbar = _GUICtrlToolbar_Create($hMainGui, BitOR($TBSTYLE_FLAT, $CCS_NOPARENTALIGN, $WS_CHILD, $WS_CLIPSIBLINGS, $WS_VISIBLE, $TBSTYLE_REGISTERDROP))
    _GUICtrlRebar_AddToolBarBand($hDrivesRebar, $hUserToolbar, '', 0, $RBBS_NOGRIPPER)
    GUISetState()
    GUIRegisterMsg($WM_NOTIFY, '_WM_NOTIFY')
    WinWaitClose($hMainGui)
    Exit
    
    Func _CloseMainGui()
        GUIDelete($hMainGui)
    EndFunc   ;==>_CloseMainGui
    
    Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
        #forceref $hWnd, $iMsg, $wParam
        Local $tNMHDR, $hWndFrom, $iCode
        $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
        $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
        $iCode = DllStructGetData($tNMHDR, 'Code')
        Switch $hWndFrom
            Case $hUserToolbar
                Switch $iCode
                    Case $TBN_GETOBJECT
                        Local $tOBJECTNOTIFY = DllStructCreate($tagNMOBJECTNOTIFY, $lParam)
                        _DebugPrint("$RBN_GETOBJECT" & @CRLF & "--> hWndFrom:" & @TAB & DllStructGetData($tOBJECTNOTIFY, "hWndFrom") & @CRLF & _
                                    "-->IDFrom:" & @TAB & DllStructGetData($tOBJECTNOTIFY, "IDFrom") & @CRLF & _
                                    "-->Code:" & @TAB & DllStructGetData($tOBJECTNOTIFY, "Code") & @CRLF & _
                                    "-->Item:" & @TAB & DllStructGetData($tOBJECTNOTIFY, "Item") & @CRLF & _
                                    "-->piid:" & @TAB & DllStructGetData($tOBJECTNOTIFY, "piid") & @CRLF & _
                                    "-->pObject:" & @TAB & DllStructGetData($tOBJECTNOTIFY, "pObject") & @CRLF & _
                                    "-->Result:" & @TAB & DllStructGetData($tOBJECTNOTIFY, "Result"))
                EndSwitch
        EndSwitch
    EndFunc
    
    Func _DebugPrint($s_Text, $sLine = @ScriptLineNumber)
        ConsoleWrite( _
                "!===========================================================" & @CRLF & _
                "+======================================================" & @CRLF & _
                "-->Line(" & StringFormat("%04d", $sLine) & "):" & @TAB & $s_Text & @CRLF & _
                "+======================================================" & @CRLF)
    EndFunc   ;==>_DebugPrint
    Alles anzeigen
  • ReparsePointGetTarget

    • Oscar
    • 28. August 2018 um 10:24

    Unter Windows gibt es ja sogenannte ReparsePoints (z.B. "c:\Dokumente und Einstellungen"). Wenn man mit AutoIt diese "Verzeichnisse" auslesen will, dann funktioniert das nicht so einfach.

    Mit "_FileListToArray" bekommt man die Fehlermeldung Nr.4 ("No File(s) Found"). Das liegt daran, weil es sich bei den ReparsePoints um Links handelt. Man muss erst den tatsächlichen Zielpfad auslesen.

    Dafür habe ich eine kleine Funktion "_ReparsePointGetTarget" geschrieben. Hier mal mit Beispiel:

    AutoIt
    #include <APIFilesConstants.au3>
    #include <Array.au3>
    #include <File.au3>
    #include <WinAPIFiles.au3>
    #include <WinAPIHObj.au3>
    
    #Region *** ReparsePoints (bei einem deutschen Windows) ***
    Global $sPath = @UserProfileDir & '\Eigene Dateien'
    ;~ Global $sPath = @UserProfileDir & '\Anwendungsdaten'
    ;~ Global $sPath = 'c:\programme'
    ;~ Global $sPath = 'c:\Dokumente und Einstellungen'
    #EndRegion *** ReparsePoints ***
    
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sPath = ' & $sPath & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    
    Global $aFiles = _FileListToArray($sPath) ; <- hier kommt die Fehlermeldung Nr. 4 ("No File(s) Found")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $aFiles = ' & $aFiles & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    ;~ _ArrayDisplay($aFiles)
    
    Global $iAttr = _WinAPI_GetFileAttributes($sPath)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iAttr = ' & $iAttr & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    Global $bReparsePoint = BitAND($iAttr, $FILE_ATTRIBUTE_REPARSE_POINT) == $FILE_ATTRIBUTE_REPARSE_POINT
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $bReparsePoint = ' & $bReparsePoint & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    
    Global $sTargetPath = _ReparsePointGetTarget($sPath)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sTargetPath = ' & $sTargetPath & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    
    Global $aFiles = _FileListToArray($sTargetPath)
    _ArrayDisplay($aFiles, 'mit TargetPath')
    
    Func _ReparsePointGetTarget($sPath)
        Local $tGUID, $hFile, $sPathName
        $tGUID = _WinAPI_CreateObjectID($sPath)
        $hFile = _WinAPI_OpenFileById($sPath, $tGUID, 0, BitOR($FILE_SHARE_DELETE, $FILE_SHARE_READ, $FILE_SHARE_WRITE), $FILE_FLAG_OPEN_REPARSE_POINT)
        If $hFile = 0 Then Return
        $sPathName = _WinAPI_GetFinalPathNameByHandleEx($hFile)
        _WinAPI_CloseHandle($hFile)
        Return $sPathName
    EndFunc
    Alles anzeigen

    Dateien

    _ReparsePointGetTarget.au3 1,99 kB – 229 Downloads
  • Icon-Show

    • Oscar
    • 28. August 2018 um 09:54

    Immer wenn ich ein Icon aus der "shell32.dll" oder der "imageres.dll" für ein Projekt brauchte, habe ich mir den Index mit dem Script "Icon-Show" von Prog@ndy aus dem Jahre 2007 anzeigen lassen.

    Das Script von Prog@ndy ist etwas "in die Jahre gekommen" und die Icons der "imageres.dll" liegen größtenteils in 256 Pixel Auflösung vor, also dachte ich mir, schreibe ich mal eine neue Version.

    Ich habe die Icongröße auf 64 Pixel voreingestellt, ihr könnt aber auch eine größere Variante wählen (Icons werden skaliert). Das Fenster ist in der Größe veränderbar, so sind noch mehr Icons gleichzeitig zu sehen.

    Außerdem kann man nun einfach einen Doppelklick auf eines der Icons machen und die DLL und der Index werden in die Zwischenablage kopiert, sodass man diese Angaben einfach in das eigene Script einfügen kann.

    Screenshot:

    Screenshot.png

    Update v1.1.0.0 (31.08.2018):

    - Auswahl-Combobox mit einigen (19) System-DLLs, die viele Icons enthalten. Unter Win7 funktionieren die alle. Ich hoffe, dass das unter Win10 auch noch so ist!?

    - Auswahl-Combobox mit mehreren Icongrößen.

    - Kontextmenü zum kopieren der ausgewählten Indizies in die Zwischenablage (durch Komma getrennt).

    - Kontextmenü zum extrahieren der ausgewählten Icons als PNG-Dateien. Man gibt eine Startdatei vor und das Programm hängt den jeweiligen Index dran.

    - Programmicon hinzugefügt (befindet sich zusammen mit dem Script im ZIP-Archiv).

    Dateien

    Icon-Show_v1_1.zip 10,25 kB – 535 Downloads
  • TreeView Root verbergen

    • Oscar
    • 22. August 2018 um 14:43

    Oder wenn Du auch die Icons zu den Dateien angezeigt haben willst:

    AutoIt
    #include <File.au3>
    #include <GuiImageList.au3>
    #include <GuiTreeView.au3>
    #include <WinAPIIcons.au3>
    #include <WinAPIShellEx.au3>
    #include <WindowsConstants.au3>
    
    Global $sPath = StringRegExpReplace(@AutoItExe, '(.+\\).+', '$1') ; <- als Beispiel das AutoIt-Verzeichnis
    
    Global $hGui = GUICreate('TreeView-Example', 400, 600)
    Global $idTreeView = GUICtrlCreateTreeView(10, 10, 380, 580, Default, $WS_EX_CLIENTEDGE)
    Global $hImageList = _GUIImageList_Create(24, 24, 5) ; ImageList erstellen
    _GUIImageList_AddIcon($hImageList, 'shell32.dll', 3) ; Directory-Icon hinzufuegen
    _GUICtrlTreeView_SetNormalImageList($idTreeView, $hImageList)
    GUISetState()
    
    ToolTip('Verzeichnis wird eingelesen. Bitte warten!', Default, Default, 'TreeView-Example', $TIP_INFOICON, $TIP_BALLOON)
    _GUICtrlTreeView_BeginUpdate($idTreeView)
    _CreatePath($sPath, $idTreeView)
    _GUICtrlTreeView_EndUpdate($idTreeView)
    ToolTip('')
    
    Do
    Until GUIGetMsg() = -3
    _GUIImageList_Destroy($hImageList)
    Exit
    
    Func _CreatePath($sPath, $idParent)
        Local $aFolder, $aFiles, $idItem, $hIcon
        Local Static $iIndex = 1 ; Index = 1, weil Eintrag 0 das Directory-Icon (von oben) ist
        If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
        $aFolder = _FileListToArray($sPath, '*', $FLTA_FOLDERS)
        If Not @error Then
            For $i = 1 To $aFolder[0]
                $idItem = GUICtrlCreateTreeViewItem($aFolder[$i], $idParent)
                _GUICtrlTreeView_SetStateImageIndex($idTreeView, $idItem, 1)
                _CreatePath($sPath & $aFolder[$i], $idItem) ; Verzeichnis, also die Funktion rekursiv aufrufen
            Next
        EndIf
        $aFiles = _FileListToArray($sPath, '*', $FLTA_FILES)
        If @error Then Return
        For $i = 1 To $aFiles[0]
            $hIcon = _WinAPI_ShellExtractAssociatedIcon($sPath & $aFiles[$i])
            _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
            _WinAPI_DestroyIcon($hIcon)
            $idItem = GUICtrlCreateTreeViewItem($aFiles[$i], $idParent)
            _GUICtrlTreeView_SetImageIndex($idTreeView, $idItem, $iIndex)
            _GUICtrlTreeView_SetSelectedImageIndex($idTreeView, $idItem, $iIndex)
            $iIndex += 1
        Next
    EndFunc
    Alles anzeigen
  • TreeView Root verbergen

    • Oscar
    • 22. August 2018 um 13:22
    Zitat von mirko2002

    nur der Inhalt des Roots angezeigt wird. Geht sowas?

    Was ist das für eine Frage?

    Es wird nur das angezeigt, was Du erstellst, also: Ja, das geht!

    Wenn Du nicht weißt, wie, dann solltest Du das dazu schreiben.

    Hier mal ein Beispiel mit rekursiver Funktion:

    AutoIt
    #include <File.au3>
    #include <WindowsConstants.au3>
    
    Global $sPath = @ScriptDir
    Global $hGui = GUICreate('TreeView-Example', 400, 600)
    Global $idTreeView = GUICtrlCreateTreeView(10, 10, 380, 580, Default, $WS_EX_CLIENTEDGE)
    GUISetState()
    _CreatePath($sPath, $idTreeView)
    Do
    Until GUIGetMsg() = -3
    
    Func _CreatePath($sPath, $idParent)
        Local $aFolder, $aFiles, $idItem
        If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
        $aFolder = _FileListToArray($sPath, '*', $FLTA_FOLDERS)
        If Not @error Then
            For $i = 1 To $aFolder[0]
                $idItem = GUICtrlCreateTreeViewItem($aFolder[$i], $idParent)
                _CreatePath($sPath & $aFolder[$i], $idItem)
            Next
        EndIf
        $aFiles = _FileListToArray($sPath, '*', $FLTA_FILES)
        If @error Then Return
        For $i = 1 To $aFiles[0]
            $idItem = GUICtrlCreateTreeViewItem($aFiles[$i], $idParent)
        Next
    EndFunc
    Alles anzeigen
  • GDI+ 90Grad Rotation und speichern

    • Oscar
    • 31. Juli 2018 um 08:24
    Zitat von UEZ

    Wenn ich die Bilder per memcmp (msvcrt.dll) vergleiche (Bitmap Binärdaten), dann sind sie identisch.

    Ok, das ist auch eigentlich das Wichtigste.

    Vielleicht ist es auch nur so, dass Kamera und PC unterschiedliche JPEG-"Routinen" zum speichern verwenden.

    Zitat von UEZ

    Letztendlich wird bei einer verlustfreien JPEG Rotation doch eine Veränderung in der Dateistruktur vorgenommen...

    Ich habe jetzt noch herausgefunden, dass es gar nicht die Rotation ist. Bereits ein Laden und Speichern des Bildes bewirkt diesen "Verlust" an der Dateigröße:

    C
    #include <FileConstants.au3>
    #include <GDIPlus.au3>
    
    $sFileOrig = @ScriptDir & '\test_o.jpg'
    $sFilename = @ScriptDir & '\test.jpg'
    $iFileSize = FileGetSize($sFileOrig)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iFileSize = ' & $iFileSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    FileCopy($sFileOrig, $sFilename, $FC_OVERWRITE)
    _GDIPlus_Startup()
    $hImage = _GDIPlus_BitmapCreateFromFile($sFileOrig)
    $aDim = _GDIPlus_ImageGetDimension($hImage)
    _GDIPlus_ImageSaveToFile($hImage, $sFilename)
    _GDIPlus_ImageDispose($hImage)
    $iFileSize = FileGetSize($sFilename)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iFileSize = ' & $iFileSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    _GDIPlus_Shutdown()
    Exit
    Alles anzeigen

    Aber im Grunde ist es egal, solange die Bilddaten vollständig erhalten bleiben. Ich setze das Thema mal auf "gelöst". Danke, für Deine Mithilfe! :)

  • GDI+ 90Grad Rotation und speichern

    • Oscar
    • 30. Juli 2018 um 12:15

    Mir ist gerade etwas aufgefallen, wofür ich keine echte Erklärung finde.

    Hier mal das Script:

    AutoIt
    #include <APIShellExConstants.au3>
    #include <GDIPlus.au3>
    #include <GDIPlusConstants.au3>
    #include <WinAPIShellEx.au3>
    
    _GDIPlus_Startup()
    $sFileOrig = @ScriptDir & '\test_o.jpg'
    $iFileSize = FileGetSize($sFileOrig) ; Originalgroesse: 7560412 bytes
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iFileSize = ' & $iFileSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    $sFilename = @ScriptDir & '\test.jpg'
    FileCopy($sFileOrig, $sFilename, $FC_OVERWRITE)
    $iFileSize = FileGetSize($sFilename) ; hier (logisch): 7560412 bytes
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iFileSize = ' & $iFileSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    _RotateImage($sFilename)
    _RotateImage($sFilename)
    _RotateImage($sFilename)
    _RotateImage($sFilename)
    $iFileSize = FileGetSize($sFilename) ; nach 4x90 Grad: 7138682 bytes
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iFileSize = ' & $iFileSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    _RotateImage($sFilename)
    _RotateImage($sFilename)
    _RotateImage($sFilename)
    _RotateImage($sFilename)
    $iFileSize = FileGetSize($sFilename) ; nach weiteren 4x90 Grad: 7138682 bytes
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iFileSize = ' & $iFileSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    _GDIPlus_Shutdown()
    
    Func _RotateImage($sImgFile)
        Local Const $sTmpFile = @ScriptDir & '\TmpRotateImage.jpg'
        Local $hImage, $sCLSID, $tData, $tParams, $ret
        $hImage = _GDIPlus_ImageLoadFromFile($sImgFile) ; <- das erzeugt einen Datei-Lock auf $sImgFile
        $sCLSID = _GDIPlus_EncodersGetCLSID('JPG')
        $tData = DllStructCreate('int Data')
        DllStructSetData($tData, 'Data', $GDIP_EVTTRANSFORMROTATE90)
        $tParams = _GDIPlus_ParamInit(1)
        _GDIPlus_ParamAdd($tParams, $GDIP_EPGTRANSFORMATION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, 'Data'))
        $ret = _GDIPlus_ImageSaveToFileEx($hImage, $sImgFile, $sCLSID, $tParams) ; <- das funktioniert nicht, weil $sImgFile hier noch gelockt ist
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret = ' & $ret & @CRLF & '>Error code: ' & @error & @CRLF) ; @extended = 7 ($GDIP_ERRWIN32ERROR)
        ; die gedrehte Bitmap muss erstmal unter einem anderen Namen ($sTmpFile) gespeichert werden:
        $ret = _GDIPlus_ImageSaveToFileEx($hImage, $sTmpFile, $sCLSID, $tParams)
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret = ' & $ret & @CRLF & '>Error code: ' & @error & @CRLF)
        _GDIPlus_ImageDispose($hImage) ; <- erst hiermit wird der Datei-Lock auf $sImgFile aufgehoben
        _WinAPI_ShellFileOperation($sTmpFile, $sImgFile, $FO_RENAME, $FOF_NOCONFIRMATION) ; $sTmpFile umbenennen
    EndFunc
    Alles anzeigen

    Das Bild ist zu groß als Anhang, deswegen auf meiner Homepage: https://technik-hobby.de/software/test_o.jpg

    So nebenbei ist mir aufgefallen, dass "_GDIPlus_ImageLoadFromFile" einen Dateilock erzeugt, der erst beim "_GDIPlus_ImageDispose" wieder entfernt wird. Man kann also das gedrehte Image nicht unter dem gleichen Namen abspeichern.

    Aber davon abgesehen, ist das eigentlich Merkwürdige, dass das Bild nach den ersten vier 90 Grad Drehungen plötzlich rund 400 KB kleiner ist.

    Ich dachte, die JPG-90-Grad-Drehung wäre verlustfrei?

    Nach weiteren vier mal 90 Grad wird es dann auch nicht mehr kleiner und das Bild sieht auch nach den 8 Drehungen noch genauso aus, wie das Original (auch in 200%-Ansicht).

    Also ist die Drehung wohl wirklich verlustfrei (was die Bilddaten betrifft). Aber was sind dann die 400 KB?

    Ok, es fehlen ein paar EXIF-Daten (kann man mit IrfanView sehen), aber das kann doch keine 400 KB ausmachen, oder?

    Ich möchte gern in meinem Programm eine Drehung der Bilder anbieten, aber ich wüsste gern, welche Daten dabei verloren gehen.

  • Softwareinventarisierung

    • Oscar
    • 27. Juli 2018 um 15:49
    Zitat von DigitalKarl

    Eine andere Methode, die ich bei der Software Paketierung verwende ist, die uninstall registry keys der installierten Software abzufragen:

    Dafür hätte ich auch eine AutoIt-Funktion:

    AutoIt
    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_UseX64=y
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    #include <Array.au3>
    
    $array = _GetSoftwareList()
    _ArrayDisplay($array)
    
    Func _GetSoftwareList()
        Local Const $sRowDel = @LF, $sColDel = '|'
        Local $sSoftwareList, $iInstance = 0, $sKey, $sName
        Local $sRegKey = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'
        Local $sRegKey32 = 'HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall'
        Do
            $iInstance += 1
            $sKey = RegEnumKey($sRegKey, $iInstance)
            If @error Then ExitLoop
            $sName = RegRead($sRegKey & '\' & $sKey, 'DisplayName')
            If $sName <> '' Then $sSoftwareList &= StringFormat('%s%s%s\%s%s', $sName, $sColDel, $sRegKey, $sKey, $sRowDel)
        Until $sKey = ''
        $iInstance = 0
        Do
            $iInstance += 1
            $sKey = RegEnumKey($sRegKey32, $iInstance)
            If @error Then ExitLoop
            $sName = RegRead($sRegKey32 & '\' & $sKey, 'DisplayName')
            If $sName <> '' Then $sSoftwareList &= StringFormat('%s%s%s\%s%s', $sName, $sColDel, $sRegKey, $sKey, $sRowDel)
        Until $sKey = ''
        If $sSoftwareList = '' Then Return SetError(1, 0, '')
        Return _StringSplit2D(StringTrimRight($sSoftwareList, 1), $sRowDel, $sColDel)
    EndFunc
    
    Func _StringSplit2D($sData, $sRowDel, $sColDel)
        Local $aRows = StringSplit($sData, $sRowDel, 3)
        Local $aCol = StringSplit($aRows[0], $sColDel, 3)
        Local $aOut[UBound($aRows)][UBound($aCol)], $aTmp
        For $iRow = 0 To UBound($aRows) - 1
            $aTmp = StringSplit($aRows[$iRow], $sColDel, 3)
            For $iCol = 0 To UBound($aCol) - 1
                $aOut[$iRow][$iCol] = $aTmp[$iCol]
            Next
        Next
        Return $aOut
    EndFunc   ;==>_StringSplit2D
    Alles anzeigen

    Aber das muss dann auf jedem Rechner laufen.

    Allerdings könnte man das als Hintergrundprogramm auf jedem Rechner installieren und es wartet dann auf eine TCP-Nachricht, um die Funktion auszuführen und an das Serverscript zu senden.

  • Koordinaten umrechnen (unbekanntes Schema => Google-Maps)

    • Oscar
    • 24. Juli 2018 um 13:42
    Zitat von autoBert

    Geo-Dienst

    Um welchen Dienst handelt es sich?

    Und Du müsstest schon mehr zu dem Datenformat schreiben.

    Ansonsten sagt meine Kristallkugel: nach den ersten beiden Stellen ein Punkt setzen, aber das wäre dann eine Position irgendwo im Iran!? :/

  • GuiCtrlStars

    • Oscar
    • 24. Juli 2018 um 13:21
    Zitat von chesstiger

    ich hätte da noch ein oder zwei Tipps, du entdeckst ja gerade fleißig, wie das Subclassing mit Win32 funktioniert

    Vielen Dank für die Tipps! :):thumbup:

    Ich habe das mal so umgesetzt. Neue Version in Post#1.

  • Mit Markierungen in Edit arbeiten

    • Oscar
    • 23. Juli 2018 um 13:55
    Zitat von ThePhantomDesigns

    Gibt es eine derartige Funktion, die in der Lage ist, dies zu tun?

    Ja: "_GUICtrlEdit_SetSel". Hier ein kleines Beispiel:

    AutoIt
     #include <GUIConstantsEx.au3>
    #include <GuiEdit.au3>
    
    Global $sText = 'wopiepwo dsfkpao sdaerg fretgerg' & @CRLF & 'asdjfk ewweop ewewpofg fdmbv ewerjf dvf'
    Global $hGui = GUICreate('Test', 400, 300)
    Global $idEdit = GUICtrlCreateEdit($sText, 10, 10, 380, 230, BitOR($GUI_SS_DEFAULT_EDIT, $ES_NOHIDESEL))
    
    ; Entweder einen Button erstellen oder ein DummyControl
    Global $idSelAll = GUICtrlCreateButton('SelectAll', 140, 250, 120, 25)
    ;~ Global $idSelAll = GUICtrlCreateDummy()
    
    GUISetState()
    Global $aAccelKeys[][2] = [['^a', $idSelAll]]
    GUISetAccelerators($aAccelKeys)
    While True
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                Exit
            Case $idSelAll
                _GUICtrlEdit_SetSel($idEdit, 0, -1)
        EndSwitch
    WEnd
    Alles anzeigen
    Zitat von ThePhantomDesigns

    Außerdem frage ich mich, ob es möglich ist, ein Edit zu durchsuchen und das, was man findet, zu markieren

    Ja, auch das: "_GUICtrlEdit_Find" (Beispiel in der Hilfe)

  • GuiCtrlStars

    • Oscar
    • 20. Juli 2018 um 14:49

    Und noch eine UDF! :)

    Wieder ein Control-Element. Ich hatte schon mal ein Script fuer eine Bewertung mit Sternen geschrieben, aber das war halt keine universelle UDF.

    Hier ist jetzt die UDF, auch wieder mit WindowProc! Man kann beliebig viele von den "Stern-Bewertungen" erstellen. Im Beispielscript habe ich mal 10 Stück erstellt. Das soll eine Art von Film-Bewertung darstellen.

    Hier mal der Screenshot dazu:

    Screenshot.png

    Die Bewertung findet mit der linken Maustaste statt. Wenn man auf einen der fünf Sterne klickt, wird die Bewertung entsprechend angezeigt. Mit der rechten Maustaste kann man auf Null Sterne zurückkehren. Für die Film-Bewertung könnte das heißen, dass man den Film noch nicht gesehen hat.

    Update v1.1.0.0 (24.07.2018):

    - Ich habe die UDF komplett umgeschrieben. Ich habe die Vorgehensweise von chesstiger übernommen. Dadurch kann man die Anzahl der Sterne mit GuiCtrlSetData setzen und auslesen mit GuiCtrlRead. Außerdem spart man sich das globale Array und es sind viel weniger Funktionen. Vielen Dank, chesstiger!

    Dateien

    GuiCtrlStars_Example.au3 4,92 kB – 286 Downloads GuiCtrlStars.au3 19,86 kB – 299 Downloads
  • GuiCtrlVolume

    • Oscar
    • 19. Juli 2018 um 18:38
    Zitat von Bitnugger

    Ja, das mit "_WinAPI_HiWord" und "_WinAPI_LoWord" findest du im MSDN

    Genau dort habe ich den Hinweis ja auch gefunden. :)

    Zitat von Bitnugger

    zickt jetzt nur noch die Prozentanzeige rechts neben dem linken Control

    Nanu?

    Die hat mit der UDF eigentlich nichts zu tun. Jedenfalls nicht direkt.

    Sie wird ja nur in der "Callback"-Funktion aktualisiert. Andererseits wird die Funktion von der WindowsProc aufgerufen.

    Vielleicht fehlt da nur ein Refresh?

    Kannst Du mal diese Funktion ausprobieren:

    AutoIt
    Func _ChangeVolume($iValue)
        Local $iVolume = BitAND($iValue, 0x7F) ; Die Bits 0-6 enthalten die Lautstaerke in Prozent (0...100)
        Local $bMute = BitAND($iValue, 0x80) = 0x80 ; Das Bit 7 dient zur Speicherung des Mute-Zustands (True/False)
        ConsoleWrite(StringFormat('Value: %i\tVolume: %i%\tMute: %s\r\n', $iValue, $iVolume, $bMute))
        GUICtrlSetData($idLabel, $iVolume & '%')
        _WinAPI_InvalidateRect(GUICtrlGetHandle($idLabel))
    EndFunc
  • GuiCtrlVolume

    • Oscar
    • 19. Juli 2018 um 17:57
    Zitat von Bitnugger

    Mir ist aber noch ein böser Fehler aufgefallen: Der Laustärkepegel läßt sich nur dann mit dem Mausrad ändern, wenn sich das Fenster auf dem primären Monitor befindet.

    Autsch! Blöder "Fehler" in "_WinAPI_HiWord" und "_WinAPI_LoWord". Die Funktionen interpretieren alles als Unsigned Int. Bei negativen Werten kommt also Mist raus. Das sollte in der Hilfe stehen! :huh:

    Das hat also nichts mit primär und sekundär zu tun, sondern, wie Du die Bildschirme angeordnet hast. Auf dem Bildschirm mit negativen Werten funktioniert es nicht. Das führte dann auch zu den Fehlern mit dem linken Mausklick.

    Ich habe jetzt meine Funktion "_WinAPI_MakePoint" so angepasst, dass sie auch mit negativen Werten klarkommt. Neue Version in Post#1.

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™