By: Paul S. Cilwa | Viewed: 5/8/2024 Posted: 8/3/2018 |
Page Views: 663 | |
Topics: #Computers #Programming #Organica #VB.NET | |||
A derived Document class to read .INI files. |
When Windows was first introduced, in included a feature then called ".INI" files. These "initialization files" stored user preferences for an application, such as whether or not to display a menu, or what color they want borders to be. Later, the name was changed to "profiles", and then to "private profiles". Finally, the functionality was moved to the System Registry. But the underlying code to parse the values in a profile remains (albeit at an unusually low level); and the files themselves are trivial to create (via Notepad, for example). In addition, since they are associated with a folder that contains them (as Registry entries are not), they actually lend themselves to providing folder information to Organica.
In this chapter, then, we shall derive a class from last chapter's Document class, to deal with this type of file.
Format
The format of profile files is quite simple. In fact, the original design notion was that Notepad would be the creator of them! A Profile is divided into Sections; each Section contains zero or more Keys, each with a Value. Here's an example:
Example.ini
[Organica]
IconPath=[UserPhoto]
DisplayName=[UserDisplayName]
UserSince=8/21/2018
[Music]
Pathname=C:\Users\Paul\My Music
Icon=Icons\Music.png
[Pictures]
Pathname=C:\Users\Paul\My Pictures
Icon=Icons\Photos.png
[Videos]
Pathname=C:\Users\Paul\My Videos
Icon=Icons\Videos.png
ProfileDocument
Because the Profile concept is so old and has been largely replaced by Windows' Registry services, there are no VB.NET procedures to access a Profile. So, in the class definition below, we must start with the neccessary Windows API function declarations.
Documents.vb (append)
Public Class ProfileDocument
Inherits Document
Private i_Section As String
Private Declare Ansi Function GetPrivateProfileString _
Lib "kernel32.dll" Alias "GetPrivateProfileStringA" _
(ByVal AppName As String, _
ByVal KeyName As String, _
ByVal DefaultValue As String, _
ByVal Value As StringBuilder, _
ByVal Size As Integer, _
ByVal FilePath As String) As Integer
Private Declare Ansi Function GetPrivateProfileSections _
Lib "kernel32.dll" Alias "GetPrivateProfileStringA" _
(p1 As Integer,
p2 As String,
p3 As String,
Bytes As Byte(),
Size As Integer,
FilePath As String) As Integer
Private Declare Ansi Function WritePrivateProfileString _
Lib "kernel32.dll" Alias "WritePrivateProfileStringA" _
(ByVal AppName As String, _
ByVal KeyName As String, _
ByVal Value As String, _
ByVal FilePath As String) As Integer
Private Declare Ansi Function GetPrivateProfileInt _
Lib "kernel32.dll" Alias "GetPrivateProfileIntA" _
(ByVal AppName As String, _
ByVal KeyName As String, _
ByVal Value As Integer, _
ByVal FilePath As String) As Integer
Private Declare Ansi Function FlushPrivateProfileString _
Lib "kernel32.dll" Alias "WritePrivateProfileStringA" _
(ByVal AppName As Integer, _
ByVal KeyName As Integer, _
ByVal Value As Integer, _
ByVal FilePath As String) As Integer
Public Sub New(ByVal Filename As String)
MyBase.New(Filename)
i_Section = "Organica"
Visible = False
End Sub
Public ReadOnly Property FilePath() As String
Get
Return i_Pathname
End Get
End Property
Public Function GetSectionNames() As String()
Dim maxsize As Integer = 500
While True
Dim bytes As Byte() = New Byte(maxsize - 1) {}
Dim size As Integer = _
GetPrivateProfileSections(0, "", "", bytes, maxsize, i_Pathname)
If size < maxsize - 2 Then
Dim Selected As String = _
Encoding.ASCII.GetString(bytes, 0, size - (If(size > 0, 1, 0)))
Return Selected.Split(New Char() {ControlChars.NullChar})
End If
maxsize *= 2
End While
Return Nothing
End Function
Public Function GetData(ByVal Section As String, _
ByVal Key As String, Optional ByVal DefaultValue As String = "")
Dim CharCount As Integer
Dim Result As New System.Text.StringBuilder(256)
CharCount = GetPrivateProfileString(Section, Key, DefaultValue, Result, Result.Capacity, i_Pathname)
If CharCount > 0 Then
GetData = Left(Result.ToString, CharCount)
Else
GetData = DefaultValue
End If
End Function
Public Function GetData(ByVal Key As String, _
Optional ByVal DefaultValue As String = "") As String
Return GetData(i_Section, Key, DefaultValue)
End Function
Public Sub WriteData(ByVal Key As String, _
ByVal Value As String)
WritePrivateProfileString(i_Section, Key, Value, i_Pathname)
FlushPrivateProfileString(0, 0, 0, i_Pathname)
End Sub
Public Sub WriteData(ByVal Section As String, _
ByVal Key As String, ByVal Value As String)
WritePrivateProfileString(Section, Key, Value, i_Pathname)
FlushPrivateProfileString(0, 0, 0, i_Pathname)
End Sub
Public Property UserSince As Date
Get
Return GetData("Organica", "UserSince", "1/1/1000")
End Get
Set(Value As Date)
WriteData("Organica", "UserSince", Value)
End Set
End Property
Public Sub WriteLink(ByVal LinkName As String, _
ByVal Pathname As String, ByVal IconPath As String)
WriteData(LinkName, "Pathname", Pathname)
WriteData(LinkName, "Icon", IconPath)
End Sub
Public ReadOnly Property Sections As Collection
Get
Dim All As String(), One As String, Result As New Collection
All = GetSectionNames()
For Each One In All
If One.ToLower <> "organica" Then
Result.Add(One)
End If
Next
Return Result
End Get
End Property
Public ReadOnly Property LinkPathname(ByVal LinkName As String)
Get
Return GetData(LinkName, "Pathname", Nothing)
End Get
End Property
Public ReadOnly Property LinkIcon(ByVal LinkName As String)
Get
Return GetData(LinkName, "Icon", Nothing)
End Get
End Property
End Class