中国程序员联盟 正在重新改版中ing 不便之处还请见谅 改版后将内容涉及java delphi .net php
 
  首页 | 数据库开发 | 网络通讯 | 多线程 | 多媒体开发 | 图像处理 | 程序人生 | 系统函数 | 控件开发 | Web服务
 
  当前位置:笨鱼delphi技术网>数据库开发>开发应用>文章内容

delphi 使用注册表

来源:国外 关于:bill 发布时间:2007-06-23   [收藏] [推荐]

The Registry is a database used to store settings and options for the 32 bit versions of Microsoft Windows; including Windows 95, 98 and NT. It contains information and settings for hardware, software, users, and preferences of the PC. Whenever a user makes changes to a Control Panel settings, or File Associations, System Policies, or installed software, the changes are reflected and stored in the Registry. In short, the registry is a shared resource to all programs running under Windows and NT.

Where is the Registry found?

The physical files that make up the registry are stored differently depending on your version of Windows; under Windows 95 & 98 it is contained in two hidden files in your Windows directory, called USER.DAT and SYSTEM.DAT, while under Windows NT the files are contained seperately in the "Windows / System32 / Config" directory.

What's the structure of the Registry?

As stated in Delphi's online help for TRegistry,

The registry is a database that an applications can use to store and retrieve configuration information. Configuration information is stored in a hierarchical tree. Each node in the tree is called a key. Every key can contain subkeys and data values that represent part of the configuration information for an application.

The Registry has a hierarchical structure. Although it looks complicated the structure is similar to the directory structure on your hard disk, with Regedit being similar to Windows Explorer. Each main branch (denoted by a folder icon in the Registry Editor, see below) is called a Hive, and Hives contains Keys. Each key can contain other keys (sometimes referred to as sub-keys), as well as Values. The values contain the actual information stored in the Registry. There are three types of values; String, Binary (similar to a Pascal record), and DWORD (Delphi specifies them as an integer) - the use of these depends upon the context.

There are six main branches, each containing a specific portion of the information stored in the Registry. They are as follows:

  • HKEY_CLASSES_ROOT : This branch contains all of your file association types, OLE information and shortcut data.
  • HKEY_CURRENT_USER : This branch links to the section of HKEY_USERS appropriate for the user currently logged onto the PC.
  • HKEY_LOCAL_MACHINE : This branch contains computer specific information about the type of hardware, software, and other preferences on a given PC, this information is used for all users who log onto this computer.
  • HKEY_USERS : This branch contains individual preferences for each user of the computer, each user is represented by a SID sub-key located under the main branch.
  • HKEY_CURRENT_CONFIG : This branch links to the section of HKEY_LOCAL_MACHINE appropriate for the current hardware configuration.
  • HKEY_DYN_DATA : This branch points to the part of HKEY_LOCAL_MACHINE, for use with the Plug-&-Play features of Windows, this section is dymanic and will change as devices are added and removed from the system.

Using the Registry

Not only can Windows itself read and write information to the registry, but so can you through your Delphi application. Many programmers will write information to the registry during the installation process of their application. When their application is running they retrieve the information using various methods of TRegistry. You are not limited to simply reading static information in the registry, but can write, edit, modify and delete information from the registry.

Caveat :: Just about every minute that your computer is running, something is being read from or written to the registry. It is not very obvious this is going on. To see what is going on, there is a tool called RegMon. It is a freeware utility which can be downloaded from

www.sysinternals.com

The RegMon tool can be of great service to you in learning what goes on behind the what you see. For instance, let's look to see what activity goes on by simply pressing the Windows Start button:

As you can see, Windows need to get information even for this simple operation. Once you have found something interesting simply double click on the line item to open up RegEdit. Remember that once RegEdit is open to be careful not to change something you don't know what that item does. Another nice tool to own is from Norton Utilities, it is called Registry Editor. One of the nice features is, bookmarks. To locate a key or value in RegEdit each time you fire it up you must search for it, or traverse the registry. In Norton's Registry Editor you can bookmark an item, then use the bookmark window to instantly go to that item.

