INI-Dateien wurden verstärkt unter Windows 3.x eingesetzt - aber auch unter Win9x/NT wird noch reichlich von diesen Dateien Gebrauch gemacht. Dieser Workshop verrät, warum Sie selbst INI-Dateien verwenden sollten und wie sich mit dem Einsatz von nur zwei API-Funktionen ein komfortabler INI-Editor zur Erstellung und Bearbeitung von INI-Dateien erstellen lässt. INI-Dateien und das Windows-API Eine INI-Datei, das ist eine Art Konfigurationsdatei, in welcher z.B. Programm- und Benutzereinstellungen einer Anwendung gespeichert werden. INI-Dateien wurden vor allem unter Windows 3.x eingesetzt. Seit Einführung des 32-Bit Betriebssystems Windows 95 nutzten viele Programmhersteller die Windows-Registrier-Datenbank, um ihre Programm- und Benutzereinstellungen zu speichern. Meiner Meinung nach ist das aber nicht der Weg, den ALLE beschreiten sollten, denn die Windows-Registrierdatenbank wird durch die große Anzahl an installierten Programmen und demzufolge durch die in der Registry eingetragenen Anwendungseinstellungen immer größer und größer - und verlangsamt somit das gesamte System. Ein weiterer Vorteil, der für die Verwendung von INI-Dateien spricht, ist die Datensicherung. Wenn die Anwendungseinstellungen in einer INI-Datei im Programmverzeichnis gespeichert werden, werden diese auch automatisch bei einer Datensicherung gesichert. Aufbau von INI-Dateien [Abschnitt1] Key1=Wert1 Key2=Wert2 Key3=Wert3 [Abschnitt2] Key1=Wert1 Key2=Wert2 Key3=Wert3 [Abschnitt3] Key1=Wert1 Key2=Wert2 Key3=Wert3 Beispiel für eine einfache INI-Datei [Start] Tagestipp=ja Datum prüfen=nein [Verzeichnisse] Texte=..\Privat\Texte Daten=..\Daten [Anwender1] User=Dieter eMail=info@vbarchiv.de [Anwender2] User=Ralph eMail=ralp@vbarchiv.de Welche Rolle spielt nun das Windows-API? Public Declare Function WritePrivateProfileString Lib "kernel32" _ Alias "WritePrivateProfileStringA" ( _ ByVal lpApplicationName As String, _ ByVal lpKeyName As Any, _ ByVal lpString As Any, _ ByVal lpFileName As String) As Long Public Declare Function GetPrivateProfileString Lib "kernel32" _ Alias "GetPrivateProfileStringA" ( _ ByVal lpApplicationName As String, _ ByVal lpKeyName As Any, _ ByVal lpDefault As String, _ ByVal lpReturnedString As String, _ ByVal nSize As Long, _ ByVal lpFileName As String) As Long Die erste Funktion WritePrivateProfileString erledigt das Speichern und Löschen von Einträgen oder auch ganzen Abschnitten. Die zweite Funktion GetPrivateProfileString dient in erster Linie zum Lesen des Wertes eines einzelnen Eintrages. Mit dieser Funktion lassen sich aber auch alle in der INI-Datei vorhandenen Abschnittsnamen ermitteln oder auch alle Schlüsselnamen eines einzelnen Abschnittes. Ohne die beiden Windows-API Funktionen wäre das Verwalten von INI-Dateien sehr sehr aufwendig. Um einen einzelnen Eintrag auszulesen müssten Sie die INI-Datei sequentiell öffnen und solange "zeilenweise" einlesen, bis Sie den gewünschten Eintrag erreicht haben. Das Löschen und Speichern von Einträgen oder ganzen Abschnitten würde dann sogar einen noch größeren Aufwand bedeuten. API: WritePrivateProfileString Die API-Funktion WritePrivateProfileString wird wie bereits erwähnt in erster Linie zum Speichern eines einzelnen neuen oder modifizierten Eintrags verwendet. Die Syntax ist hierbei folgende:
' Einzelnen Eintrag im Abschnitt "Start" speichern Dim myIniFile As String myIniFile = App.Path & "\" & App.EXEName & ".ini" WritePrivateProfileString "Start", "Tagestipp", "ja", _ myIniFile Wie ebenfalls bereits erwähnt lassen sich mit der WritePrivateProfileString-Funktion aber auch einzelne Einträge oder auch ganze Abschnitte löschen. ' Löschen eines einzelnen Eintrags aus der INI-Datei WritePrivateProfileString "Start", "Tagestipp", vbNullString, _ myIniFile ' Löschen eines gesamten Abschnittes WritePrivateProfileString "Start", vbNullString, "", myIniFile ' Löschen aller Abschnitte WritePrivateProfileString vbNullString, "", "", myIniFile Wie Sie anhand der Funktionsaufrufe sehen, können Teile der INI-Datei durch Angabe von vbNullString gelöscht werden - je nachdem, für welchen Parameter Sie vbNullString einsetzen, handelt es sich um einen einzelnen Eintrag, einen einzelnen Abschnitt oder auch um alle Abschnitte. API: GetPrivateProfileString Um nun gespeicherte Einträge in der INI-Datei auszulesen, wird die GetPrivateProfileString-Funktion benutzt. Die Syntax ist hierbei folgende:
Die Funktion selbst gibt als Rückgabewert die Länge des tatsächlich gelesenen Wertes zurück. Wichtig beim Einsatz der Funktion ist, dass Sie die Rückgabevariable lpReturnString vor dem Funktionsaufruf mit ausreichend Leerstellen füllen und die Größe der Variable dann im Parameter nSize angeben. ' Einzelnen Eintrag im Abschnitt "Start" lesen Dim myIniFile As String Dim sValue As String Dim lResult As Long myIniFile = App.Path & "\" & App.EXEName & ".ini" ' Rückgabewert mit ausreichend Leerzeichen füllen sValue = Space$(255) lResult = GetPrivateProfileString("Start", "Tagestipp", _ "ja", sValue, Len(sValue), myIniFile) ' tatsächliche Länge des Rückgabewertes sValue = Left$(sValue, lResult) Eine kleine Hilfsfunktion ' Eintrag aus INI-Datei lesen Public Function GetIniString(ByVal Sektion As String, _ ByVal Titel As String, ByVal Vorgabe As String, _ ByVal INIFile As String, _ Optional ByVal nSize As Integer = 256) As String Dim lResult As Long Dim sValue As String sValue = Space$(nSize) lResult = GetPrivateProfileString(Sektion, Titel, _ Vorgabe, sValue, nSize, INIFile) GetIniString = Left$(sValue, lResult) End Function Um nun den Eintrag "Tagestipp" im Abschnitt "Start" auszulesen, verwenden Sie also zukünftig einfach folgenden Funktionsaufruf: ' Einzelnen Eintrag im Abschnitt "Start" lesen Dim sValue As String sValue = GetIniString("Start", "Tagestipp", ja, myIniFile) Die Funktion GetPrivateProfileString lässt sich aber auch dazu verwenden, um:
Analog zur WritePrivateProfileString-Funktion müssen Sie hierfür die Konstante vbNullString als Parameter einsetzen: ' Alle Schlüsselnamen im Abschnitts "Start" ermitteln Dim sKeyNames As String sKeyNames = GetIniString("Start", vbNullString, "", _ myIniFile, 32767) ' oder: alle vorhandenen Abschnittsnamen ermitteln Dim sSectionNames As String sSectionNames = GetIniString(vbNullString, "", "", _ myIniFile, 32767) Als Rückgabe erhalten Sie die Bezeichnungen aller Schlüssel bzw. Abschnitte - getrennt durch ein vbNullChar-Zeichen. Um die einzelnen Bezeichner nun z.B. in einer ListBox anzuzeigen, verwenden Sie einfach die Split-Funktion (erst ab VB6 verfügbar!): ' Alle Abschnittsnamen ermitteln und in ' einer Listbox anzeigen Dim sSections as String Dim Section() As String Dim I As Integer ' Rückgabe-String vorbereiten sSections = Space$(32767) ' vbNullString übergeben, um alle gespeicherten ' Abschnittsnamen zu ermitteln lResult = GetIniString(vbNullString, "", "", _ sSections, myIniFile, Len(sSections)) ' Sind überhaupt Abschnitte vorhanden? If sSections <> "" Then ' Rückgabestring "splitten" Section = Split(sSections, vbNullChar) ' Alle Abschnitt der ListBox hinzufügen With List1 For I = 0 To UBound(Section) - 1 .AddItem Section(I) Next I End With End If Projekt: Ein INIFile-Editor Mit den in den vorigen Abschnitten besprochenen und vorgestellten Code-Routinen soll nun ein kleiner INI-Editor erstellt werden. Die Aufgabe des INI-Editors soll es sein, den Inhalt einer beliebigen INI-Datei übersichtlich in einem Formular (Fenster) anzuzeigen. Hierbei sollen alle vorhandenen Abschnittsnamen in einer ListBox erscheinen. Beim Auswählen eines Abschnittes sollen dann alle in diesem Abschnitt gespeicherten Schlüsselnamen und deren Werte in einer weiteren (rechts daneben befindlichen) Liste dargestellt werden. Das ist aber noch nicht alles - denn dann wäre es ja nur eine Art "Viewer". Zusätzlich soll die Möglichkeit bestehen, neue Abschnitte zu erstellen bzw. einzelne Abschnitte per Knopfdruck zu löschen. Ebenfalls stellen wir die Anforderung, dass sich einem Abschnitt ein neuer Eintrag hinzufügen, bearbeiten oder löschen lässt. Auf eine Suchroutine soll erst einmal verzichtet werden. Das hört sich jetzt nach ganz schön viel Arbeit an - meinen Sie nicht auch? Das Modul basINI.bas Option Explicit ' zunächst die benötigten API-Deklarationen (INI) Public Declare Function WritePrivateProfileString Lib "kernel32" _ Alias "WritePrivateProfileStringA" ( _ ByVal lpApplicationName As String, _ ByVal lpKeyName As Any, _ ByVal lpString As Any, _ ByVal lpFileName As String) As Long Public Declare Function GetPrivateProfileString Lib "kernel32" _ Alias "GetPrivateProfileStringA" ( _ ByVal lpApplicationName As String, _ ByVal lpKeyName As Any, _ ByVal lpDefault As String, _ ByVal lpReturnedString As String, _ ByVal nSize As Long, _ ByVal lpFileName As String) As Long ' Eintrag aus INI-Datei lesen Public Function GetIniString(ByVal Sektion As String, _ ByVal Titel As String, ByVal Vorgabe As String, _ ByVal INIFile As String, _ Optional ByVal nSize As Integer = 256) As String Dim lResult As Long Dim sValue As String sValue = Space$(nSize) lResult = GetPrivateProfileString(Sektion, Titel, _ Vorgabe, sValue, nSize, INIFile) GetIniString = Left$(sValue, lResult) End Function Vorbereitung: Das Formular-Layout
Die Optik könnte dann der des Registrier-Datenbank-Editors ähneln (RegEdit). Und was verwendet "RegEdit" für die Anzeige der Schlüsselnamen und deren Werte? Genau! Nicht die Standard-ListBox, sondern ein ListView-Control, da man hier Spalten definieren kann - und wir brauchen schliesslich ebenfalls zwei Spalten: Eine für den Schlüsselnamen und eine weitere (rechts daneben) für den jeweiligen Wert. Also erstellen Sie ein Formular und plazieren die benötigten Steuerelemente darauf. Das sollte dann in etwa so aussehen: Und hier die Eigenschaften der Steuerelemente
cmdOpen (CommandButton)
lstSections (ListBox)
lvwKeys (ListView)
Unterhalb der linken ListBox plaziern Sie dann die beiden Schaltflächen cmdSectionsAdd und cmdSectionsDelete. Unterhalb des ListView-Controls fügen Sie weitere drei Schaltflächen ein: cmdEdit, cmdAdd und cmdDelete. INI-Datei auswählen und Inhalt anzeigen 1. Auswahl der INI-Datei per CommonDialog-Control Private Sub cmdOpen_Click() ' INI-Datei auswählen On Local Error Resume Next With CommonDialog1 .CancelError = True .Filter = "INI-Datei (*.ini)|*.ini" .ShowOpen If Err = 0 Then txtINIFile.Text = .FileName INIFile = .FileName ' INI-Datei auslesen und anzeigen Init_Sections INIFile End If End With End Sub Der ausgewählte Dateiname wird - falls der Dialog nicht abgebrochen wurde - in der TextBox txtINIFile angezeigt. Gleichzeitig speichern wir den Dateinamen zusätzlich in der Form-Globalen Variable INIFile. 2. Alle Abschnittsnamen auslesen und in der linken ListBox anzeigen ' INI-Datei auslesen (alle Abschnitte ermitteln und ' in "lstSections" anzeigen) Private Sub Init_Sections(ByVal INIFile As String) Dim strSections As String Dim Section() As String Dim I As Integer ' ListBoxen löschen lstSections.Clear lvwKeys.ListItems.Clear ' vbNullString übergeben, um alle gespeicherten ' Abschnittsnamen zu ermitteln strSections = GetIniString(vbNullString, "", "", _ INIFile, 32767) ' Sind überhaupt Abschnitte vorhanden? strSections = Left$(strSections, lResult) If strSections <> "" Then ' Rückgabestring "splitten" Section = Split(strSections, Chr$(0)) ' Alle Abschnitt der ListBox hinzufügen With lstSections For I = 0 To UBound(Section) - 1 .AddItem Section(I) Next I ' Ersten Eintrag markieren ' (und autom. die gespeicherten Keys anzeigen) ' (wird in lstSections_Click erledigt) If .ListCount > 0 Then .ListIndex = 0 .Enabled = True End With End If End Sub 3. Alle Einträge des selektierten Abschnittes im ListView-Control anzeigen ' Abschnitt ausgewählt, d.h. jetzt alle Einträge des ' Abschnittes in der zweiten ListBox anzeigen Private Sub lstSections_Click() With lstSections ' Ist überhaupt ein Eintrag ausgewählt? If .ListIndex > -1 Then Init_Keys .List(.ListIndex), INIFile End If End With End Sub ' Alle Schlüsselwörter eines Abschnittes auslesen ' und in der zweiten ListBox anzeigen Private Sub Init_Keys(ByVal strSection As String, _ ByVal INIFile As String) Dim strKeys As String Dim Key() As String Dim I As Integer Dim itemX As ListItem ' ListView löschen lvwKeys.ListItems.Clear ' vbNullString übergeben, um alle gespeicherten ' Keys zu ermitteln strKeys = GetIniString(strSection, vbNullString, _ "", INIFile, 32767) ' Sind überhaupt Einträge vorhanden? If strKeys <> "" Then ' Rückgabestring "splitten" Key = Split(strKeys, Chr$(0)) ' Alle Einträge der ListBox hinzufügen With lvwKeys.ListItems For I = 0 To UBound(Key) - 1 Set itemX = .Add(, , Key(I)) itemX.SubItems(1) = GetIniString(strSection, _ Key(I), "", INIFile) Next I End With With lvwKeys ' Ersten Eintrag markieren If .ListItems.Count > 0 Then Set .SelectedItem = .ListItems(1) End If .Enabled = True End With End If End Sub Abschnitte und Einträge bearbeiten Der bisherige Code funktioniert bereits. Starten Sie das Projekt und probieren Sie es einmal aus. In der linken ListBox werden alle Abschnittsnamen der ausgewählten INI-Datei angezeigt, wohingegen die rechte Liste alle Einträge des ausgewählten Abschnittes enthält (Schlüsselnamen und Werte). Was jetzt noch fehlt, sind die Bearbeitungsfunktionen! 4. Neuen Abschnitt hinzufügen ' Neuen Abschnitt erstellen Private Sub cmdSectionAdd_Click() Dim strSection As String ' Frage nach Bezeichnung strSection = InputBox("Bezeichnung des neuen Abschnittes:", _ "Neuer Abschnitt", "") If strSection <> "" Then ' Prüfen, ob Abschnitt bereits existiert If IsInListe(lstSections, strSection) >= 0 Then MsgBox "Dieser Abschnitt existiert bereits!", 64 Else ' Abschnitt hinzufügen With lstSections .AddItem strSection .ListIndex = IsInListe(lstSections, strSection) End With End If End If End Sub 5. Abschnitt mit allen zugehörigen Einträgen löschen ' Gesamten INI-Abschnitt löschen Private Sub cmdSectionDelete_Click() Dim strSection As String Dim iIndex As Integer If MsgBox("Markierten Abschnitt wirklich löschen?", _ vbYesNo, "Löschen") = vbYes Then ' Das Löschen erfolgt durch Übergabe von ' vbNullString im Paramater "lpKeyName" With lstSections iIndex = .ListIndex strSection = .List(iIndex) WritePrivateProfileString strSection, vbNullString, _ "", INIFile ' Abschnitt aus der Listbox entfernen .RemoveItem iIndex ' Nachfolgenden Abschnitt markieren If iIndex > .ListCount - 1 Then _ iIndex = .ListCount - 1 .ListIndex = iIndex End With End If End Sub Nach dem Löschen des Abschnittes aus der INI-Datei wird der entsprechende Eintrag auch aus der ListBox entfernt und der nachfolgende Eintrag (sollte es noch einen geben) automatisch selektiert. 6. Einzelnen Eintrag bearbeiten Und hier der gesamte Code für das Eingabeformular Option Explicit Private Sub cmdCancel_Click() ' Abbrechen Me.Tag = False Me.Hide End Sub Private Sub cmdOK_Click() ' OK Me.Tag = True Me.Hide End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) ' Schließen If UnloadMode <> 1 Then Cancel = True cmdCancel.Value = True End If End Sub Private Sub Form_Unload(Cancel As Integer) Set frmKey = Nothing End Sub Private Sub txtKey_Change() ' Prüfen cmdOK.Enabled = (Trim$(txtKey.Text) <> "") End Sub Über die Tag-Eigenschaft der Form merken wir uns, ob auf OK oder auf Abbrechen bzw. auf das Schliessen-Symbol der Form geklickt wurde. In der Prozedur cmdEdit_Click im Hauptformular benötigen wir folgenden Code: ' Schlüssel / Wert bearbeiten Private Sub cmdEdit_Click() Dim strSection As String Dim itemX As ListItem ' Zunächst benötigte Infos ermitteln Set itemX = lvwKeys.SelectedItem ' Form laden Load frmKey With frmKey ' bisherige Daten im Formular anzeigen .txtKey.Text = itemX.Text .txtValue.Text = itemX.SubItems(1) ' Form anzeigen .Show 1 If .Tag = True Then ' Geänderten Eintrag speichern strSection = lstSections.List(lstSections.ListIndex) ' Was hat sich geändert? If Trim$(.txtKey.Text) <> itemX.Text Then ' Schlüsselnamen hat sich geändert ' also alten Schüssel zunächst löschen WritePrivateProfileString strSection, _ itemX.Text, vbNullString, INIFile End If ' Neuen Schlüssel/Wert speichern WritePrivateProfileString strSection, _ Trim$(.txtKey.Text), .txtValue.Text, INIFile ' ListView aktualisieren itemX.Text = Trim$(.txtKey.Text) itemX.SubItems(1) = .txtValue End If End With Unload frmKey End Sub 7. Neuen Eintrag hinzufügen ' Neuen Schlüssel hinzufügen Private Sub cmdNew_Click() Dim strSection As String Dim itemX As ListItem ' Form anzeigen Load frmKey With frmKey .Show 1 If .Tag = True Then ' Neuen Eintrag speichern strSection = lstSections.List(lstSections.ListIndex) WritePrivateProfileString strSection, _ Trim$(.txtKey.Text), .txtValue.Text, INIFile ' ListView aktualisieren Set itemX = lvwKeys.ListItems.Add(, , _ Trim$(.txtKey.Text)) itemX.SubItems(1) = .txtValue ' Eintrag suchen und markieren Set lvwKeys.SelectedItem = itemX End If End With Unload frmKey End Sub 8. Eintrag löschen ' Schlüssel löschen Private Sub cmdDelete_Click() Dim lIndex As Long Dim strSection As String If MsgBox("Schlüssel wirklich löschen?", _ vbYesNo, "Löschen") = vbYes Then strSection = lstSections.List(lstSections.ListIndex) With lvwKeys lIndex = .SelectedItem.Index ' Eintrag wird per vbNullString im Parameter ' "sText" gelöscht WritePrivateProfileString strSection, _ .SelectedItem.Text, vbNullString, INIFile ' Eintrag aus dem ListView entfernen .ListItems.Remove lIndex ' Nächsten Eintrag selektieren If lIndex > .ListItems.Count Then _ lIndex = .ListItems.Count If lIndex > 0 Then _ Set .SelectedItem = .ListItems(lIndex) End With End If End Sub Im Code-Abschnitt, bei dem innerhalb der ListBox nach einem bereits existierenden Eintrag gesucht wird, wird auf die Funktion IsInListe verwiesen. Hierbei handelt es sich um keine VB-Standardfunktion, vielmehr erfolgt die Suche anhand der schnellen Windows-API Funktion. Fügen Sie demnach noch nachfolgenden Codeabschnitt im Allgemein Teil der Form ein: ' Schnelle Suche innerhalb einer ListBox Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" ( _ ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ ByVal lParam As String) As Long Private Const LB_FINDSTRING = &H18F Und nun noch die Funktion IsInListe: ' Prüft, ob ein Wert in einer ListBox enthalten ist ' und gibt als Ergebnis den ListIndex zurück ' (-1, wenn nicht vorhanden) Public Function IsInListe(Liste As ListBox, _ ByVal Item As String) As Integer IsInListe = SendMessage(Liste.hwnd, _ LB_FINDSTRING, -1, Item) End Function Das Projekt ist fertig Mit relativ wenig Aufwand haben wir jetzt einen vollvertigen INIFile-Editor erstellt. Mit diesem kleinen Programm können Sie von nun an Ihre INI-Dateien komfortabel erstellen und bearbeiten. Lediglich eine Suchfunktion fehlt noch - dann wäre der INIFile-Editor absolut perfekt Vielleicht haben Sie ja Lust, das Projekt um eine solche Suchfunktion zu erweitern? infovbarchiv.de Dieser Workshop wurde bereits 124.451 mal aufgerufen.
Anzeige
Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
sevISDN 1.0 Überwachung aller eingehender Anrufe! Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Tipp des Monats November 2024 Dieter Otter WAVE-Dateien aufnehmen Ein Code-Ausschnitt, mit dem sich WAVE-Dateien in verschiedenen Aufnahmequalitäten aufnehmen lassen. sevZIP40 Pro DLL Zippen und Unzippen wie die Profis! Mit nur wenigen Zeilen Code statten Sie Ihre Anwendungen ab sofort mit schnellen Zip- und Unzip-Funktionen aus. Hierbei lassen sich entweder einzelnen Dateien oder auch gesamte Ordner zippen bzw. entpacken. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |