Registry
  1. Registry-- Accessing it, and using it instead of WIN.INI
  2. How to get a registered OCX?
  3. Win95 installation directory.
  4. How to get time zone info (DST) from registry?
  5. TStringList in TIniFile
  6. Store Fontstyle in INI
  7. How to find the program associated with one file extension
  8. Font & Tregistry

Registry-- Accessing it, and using it instead of WIN.INI

From: "Mark Goodrich" <mgood@ns.net>


uses
   Registry, Windows;

var
   TheReg: TRegistry;
   KeyName: String;
   ValueStr: String;

begin
   TheReg := TRegistry.Create;
   try
      TheReg.RootKey := HKEY_CURRENT_USER;
      KeyName := 'Software\MyTinyApp\StartUp;
      if TheReg.OpenKey(KeyName, False) then
      begin
         ValueStr := TheReg.ReadString('WorkPath');
         TheReg.CloseKey;
      end;
   finally
      TheReg.Free;
   end;
end;

Also note, the correct place to store the path to your application's EXE under the Win95 registry is in:


HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\AppPaths\MYAPP.EXE

Store the complete path to your app as the default value under that key.

Regstr.pas defines a constant for this path up through ...\App Paths\ as REGSTR_PATH_APPPATHS.

Storing the path to your application's EXE here will allow a user to simply type MYAPP (or whatever its name is) in Start|Run on the taskbar and your application will launch. Here's an example of how to create it:


uses
   Registry, Regstr;

var
   TheReg: TRegistry;
   KeyName: String;

begin
   TheReg := TRegistry.Create;
   try
      {Check AppPath setting, update if necessary}
      TheReg.RootKey := HKEY_LOCAL_MACHINE;
      KeyName := REGSTR_PATH_APPPATHS + ExtractFileName(Application.ExeName);
      if TheReg.OpenKey(KeyName, True) then
      begin
         if CompareText(TheReg.ReadString(''), Application.ExeName) <> 0 then
            TheReg.WriteString('', Application.ExeName);
         TheReg.CloseKey;
      end;
   finally
      TheReg.Free;
   end;
end;

How to get a registered OCX?

You are right: before an OCX can be used, it must be registered with the System Registry.

Suppose the OCX you want to use is called "test.ocx".

Try this code:


var
  OCXHand: THandle;
  RegFunc: TDllRegisterServer;   //add OLECtl to the uses clause
begin
  OCXHand:= LoadLibrary('c:\windows\system\test.ocx');
  RegFunc:= GetProcAddress(OCXHand, 'DllRegisterServer');  //case
sensitive?
  if RegFunc <> 0 then ShowMessage('Error!');
  FreeLibrary(OCXHand);
end;

You can the same way unregister the OCX: all you have to do is to replace 'DllRegisterServer' by 'DllUnregisterServer'.

You should add some validation code: "Does the file exist", "Was the call to LoadLibrary successful?", ...

Some explanations:

An OCX is a special form of dll, so you can load it in memory with a call to the LoadLibrary() API function. An OCX exports two functions to register and unregister the control. You then use GetProcAddress to obtain the address of these functions. You just have then to call the appropriate function. And that's it! You can explore the Registry (with regedit.exe) to verify that the OCX is registered.

Win95 installation directory.

From: "None of your Business" <someone@someplace.org>


function FindWindowsDir : string;
var
pWindowsDir : array [0..255] of Char;
sWindowsDir : string;
begin
// GetWindowsDirectory(LPTSTR,UINT);
// LPTSTR  lpBuffer,    // address of buffer for Windows directory
// UINT  uSize          // size of directory buffer
   GetWindowsDirectory (pWindowsDir, 255);
    sWindowsDir := StrPas (pWindowsDir);
    Result := sWindowsDir ;
end;

How to get time zone info (DST) from registry?

From: rds@melbpc.org.au (Robert Small)

>
>HKEYLocal Machine/Software/Microsoft/Windows/CurrentVersion/TimeZones/
>
>is the place where Timezone infos are stored in the registry. The
>binary 'TZI' entry should be the info for start and end times of
>daylight saving times. Anyone has an idea how to extract the dates
>from this value?
>