To Access the Registry in Delphi

  1. Add registry to the uses clause of the unit you are going to open the registry with.
  2. In the routine which will open the registry declare a variable of type TRegistry.

    Example:

      Reg: TRegistry;
    

  3. Use the Create method to instantiate a TRegistry object.

    Example

      Reg := TRegistry.Create ;
    

    For Delphi 5 the Create method has been overloaded:

      constructor Create(AAccess:LongWord); overload;
    

    AAccess sets the value of the Access property (new) which is used to specify the desired access whenever a key is opened. An example:

      Reg.Create(KEY_ALL_ACCESS);
    

  4. Next we must tell our object which branch of the registry to work with:

      Reg.RootKey := HKEY_LOCAL_MACHINE;
    

    By default the rootkey is HKEY_CURRENT_USER, so if this is the branch you intend to work with there is no need to set the rootkey.

  5. Now you can use OpenKey to open up the desired key.
  6. Finally use the Read and Write methods to read and write information from and to the Registry.

Access Level in TRegistry

Delphi 5 introduced a new property for TRegistry which allows you to set the access level to use when opening a key:

property Access: LongWord;

Description

Use Access to specify the level of security access to use when opening keys.
The OpenKey method uses the value of Access when opening a registry key. Access is initialized by the TRegistry constructor, but can be altered before calling OpenKey.

The value of Access is a set of flags or抎 together, where each flag indicates a type of permission. Choose a value that grants sufficient permission to allow the desired actions while not exceeding the access level of the system running the application. The following table lists the flags that can be included:

Flag Meaning
KEY_ALL_ACCESS combination of KEY_READ, KEY_WRITE, and KEY_CREATE_LINK.
KEY_READ combination of KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY.
KEY_WRITE combination of KEY_SET_VALUE and KEY_CREATE_SUB_KEY.
KEY_QUERY_VALUE grants permission to query subkey data.
KEY_ENUMERATE_SUB_KEYS grants permission to enumerate subkeys.
KEY_NOTIFY grants ability to receive change notifications.
KEY_SET_VALUE grants permission to set subkey data.
KEY_CREATE_SUB_KEY grants permission to create subkeys.
KEY_CREATE_LINK grants permission to create symbolic links.
KEY_EXECUTE restricts permission to read-only access.

Note: Access is ignored by the CreateKey method, which always uses KEY_ALL_ACCESS.

Uses for Registry Access

A good example for writing new keys and values to the registry is when your application does not use an installation program to write information to the registry.

An example for modifying information is, each time your application closes it stores various pieces of information about the applications current status (form placement, menu item configuration etc) which is used when the application fires up next time.

An example for deleting information, your application only stores information if the user customizes various parts of the application. If they press a "restore defaults" button then you delete all the custom settings.

Understanding the Registry Structure

Before you begin to actually change data in the registry you must understand the structure of the registry. Key elements of the registry are illustrated in the image below:

You can see the hierarchy of the registry. Each folder is a key within the structure of the registry. On the right hand side there are two columns, on the left (name) are keys, on the right values (data).

Suppose you want to know the color the current user has selected for ButtonFace. The first thing you will need to do is find the key in the registry which stores the colors used by the current user.

  • Your first lead is that this value is for the currently logged-in user, so begin with HKEY_CURRENT_USER.
  • Once this key is open, look for any key, which might appear to lead in the direction of a place to store colors. Well it appears that there is a key called Control Panel, hum, seems like a good candidate to me, let's open it up. Sure enough there is another key called colors. Single click on colors and we have found the key called ButtonFace.

Now, all we need to do is figure out how to open the value for the key. Our starting point is to create an object to reference the key. As with manually creating any object, a declaration is in order. Once the object has been created we can begin using it.

The key elements to accessing data are:

  • Usually before opening the key to read, you must set the root key to let the object know the major branch of the registry to open. The default is HKEY_CURRENT_USER. In our example we are using HKEY_CURRENT_USER so this step is not required.

  • next, open up the registry branch where the desired data resides in the registry. We can move directly to opening the desired key - ControlPanel\Colors. The OpenKey method of TRegistry accomplishes this.

    Note that the method OpenKey returns a Boolean indicating whether the key was opened. The second argument is a Boolean, if set to True, will create the key if it does not exist. If you set it to False and the key does not exist, OpenKey returns a value of False, indicating that the key could not be opened. If this key does not exist, we can not continue.

  • Assuming OpenKey returned True, next we open the key called ButtonFace and retrieve its value, using the ReadString method (or another 'Read' method, if the return type is not string).

    procedure TForm1.ButtonDemoClick(Sender: TObject);
    const
      BaseKey = 'Control Panel\Colors' ;
      TheKey = 'ButtonFace' ; 
    var
      Reg: TRegistry ; 
    
    begin
      { We create a registry object used to access 
        the  value  stored in  ButtonFace  } 
      Reg := TRegistry.Create ; 
      { To ensure the object is freed the code is wrapped 
        into a Try..Finally statement } 
      try 
        with Reg do 
        begin
        { This is not needed in this example since it is the default
          RootKey is HKEY_CURRENT_USER. If you needed to change
          the RootKey, this is where to do it. }
     
          RootKey := HKEY_CURRENT_USER ;
    
        { Now we can open the "key" <Control Panel\Colors> to 
          access the "value" <ButtonFace>. You do not need to
          check if the "key" was opened, although it is wise
          to do so. }
    
          if OpenKey(BaseKey, False) then
    
         { Again it is wise to check to see if something exists
           prior to accessing it. So ValueExists checks to see
           if the "value" <ButtonFace> truly exist then reads
           the value from it. }
    
            if ValueExists(TheKey) then
              ShowMessage('ButtonFace= ' + ReadString(TheKey)) ;
        end ;
      finally
        Reg.Free ;
      end ;
    end;
    

The above example was fairly straightforward, open a key and read the data. There will be times when the information needed from the registry is not an easy path. For instance there are some values stored in the registry which can only be found by first going to one key, pick up some directions to another key which then houses the data you want. Other times there will be a need to use API calls to access sections of the registry. Let's examine both cases.

Unless you have been living on an island you have heard of Microsoft ADO. To get version information for ADO you need to dig into the Registry. Your first thought might be to search for ADO in the Registry but this will lead to several findings. First, ADO will most likely appear about 600 times, secondly you will see several version numbers if you had installed, then updated it.

So a different approach needs to be taken! To accomplish the task you need to do some research. Rather than keep you guessing I will tell you the information for locating this data is located on the home page at Microsoft for ADO/DCOM.

Here is the is the key to start off with. The root key is HKEY_CLASSES_ROOT and the sub-key is CLSID\{bdc67890-4fc0-11d0-a805-00aa006d2ea4}\InstalledVersion. Once here we then read the default value of InstalledVersion. This returns a value formatted with commas. This is the version of DCOM installed on the computer. This is a necessary component of ADO. Compare the returned value to what ADO expects to find. If the version is correct then we move to the next query (see below).

function GetDCOMVersion: String ;
const
  sSubKey = 'CLSID\{bdc67890-4fc0-11d0-a805-00aa006d2ea4}\InstalledVersion' ;
var
  Reg: TRegistry ;
begin
  if not DCOMEnabled then   begin
    Result := 'DCOM not installed' ;
  end ;
  Reg := TRegistry.Create ;
  try
    Reg.RootKey := HKEY_CLASSES_ROOT ;
    try
      if Reg.OpenKey(sSubKey,False) then
        if Reg.ValueExists('') then
          Result := Reg.ReadString('') ;
    except
      Result := 'ERROR' ;
    end ;
  finally
    Reg.Free ;
  end ;
end ; 

Now comes a "seek and find" operation. The version for ADO is stored in a DLL with a name that appears to indicate the version of ADO, it is not. Microsoft has no reasoning for this. To obtain the version we first start by reading HKEY_CLASSES_ROOT\ADODB.Connection\CLSID, read the default value for the key, remember it within a string variable so that it can be used to read yet another key:

'CLSID\' + cKey +'\InprocServer32'

In the code above cKey represents the value taken from the first key read. Now by reading the key shown above we can get the version of ADO (although the function name is MDAC_Version. At this point we have the name of the file which contains the version number. Simply take the file name and use a component which can extract the version number and we are done. The attached example contains all the code required to retrieve the version number.

Concerns using straight API routines to access the Registry

The class TRegistry can run into problems if the value it needs to read is locked by another application. This means that another program has denied access to anyone else attempting to read the information we want. A good example is, you are on a computer with a modem to connect to the internet and your browser is Microsoft Internet Explorer. IE will open up the registry and lock up a section. Using the Delphi wrapper TRegistry to read the value we need will end up with a Windows violation message and fail to open the required key.

The only way around this problem is to either write a new class or write a function which uses the same functions TRegistry does but by altering some parameters and logic. Below is an example which will properly open the key which IE might have open.

unit IE_Connected;

interface
uses
  Windows, Messages, SysUtils, Controls, Dialogs, StdCtrls, Registry;

function IsConnected: boolean ;

implementation

function IsConnected: boolean ;
const
  cMsg = 'Place your error message here ' ;  { for demoing only }
  sSubKey = 'System\CurrentControlSet\Services\RemoteAccess' ;
  sKeyValue = 'Remote Connection' ;
var
  pKey: hKey ;
  lpData,
  DataSize: Longint ;
begin
  lpData := $0 ;
  if RegOpenKeyEx(HKEY_LOCAL_MACHINE,sSubKey,0,KEY_QUERY_VALUE,pKey) = 0 then
  begin
    try
      DataSize := Sizeof(lpData);
      if RegQueryValueEx(pKey,sKeyValue,nil,nil,@lpData,@DataSize) <> 0 then
        raise Exception.Create(cMsg + #13 + SysErrorMessage(GetLastError)) ;
    finally
      RegCloseKey(pKey) ;
    end;
    if lpData > 0 then
      Result := True
    else
      Result := False ;
  end 
  else
    raise Exception.Create(cMsg + #13 + SysErrorMessage(GetLastError)) ;
  end ;
end.

How to read information from the registry

There are nine different types of data which you can read from the Registry. Each is shown below along with the method used to read the specific data.

Type Description
Binary

Returns data similar to an Object Pascal record type.

Use ReadBinaryData method to read data

Boolean

Returns data resembling Logical type i.e. True or False

Use ReadBool method to read data.

Note: The registry stores Boolean values as integers, Delphi transposes them to Boolean type for you.

Currency

Returns the value of a key as currency. If the key being read is not the proper type then an exception is raised.

Use ReadCurrency method to read data.

Date

Returns the date part of a TDateTime type.

Use ReadDate method read data.

Note: Many data types can be checked using TRegistry.GetDataType, but not with dates. As stated in Delphi's online help, only using the method ReadDate when you have written a value to a key with WriteDate method.

DateTime

Returns a TDateTime value from a specific key in the registry.

Use ReadDateTime to read data.

Float

Returns a number with the format 00.00

Use ReadFloat to read data.

Integer

Returns a number with no fractional part.

Use ReadInteger to read data.

String

Returns a string.

Use ReadString to read data.

Time

Returns the time portion of a TDateTime type.

Use ReadTime to read data.

Note: Many data types can be checked using TRegistry.GetDataType, but not with dates/times. As stated in Delphi's online help, only use the method ReadDate when you have written a value to a key with WriteTime method.

Simple demo of reading a string from the registry

Reading a string from a key. The key, which the following code reads, is for finding out the keyboard speed and delay factor.

Create a new form, add registry to the uses clause. Next place a button and a ListBox on the form. Double click the button and place the following code into it.

procedure TForm1.Button1Click(Sender: TObject);
var
  Reg: TRegistry ;
begin
  Reg := TRegistry.Create ;
  try
    Reg.RootKey := HKEY_CURRENT_USER ;
    if Reg.OpenKey('Control Panel\Keyboard', False) then
    begin
      ListBox1.Items.add(Reg.ReadString('KeyboardDelay')) ;
      ListBox1.Items.add(Reg.ReadString('KeyboardSpeed')) ;
    end ;
  finally
    Reg.Free ;
  end ;
end;

The first statement creates a local instance of a TRegistry object. The remaining statements are enclosed with in an exception block to ensure that the object is destroyed and the reference to the registry is closed. To tell the object were to read from we use the property RootKey to point to HKEY_CURRENT_USER (you can also read from HKEY_CLASSES_ROOT, HKEY_CURRENT_CONFIG, HKEY_DYN_DATA, HKEY_LOCAL_MACHINE and HKEY_USERS). Next using the method OpenKey we pass in the branch of HKEY_CURRENT_USER to read from. An if statement is used to determine if the key was opened or not. The second argument to OpenKey determines if the key is to be created if not located. Once the key has been opened the method ReadString is used to read the entries of two values from the keys we have indicated to read. If either of the keys was not located then nothing is returned. One failure does not mean a valid call to ReadString will fail.

Caveat: Delphi supplies (not in the standard version) a file called RegStr which is filled with constants for many known pieces of information and paths into the registry. You should take time to examine the file's content.

Example

Reading the current color scheme for the current user

The following example requires a new form, and command button. It will retrieve the colors for the current user. Enter the code and run the project.

Partial image of the end result

procedure TForm1.Button3Click(Sender: TObject);
procedure ShowColors(cCaption, Value: String; TheTop: Integer) ;
  var
  L: TLabel ;
  P: TPanel ;
  x: Integer ;
  R: Integer ;
  G: Integer ;
  B: Integer ;
  S: String ;
  begin
    S := Value ;
    { Create labels for each system color }
    l := TLabel.Create(Self);
    l.Name := 'Label' + IntToStr(TheTop) ;
    l.Caption := cCaption ;
    l.Parent := Self;
    l.Top := TheTop ;
    l.Left := 10 ;
    l.Visible := True ;
    { Create a panel to show the color for corresponding
      label above }
    P := TPanel.Create(Self) ;
    P.Name := 'Panel' + IntToStr(TheTop) ;
    P.Visible := False ;
    P.Caption := '' ;
    P.Parent := Self ;
    { Convert string RGB to individual integers for
      showing color below }
    x := Pos(#32,S) ;
    R := StrToInt(Copy(S,1,x -1)) ;
    Delete(S,1, x) ;
    x := Pos(#32,S) ;
    G := StrToInt(Copy(S,1,x -1)) ;
    Delete(S,1, x ) ;
    B := StrToInt(S) ;
    P.Color := TColor(Windows.rgb(R,G,B)) ;
    P.Top := L.Top + 1 ;
    P.Left := 150 ;
    P.Width := 11 ;
    P.Height := 11 ;
    P.Visible := True ;
  end ;
  //------------------------------------
const
  BaseKey = 'Control Panel\Colors' ;
var
  Reg: TRegistry ;
  aList: TStringList ;
  iCount: Integer ;
  iValue: Integer ;
  cValue: String ;
  iTop: Integer ;
begin
  Reg := TRegistry.Create ;
  try
    with Reg do
    begin
      RootKey := HKEY_CURRENT_USER ;
      if OpenKey(BaseKey, False) then
      begin
        aList := TStringList.Create ;
        lockWindowUpdate(handle) ;
        try
          GetValueNames(aList) ;
          iCount := aList.Count ;
          CloseKey ;
          iTop := 5 ;
          for iValue := 0 to iCount -1 do
          begin
            if OpenKey(BaseKey,False) then
              begin
                cValue := ReadString(aList.Strings[iValue]) ;
                CloseKey ;
                ShowColors(aList.Strings[iValue],cValue,iTop) ;
                { label height plus fill between next label }
                Inc(iTop, 16) ;
              end ;
          end ;
        finally
          aList.Free ;
          Sleep(1000) ;
          lockWindowUpdate(0) ;
        end ;
    end ;
  finally
    Reg.Free ;
  end ;
  Button3.Enabled := False ;
end;

Reading unknown keys in a branch

Suppose that you need to obtain some string values for a branch of the registry where you do not know how many keys there are. Building on the first example we can get the number of entries and their values. Note that an assumption that all the keys are of type string. The key to getting all the entries is a method called GetValueNames. This method will return all the keys under the branch of the registry currently open. The current branch for this example is HKEY_CURRENT_USER\ Control Panel\Keyboard.

procedure TForm1.Button1Click(Sender: TObject);
var
  Reg: TRegistry ;
  SomeValues: TStringList ;
  iCount, i: Integer ;
begin
  Reg := TRegistry.Create ;
  SomeValues := TStringList.Create ;
  try
    Reg.RootKey := HKEY_CURRENT_USER ;
    if Reg.OpenKey('Control Panel\Keyboard', False) then
    begin
      Reg.GetValueNames(SomeValues) ;
      iCount := SomeValues.Count ;
      if iCount >0 then
      for i := 0 to iCount -1 do
        Listbox1.Items.Add(SomeValues.Strings[i] + '-->' +
        Reg.ReadString(SomeValues.Strings[i])) ;
    end ;
  finally
    Reg.Free ;
    SomeValues.Free ;
  end ;
end ;

How to Enumerate an entire Branch of the registry

This example goes through the registry searching for &^quot;CurrentVersion" under the root key HKEY_CURRENT_USER. Once it finds the key it increments a counter, when completed the times which "CurrentVersion" was found is displayed. In a real life example you might need to narrow your search to a key or a value. This is a simple example.

To run this example, on a new form place a memo control and a command button.

type
  TEnumerateRegBranch = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    iRanIt:boolean ;
  public
end;
var
  EnumerateRegBranch: TEnumerateRegBranch;

implementation
{$R *.DFM}
uses registry ;
procedure TEnumerateRegBranch.Button1Click(Sender: TObject);
var
  indent: Integer;
  iMatches: Integer ;
  procedure EnumAllKeys( hkey: THandle );
  var
    l: TStringList;
    n: Integer;
  begin
    Inc(indent, 2);
    with Tregistry.Create do
    try
      RootKey := hkey;
      OpenKey( EmptyStr, false );
      l := TStringLIst.Create;
      try
        GetKeynames(l);
        CloseKey;
        for n := 0 To l.Count-1 do 
        begin
          memo1.lines.add( StringOfChar(' ',indent) +l [n]);
          try
            if CompareStr('CurrentVersion',L.Strings[n]) = 0 then
              Inc(iMatches) ;
          except
          end ;
          if OpenKey( l[n], false ) then 
          begin
            EnumAllKeys( CurrentKey );
            CloseKey;
          end;
        end;
      finally
        l.Free
      end;
    finally
      Free;
    end;
    Dec(indent, 2);
  end;
  //-----------------------------------------

begin 
  { Searches Key and Values for "CurrentVersion" while traversing. }
  Memo1.Clear;
  memo1.lines.add('Keys under HKEY_CURRENT_USER');
  indent := 0;
  Button1.Enabled := False ;
  EnumAllKEys( HKEY_CURRENT_USER );
  Button1.Enabled := True ;
  iRanIt := True ;
  if iMatches >0 then
    ShowMessage('Found ' + IntToStr(iMatches) + ' of "CurrentVersion"')
  else
    ShowMessage('Did not find CurrentVersion') ;
end ;
  //------------------------------------------

procedure TEnumerateRegBranch.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if iRanIt then
    ShowMessage('This may take a while') ;
end;

Writing data to the registry

Delphi provides all the routines which are needed to write information to the registry as shown below:

Type Description
WriteBinaryData Used to write binary data to the Registry
WriteBool Used to write Boolean data to the registry
WriteCurrency Used to write Currency data to the registry
WriteDate Used to write the date part of a TDateTime type to the registry
WriteDateTime Used to write a TDateTime type to the registry
WriteExpandString Used to store a string that contains unexpanded references to environment variables such as "%PATH%. The string is stored in a data value associated with the current key.
WriteFloat Used to store a float to the registry
WriteInteger Used to store an integer to the registry
WriteString Used to store an ordinary string to the registry
WriteTime Used to store the Time part of a TDateTime type to the registry.

Demo for writing information to the registry

The following example creates a new key under the HKEY_CURRENT_USER branch of the registry. Once created several keys and values are set. After the values are written to the registry they are read back to confirm they are indeed in the registry. Lastly all the data which was written is removed.

Create a new form, place a ListBox and a command button on the form followed by the code below.

The following code shows some simple examples of reading, writing and returning information back from the registry.

NOTE 1: Little exception handling is done since I want to keep the code clear.

NOTE 2: Since I don't have Windows-NT there is no way for me to check how to deal with NT-security.

procedure TForm1.Button1Click(Sender: TObject);
{ This record is used to demo read/write operations to
  the registry }
type
  TSomeData = record
    Top,
    Left,
    Width,
    Height:Integer ;
    Caption:String ;
end;

{ Key beneath HKEY_CURRENT_USER to work with }
const>
BaseKey = 'a_test' ;
var
  Reg: TRegistry ;
  MyCurrency: Currency ;
  FSomeData : TSomeData ;
begin
  ListBox1.Clear ;
  { Assign a value to store into the registry }
  FSomeData.Top := Top ;
  FSomeData.Left := Left ;>
  FSomeData.Width := Width ;
  FSomeData.Height := Height ;
  FSomeData.Caption := Caption ;
  MyCurrency := 1000000.90 ;
  { Create an object to access the system registry }
  Reg := TRegistry.Create ;
  try
    Reg.RootKey := HKEY_CURRENT_USER ;
    if not Reg.CreateKey(BaseKey) then
    begin
      ShowMessage('Failed to make it new entry for "' + BaseKey + '"');
      exit ;
    end ;
    Reg.OpenKey(BaseKey,False) ;
    { Write our data to the currency and binary values to the registry }
    Reg.WriteCurrency('Currency Example',MyCurrency) ;
    Reg.WriteBinaryData('BinaryData Example',FSomeData,SizeOf(TSomeData)) ;
    
    { Now read back the data for currency }
    ListBox1.Items.Add(Format('Currency Example = %m',
    [Reg.ReadCurrency('Currency Example')])) ;
    
    { Nullify the record to ensure we get back the data }
    FSomeData.Top := -1 ;
    FSomeData.Left := -1 ;
    FSomeData.Width := -1 ;
    FSomeData.Height := -1 ;
    FSomeData.Caption := '' ;
    
    { Screw a bit with the form, later we restore it with the
      registry data }
    Top := Top - 100 ;
    Left := Left - 100 ;
    Caption := 'Just demoing...' ;
    
    { Timely pause for reflection }
    Sleep(2000) ;
    
    { Okay let's get the data back }
    Reg.ReadBinaryData('BinaryData Example',
    FSomeData,SizeOf(TSomeData)) ;
    
    { Show the returned members retrieved from the registry }
    ListBox1.Items.Add('Top = ' + IntToStr(FSomeData.Top)) ;
    ListBox1.Items.Add('Left = ' + IntToStr(FSomeData.Left)) ;
    ListBox1.Items.Add('Width = ' + IntToStr(FSomeData.Width)) ;
    ListBox1.Items.Add('Height = ' + IntToStr(FSomeData.Height)) ;
    ListBox1.Items.Add('Caption = ' + FSomeData.Caption) ;
    
    { Using registry data restore the form's position }
    Top := FSomeData.Top ;
    Left := FSomeData.Left ;
    Caption := FSomeData.Caption ;
    
    { Close the current key }
    Reg.CloseKey ;
    
    { Remove it since we are done with it }
    Reg.DeleteKey(BaseKey) ;
  finally
    Reg.CloseKey ;
    Reg.Free ;
  end ;
end;

Simple demo for reading and writing to the registry

The following example shows how to save the position of a form on exit and restoring the forms position next time it is shown. Note, this is a simplified version, it was kept simple to show how to work with the registry rather then clouding the example with code, which is not really relevant to exploring the registry.

Start with a new project with one form, add the code shown below:

procedure TForm1.FormCreate(Sender: TObject);
var
  PriorState:TWindowState ;
  Reg: TRegistry ;
begin 
  { Restore form state as saved in the
  registry on closure of this form }
  Reg := TRegistry.Create ;
  try
    if Reg.OpenKey(MyBaseKey,False) then
    begin
      if Reg.OpenKey(MyAppSettings,False) then
      begin
        with Reg do
        begin
          if ValueExists('Top') and ValueExists('Left') 
          and ValueExists('Width') and ValueExists('Height') 
          and ValueExists('WindowState') then
          begin
            Self.SetBounds(ReadInteger('Left'),
            ReadInteger('Top'),
            ReadInteger('Width'),
            ReadInteger('Height')) ;
            PriorState := TWindowState( ReadInteger('WindowState') ) ;
            if PriorState = wsMinimized then
            begin
              Visible := True ;
              Application.Minimize ;
            end
            else
              WindowState := PriorState ;
          end ;
        end ;
      end 
      else
        ShowMessage('Failed to open ' + MyAppSettings) ;
    end 
    else 
      ShowMessage('Failed to open ' + MyBaseKey) ;
  finally
    Reg.Free ;
  end ;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  Reg: TRegistry ;
begin
  Reg := TRegistry.Create ;
  try
    if Reg.OpenKey(MyBaseKey,True) then
      if Reg.OpenKey(MyAppSettings,True) then
      begin
        with Reg do
        begin
          { Store the current form settings }
          WriteInteger('Top',Top) ;
          WriteInteger('Left',Left) ;
          WriteInteger('Width',Width) ;
          WriteInteger('Height',Height) ;
          WriteInteger('WindowState',Ord(WindowState)) ;
        end ;
      end ;
  finally
    Reg.Free ;
  end ;
end;

The form's Close event opens the key HKEY_CURRENT_USER\JEDI_Registry_Demo if it exists. If the key does not exist it is created. Notice that the second argument to OpenKey is set to True, if it was set to False then the call to OpenKey would fail if the key didn't exist. The first time this code runs it creates the key, if the key gets deleted then it will be recreated.

if Reg.OpenKey(MyBaseKey,True) then

The line following the above uses the exact same logic for

HKEY_CURRENT_USER\JEDI_Registry_Demo\FormSettings

since the second parameter to OpenKey is set to True.

if Reg.OpenKey(MyAppSettings,True) then

The next several lines of code check to see if values exist under

HKEY_CURRENT_USER\JEDI_Registry_Demo\FormSettings

and if not found are created. If they exist then we move on to the next several lines of code which place current form properties into the values.

Now when the form is used again, there is code in the Create event which reads back the data we stored in the Close event. Notice that the code in the Create event opens our keys using OpenKey with the second parameter set to False. This means that if the keys do not exists a message is displayed informing us of an error. If the keys do exist we then check to see if the values are found, if they are not an error message is displayed alerting you of a problem. If the values are located then they are retrieved and used to restore the forms position.

You could take the code presented here and expand upon it, or surf on over to your favorite Delphi web site and find several good components which handle positioning without any coding. The entire purpose of this example is for learning the registry, not building perfect code to position forms.

Unstable operations

LoadKey and SaveKey methods of TRegistry provide ways to save a branch of the registry to a binary disk file and later import the information back into the registry. Between trying both methods myself and doing research over the web it is my conclusion that they do not work well. Using them resulted in unusual error messages with small parts my registry locking up until I restarted my computer.

The code below shows how to mess up a computer with Load/SaveKey

Make sure to add the registry unit to the uses clause

const
  SaveRestoreKey = 'JEDIRegistryDemo' ;
  SaveRestoreFile = 'JEDI_1' ;

....
procedure TForm1.LoadMeClick(Sender: TObject);
var
  Reg: TRegistry ;
begin
  if not FileExists(SaveRestoreFile) then
  begin
    ShowMessage('Restore file (' + SaveRestoreFile + ')not found') ;
    exit ;
  end ;
  Reg := TRegistry.Create ;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.LoadKey(SaveRestoreKey, SaveRestoreFile) then
      ShowMessage('Key has been restored')
    else
      ShowMessage('Restorekey failed with the following error' + #13 +
      SysErrorMessage( GetLastError ) );
  finally
    Reg.CloseKey ;
    Reg.Free ;
  end ;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  Reg: TRegistry ;
begin
  Reg := TRegistry.Create ;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE ;
    if not Reg.KeyExists(SaveRestoreKey) then
    begin
      ShowMessage('HKEY_LOCAL_MACHINE\' + SaveRestoreKey + 'does not exist') ;
    end ;
    if Reg.SaveKey(SaveRestoreKey,SaveRestoreFile) then
    begin
      ShowMessage(SaveRestoreKey + ' was saved') ;
      Application.ProcessMessages ;
      
      {if Reg.KeyExists(SaveRestoreKey) then
        if Reg.DeleteKey(SaveRestoreKey) then
        begin
          ShowMessage(SaveRestoreKey + ' deleted') ;
          Button5.Enabled := True ;
        end 
        else
        begin
          ShowMessage('delete failed with the following error' + #13 +
          SysErrorMessage( GetLastError ) );
        end ;}
    end 
    else
      ShowMessage('SaveKey failed with the following error' + #13 +
      SysErrorMessage( GetLastError ) );
  finally
    Reg.CloseKey ;
    Reg.Free ;
  end ;
  Reg := TRegistry.Create ;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE ;
    if Reg.KeyExists('JEDIRegistryDemo') then
      if Reg.DeleteKey('JEDIRegistryDemo') then
        ListBox1.Items.Add('Worked') ;
  finally
    Reg.CloseKey ;
    Reg.Free ;
  end ;
end;

[浏览: 次]   
上一篇:delphi treeview 使用   下一篇:delphi Lessons in Good Programming
[收藏] [推荐] [返回顶部] [打印本页] [关闭窗口]  
    评论加载中…
google adsense热点文章
·delphi Delphi_三谈多态——善用virtua
·delphi 条形码处理
·delphi Delphi_三层开发基本概念介绍
·delphi 汉字转拼音码(上)
·delphi Olevariant
·delphi CS构架下的客户端自动更新程序
·delphi 在Dephi中使用TStream读写数据
·delphi 汉字转拼音码(下)
·delphi delphi处理流
·delphi 关于使用COM对象的方法
·delphi MTS组件——从理论到实践
·delphi 汉字转拼音码(中3)
     delphi技术网 | firefox 下载 | Avant Browser下载 | dedecms 技术网 | drupal 爱好者 | php 技术网
  Copyright@www.delphichm.com,2006-2009.All Rights Reserved.
 
程序员联盟 | delphi Java .net|QQ:707102932