You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
484 lines
19 KiB
484 lines
19 KiB
Attribute VB_Name = "Utility"
|
|
Option Explicit
|
|
|
|
' Registry access API
|
|
Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
|
|
Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As Long, ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) As Long
|
|
Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpData As Any, ByVal cbData As Long) As Long
|
|
Declare Function RegQueryInfoKey Lib "advapi32.dll" Alias "RegQueryInfoKeyA" (ByVal hKey As Long, ByVal lpClass As String, lpcbClass As Long, ByVal lpReserved As Long, lpcSubKeys As Long, lpcbMaxSubKeyLen As Long, lpcbMaxClassLen As Long, lpcValues As Long, lpcbMaxValueNameLen As Long, lpcbMaxValueLen As Long, lpcbSecurityDescriptor As Long, ByVal lpftLastWriteTime As Long) As Long
|
|
Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long
|
|
Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long, ByVal samDesired As Long, ByVal lpSecurityAttributes As Long, phkResult As Long, lpdwDisposition As Long) As Long
|
|
Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hKey As Long, ByVal lpSubKey As String) As Long
|
|
Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
|
|
|
|
Declare Function GetTempPath Lib "Kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
|
|
Declare Function GetTempFileNameAPI Lib "Kernel32" Alias "GetTempFileNameA" (ByVal lpszPath As String, ByVal lpPrefixString As String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long
|
|
Public Const MAX_PATH = 260
|
|
|
|
' Registry constants
|
|
Public Const ERROR_SUCCESS = 0
|
|
Public Const HKEY_CURRENT_USER = &H80000001
|
|
Public Const HKEY_LOCAL_MACHINE = &H80000002
|
|
Public Const REG_OPTION_NON_VOLATILE = 0
|
|
Public Const KEY_ALL_ACCESS = &HF003F ' ((STANDARD_RIGHTS_ALL Or KEY_QUERY_VALUE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY Or KEY_CREATE_LINK) And (Not SYNCHRONIZE))
|
|
Public Const REG_SZ = 1
|
|
|
|
Public Function AddItemToList(ctrControl As Control, ByVal sItem As String) As Boolean
|
|
' Adds an item to the control's list if it is not a duplicate
|
|
' Returns true if the item was added
|
|
Dim i As Integer
|
|
Dim bAddItem As Boolean
|
|
|
|
sItem = Trim(sItem)
|
|
With ctrControl
|
|
bAddItem = True
|
|
For i = 0 To .ListCount - 1
|
|
If StrComp(sItem, .List(i), vbTextCompare) = 0 Then
|
|
bAddItem = False
|
|
Exit For
|
|
End If
|
|
Next
|
|
If bAddItem Then
|
|
.AddItem sItem
|
|
End If
|
|
AddItemToList = bAddItem
|
|
End With
|
|
End Function
|
|
|
|
Sub AlignTextToBottom(ctlControl As Control, sText As String)
|
|
' Sets the default property of the specified control to the specified text such that the text is aligned to
|
|
' to the bottom of the control. Wordwrap must be set to True.
|
|
' Currently, only Label controls are supported.
|
|
Debug.Assert TypeName(ctlControl) = "Label"
|
|
Dim iMaxLines As Integer ' The max number of lines the control can handle
|
|
Dim iNumLines As Integer ' The number of lines in the current message
|
|
With ctlControl
|
|
iMaxLines = Int(.Height / .Parent.TextHeight("A"))
|
|
iNumLines = Int(.Parent.TextWidth(sText) / .Width) + 1 ' Leave an additional line for wordwrap overflow
|
|
If iNumLines < iMaxLines Then
|
|
ctlControl = String(iMaxLines - iNumLines, vbCrLf) & sText ' Pad with blank lines
|
|
Else
|
|
ctlControl = sText
|
|
End If
|
|
.Refresh
|
|
End With
|
|
End Sub
|
|
|
|
Sub LoadResStrings(frm As Form)
|
|
On Error Resume Next
|
|
|
|
Dim ctl As Control
|
|
Dim Obj As Object
|
|
Dim iResID As Integer, i As Integer
|
|
|
|
'set the form's caption
|
|
If IsNumeric(frm.Tag) Then
|
|
frm.Caption = LoadResString(CInt(frm.Tag))
|
|
End If
|
|
|
|
'set the controls' captions using the caption
|
|
'property for menu items and the Tag property
|
|
'for all other controls
|
|
For Each ctl In frm.Controls
|
|
Err.Clear
|
|
Select Case TypeName(ctl)
|
|
Case "Menu":
|
|
iResID = CInt(Left$(ctl.Caption, 5)) ' Upto first 5 characters for res id, pad with spaces
|
|
If Err = 0 Then
|
|
ctl.Caption = LoadResString(iResID)
|
|
End If
|
|
Case "SSTab":
|
|
For i = 0 To ctl.Tabs - 1
|
|
iResID = CInt(Left$(ctl.TabCaption(i), 5)) ' Upto first 5 characters for res id, pad with spaces
|
|
If Err = 0 Then
|
|
ctl.TabCaption(i) = LoadResString(iResID)
|
|
End If
|
|
Next
|
|
Case "TabStrip":
|
|
For Each Obj In ctl.Tabs
|
|
Err.Clear
|
|
If IsNumeric(Obj.Tag) Then
|
|
Obj.Caption = LoadResString(CInt(Obj.Tag))
|
|
End If
|
|
'check for a tooltip
|
|
If IsNumeric(Obj.ToolTipText) Then
|
|
If Err = 0 Then
|
|
Obj.ToolTipText = LoadResString(CInt(Obj.ToolTipText))
|
|
End If
|
|
End If
|
|
Next
|
|
Case "Toolbar":
|
|
For Each Obj In ctl.Buttons
|
|
Err.Clear
|
|
If IsNumeric(Obj.Tag) Then
|
|
Obj.ToolTipText = LoadResString(CInt(Obj.Tag))
|
|
End If
|
|
Next
|
|
Case "ListView":
|
|
For Each Obj In ctl.ColumnHeaders
|
|
Err.Clear
|
|
If IsNumeric(Obj.Tag) Then
|
|
Obj.Text = LoadResString(CInt(Obj.Tag))
|
|
End If
|
|
Next
|
|
Case Else
|
|
If IsNumeric(ctl.Tag) Then
|
|
If Err = 0 Then
|
|
ctl.Caption = LoadResString(CInt(ctl.Tag))
|
|
End If
|
|
End If
|
|
'check for a tooltip
|
|
If IsNumeric(ctl.ToolTipText) Then
|
|
If Err = 0 Then
|
|
ctl.ToolTipText = LoadResString(CInt(ctl.ToolTipText))
|
|
End If
|
|
End If
|
|
End Select
|
|
Next
|
|
End Sub
|
|
|
|
Public Function RegKeyExists(hRootKey As Long, sKey As String) As Boolean
|
|
' Returns True if the specified key exists under the specified root key, else returns False
|
|
Dim hKey As Long
|
|
If RegOpenKeyEx(hRootKey, sKey, 0, KEY_ALL_ACCESS, hKey) = ERROR_SUCCESS Then
|
|
RegCloseKey hKey
|
|
RegKeyExists = True
|
|
Else
|
|
RegKeyExists = False
|
|
End If
|
|
End Function
|
|
|
|
Public Function SaveRegSetting(strMainKey As String, strSubKey As String, strValueName As String, _
|
|
strValue As String) As Boolean
|
|
' Saves the specified value in the registry under the key composed of the specified key and subkey.
|
|
' Only string values supported for now.
|
|
' Returns true if successful
|
|
Dim hKey As Long, cbData As Long
|
|
Dim strKey As String
|
|
|
|
On Error GoTo SaveRegSettingError
|
|
|
|
If strSubKey = "" Then
|
|
strKey = strMainKey
|
|
Else
|
|
strKey = strMainKey & "\" & strSubKey
|
|
End If
|
|
If (RegCreateKeyEx(HKEY_LOCAL_MACHINE, strKey, 0, vbNullString, _
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, hKey, 0)) = ERROR_SUCCESS Then
|
|
cbData = LenB(StrConv(strValue, vbFromUnicode))
|
|
If RegSetValueEx(hKey, strValueName, 0, REG_SZ, ByVal strValue, cbData) <> ERROR_SUCCESS Then
|
|
RegCloseKey hKey
|
|
Err.Raise E_UNEXPECTED
|
|
End If
|
|
RegCloseKey hKey
|
|
SaveRegSetting = True
|
|
Else
|
|
Err.Raise E_UNEXPECTED
|
|
End If
|
|
|
|
SaveRegSettingResume:
|
|
Exit Function
|
|
|
|
SaveRegSettingError:
|
|
SaveRegSetting = False
|
|
Resume SaveRegSettingResume
|
|
End Function
|
|
|
|
Public Sub SelectListItem(ctlList As Control, strValue As String)
|
|
' Selects the item that matches strValue in ctlList (ListBox or Combo)
|
|
|
|
Dim i As Integer, iNewIndex As Integer
|
|
|
|
Debug.Assert TypeName(ctlList) = "ComboBox" Or TypeName(ctlList) = "ListBox"
|
|
|
|
With ctlList
|
|
iNewIndex = -1
|
|
For i = 0 To .ListCount - 1
|
|
If .List(i) = strValue Then iNewIndex = i
|
|
Next
|
|
.ListIndex = iNewIndex
|
|
End With
|
|
End Sub
|
|
|
|
Public Function GetRegSetting(strMainKey As String, strSubKey As String, strValueName As String, _
|
|
Optional strDefault As String = "", Optional hRootKey As Long = HKEY_LOCAL_MACHINE) As String
|
|
' Gets the specified value from the registry key composed of the specified key and subkey.
|
|
' Only string values supported for now.
|
|
Dim hKey As Long, cbData As Long, lType As Long
|
|
Dim strKey As String, strData As String * glMAX_NAME_LENGTH
|
|
|
|
If strSubKey = "" Then
|
|
strKey = strMainKey
|
|
Else
|
|
strKey = strMainKey & "\" & strSubKey
|
|
End If
|
|
|
|
If RegOpenKeyEx(hRootKey, strKey, 0, KEY_ALL_ACCESS, hKey) = ERROR_SUCCESS Then
|
|
cbData = LenB(StrConv(strData, vbFromUnicode))
|
|
Dim lReserved As Long
|
|
If RegQueryValueEx(hKey, strValueName, 0, lType, ByVal strData, cbData) = ERROR_SUCCESS Then
|
|
GetRegSetting = TruncateAtNull(strData)
|
|
Else
|
|
GetRegSetting = strDefault
|
|
End If
|
|
RegCloseKey hKey
|
|
Else
|
|
GetRegSetting = strDefault
|
|
End If
|
|
End Function
|
|
|
|
Public Function GetTempDir() As String
|
|
' Returns the temp directory path
|
|
Dim TmpDirLen As Long
|
|
Dim TmpDir As String
|
|
Dim TmpDirLenActual As Long
|
|
|
|
TmpDirLen = GetTempPath(0, TmpDir) ' Get the length needed for the temp directory
|
|
TmpDir = Space(TmpDirLen) ' Create enough space for it then get it
|
|
TmpDirLenActual = GetTempPath(TmpDirLen, TmpDir)
|
|
' Strip off any extra stuff
|
|
If TmpDirLen > TmpDirLenActual Then
|
|
GetTempDir = Left(TmpDir, TmpDirLenActual)
|
|
Else
|
|
GetTempDir = App.Path & "\" ' This code should never get executed - but, just in case
|
|
End If
|
|
End Function
|
|
|
|
Public Function GetTempFileName() As String
|
|
' Returns a unique filename.
|
|
Dim sTempDir As String, sFileName As String
|
|
|
|
sTempDir = GetTempDir
|
|
sFileName = Space$(MAX_PATH)
|
|
If GetTempFileNameAPI(sTempDir, "ape", 0, sFileName) <> 0 Then
|
|
GetTempFileName = TruncateAtNull(sFileName)
|
|
Else
|
|
GetTempFileName = ""
|
|
End If
|
|
End Function
|
|
|
|
Function Substitute(sString As String, sFind As String, sReplace As String) As String
|
|
' Substitutes string sReplace in place of string sFind in sString
|
|
Dim lStart As Long, lEnd As Long, lFindLength As Long
|
|
Dim sNewString As String
|
|
|
|
sNewString = ""
|
|
lFindLength = Len(sFind)
|
|
lStart = 1
|
|
lEnd = InStr(lStart, sString, sFind)
|
|
Do While lEnd > 0
|
|
sNewString = sNewString & Mid(sString, lStart, lEnd - lStart) & sReplace
|
|
lStart = lEnd + lFindLength
|
|
lEnd = InStr(lStart, sString, sFind)
|
|
Loop
|
|
Substitute = sNewString & Mid(sString, lStart)
|
|
End Function
|
|
|
|
Public Function RemoveAmpersands(strString As String) As String
|
|
' Removes the ampersands in the specified string.
|
|
RemoveAmpersands = Substitute(strString, "&", "")
|
|
End Function
|
|
|
|
Public Function DSNExists(sDSN As String) As Boolean
|
|
' Returns True if the specified DSN exists, else returns False.
|
|
If sDSN = "" Then
|
|
DSNExists = False
|
|
Else
|
|
DSNExists = RegKeyExists(HKEY_CURRENT_USER, gsODBC_INI_REG_KEY & "\" & sDSN)
|
|
End If
|
|
End Function
|
|
|
|
Public Function GetDSNValue(sDSN As String, sValueName As String) As String
|
|
' Returns the specified value (sValueName) of the specified DSN (sDSN)
|
|
GetDSNValue = GetRegSetting(gsODBC_INI_REG_KEY, sDSN, sValueName, "", HKEY_CURRENT_USER)
|
|
End Function
|
|
|
|
Public Function GetAllRegSettings(strMainKey As String, strSubKey As String) As Variant
|
|
' Returns an array of all values under the registry key composed of the specified key and subkey.
|
|
' Only string values supported for now.
|
|
Dim hKey As Long, cbData As Long, cbValueName As Long, lType As Long
|
|
Dim strKey As String, strData As String * giMAX_REG_DATA_LENGTH, strValueName As String * glMAX_NAME_LENGTH
|
|
Dim aValues() As String
|
|
|
|
If strSubKey = "" Then
|
|
strKey = strMainKey
|
|
Else
|
|
strKey = strMainKey & "\" & strSubKey
|
|
End If
|
|
If (RegCreateKeyEx(HKEY_LOCAL_MACHINE, strKey, 0, vbNullString, _
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, hKey, 0)) = ERROR_SUCCESS Then
|
|
' Iterate over all the values in this key
|
|
Dim strClass As String * glMAX_NAME_LENGTH
|
|
Dim cbClass As Long, cSubKeys As Long, cbMaxSubKeyLen As Long, cbMaxClassLen As Long, lReserved As Long
|
|
Dim cValues As Long, cbMaxValueNameLen As Long, cbMaxValueLen As Long, cbSecurityDescriptor As Long
|
|
|
|
cbClass = LenB(StrConv(strClass, vbFromUnicode))
|
|
If RegQueryInfoKey(hKey, strClass, cbClass, lReserved, cSubKeys, cbMaxSubKeyLen, cbMaxClassLen, cValues, cbMaxValueNameLen, _
|
|
cbMaxValueLen, cbSecurityDescriptor, 0) = ERROR_SUCCESS Then
|
|
If cValues > 0 Then
|
|
ReDim aValues(0 To cValues - 1, 0 To 1)
|
|
Dim i As Long
|
|
For i = 0 To cValues - 1
|
|
cbValueName = LenB(StrConv(strValueName, vbFromUnicode))
|
|
cbData = LenB(StrConv(strData, vbFromUnicode))
|
|
If RegEnumValue(hKey, i, strValueName, cbValueName, 0, lType, strData, cbData) = ERROR_SUCCESS Then
|
|
aValues(i, 0) = TruncateAtNull(strValueName)
|
|
aValues(i, 1) = TruncateAtNull(strData)
|
|
End If
|
|
Next
|
|
GetAllRegSettings = aValues
|
|
End If
|
|
End If
|
|
RegCloseKey hKey
|
|
End If
|
|
End Function
|
|
|
|
Public Function DeleteRegSettings(strMainKey As String, strSubKey As String) As Boolean
|
|
' Deletes the specified key and all its sub keys
|
|
' Returns true is successful
|
|
Dim strKey As String
|
|
|
|
If strSubKey = "" Then
|
|
strKey = strMainKey
|
|
Else
|
|
strKey = strMainKey & "\" & strSubKey
|
|
End If
|
|
DeleteRegSettings = (RegDeleteKey(HKEY_LOCAL_MACHINE, strKey) = ERROR_SUCCESS)
|
|
End Function
|
|
|
|
Public Function Min(a, b)
|
|
If a < b Then
|
|
Min = a
|
|
Else
|
|
Min = b
|
|
End If
|
|
End Function
|
|
|
|
Public Function Max(a, b)
|
|
If b > a Then
|
|
Max = b
|
|
Else
|
|
Max = a
|
|
End If
|
|
End Function
|
|
|
|
Public Function TruncateAtNull(ByVal strText As String) As String
|
|
' Returns the specified string truncated at the first null character
|
|
Dim lLen As Long
|
|
|
|
lLen = InStr(strText, Chr(0))
|
|
If lLen < 1 Then
|
|
TruncateAtNull = strText
|
|
Else
|
|
TruncateAtNull = Left(strText, lLen - 1)
|
|
End If
|
|
End Function
|
|
|
|
Public Function TruncateFile(sFileName As String, dSize As Double)
|
|
' Truncates the specified file to lSize bytes. Truncation occurs at the beginning of the file.
|
|
Const CHUNK_SIZE = 65535 ' Size of chunk for copying file contents
|
|
|
|
Dim dOverflow As Double
|
|
dOverflow = CDbl(FileLen(sFileName)) - dSize
|
|
If dOverflow > 0 Then
|
|
Dim sTempFile As String, baChunk(CHUNK_SIZE) As Byte
|
|
Dim lFileNum As Long, lTempFileNum As Long
|
|
sTempFile = GetTempFileName
|
|
lFileNum = FreeFile
|
|
Open sFileName For Binary Access Read As lFileNum
|
|
lTempFileNum = FreeFile
|
|
Open sTempFile For Binary Access Write As lTempFileNum
|
|
Seek lFileNum, dOverflow + 1
|
|
' Start copying file from first complete line - fill the very first (incomplete) line with "." characters.
|
|
Get lFileNum, , baChunk
|
|
Dim l As Long
|
|
For l = LBound(baChunk) To UBound(baChunk)
|
|
If baChunk(l) <> 13 Then ' = vbCr
|
|
baChunk(l) = 46 ' = Asc(".")
|
|
Else
|
|
Put lTempFileNum, , baChunk
|
|
Exit For
|
|
End If
|
|
Next
|
|
Do While Not EOF(lFileNum)
|
|
Get lFileNum, , baChunk
|
|
Put lTempFileNum, , baChunk
|
|
Loop
|
|
Close lFileNum
|
|
Close lTempFileNum
|
|
FileCopy sTempFile, sFileName
|
|
Kill sTempFile
|
|
End If
|
|
End Function
|
|
|
|
Public Function StripPath(strFileName As String, Optional bStripExtension As Boolean = False) As String
|
|
' Strips the path off the specified fully qualified filename. If bStripExtension is True, the file extension is stripped as well.
|
|
Dim iStart As Integer, iNext As Integer, iActualStart As Integer
|
|
|
|
' First, find the beginning of the actual filename
|
|
iStart = 0
|
|
Do
|
|
iNext = InStr(iStart + 1, strFileName, "\")
|
|
If iNext = 0 Then
|
|
Exit Do
|
|
End If
|
|
iStart = iNext
|
|
Loop
|
|
iActualStart = iStart + 1 ' Point to beginning of actual filename
|
|
' Next, find the beginning of the extension (which immediately follows the last period in the filename)
|
|
If bStripExtension Then
|
|
Do
|
|
iNext = InStr(iStart + 1, strFileName, ".")
|
|
If iNext = 0 Then
|
|
Exit Do
|
|
End If
|
|
iStart = iNext
|
|
Loop
|
|
End If
|
|
If iStart = iActualStart - 1 Then ' If no extension
|
|
StripPath = Mid(strFileName, iActualStart)
|
|
Else
|
|
StripPath = Mid(strFileName, iActualStart, iStart - iActualStart)
|
|
End If
|
|
End Function
|
|
|
|
Public Sub SizeToFit(ctl As Control)
|
|
' Resizes the control to fit the displayed text
|
|
With ctl
|
|
Select Case TypeName(ctl)
|
|
Case "CheckBox", "OptionButton"
|
|
.Width = .Parent.TextWidth(.Caption) + .Height ' Compensate for non-text area
|
|
Case Else
|
|
Debug.Assert False
|
|
End Select
|
|
End With
|
|
End Sub
|
|
|
|
Public Function SubstituteParams(bstrString As String, ParamArray aParams()) As String
|
|
' Substitutes the parameters in the paramarray for placeholders in the string. The placeholders are of the format
|
|
' '%n' where 'n' represents the index of the parameter in the paramarray.
|
|
' A maximum of 10 parameters (0 - 9) are supported.
|
|
|
|
Dim iStart As Integer, iPtr As Integer, iParamNum As Integer
|
|
Dim cChar As String * 1
|
|
Dim bstrReturn As String
|
|
|
|
iStart = 1
|
|
iPtr = InStr(bstrString, "%")
|
|
Do While iPtr > 0 And iPtr < Len(bstrString)
|
|
bstrReturn = bstrReturn & Mid$(bstrString, iStart, iPtr - iStart)
|
|
cChar = Mid(bstrString, iPtr + 1, 1)
|
|
If IsNumeric(cChar) Then
|
|
iParamNum = Val(cChar)
|
|
If iParamNum <= UBound(aParams) Then
|
|
bstrReturn = bstrReturn & aParams(iParamNum)
|
|
End If
|
|
End If
|
|
iStart = iPtr + 2
|
|
iPtr = InStr(iStart, bstrString, "%")
|
|
Loop
|
|
SubstituteParams = bstrReturn & Mid(bstrString, iStart)
|
|
End Function
|
|
|
|
|