The TZI entry seems to be structured as follows:


int32 Bias;             // Minutes from GMT
                        // (Sydney -600; 0xfffffda8;
                        // or a8, fd, ff, ff)
int32 StandardBias;     // Bias for Standard time (0)
int32 DaylightBias;     // Bias for Daylight time (-60
                        // or 0xffffffc4 )
int16 ??                          // 0
int16 StandardStartMonth;         // 3 => March
int16 StandardStartDayOfWeek??;   // 0 => Sun
int16 StandardStartDOWoccurrence; // 1 => 1st
int16 StandardStartHour;          // 2 => 02:00:00.00
int16 StandardStartMins??;        // 0 => 02:00:00.00
int16 StandardStartSecs??;        // 0 => 02:00:00.00
int16 StandardStartHunds??;       // 0 => 02:00:00.00
int16 ??                          // 0
int16 DaylightStartMonth;         // 0x0a (10) => October
int16 DaylightStartDayOfWeek??;   // 0 => Sun
int16 DaylightStartDOWoccurrence; // 5 => last
int16 DaylightStartHour;          // 2 => 02:00:00.00
int16 DaylightStartMins??;        // 0 => 02:00:00.00
int16 DaylightStartSecs??;        // 0 => 02:00:00.00
int16 DaylightStartHunds??;       // 0 => 02:00:00.00

TStringList in TIniFile

From: Vito Palmisano <vi.palmisano@area.ba.cnr.it>

From "Visual Developer Journal" June/July 1996 page 108, unit IniStr written by Ed Jordan:


unit IniStr;
{Written by Ed Jordan}
interface

uses Classes;

type
TIniStringlist = class( TStringList )
public
  procedure LoadFromIni( const FileName, Section: string);
  procedure SaveToIni( const FileName, Section: string);
end;

implementation

uses IniFiles, SysUtils;

procedure TIniStringList.LoadFromIni( const FileName,Section: string);
var
  Index: Integer;
  Line: string;
begin
  with TIniFile.Create( FileName ) do
  try
    ReadSectionValues( Section, Self);
    for Index:= 0 to Count - 1 do
    begin
      { Remove the identifier name ...}
      Line:= Values[ IntToStr( Index ) ];
      { Delete the tilde ... }
      System.Delete( Line, 1, 1);
      Strings[ Index ]:= Line;
    end;
  finally
    Free;
  end;
end;

procedure TIniStringList.SaveToIni( const FileName, Section: string);
var
  Index: Integer;
  Line: string;
begin
  with TIniFile.Create( FileName ) do
  try
    EraseSection( Section );
    for Index:= 0 to Count - 1 do
    begin
      { Preserve leading white space, blank lines ...}
      Line:= '~' + Strings[ Index ];
      WriteString( Section, IntToStr( Index ), Line);
    end;
  finally
    Free;
  end;
end;

end.


Usage:

var
  L: TIniStringList;
begin
  L:= TIniStringList.Create;
  L.LoadFromIni('MyFile.Ini', 'Alati');
  {process L..}
  L.Free;
end.

Store Fontstyle in INI

From: jxidus@aol.com (JXidus)

My solution: (to store the entire font, actually)


function FontToStr(font: TFont): string;
procedure yes(var str:string);
begin
     str := str + 'y';
end;
procedure no(var str:string);
begin
     str := str + 'n';
end;
begin
     {encode all attributes of a TFont into a string}
     Result := '';
     Result := Result + IntToStr(font.Color) + '|';
     Result := Result + IntToStr(font.Height) + '|';
     Result := Result + font.Name + '|';
     Result := Result + IntToStr(Ord(font.Pitch)) + '|';
     Result := Result + IntToStr(font.PixelsPerInch) + '|';
     Result := Result + IntToStr(font.size) + '|';
     if fsBold in font.style then yes(Result) else no(Result);
     if fsItalic in font.style then yes(Result) else no(Result);
     if fsUnderline in font.style then yes(Result) else no(Result);
     if fsStrikeout in font.style then yes(Result) else no(Result);
end;

procedure StrToFont(str: string; font: TFont);
begin
     if str = '' then Exit;
     font.Color := StrToInt(tok('|', str));
     font.Height := StrToInt(tok('|', str));
     font.Name := tok('|', str);
     font.Pitch := TFontPitch(StrToInt(tok('|', str)));
     font.PixelsPerInch := StrToInt(tok('|', str));
     font.Size := StrToInt(tok('|', str));
     font.Style := [];
     if str[0] = 'y' then font.Style := font.Style + [fsBold];
     if str[1] = 'y' then font.Style := font.Style + [fsItalic];
     if str[2] = 'y' then font.Style := font.Style + [fsUnderline];
     if str[3] = 'y' then font.Style := font.Style + [fsStrikeout];
end;

function tok(sep: string; var s: string): string;
     function isoneof(c, s: string): Boolean;
     var
        iTmp: integer;
     begin
          Result := False;
          for iTmp := 1 to Length(s) do
          begin
              if c = Copy(s, iTmp, 1) then
              begin
                   Result := True;
                   Exit;
              end;
          end;
     end;
var
   c, t: string;
begin
     if s = '' then
     begin
          Result := s;
          Exit;
     end;
     c := Copy(s, 1, 1);
     while isoneof(c, sep) do
     begin
          s := Copy(s, 2, Length(s) - 1);
          c := Copy(s, 1, 1);
     end;
     t := '';
     while (not isoneof(c, sep)) and (s <> '') do
     begin
          t := t + c;
          s := Copy(s, 2, length(s)-1);
          c := Copy(s, 1, 1);
     end;
     Result := t;
end;

Note that you can keep stuff like this really handy by creating your own subclass of the TIniFile class, and adding routines like this.

How to find the program associated with one file extension

From: Stefan.Hoffmeister@Uni-Passau.De (Stefan Hoffmeister)

>I will like to know how to find the program (exe) associated with
>one file extension from register (not win.ini).

 const
      BufferSize = {$IFDEF Win32} 540 {$ELSE} 80 {$ENDIF};
  var
      Buffer : PChar;
      StringPosition : PChar;
      ReturnedData: Longint;
begin
  Buffer := StrAlloc(BufferSize);
  try
    { get the first entry, don't bother about the version !}
    ReturnedData := BufferSize;
    StrPCopy(Buffer, '.xls');
    RegQueryValue(hKey_Classes_Root, Buffer, Buffer, ReturnedData);
    if StrLen(Buffer) > 0 then
    begin

Font & Tregistry

From: nojunkmail@tempest-sw.com (Ray Lischner) On 28 Mar 1997 05:57:38 GMT, "Alex" wrote:
does anybody know a way to save a total Font setting of a
form/panel/listbox etc. etc. to the registry, it's not so dificult doing it
line by line, but with the FontStyle it becomes a lot of lines, so is there
and easy/shorter way ?
Secrets of Delphi 2 has some code that recursively saves any object's published properties to the registry. The example specifically shows how it works for TFont.


uses TypInfo;

{ Define a set type for accessing an integer's bits. }
const
  BitsPerByte = 8;
type
  TIntegerSet = set of 0..SizeOf(Integer)*BitsPerByte - 1;

{ Save a set property as a subkey. Each element of the enumerated type
  is a separate Boolean value. True means the item is in the set, and
  False means the item is excluded from the set. This lets the user
  modify the configuration easily, with REGEDIT. }
procedure SaveSetToRegistry(const Name: string; Value: Integer;
   TypeInfo: PTypeInfo; Reg: TRegistry);
var
  OldKey: string;
  I: Integer;
begin
  TypeInfo := GetTypeData(TypeInfo)^.CompType;
  OldKey := '\' + Reg.CurrentPath;
  if not Reg.OpenKey(Name, True) then
    raise ERegistryException.CreateFmt('Cannot create key: %s',
[Name]);

  { Loop over all the items in the enumerated type. }
  with GetTypeData(TypeInfo)^ do
    for I := MinValue to MaxValue do
      { Write a Boolean value for each set element. }
      Reg.WriteBool(GetEnumName(TypeInfo, I), I in
TIntegerSet(Value));

  { Return to the parent key. }
  Reg.OpenKey(OldKey, False);
end;

{ Save an object to the registry by saving it as a subkey. }
procedure SaveObjToRegistry(const Name: string; Obj: TPersistent;
   Reg: TRegistry);
var
  OldKey: string;
begin
  OldKey := '\' + Reg.CurrentPath;
  { Open a subkey for the object. }
  if not Reg.OpenKey(Name, True) then
    raise ERegistryException.CreateFmt('Cannot create key: %s',
[Name]);

  { Save the object's properties. }
  SaveToRegistry(Obj, Reg);

  { Return to the parent key. }
  Reg.OpenKey(OldKey, False);
end;

{ Save a method to the registry by saving its name. }
procedure SaveMethodToRegistry(const Name: string; const Method:
TMethod;
   Reg: TRegistry);
var
  MethodName: string;
begin
  { If the method pointer is nil, then store an empty string. }
  if Method.Code = nil then
    MethodName := ''
  else
    { Look up the method name. }
    MethodName := TObject(Method.Data).MethodName(Method.Code);
  Reg.WriteString(Name, MethodName);
end;

{ Save a single property to the registry, as a value of the current
key. }
procedure SavePropToRegistry(Obj: TPersistent; PropInfo: PPropInfo;
Reg: TRegistry);
begin
  with PropInfo^ do
    case PropType^.Kind of
    tkInteger,
    tkChar,
    tkWChar:
      { Store ordinal properties as integer. }
      Reg.WriteInteger(Name, GetOrdProp(Obj, PropInfo));
    tkEnumeration:
      { Store enumerated values by name. }
      Reg.WriteString(Name, GetEnumName(PropType, GetOrdProp(Obj,
PropInfo)));
    tkFloat:
      { Store floating point values as Doubles. }
      Reg.WriteFloat(Name, GetFloatProp(Obj, PropInfo));
    tkString,
    tkLString:
      { Store strings as strings. }
      Reg.WriteString(Name, GetStrProp(Obj, PropInfo));
    tkVariant:
      { Store variant values as strings. }
      Reg.WriteString(Name, GetVariantProp(Obj, PropInfo));      
    tkSet:
      { Store a set as a subkey. }
      SaveSetToRegistry(Name, GetOrdProp(Obj, PropInfo), PropType,
Reg);
    tkClass:
      { Store a class as a subkey, with its properties as values
        of the subkey. }
      SaveObjToRegistry(Name, TPersistent(GetOrdProp(Obj, PropInfo)),
Reg);
    tkMethod:
      { Save a method by name. }
      SaveMethodToRegistry(Name, GetMethodProp(Obj, PropInfo), Reg);
    end;
end;

{ Save an object to the registry by storing its published properties.
}
procedure SaveToRegistry(Obj: TPersistent; Reg: TRegistry);
var
  PropList: PPropList;
  PropCount: Integer;
  I: Integer;
begin
  { Get the list of published properties. }
  PropCount := GetTypeData(Obj.ClassInfo)^.PropCount;
  GetMem(PropList, PropCount*SizeOf(PPropInfo));
  try
    GetPropInfos(Obj.ClassInfo, PropList);
    { Store each property as a value of the current key. }
    for I := 0 to PropCount-1 do
      SavePropToRegistry(Obj, PropList^[I], Reg);
  finally
    FreeMem(PropList, PropCount*SizeOf(PPropInfo));
  end;
end;

{ Save the published properties as values of the given key.
  The key is relative to HKEY_CURRENT_USER. }
procedure SaveToKey(Obj: TPersistent; const KeyPath: string);
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
    if not Reg.OpenKey(KeyPath, True) then
      raise ERegistryException.CreateFmt('Cannot create key: %s',
[KeyPath]);
    SaveToRegistry(Obj, Reg);
  finally
    Reg.Free;
  end;
end;


Please email me and tell me if you liked this page.