• na das ist ja Wunderbar :D

    nur hab ich schon ein Problem festgestellt...
    Wen ich auf der Spalte "Titel" Auf nen Song doppelklicke, nimmt er den Ersten im ListView
    Wen ich auf "Artist" den zweiten eintrag
    bei "Legth" den Dritten
    bei "Album" den 4 uws... ^^


    Ich habe noch was wie folgt abgeändert.

    Spoiler anzeigen

    Von

    [autoit]

    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt
    If MsgBox(32 + 4, 'Beenden', 'Wollen sie das Programm wirklich beenden?') = 6 Then _End() ; wenn ja, dann End-Funktion aufrufen

    [/autoit]


    Zu

    [autoit]

    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt
    _End() ; wenn ja, dann End-Funktion aufrufen

    [/autoit]


    Und noch
    Von

    [autoit]

    Func _End()
    ;~ Save() ; wenn der vordere Kommentar entfernt wird, dann werden vor dem beenden noch die Daten gespeichert
    Exit ; Programm beenden
    EndFunc ;==>End

    [/autoit]


    zu

    [autoit]

    Func _End()
    If MsgBox(32 + 4, 'Save', 'Wollen sie vor beenden noch Speichern?') = 6 Then Save() ;Fragt bei Beendung ob man noch Speichern möchte. Ja Then Save / Nein Then Exit
    Exit ; Programm beenden
    EndFunc ;==>End

    [/autoit]


    Da mich persönlich das "Dauernde" Fragen ob ich Wirklich Beenden will, doof finde ^^
    is meiner meinung nach Besser wen man´s dan so mach,ob man noch Speichern will :D *Find ich*

    Einmal editiert, zuletzt von Skilkor (29. Juli 2010 um 17:13)

    • Offizieller Beitrag

    Ändere mal in Zeile 195:

    [autoit]

    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, DllStructGetData($tInfo, "SubItem"), 8)

    [/autoit]


    das "SubItem" in "Item" und teste dann mal.
    Es hat mich nämlich schon gewundert, warum da bei mir der Index, also das Item ausgegeben wird. Aber bei mir funktioniert das nur mit "SubItem". Bei "Item" kommt bei mir immer "0" raus. ?(

  • Leider immernoch so
    Wen ich auf der Spalte "Titel" Auf nen Song doppelklicke, nimmt er den Ersten im ListView
    Wen ich auf "Artist" den zweiten eintrag
    bei "Legth" den Dritten
    bei "Album" den 4 uws... ^^
    ob "Item" oder "SubItem"

    KOREKTUR!!!!!!!!!!!!!
    Er nimmt Bei "Item" IMMER nur den Ersten.
    mit "SubItem" so wie vorhin geschrieben

    Edit
    Ich lass ihn mal neu suchen. vll liegt es an der alten .txt. die ich einfach zu .db3 unbenannt hab ^^
    ich meld mich wider :D

    2 Mal editiert, zuletzt von Skilkor (29. Juli 2010 um 17:31)

    • Offizieller Beitrag

    Nee, das mit der Datenbank hat damit nichts zu tun (habe ich auch schon getestet).

    Tausch mal die Funktion "_WM_NOTIFY" gegen diese hier aus:

    [autoit]


    Func _WM_NOTIFY($hWnd, $msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $iSelected, $sExecutePath
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
    $iCode = DllStructGetData($tNMHDR, 'Code')
    Switch $hWndFrom
    Case $hLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $iSelected = ControlListView($hGui, '', $hListView, 'GetSelected')
    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, $iSelected, 8)
    ShellExecute($sExecutePath)
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc

    [/autoit]
    • Offizieller Beitrag

    Nachdem wir das mit den MP3s geklärt haben, kommt hier die nächste Version: mit Suchfunktion für die Liste. :)

    Skript:

    Spoiler anzeigen
    [autoit]


    #include <ButtonConstants.au3>
    #include <Date.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    #include <ListViewConstants.au3>
    #include <StaticConstants.au3>
    #include <StructureConstants.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $sHeader = 'Title|Artist|Length|Album|Year|MPEG-Version|Bitrate|Sample-Freq.|Path' ; Die Überschriften für das Listview
    Global $sInifile = @ScriptDir & '\MP3-Search.ini' ; Inidatei

    [/autoit] [autoit][/autoit] [autoit]

    Global $iWidth = IniRead($sInifile, 'Config', 'Width', 770)
    Global $iHeight = IniRead($sInifile, 'Config', 'Height', 406)
    Global $iLeft = IniRead($sInifile, 'Config', 'Left', @DesktopWidth / 2 - 385)
    Global $iTop = IniRead($sInifile, 'Config', 'Top', @DesktopHeight / 2 - 203)

    [/autoit] [autoit][/autoit] [autoit]

    #region Hauptfenster
    Global $sStyle = BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX)
    Global $hGui = GUICreate('MP3-Search', 770, 406, $iLeft, $iTop, $sStyle) ; Hauptfenster erstellen
    GUISetBkColor(0xAAAAAA)

    [/autoit] [autoit][/autoit] [autoit]

    Global $hListView = GUICtrlCreateListView($sHeader, 5, 5, 760, 280, $LVS_SHOWSELALWAYS, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_DOUBLEBUFFER, $WS_EX_WINDOWEDGE)) ; Listview erstellen
    GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
    GUICtrlSetBkColor(-1, 0xaabbff)
    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumnWidth($hLVHandle, 0, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 1, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 2, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 3, 120)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 4, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 5, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 6, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 7, 90)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 8, 800)

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlCreateLabel('Suchbegriff:', 10, 302, 70, 22, $SS_RIGHT)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hInput = GUICtrlCreateInput('', 90, 300, 300, 22)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hInputOk = GUICtrlCreateButton('Suche starten', 400, 300, 100, 22)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)

    [/autoit] [autoit][/autoit] [autoit]

    Global $hSearch = GUICtrlCreateButton('Alle Festplatten durchsuchen', 10, 340, 120, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hSearchPath = GUICtrlCreateButton('Verzeichnis durchsuchen', 140, 340, 100, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hLoad = GUICtrlCreateButton('Laden', 250, 340, 70, 35)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hSave = GUICtrlCreateButton('Speichern', 330, 340, 70, 35)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hDel = GUICtrlCreateButton("Markierte Einträge löschen", 410, 340, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    GUICtrlSetState(-1, $GUI_DISABLE)
    Global $hDelAll = GUICtrlCreateButton('Alle Einträge löschen', 510, 340, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)

    [/autoit] [autoit][/autoit] [autoit]

    Global $aParts[3] = [300, 360, -1], $aText[3] = ['Fertig.', '0', '']
    Global $hStatus = _GUICtrlStatusBar_Create($hGui, $aParts, $aText)
    #endregion Hauptfenster

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

    [/autoit] [autoit][/autoit] [autoit]

    Global $fStop = False, $iSearchIndex = -1, $iSelCount, $iSelOld
    HotKeySet('{ESC}', '_Stop')

    [/autoit] [autoit][/autoit] [autoit]

    Dim $aAccelKeys[1][2] = [['{DEL}', $hDel]] ; beim drücken der [Delete]-Taste wird "Case $hDel" ausgeführt
    GUISetAccelerators($aAccelKeys, $hGui)

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_SIZE, '_WM_SIZE')
    GUIRegisterMsg($WM_MOVE, '_WM_MOVE')
    GUIRegisterMsg($WM_GETMINMAXINFO, '_WM_GETMINMAXINFO')
    GUIRegisterMsg($WM_NOTIFY, '_WM_NOTIFY')
    GUIRegisterMsg($WM_COMMAND, '_WM_COMMAND')

    [/autoit] [autoit][/autoit] [autoit]

    WinMove($hGui, '', $iLeft, $iTop, $iWidth, $iHeight)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Switch GUIGetMsg() ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hSearch
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    $iLVCount = 0 ; Zähler auf Null setzen
    $aDrives = DriveGetDrive('FIXED') ; Alle Festplatten-Buchstaben holen
    If Not @error Then
    GUISetCursor(15, 1, $hGui)
    For $i = 1 To $aDrives[0] ; Alle Festplatten durchgehen
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Festplatte "' & StringUpper($aDrives[$i]) & '\"', 0)
    _DriveSearch(StringUpper($aDrives[$i]))
    Next
    GUISetCursor(2, 1, $hGui)
    EndIf
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    Case $hSearchPath
    $sPath = FileSelectFolder('Verzeichnis auswählen!', '', 2, '', $hGui)
    If FileExists($sPath) Then
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iLVCount = 0 ; Zähler auf Null setzen
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Verzeichnis "' & $sPath & '"', 0)
    _DriveSearch($sPath)
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    EndIf
    Case $hInput, $hInputOk
    _GUICtrlStatusBar_SetText($hStatus, 'Suche in Liste...', 0)
    GUISetCursor(15, 1, $hGui)
    _LVSearch()
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    Case $hListView ; User hat auf eine Spaltenüberschrift geklickt (sortieren)
    If _GUICtrlListView_GetItemCount($hLVHandle) > 0 Then
    Dim $aDescending[_GUICtrlListView_GetColumnCount($hLVHandle)]
    GUISetCursor(15, 1, $hGui)
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, 'Sortiere Daten! Bitte warten...', 0)
    _GUICtrlListView_SimpleSort($hLVHandle, $aDescending, GUICtrlGetState($hListView))
    _GUICtrlStatusBar_SetText($hStatus, _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms'), 2)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hLoad ; User hat auf 'Laden' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten...', 0)
    Load()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    Case $hSave ; User hat auf 'Speichern' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Speichere Daten...', 0)
    Save()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    GUISetCursor(2, 1, $hGui)
    Case $hDel
    GUISetCursor(15, 1, $hGui)
    _GUICtrlListView_DeleteItemsSelected($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    GUISetCursor(2, 1, $hGui)
    Case $hDelAll ; User hat auf 'Alle Einträge löschen' geklickt
    If MsgBox(256 + 32 + 4, 'Einträge löschen', 'Wollen sie wirklich alle Einträge löschen?') = 6 Then
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    EndIf
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt
    ;~ If MsgBox(32 + 4, 'Save', 'Wollen sie vor beenden noch Speichern?') = 6 Then Save()
    Exit ; Programm beenden
    EndSwitch
    $iSelCount = _GUICtrlListView_GetSelectedCount($hLVHandle) ; Anzahl der markierten Items holen
    If $iSelCount <> $iSelOld Then ; vergleichen ob der Wert vom vorherigen abweicht (Flackern vermeiden)
    $iSelOld = $iSelCount ; wenn ja, dann alten gleich neuen Wert
    If $iSelCount > 0 Then ; wenn Einträge markiert sind
    GUICtrlSetState($hDel, $GUI_ENABLE) ; dann Button aktivieren
    GUICtrlSetData($hDel, StringFormat('(%i) Markierte Einträge löschen', $iSelCount)) ; und den Text auf dem Button anpassen
    Else ; keine Einträge markiert
    GUICtrlSetState($hDel, $GUI_DISABLE) ; dann Button deaktivieren
    GUICtrlSetData($hDel, 'Markierte Einträge löschen') ; und den Text auf dem Button anpassen
    EndIf
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Stop()
    $fStop = True
    EndFunc ;==>_Stop

    [/autoit] [autoit][/autoit] [autoit]

    Func _DriveSearch($sPath)
    Local $aNewMP3, $aID3Tags, $sNewItem, $aItem
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte warten...', 2)
    $aNewMP3 = _RecursiveFileListToArray($sPath, '\.mp3', 1) ; Alle MP3s auf der Festplatte auslesen
    If Not @error And $aNewMP3[0] > 0 Then
    _GUICtrlListView_SetItemCount($hListView, _GUICtrlListView_GetItemCount($hLVHandle) + $aNewMP3[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lese ID3-Tags... (' & $aNewMP3[0] & ')', 0)
    For $j = 1 To $aNewMP3[0] ; die gefundenen MP3s durchgehen
    $aID3Tags = _ReadID3Tag($aNewMP3[$j]) ; die ID3-Tags auslesen
    If Not @error Then
    For $k = 0 To 10
    $aID3Tags[$k][1] = StringReplace($aID3Tags[$k][1], '|', '') ; evtl. vorhandene "|" entfernen
    Next
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, $aNewMP3[$j], 2)
    $sNewItem = $aID3Tags[0][1] & '|' & $aID3Tags[1][1] & '|' & $aID3Tags[4][1] & '|' & $aID3Tags[2][1] & '|' & $aID3Tags[3][1]
    $sNewItem &= '|' & $aID3Tags[8][1] & '|' & $aID3Tags[9][1] & '|' & $aID3Tags[10][1] & '|' & $aNewMP3[$j]
    GUICtrlCreateListViewItem($sNewItem, $hListView)
    EndIf
    If $fStop Then ExitLoop
    Next
    EndIf
    EndFunc ;==>_DriveSearch

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_COMMAND($hWnd, $msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0xFFFF)
    If $nID = $hInput And $nNotifyCode = 256 Then
    GUICtrlSetBkColor($hInput, 0xffffff)
    $iSearchIndex = -1
    GUICtrlSetData($hInputOk, 'Suche starten')
    _GUICtrlListView_SetItemSelected($hLVHandle, -1, False)
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_COMMAND

    [/autoit] [autoit][/autoit] [autoit]

    Func _LVSearch()
    If _GUICtrlListView_GetItemCount($hLVHandle) = 0 Then Return
    Local $sSearch
    $sSearch = GUICtrlRead($hInput)
    $iSearchIndex = _GUICtrlListView_FindInText($hLVHandle, $sSearch, $iSearchIndex)
    If $iSearchIndex > -1 Then
    _GUICtrlListView_EnsureVisible($hLVHandle, $iSearchIndex)
    _GUICtrlListView_SetItemSelected($hLVHandle, $iSearchIndex)
    GUICtrlSetBkColor($hInput, 0xaaffaa)
    GUICtrlSetData($hInputOk, 'weitersuchen...')
    Else
    _GUICtrlListView_EnsureVisible($hLVHandle, 0)
    _GUICtrlListView_SetItemSelected($hLVHandle, -1, False)
    GUICtrlSetBkColor($hInput, 0xffaaaa)
    EndIf
    EndFunc ;==>_LVSearch

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_NOTIFY($hWnd, $msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $iSelected, $sExecutePath
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
    $iCode = DllStructGetData($tNMHDR, 'Code')
    Switch $hWndFrom
    Case $hLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $iSelected = ControlListView($hGui, '', $hListView, 'GetSelected')
    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, $iSelected, 8)
    ShellExecute($sExecutePath)
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_NOTIFY

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Width', $aGuiPos[2])
    IniWrite($sInifile, 'Config', 'Height', $aGuiPos[3])
    EndIf
    _GUICtrlStatusBar_Resize($hStatus)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_SIZE

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_MOVE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Left', $aGuiPos[0])
    IniWrite($sInifile, 'Config', 'Top', $aGuiPos[1])
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_MOVE

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_GETMINMAXINFO($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGui Then
    Local $minmaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($minmaxinfo, 7, 786) ; min X
    DllStructSetData($minmaxinfo, 8, 444) ; min Y
    ;~ DllStructSetData($minmaxinfo, 9, 800) ; max X
    ;~ DllStructSetData($minmaxinfo, 10, 800) ; max Y
    EndIf
    EndFunc ;==>_WM_GETMINMAXINFO

    [/autoit] [autoit][/autoit] [autoit]

    Func Load() ; Datenbank-Datei laden
    Local $sDBFile, $hFile, $sContent, $aNewItems, $iTimer, $iCount
    FileChangeDir(@ScriptDir)
    $sDBFile = FileOpenDialog('MP3-Datenbank-Datei auswählen', @ScriptDir, 'MP3-Datenbank (*.db3)', 3, '', $hGui)
    If Not FileExists($sDBFile) Then Return
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_SetItemCount($hLVHandle, $aNewItems[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten... (' & $aNewItems[0] & ')', 0)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    $iTimer = TimerInit()
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    $iCount += 1
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    EndIf
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    EndFunc ;==>Load

    [/autoit] [autoit][/autoit] [autoit]

    Func Save() ; Datenbank-Datei speichern
    Local $sDBFile, $hFile, $iCount, $iTimer
    $sDBFile = FileSaveDialog('MP3-Datenbank-Datei auswählen', '', 'MP3-Datenbank (*.db3)', 18, '', $hGui)
    If @error Then Return
    If StringRight($sDBFile, 4) <> '.db3' Then $sDBFile &= '.db3'
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle); Anzahl der Listview-Einträge holen
    If $iCount = 0 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1 ; Schleife, um alle Listview-Einträge durchzugehen
    FileWriteLine($hFile, _GUICtrlListView_GetItemTextString($hLVHandle, $i))
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i + 1, 2)
    EndIf
    Next
    FileClose($hFile) ; Datei schließen
    EndFunc ;==>Save

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $iRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $iRecursion = Verzeichnisse rekursiv durchsuchen
    ; 0 = Nein
    ; 1 = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $iRecursion = 1, $sDelim = @CRLF)
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While Not $fStop
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $iRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _ReadID3Tag($sPath)
    ; Description:: gibt ein Array mit den Daten aus den ID3-Tags zurück
    ; unterstützt werden die ID3-Tag-Versionen 1.0, 1.1, 2.3 und 2.4
    ; bei v2.4 müssen sich die ID3-Tags am Anfang der Datei befinden
    ; Parameter(s): $sPath = Pfad zu einer MP3-Datei
    ; Requirement(s): min. AutoIt v3.3.0.0
    ; Return Value(s): bei Erfolg: Array mit den ID3-Tagdaten (@error = 0)
    ; im Fehlerfall bekommt @error:
    ; 1 = Datei existiert nicht
    ; 2 = Datei konnte nicht zum lesen geöffnet werden
    ; 3 = falsche ID3 v2 Version
    ; 4 = Datei ist keine MP3-Datei
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ReadID3Tag($sPath)
    If Not FileExists($sPath) Then Return SetError(1, 0, 0)
    Local $hFile, $sData, $sID3Header, $iID3HeaderSize = 0, $iOffset, $iSize, $tmp
    Local $aID3v2Tags[8] = ['TIT2', 'TPE1', 'TALB', 'TYER', 'TLEN', 'TRCK', 'TCON', 'TENC']
    Local $aID3[11][2] = [ _
    ['Title', ''],['Artist', ''],['Album', ''],['Year', ''], _
    ['Length', '0'],['Track', ''],['Genre', ''],['Encoder', ''], _
    ['MPEG-Version', ''],['Bitrate', '-'],['Sample-Freq.', '']]
    Local $aMP3Version[4] = ['MPEG2.5', 'Reserved', 'MPEG2', 'MPEG1']
    Local $aMP3Layer[4] = ['Reserved', 'Layer III', 'Layer II', 'Layer I']
    Local $aMP3Bitrate[5][16] = [ _
    [000, 032, 064, 096, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 384, 000], _
    [000, 032, 040, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 144, 160, 176, 192, 224, 256, 000], _
    [000, 008, 016, 024, 032, 040, 048, 056, 064, 080, 096, 112, 128, 144, 160, 000]]
    Local $aSampleFreq[3][4] = [[44100, 48000, 32000, 0],[22050, 24000, 16000, 0],[11025, 12000, 8000, 0]]
    Local $sMP3FrameHeader, $iMP3Version, $sMP3Version, $sMP3Layer, $iMP3Bitrate, $iMP3SampleFreq
    Local $iVBRFrames = -1, $iVBRFilesize, $iVBRFlags
    $hFile = FileOpen($sPath, 16)
    If $hFile = -1 Then Return SetError(2, 0, 0)
    $sData = Binary(FileRead($hFile, 4))
    If BinaryMid($sData, 1, 3) = '0x494433' Then ; ID3 v2.x Kennung gefunden
    If (BinaryMid($sData, 4, 1) = '0x03') Or (BinaryMid($sData, 4, 1) = '0x04') Then ; nur v2.3 und 2.4
    FileRead($hFile, 2) ; 2 Bytes überspringen
    For $i = 0 To 3 ; berechne ID3-Headergröße (4 Bytes, jedoch nur jeweils die unteren 7 Bit)
    $iID3HeaderSize = BitShift($iID3HeaderSize, -7) + BitAND(Binary(FileRead($hFile, 1)), 0x7F)
    Next
    If $iID3HeaderSize > 0 Then
    $sID3Header = Binary(FileRead($hFile, $iID3HeaderSize)) ; lese gesamten ID3-Header
    For $i = 0 To 7
    $iOffset = StringInStr(BinaryToString($sID3Header), $aID3v2Tags[$i]) ; Offset zu dem ID3-Tag
    If $iOffset > 0 Then
    $iSize = Hex(BinaryMid($sID3Header, $iOffset + 4, 4)) ; Größe des ID3-Frames
    $tmp = BinaryMid($sID3Header, $iOffset + 11, Dec($iSize) - 1)
    If BinaryMid($tmp, 1, 2) = '0xFFFE' Then
    For $x = 3 To BinaryLen($tmp) Step 2
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 2), 2)
    Next
    Else
    For $x = 1 To BinaryLen($tmp)
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 1))
    Next
    EndIf
    $aID3[$i][1] = StringReplace($aID3[$i][1], Chr(0), '')
    EndIf
    Next
    EndIf
    Do
    $sData = String(FileRead($hFile, 1))
    If @error Then ExitLoop
    If BitAND($sData, 0xff) = 0xff Then
    FileSetPos($hFile, -1, 1)
    $sData = String(FileRead($hFile, 4))
    EndIf
    Until BitAND($sData, 0xFFE00000) = 0xFFE00000
    Else
    FileClose($hFile)
    Return SetError(3, 0, 0)
    EndIf
    Else ; ID3 v1.x
    $iOffset = FileGetPos($hFile)
    FileSetPos($hFile, -128, 2)
    $sID3Header = BinaryToString(FileRead($hFile, 3))
    If $sID3Header = 'TAG' Then
    $aID3[0][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[1][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[2][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[3][1] = StringReplace(BinaryToString(FileRead($hFile, 4)), Chr(0), '')
    EndIf
    FileSetPos($hFile, $iOffset, 0)
    EndIf
    $sMP3FrameHeader = String($sData)
    If BitAND($sMP3FrameHeader, 0xFFE00000) <> 0xFFE00000 Then
    FileClose($hFile)
    Return SetError(4, 0, 0) ; keine MP3-Datei, dann Return
    EndIf
    $iMP3Version = BitShift(BitXOR($sMP3FrameHeader, 0xFFE00000), 19) ; welche MP3-Version
    $sMP3Version = $aMP3Version[$iMP3Version] ; in Textform
    $sMP3Layer = $aMP3Layer[BitShift(BitAND($sMP3FrameHeader, 0x60000), 17)] ; welcher Layer
    $aID3[8][1] = $sMP3Version & ' / ' & $sMP3Layer ; ins Ausgabe-Array
    $iMP3Bitrate = BitShift(BitAND($sMP3FrameHeader, 0xF000), 12) ; Bitraten-Index auslesen
    Switch $sMP3Version ; je nach MPEG-Version Bitrate aus der Tabelle holen
    Case 'MPEG1'
    $aID3[9][1] = $aMP3Bitrate[$iMP3Version - ($iMP3Version > 1)][$iMP3Bitrate]
    Case 'MPEG2', 'MPEG2.5'
    If $sMP3Layer = 'Layer I' Then
    $aID3[9][1] = $aMP3Bitrate[3][$iMP3Bitrate]
    Else
    $aID3[9][1] = $aMP3Bitrate[4][$iMP3Bitrate]
    EndIf
    EndSwitch
    $iMP3SampleFreq = BitShift(BitAND($sMP3FrameHeader, 0xC00), 10) ; Sample-Frequenz-Index auslesen
    $aID3[10][1] = $aSampleFreq[2 - ($iMP3Version - ($iMP3Version > 1))][$iMP3SampleFreq] ; und Wert aus der Tabelle holen
    Do ; evtl. Leerbytes überspringen
    $tmp = FileRead($hFile, 1)
    If @error Then ExitLoop
    Until $tmp <> 0x00 Or @error
    If $tmp = 0x58 And BinaryToString(FileRead($hFile, 3)) = 'ing' Then ; MP3 mit VBR (Xing-Header gefunden)?
    $iVBRFlags = '0x' & Hex(FileRead($hFile, 4)) ; VBR-Flags auslesen
    If BitAND($iVBRFlags, 0x3) Then ; wenn die Einträge vorhanden sind, dann...
    $iVBRFrames = Dec(Hex(FileRead($hFile, 4))) ; Anzahl der VBR-Frames auslesen
    $iVBRFilesize = Dec(Hex(FileRead($hFile, 4))) ; Dateigröße auslesen
    $aID3[4][1] = $iVBRFrames * 1152 / $aID3[10][1] * 1000 ; VBR Laufzeit
    $aID3[9][1] = 'VBR ~' & Int($iVBRFilesize * 8 / ($aID3[4][1] / 1000) / 1000) ; VBR durchschnittliche Bitrate
    EndIf
    Else
    If $aID3[4][1] = 0 Then $aID3[4][1] = (FileGetSize($sPath) * 8) / ($aID3[9][1] * 1000) * 1000 ; alternative CBR Laufzeit
    $aID3[9][1] = 'CBR ' & $aID3[9][1]
    EndIf
    $aID3[4][1] = _TicksToTimeFormat($aID3[4][1]) ; Laufzeit (Ticks to hour:min:sec)
    $aID3[9][1] &= ' kBit/s'
    $aID3[10][1] &= ' Hz'
    FileClose($hFile)
    Return SetError(0, 0, $aID3)
    EndFunc ;==>_ReadID3Tag

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    ; Description:: Diese Funktion wandelt Millisekunden in ein anzugebenes Zeitformat um
    ; Parameter(s): $iTicks = Zeit in Millisekunden
    ; $sFormat:
    ; %hh für Stunden
    ; %mm für Minuten
    ; %ss für Sekunden
    ; %ms für Millisekunden
    ; sonstige Zeichen, die dazwischen stehen, werden übernommen
    ; Requirement(s): -
    ; Return Value(s): Zeit im ausgewählten Format (String)
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    Local $aTime[4] = [0, 0, 0, 0], $sOut, $aTimeFormat[4] = ['hh', 'mm', 'ss', 'ms'], $aFormat
    $aTime[2] = Int($iTicks / 1000)
    $aTime[3] = $iTicks - $aTime[2] * 1000
    $aTime[0] = Int($aTime[2] / 3600)
    $aTime[2] = Mod($aTime[2], 3600)
    $aTime[1] = Int($aTime[2] / 60)
    $aTime[2] = Mod($aTime[2], 60)
    $aFormat = StringRegExp($sFormat, '%([^%]+)', 3)
    If Not IsArray($aFormat) Then Return SetError(1, 0, $iTicks)
    For $i = 0 To UBound($aFormat) - 1
    For $j = 0 To UBound($aTimeFormat) - 1
    If StringLeft($aFormat[$i], 2) = $aTimeFormat[$j] Then $sOut &= StringFormat('%02i', $aTime[$j]) & StringMid($aFormat[$i], 3)
    Next
    Next
    Return $sOut
    EndFunc ;==>_TicksToTimeFormat

    [/autoit]
  • Mit Such Funktion oO
    Aba das Prog is doch ne Einiziges Search and Sort Prog ^^
    Ich fänds noch Cool (Wens machbar ist und ned zuviel arbeit :D) wen man da wo du alles Auskomentierst, ne progress bar hinhaut, u der test was er gerade tut in der Progress bar drine (Wen das überhaupt geht) ^^

    PS, Bis jetz keine fehler an der SuFu gefunden xD ^^
    Edit*
    Doch, da is was. kein bug oder fehler aber,
    wen man die suche startet istt das listView nich mehr aktiviert, was zurfolge hat man muss ins listView klicken, macht man dies, Gefundene Eintrag ned mehr markiert ^^

    wen das so gewollt ist, dann ist das ok ^^

    • Offizieller Beitrag

    Du hast recht, die Suche innerhalb der Liste bzw. die Anzeige des Ergebnisses gefiel mir auch nicht so richtig. Nur markieren ist blöd, weil man nicht alle Suchergebnisse überblicken kann.
    Ich habe jetzt ein zweites Listview (das ist erstmal versteckt und wird nur als Ergebnis angezeigt) erstellt und da kommen dann die Suchergebnisse rein. Das gefällt mir viel besser. ^^

    Außerdem habe ich jetzt die großen Buttons (zum einlesen der MP3s, laden und speichern usw.) oberhalb der Liste angeordnet. Die SuFu ist weiterhin unterhalb. So sieht das übersichtlicher aus, finde ich.

    Ich habe auch noch an verschiedenen Ecken an der Geschwindigkeit gefeilt. Das einlesen der MP3s und das sortieren nach Listviewspalte geht jetzt schneller vonstatten.

    Eine Progressbar in die Statusleiste packen geht zwar, aber da gibt es Probleme mit dem Resizing (die Progressbar bleibt nicht da, wo sie hingehört). Vielleicht mache ich aber noch eine Progressbar außerhalb der Statusleiste?! :S

    Skript:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <Date.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    #include <ListViewConstants.au3>
    #include <ProgressConstants.au3>
    #include <StaticConstants.au3>
    #include <StructureConstants.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Global $sHeader = 'Title|Artist|Length|Album|Year|MPEG-Version|Bitrate|Sample-Freq.|Path' ; Die Überschriften für das Listview
    Global $sInifile = @ScriptDir & '\MP3-Search.ini' ; Inidatei

    [/autoit] [autoit][/autoit] [autoit]

    Global $iWidth = IniRead($sInifile, 'Config', 'Width', 770)
    Global $iHeight = IniRead($sInifile, 'Config', 'Height', 406)
    Global $iLeft = IniRead($sInifile, 'Config', 'Left', @DesktopWidth / 2 - 385)
    Global $iTop = IniRead($sInifile, 'Config', 'Top', @DesktopHeight / 2 - 203)

    [/autoit] [autoit][/autoit] [autoit]

    #region Hauptfenster
    Global $sStyle = BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX)
    Global $hGui = GUICreate('MP3-Search', 770, 406, $iLeft, $iTop, $sStyle) ; Hauptfenster erstellen
    GUISetBkColor(0xAAAAAA)

    [/autoit] [autoit][/autoit] [autoit]

    Global $hListView = GUICtrlCreateListView($sHeader, 5, 55, 760, 240, $LVS_SHOWSELALWAYS, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_WINDOWEDGE)) ; Listview erstellen
    GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
    GUICtrlSetBkColor(-1, 0xffffff)
    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumnWidth($hLVHandle, 0, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 1, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 2, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 3, 120)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 4, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 5, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 6, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 7, 90)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 8, 800)

    [/autoit] [autoit][/autoit] [autoit]

    Global $hSearchListView = GUICtrlCreateListView($sHeader, 5, 55, 760, 240, $LVS_SHOWSELALWAYS, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_WINDOWEDGE)) ; Listview erstellen
    GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
    GUICtrlSetBkColor(-1, 0xaaffbb)
    Global $hSearchLVHandle = GUICtrlGetHandle($hSearchListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 0, 180)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 1, 180)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 2, 60)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 3, 120)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 4, 60)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 5, 100)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 6, 100)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 7, 90)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 8, 800)
    GUICtrlSetState($hSearchListView, $GUI_HIDE)

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlCreateGroup('', 5, 300, 760, 75)
    GUICtrlSetResizing(-1, 512 + 64)
    GUICtrlCreateLabel('Suchbegriff:', 15, 322, 70, 22, $SS_RIGHT)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hInput = GUICtrlCreateInput('', 90, 320, 300, 22)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hInputOk = GUICtrlCreateButton('Suche starten', 400, 320, 100, 22, $BS_DEFPUSHBUTTON)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hCaseSens = GUICtrlCreateCheckbox('Groß-/Kleinschreibung beachten', 90, 345, 240, 22)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    GUICtrlCreateGroup('', -99, -99, 1, 1)

    [/autoit] [autoit][/autoit] [autoit]

    Global $hSearch = GUICtrlCreateButton('Alle Festplatten durchsuchen', 10, 10, 100, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    Global $hSearchPath = GUICtrlCreateButton('Verzeichnis durchsuchen', 120, 10, 80, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    Global $hLoad = GUICtrlCreateButton('Liste laden', 230, 10, 70, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    Global $hSave = GUICtrlCreateButton('Liste speichern', 310, 10, 70, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    Global $hDel = GUICtrlCreateButton("Markierte Einträge löschen", 410, 10, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    GUICtrlSetState(-1, $GUI_DISABLE)
    Global $hDelAll = GUICtrlCreateButton('Alle Einträge löschen', 510, 10, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)

    [/autoit] [autoit][/autoit] [autoit]

    Global $aParts[3] = [300, 360, -1], $aText[3] = ['Fertig.', '0', '']
    Global $hStatus = _GUICtrlStatusBar_Create($hGui, $aParts, $aText, $SBARS_SIZEGRIP)
    _GUICtrlStatusBar_SetSimple($hStatus, False)
    _GUICtrlStatusBar_SetMinHeight($hStatus, 20)
    #endregion Hauptfenster

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

    [/autoit] [autoit][/autoit] [autoit]

    Global $fStop = False, $iSearchIndex = -1, $iSelCount, $iSelOld, $aListview
    HotKeySet('{ESC}', '_Stop')

    [/autoit] [autoit][/autoit] [autoit]

    Dim $aAccelKeys[1][2] = [['{DEL}', $hDel]] ; beim drücken der [Delete]-Taste wird "Case $hDel" ausgeführt
    GUISetAccelerators($aAccelKeys, $hGui)

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_SIZE, '_WM_SIZE')
    GUIRegisterMsg($WM_MOVE, '_WM_MOVE')
    GUIRegisterMsg($WM_GETMINMAXINFO, '_WM_GETMINMAXINFO')
    GUIRegisterMsg($WM_NOTIFY, '_WM_NOTIFY')
    GUIRegisterMsg($WM_COMMAND, '_WM_COMMAND')

    [/autoit] [autoit][/autoit] [autoit]

    WinMove($hGui, '', $iLeft, $iTop, $iWidth, $iHeight)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Switch GUIGetMsg() ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hSearch
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    $iLVCount = 0 ; Zähler auf Null setzen
    $aDrives = DriveGetDrive('FIXED') ; Alle Festplatten-Buchstaben holen
    If Not @error Then
    GUISetCursor(15, 1, $hGui)
    For $i = 1 To $aDrives[0] ; Alle Festplatten durchgehen
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Festplatte "' & StringUpper($aDrives[$i]) & '\"', 0)
    _DriveSearch(StringUpper($aDrives[$i]))
    Next
    GUISetCursor(2, 1, $hGui)
    EndIf
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    Case $hSearchPath
    $sPath = FileSelectFolder('Verzeichnis auswählen!', '', 2, '', $hGui)
    If FileExists($sPath) Then
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iLVCount = 0 ; Zähler auf Null setzen
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Verzeichnis "' & $sPath & '"', 0)
    _DriveSearch($sPath)
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    EndIf
    Case $hInputOk
    ControlFocus($hGui, '', $hInputOk)
    _GUICtrlStatusBar_SetText($hStatus, 'Suche in Liste...', 0)
    GUISetCursor(15, 1, $hGui)
    _LVSearch()
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    Case $hListView ; User hat auf eine Spaltenüberschrift geklickt (sortieren)
    If _GUICtrlListView_GetItemCount($hLVHandle) > 0 Then
    GUISetCursor(15, 1, $hGui)
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    _GUICtrlStatusBar_SetText($hStatus, 'Sortiere Daten! Bitte warten...', 0)
    If Not IsArray($aListview) Then
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle)
    Dim $aListview[$iCount][9]
    For $i = 0 To $iCount - 1
    For $j = 0 To 8
    $aListview[$i][$j] = ControlListView($hGui, '', $hListView, 'GetText', $i, $j)
    Next
    Next
    EndIf
    _ArraySort($aListview, 0, 0, 0, GUICtrlGetState($hListView))
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_AddArray($hLVHandle, $aListview)
    _GUICtrlStatusBar_SetText($hStatus, _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms'), 2)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hLoad ; User hat auf 'Laden' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten...', 0)
    Load()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    $aListview = ''
    Case $hSave ; User hat auf 'Speichern' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Speichere Daten...', 0)
    Save()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    GUISetCursor(2, 1, $hGui)
    Case $hDel
    If MsgBox(256 + 32 + 4, 'Markierte Einträge löschen', 'Wollen sie wirklich die markierten Einträge löschen?') = 6 Then
    GUISetCursor(15, 1, $hGui)
    _GUICtrlListView_DeleteItemsSelected($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    GUISetCursor(2, 1, $hGui)
    $aListview = ''
    EndIf
    Case $hDelAll ; User hat auf 'Alle Einträge löschen' geklickt
    If MsgBox(256 + 32 + 4, 'Einträge löschen', 'Wollen sie wirklich alle Einträge löschen?') = 6 Then
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    $aListview = ''
    EndIf
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt
    ;~ If MsgBox(32 + 4, 'Save', 'Wollen sie vor beenden noch Speichern?') = 6 Then Save()
    Exit ; Programm beenden
    EndSwitch
    $iSelCount = _GUICtrlListView_GetSelectedCount($hLVHandle) ; Anzahl der markierten Items holen
    If $iSelCount <> $iSelOld Then ; vergleichen ob der Wert vom vorherigen abweicht (Flackern vermeiden)
    $iSelOld = $iSelCount ; wenn ja, dann alten gleich neuen Wert
    If $iSelCount > 0 Then ; wenn Einträge markiert sind
    GUICtrlSetState($hDel, $GUI_ENABLE) ; dann Button aktivieren
    GUICtrlSetData($hDel, StringFormat('(%i) Markierte Einträge löschen', $iSelCount)) ; und den Text auf dem Button anpassen
    Else ; keine Einträge markiert
    GUICtrlSetState($hDel, $GUI_DISABLE) ; dann Button deaktivieren
    GUICtrlSetData($hDel, 'Markierte Einträge löschen') ; und den Text auf dem Button anpassen
    EndIf
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Stop()
    $fStop = True
    EndFunc ;==>_Stop

    [/autoit] [autoit][/autoit] [autoit]

    Func _DriveSearch($sPath)
    Local $aNewMP3, $aID3Tags, $sNewItem, $aItem, $iTimer = TimerInit(), $iCount = _GUICtrlListView_GetItemCount($hLVHandle)
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte warten...', 2)
    $aNewMP3 = _RecursiveFileListToArray($sPath, '\.mp3', 1) ; Alle MP3s auf der Festplatte auslesen
    If Not @error And $aNewMP3[0] > 0 Then
    _GUICtrlListView_SetItemCount($hListView, $iCount + $aNewMP3[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lese ID3-Tags... (' & $aNewMP3[0] & ')', 0)
    For $j = 1 To $aNewMP3[0] ; die gefundenen MP3s durchgehen
    $aID3Tags = _ReadID3Tag($aNewMP3[$j]) ; die ID3-Tags auslesen
    If Not @error Then
    For $k = 0 To 10
    $aID3Tags[$k][1] = StringReplace($aID3Tags[$k][1], '|', '') ; evtl. vorhandene "|" entfernen
    Next
    If TimerDiff($iTimer) > 50 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount + $j, 1)
    _GUICtrlStatusBar_SetText($hStatus, $aNewMP3[$j], 2)
    EndIf
    $sNewItem = $aID3Tags[0][1] & '|' & $aID3Tags[1][1] & '|' & $aID3Tags[4][1] & '|' & $aID3Tags[2][1] & '|' & $aID3Tags[3][1]
    $sNewItem &= '|' & $aID3Tags[8][1] & '|' & $aID3Tags[9][1] & '|' & $aID3Tags[10][1] & '|' & $aNewMP3[$j]
    GUICtrlCreateListViewItem($sNewItem, $hListView)
    EndIf
    If $fStop Then ExitLoop
    Next
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    EndIf
    EndFunc ;==>_DriveSearch

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_COMMAND($hWnd, $msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0xFFFF)
    If $nID = $hInput And $nNotifyCode = 256 Then
    GUICtrlSetState($hSearchListView, $GUI_HIDE)
    GUICtrlSetState($hListView, $GUI_SHOW)
    GUICtrlSetBkColor($hInput, 0xffffff)
    GUICtrlSetData($hInput, '')
    GUICtrlSetState($hInputOk, $GUI_ENABLE)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    _GUICtrlListView_SetItemSelected($hLVHandle, -1, False)
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_COMMAND

    [/autoit] [autoit][/autoit] [autoit]

    Func _LVSearch()
    Local $sSearch, $iTimer, $iCount, $iCase, $iFound, $sMsg = ' Einträge'
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle)
    If $iCount = 0 Then Return
    $sSearch = GUICtrlRead($hInput)
    If $sSearch = '' Then Return
    _GUICtrlListView_SetItemSelected($hLVHandle, -1, False)
    _GUICtrlListView_DeleteAllItems($hSearchLVHandle)
    $iCase = Number(BitAND(GUICtrlRead($hCaseSens), $GUI_CHECKED) = $GUI_CHECKED)
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1
    $sItem = ''
    For $j = 0 To 8
    $sItem &= ControlListView($hGui, '', $hListView, 'GetText', $i, $j) & '|'
    Next
    If StringInStr($sItem, $sSearch, $iCase) Then GUICtrlCreateListViewItem(StringTrimRight($sItem, 1), $hSearchListView)
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i, 2)
    EndIf
    Next
    GUICtrlSetState($hInputOk, $GUI_DISABLE)
    $iFound = _GUICtrlListView_GetItemCount($hSearchLVHandle)
    If $iFound = 1 Then $sMsg = ' Eintrag'
    _GUICtrlStatusBar_SetText($hStatus, $iFound & $sMsg & ' gefunden', 2)
    If $iFound Then
    GUICtrlSetBkColor($hInput, 0xaaffaa)
    GUICtrlSetState($hSearchListView, $GUI_SHOW)
    GUICtrlSetState($hListView, $GUI_HIDE)
    Else
    GUICtrlSetBkColor($hInput, 0xffaaaa)
    EndIf
    EndFunc ;==>_LVSearch

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_NOTIFY($hWnd, $msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $iSelected, $sExecutePath
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
    $iCode = DllStructGetData($tNMHDR, 'Code')
    Switch $hWndFrom
    Case $hLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $iSelected = ControlListView($hGui, '', $hListView, 'GetSelected')
    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, $iSelected, 8)
    ShellExecute($sExecutePath)
    EndSwitch
    Case $hSearchLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $iSelected = ControlListView($hGui, '', $hSearchListView, 'GetSelected')
    $sExecutePath = _GUICtrlListView_GetItemText($hSearchLVHandle, $iSelected, 8)
    ShellExecute($sExecutePath)
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_NOTIFY

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Width', $aGuiPos[2])
    IniWrite($sInifile, 'Config', 'Height', $aGuiPos[3])
    EndIf
    _GUICtrlStatusBar_Resize($hStatus)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_SIZE

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_MOVE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Left', $aGuiPos[0])
    IniWrite($sInifile, 'Config', 'Top', $aGuiPos[1])
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_MOVE

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_GETMINMAXINFO($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGui Then
    Local $minmaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($minmaxinfo, 7, 786) ; min X
    DllStructSetData($minmaxinfo, 8, 444) ; min Y
    ;~ DllStructSetData($minmaxinfo, 9, 800) ; max X
    ;~ DllStructSetData($minmaxinfo, 10, 800) ; max Y
    EndIf
    EndFunc ;==>_WM_GETMINMAXINFO

    [/autoit] [autoit][/autoit] [autoit]

    Func Load() ; Datenbank-Datei laden
    Local $sDBFile, $hFile, $sContent, $aNewItems, $iTimer, $iCount
    FileChangeDir(@ScriptDir)
    $sDBFile = FileOpenDialog('MP3-Datenbank-Datei auswählen', @ScriptDir, 'MP3-Datenbank (*.db3)', 3, '', $hGui)
    If Not FileExists($sDBFile) Then Return
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_SetItemCount($hLVHandle, $aNewItems[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten... (' & $aNewItems[0] & ')', 0)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    $iTimer = TimerInit()
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    $iCount += 1
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    EndIf
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    EndFunc ;==>Load

    [/autoit] [autoit][/autoit] [autoit]

    Func Save() ; Datenbank-Datei speichern
    Local $sDBFile, $hFile, $iCount, $iTimer
    $sDBFile = FileSaveDialog('MP3-Datenbank-Datei auswählen', '', 'MP3-Datenbank (*.db3)', 18, '', $hGui)
    If @error Then Return
    If StringRight($sDBFile, 4) <> '.db3' Then $sDBFile &= '.db3'
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle); Anzahl der Listview-Einträge holen
    If $iCount = 0 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1 ; Schleife, um alle Listview-Einträge durchzugehen
    FileWriteLine($hFile, _GUICtrlListView_GetItemTextString($hLVHandle, $i))
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i + 1, 2)
    EndIf
    Next
    FileClose($hFile) ; Datei schließen
    EndFunc ;==>Save

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $iRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $iRecursion = Verzeichnisse rekursiv durchsuchen
    ; 0 = Nein
    ; 1 = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $iRecursion = 1, $sDelim = @CRLF)
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While Not $fStop
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $iRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _ReadID3Tag($sPath)
    ; Description:: gibt ein Array mit den Daten aus den ID3-Tags zurück
    ; unterstützt werden die ID3-Tag-Versionen 1.0, 1.1, 2.3 und 2.4
    ; bei v2.4 müssen sich die ID3-Tags am Anfang der Datei befinden
    ; Parameter(s): $sPath = Pfad zu einer MP3-Datei
    ; Requirement(s): min. AutoIt v3.3.0.0
    ; Return Value(s): bei Erfolg: Array mit den ID3-Tagdaten (@error = 0)
    ; im Fehlerfall bekommt @error:
    ; 1 = Datei existiert nicht
    ; 2 = Datei konnte nicht zum lesen geöffnet werden
    ; 3 = falsche ID3 v2 Version
    ; 4 = Datei ist keine MP3-Datei
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ReadID3Tag($sPath)
    If Not FileExists($sPath) Then Return SetError(1, 0, 0)
    Local $hFile, $sData, $sID3Header, $iID3HeaderSize = 0, $iOffset, $iSize, $tmp
    Local $aID3v2Tags[8] = ['TIT2', 'TPE1', 'TALB', 'TYER', 'TLEN', 'TRCK', 'TCON', 'TENC']
    Local $aID3[11][2] = [ _
    ['Title', ''],['Artist', ''],['Album', ''],['Year', ''], _
    ['Length', '0'],['Track', ''],['Genre', ''],['Encoder', ''], _
    ['MPEG-Version', ''],['Bitrate', '-'],['Sample-Freq.', '']]
    Local $aMP3Version[4] = ['MPEG2.5', 'Reserved', 'MPEG2', 'MPEG1']
    Local $aMP3Layer[4] = ['Reserved', 'Layer III', 'Layer II', 'Layer I']
    Local $aMP3Bitrate[5][16] = [ _
    [000, 032, 064, 096, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 384, 000], _
    [000, 032, 040, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 144, 160, 176, 192, 224, 256, 000], _
    [000, 008, 016, 024, 032, 040, 048, 056, 064, 080, 096, 112, 128, 144, 160, 000]]
    Local $aSampleFreq[3][4] = [[44100, 48000, 32000, 0],[22050, 24000, 16000, 0],[11025, 12000, 8000, 0]]
    Local $sMP3FrameHeader, $iMP3Version, $sMP3Version, $sMP3Layer, $iMP3Bitrate, $iMP3SampleFreq
    Local $iVBRFrames = -1, $iVBRFilesize, $iVBRFlags
    $hFile = FileOpen($sPath, 16)
    If $hFile = -1 Then Return SetError(2, 0, 0)
    $sData = Binary(FileRead($hFile, 4))
    If BinaryMid($sData, 1, 3) = '0x494433' Then ; ID3 v2.x Kennung gefunden
    If (BinaryMid($sData, 4, 1) = '0x03') Or (BinaryMid($sData, 4, 1) = '0x04') Then ; nur v2.3 und 2.4
    FileRead($hFile, 2) ; 2 Bytes überspringen
    For $i = 0 To 3 ; berechne ID3-Headergröße (4 Bytes, jedoch nur jeweils die unteren 7 Bit)
    $iID3HeaderSize = BitShift($iID3HeaderSize, -7) + BitAND(Binary(FileRead($hFile, 1)), 0x7F)
    Next
    If $iID3HeaderSize > 0 Then
    $sID3Header = Binary(FileRead($hFile, $iID3HeaderSize)) ; lese gesamten ID3-Header
    For $i = 0 To 7
    $iOffset = StringInStr(BinaryToString($sID3Header), $aID3v2Tags[$i]) ; Offset zu dem ID3-Tag
    If $iOffset > 0 Then
    $iSize = Hex(BinaryMid($sID3Header, $iOffset + 4, 4)) ; Größe des ID3-Frames
    $tmp = BinaryMid($sID3Header, $iOffset + 11, Dec($iSize) - 1)
    If BinaryMid($tmp, 1, 2) = '0xFFFE' Then
    For $x = 3 To BinaryLen($tmp) Step 2
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 2), 2)
    Next
    Else
    For $x = 1 To BinaryLen($tmp)
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 1))
    Next
    EndIf
    $aID3[$i][1] = StringReplace($aID3[$i][1], Chr(0), '')
    EndIf
    Next
    EndIf
    Do
    $sData = String(FileRead($hFile, 1))
    If @error Then ExitLoop
    If BitAND($sData, 0xff) = 0xff Then
    FileSetPos($hFile, -1, 1)
    $sData = String(FileRead($hFile, 4))
    EndIf
    Until BitAND($sData, 0xFFE00000) = 0xFFE00000
    Else
    FileClose($hFile)
    Return SetError(3, 0, 0)
    EndIf
    Else ; ID3 v1.x
    $iOffset = FileGetPos($hFile)
    FileSetPos($hFile, -128, 2)
    $sID3Header = BinaryToString(FileRead($hFile, 3))
    If $sID3Header = 'TAG' Then
    $aID3[0][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[1][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[2][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[3][1] = StringReplace(BinaryToString(FileRead($hFile, 4)), Chr(0), '')
    EndIf
    FileSetPos($hFile, $iOffset, 0)
    EndIf
    $sMP3FrameHeader = String($sData)
    If BitAND($sMP3FrameHeader, 0xFFE00000) <> 0xFFE00000 Then
    FileClose($hFile)
    Return SetError(4, 0, 0) ; keine MP3-Datei, dann Return
    EndIf
    $iMP3Version = BitShift(BitXOR($sMP3FrameHeader, 0xFFE00000), 19) ; welche MP3-Version
    $sMP3Version = $aMP3Version[$iMP3Version] ; in Textform
    $sMP3Layer = $aMP3Layer[BitShift(BitAND($sMP3FrameHeader, 0x60000), 17)] ; welcher Layer
    $aID3[8][1] = $sMP3Version & ' / ' & $sMP3Layer ; ins Ausgabe-Array
    $iMP3Bitrate = BitShift(BitAND($sMP3FrameHeader, 0xF000), 12) ; Bitraten-Index auslesen
    Switch $sMP3Version ; je nach MPEG-Version Bitrate aus der Tabelle holen
    Case 'MPEG1'
    $aID3[9][1] = $aMP3Bitrate[$iMP3Version - ($iMP3Version > 1)][$iMP3Bitrate]
    Case 'MPEG2', 'MPEG2.5'
    If $sMP3Layer = 'Layer I' Then
    $aID3[9][1] = $aMP3Bitrate[3][$iMP3Bitrate]
    Else
    $aID3[9][1] = $aMP3Bitrate[4][$iMP3Bitrate]
    EndIf
    EndSwitch
    $iMP3SampleFreq = BitShift(BitAND($sMP3FrameHeader, 0xC00), 10) ; Sample-Frequenz-Index auslesen
    $aID3[10][1] = $aSampleFreq[2 - ($iMP3Version - ($iMP3Version > 1))][$iMP3SampleFreq] ; und Wert aus der Tabelle holen
    Do ; evtl. Leerbytes überspringen
    $tmp = FileRead($hFile, 1)
    If @error Then ExitLoop
    Until $tmp <> 0x00 Or @error
    If $tmp = 0x58 And BinaryToString(FileRead($hFile, 3)) = 'ing' Then ; MP3 mit VBR (Xing-Header gefunden)?
    $iVBRFlags = '0x' & Hex(FileRead($hFile, 4)) ; VBR-Flags auslesen
    If BitAND($iVBRFlags, 0x3) Then ; wenn die Einträge vorhanden sind, dann...
    $iVBRFrames = Dec(Hex(FileRead($hFile, 4))) ; Anzahl der VBR-Frames auslesen
    $iVBRFilesize = Dec(Hex(FileRead($hFile, 4))) ; Dateigröße auslesen
    $aID3[4][1] = $iVBRFrames * 1152 / $aID3[10][1] * 1000 ; VBR Laufzeit
    $aID3[9][1] = 'VBR ~' & Int($iVBRFilesize * 8 / ($aID3[4][1] / 1000) / 1000) ; VBR durchschnittliche Bitrate
    EndIf
    Else
    If $aID3[4][1] = 0 Then $aID3[4][1] = (FileGetSize($sPath) * 8) / ($aID3[9][1] * 1000) * 1000 ; alternative CBR Laufzeit
    $aID3[9][1] = 'CBR ' & $aID3[9][1]
    EndIf
    $aID3[4][1] = _TicksToTimeFormat($aID3[4][1]) ; Laufzeit (Ticks to hour:min:sec)
    $aID3[9][1] &= ' kBit/s'
    $aID3[10][1] &= ' Hz'
    FileClose($hFile)
    Return SetError(0, 0, $aID3)
    EndFunc ;==>_ReadID3Tag

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    ; Description:: Diese Funktion wandelt Millisekunden in ein anzugebenes Zeitformat um
    ; Parameter(s): $iTicks = Zeit in Millisekunden
    ; $sFormat:
    ; %hh für Stunden
    ; %mm für Minuten
    ; %ss für Sekunden
    ; %ms für Millisekunden
    ; sonstige Zeichen, die dazwischen stehen, werden übernommen
    ; Requirement(s): -
    ; Return Value(s): Zeit im ausgewählten Format (String)
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    Local $aTime[4] = [0, 0, 0, 0], $sOut, $aTimeFormat[4] = ['hh', 'mm', 'ss', 'ms'], $aFormat
    $aTime[2] = Int($iTicks / 1000)
    $aTime[3] = $iTicks - $aTime[2] * 1000
    $aTime[0] = Int($aTime[2] / 3600)
    $aTime[2] = Mod($aTime[2], 3600)
    $aTime[1] = Int($aTime[2] / 60)
    $aTime[2] = Mod($aTime[2], 60)
    $aFormat = StringRegExp($sFormat, '%([^%]+)', 3)
    If Not IsArray($aFormat) Then Return SetError(1, 0, $iTicks)
    For $i = 0 To UBound($aFormat) - 1
    For $j = 0 To UBound($aTimeFormat) - 1
    If StringLeft($aFormat[$i], 2) = $aTimeFormat[$j] Then $sOut &= StringFormat('%02i', $aTime[$j]) & StringMid($aFormat[$i], 3)
    Next
    Next
    Return $sOut
    EndFunc ;==>_TicksToTimeFormat

    [/autoit]

    Edit: Man konnte aus dem Suchergebnis das MP3 nicht starten (Doppelklick). Behoben!

  • Hey Oscar
    Ich mach mir seid geraumer zeit gedanken, wie man das verschieben coden soll. In combi mit deiner mehr alls ausführlichen array sammlung :D
    Kann man das auch mit array machen? Leider hab ich halt noch nicht sooo viel array arfahrung :)
    Was meinst du dazu?

    Mfg Skilkor

  • Nach/Bei der 65271. Datei wird das Suchfeld während des einlesens rot und dann geht nichts mehr.

    Mhhhh. Da muß ich dann doch die Ordner nach und nach einlesen?
    Wie soll ich es jetzt machen? Nach Buchstaben sortieren oder ??? ?

    LG, Lina.

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl

  • Hey Alina, o Lina?
    Was dasmit dem fehler angeht, danke das du uns dies mitteilst. Leider hat von und keiner mehr als 40'000 files. Deswegen wahr uns dieser fehler unbekannt. Ich bin aber guter dinge das man den fehler beheben kann :)

    Sortieren kann man noch nicht.
    Nur die listview sortieren :)
    Man kann momentan das ganze in einer datenbank speichern. Mit den infos aus der listview. Wen du dies versuchen möchtest , ist es do h sinnvoller wen du mal ein ordner scanst, sonnst bekommst ja den fehler wider :)

    Mfg Skilkor

    • Offizieller Beitrag

    Skilkor: Wieso? Das verschieben der Dateien funktioniert doch bereits! Wenn Du Einträge markiert hast, kannst Du diese kopieren, verschieben oder löschen.

    Alina: Das Suchfeld wird während des einlesens der MP3-Dateien rot? Das dürfte eigentlich nicht passieren. Es sei denn, das da irgendeine Grenze bei AutoIt überschritten wird?! ?(
    Ich habe das Programm bisher "nur" mit 42022 Dateien getestet. Da funktioniert aber alles problemlos. Allerdings ziehen sich dann sämtliche Funktionen etwas in die Länge. Von daher ist eine Aufteilung keine schlechte Idee. Deshalb habe ich ja auch die Möglichkeit geschaffen einzelne Ordner/Festplatten einlesen zu lassen. Du kannst also die Funktion "Verzeichnis nach MP3s durchsuchen" benutzen und dann z.B. "C:\" auswählen. Diese Liste speicherst Du dann als "MP3s_auf_c" oder so.

  • Ho? Steh ich so auf der stecke oO
    Ach du dunkles srück dreck....
    Da hab ich wohl überhaupt ned aufgepasst
    Naich komm jetz au nach hause da kann ich das besser sehn :# so mitm handy geht das posten erschwehrt. Ich kann zwar aufn rechner connecten u via handy n script scbreiben. Nur ned ausführen, u. ohne wifi gehts au ned :)

  • Hallo zusammen.

    Oscar
    Alleine auf einer Festplatte habe ich alle MP's. Aber ich werde sie nun nach Interpret sortieren und dann die Ordner durchgehen.

    Aber eines noch: Ich finde das Tool wirklich supppppppper !!!

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl

  • Hey Oscar :D

    Ich hab den ganzen Mp3 Searcher Getestet.
    Alle Funktionen bis auf das limit von 65532 GUI-Controls wie du sagtest, läuft ein wahn frein.
    Mir fehlt aber noch etwas :D

    Das Copy per Path is ja gut und recht. nur muss ich so die Ordner erstellen (Faulheit 4tw xD)
    ich würd mich freuen über eine func (vll bekomm ichs Selber hin)
    die ALLE in der ListView eingetragenen Tags in einen Ordner (z.B. Meine Mukke) kopiert und Volgendes macht.
    Copy =
    Hauptordner(Wird angegeben)
    ->Inperpret(Ordner wird vom Prog erstellt)
    -->Album(Ordner wird vom Prog erstellt)

    und sie dan so kopiert das die MP3´s dan im richtigen Interpreten und Album sind.
    Bei mp3´s die einen interpreten haben aber kein album, sollte er "Unbekanntes Album" erstellen,und diese dan dort rein schieben, aber zum richtigen Interpreten.
    Das selbe beim Interpreten. fals nicht vorhanden dan soll er den Ordner "Unbekannter Interpret" erstellen.
    Ich hoffe du weist was ich Meine ^^
    den Um genau diesen Punkt,ging es mir eigentlich :D

    Mfg Skilkor

  • Oscar

    Mach Dir ja kein Stress.
    Habe jetzt die Dateien, die ich bereits sortiert, habe in die Ordner kopiert. Jeder Interpret bekommt jetzt seinen Ordner und dann läuft Dein Tool superschnell durch.
    Wenn alles durch ist, dann kann man ja die *.db3 alle zu einer machen.

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl