在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
32位Delphi程序中可利用TRegistry对象来存取注册表文件中的信息。 一、创建和释放TRegistry对象 1.创建TRegistry对象。为了操作注册表,要创建一个TRegistry对象:ARegistry := TRegistry.Create; 2.释放TRegistry对象。对注册表操作结束后,应释放TRegistry对象所占内存:ARegistry.Destroy。 二、指定要操作的键 操作注册表时,首先应指定操作的主键:先给属性RootKey赋值以指定根键,然后用方法OpenKey来指定要操作的主键名。 1.指定根键(RootKey)。 根键是注册表的入口,也注册表信息的分类,其值可为: HKEY—CLASSES—ROOT:存储整个系统对象类信息,如ActiveX对象注册、文件关联等信息。 HKEY—CURRENT—USER:存储当前用户的配置信息。为属性RootKey的默认值。 HKEY—LOCAL—MACHINE:存储当前系统的软硬件配置信息。应用程序自己的信息可以存储在该根键下。 HKEY—USERS:存储所有用户通用的配置信息。 还可以是HKEY—CURRENT—CONFIG、HKEY—DYN—DATA。 2.指定要操作的主键。 Function OpenKey(const Key: string; CanCreate: Boolean): Boolean; Key:主键名,是键名全名中除去根键的部分,如Software\Borland\Delphi。 CanCreate:在指定的主键名不存在时,是否允许创建该主键,True表示允许。 返回值True表示操作成功。 3.关闭当前主键。 在读取或存储信息之后,应及时将关闭当前主键:procedure CloseKey。 三、从注册表中读取信息 Read系列方法从注册表读取指定的信息(字符串、二进制和十六进制),并转换为指定的类型。 1.Read系列方法。 function ReadString(const Name: string): string; 读取一个字符串值,Name为字符串名称。 function ReadInteger(const Name: string): Integer; 读取一个整数值,Name为整数名称。 function ReadBinaryData(const Name: string; var Buffer; BufSize: Integer):Integer; 读取二进制值,Name为二进制值名称,Buffer为接收缓冲区,BufSize为缓冲区大小,返回为实际读取的字节数。 其它方法还有:ReadBool、ReadCurrency、ReadDate、ReadDateTime、ReadFloat、ReadTime。 2.读取信息一例(显示Windows的版本)。 在HKEY—LOCAL—MACHINE\Software\Microsoft\Windows\CurrentVersion下,有三个字符串值Version、VersionNumber和SubVersionNumber,用于记录当前Windows的版本号。 {请在Uses中包含Registry单元} procedure TForm1.Button1Click(Sender:TObject); var ARegistry : TRegistry; begin ARegistry := TRegistry.Create; //建立一个TRegistry实例 with ARegistry do begin RootKey := HKEY—LOCAL—MACHINE;//指定根键为HKEY—LOCAL—MACHINE //打开主键Software\Microsoft\Windows\CurrentVersion if OpenKey( ′Software\Microsoft\Windows\CurrentVersion′,false ) then begin memo1.lines.add('Windows版本:′+ ReadString(′Version′)); memo1.lines.add('Windows版本号:′+ ReadString(′VersionNumber′)); memo1.lines.add(′Windows子版本号:′+ ReadString(′SubVersionNumber′)); end; CloseKey;//关闭主键 Destroy;//释放内存 end; end; 四、向注册表中写入信息 Write系列方法将信息转化为指定的类型,并写入注册表。 1.Write系列方法。 procedure WriteString(const Name, Value: string); 写入一个字符串值,Name为字符串的名称,Value为字符串值。 procedure WriteInteger(const Name: string; Value: Integer); 写入一个整数值。 procedure WriteBinaryData(const Name: string; var Buffer; BufSize: Integer); 写入二进制值,Name为二进制值的名称,Buffer为包含二进制值的缓冲区,BufSize为缓冲区大小。 其它方法还有:WriteBool、WriteCurrency、WriteDate、WriteDateTime、WriteFloat、WriteTime。 2.写入信息一例。 下面程序使Delphi随Windows启动而自动运行。 var ARegistry : TRegistry; begin ARegistry := TRegistry.Create; //建立一个TRegistry实例 with ARegistry do begin RootKey:=HKEY—LOCAL—MACHINE; if OpenKey(′Software\Microsoft\Windows\CurrentVersion\Run′,True) then WriteString(′delphi′,′C:\Program Files\borland\delphi3\bin\delphi32.exe′); CloseKey; Destroy; end; end; 五、键值维护 除了在注册表中读取、存储外,程序可能还需要增加主键、删除主键、主键改名、数据值改名等。 1.创建新主键:function CreateKey(const Key: string): Boolean。 Key即为主键名,返回值True表示操作成功。 2.删除主键:function DeleteKey(const Key: string): Boolean。 Key即为主键名,返回值True表示操作成功。 3.复制或移动主键:procedure MoveKey(const OldName, NewName: string; Delete: Boolean)。 OldName、NewName分别表示源主键名和目标主键名;Delete表示是否删除源主键,True表示删除,False表示保留。 复制或移动一个主键将复制或移动该子键下的所有数据值和子键内容。 4.判断指定主键是否存在,其下是否有主键,并获取主键名称。 KeyExists用于判断指定主键是否存在: function KeyExists(const Key: string): Boolean;//返回值为True表示主键存在。 HasSubKeys用于判断指定主键下是否有子键:function HasSubKeys: Boolean; 返回值为True表示主键下有子键。 GetKeyNames用于获取子键名称:procedure GetKeyNames(Strings: TStrings); Strings用于返回当前主键下各子键的名称。 5.获取主键下的数据值名称:procedure GetValueNames(Strings: TStrings)。 Strings用于返回当前主键下各数值名称。 如要获取当前系统中的拨号连接名称,可利用获取主键HKEY—USERS \.DEFAULT\RemoteAccess\Addresses下的数值名称的方法来进行。 6.判断数值名称存在、数值名称改名。 ValueExists用于判断数值名称是否存在: function ValueExists(const Name: string): Boolean; 返回值为True表示数值名称存在。 RenameValue用于数值名称改名: procedure RenameValue(const OldName, NewName: string); 以上是注册表常用操作所对应的TRegistry的方法和属性,其它方法和属性请参见Delphi联机帮助文件。 以上程序在PWIN 98+Delphi 3.0下调试通过。 2003-11-20 11:53:00 查看评语»»» 2003-11-20 11:59:20 注册表中对编程常用的几项(ODBC/BDE/Internet/Windows) 我用的是 WINDOWS 2000, WIN2000 的 REGEDIT 提供了类似 IE 中收藏夹的功能,我的收藏夹中有几个或许对大家编程时会有帮助(这是本人在编程过程中的探索出来的,请高手指教): 1。关于 ODBC 和 DBE: HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC File DSN 有你的 COMPUTER 上 ODBC 的 FILE DSN 的存放的缺省路径,如果你建立 FILE DSN 的时候选择了自己的路径,那你就得小心了,系统不会为你保存该路径,你的自己记住它,:-(; HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers 列出了你的所有 ODBC DRIVER, 关于 ODBC DRIVER 的名称,有一个比较有趣的地方:不知大家又没有用TSession.GetDriverNames 取过系统 ODBC DRIVER 名,我用的时候 DRIVER 名最长只能取到 31 个字符,剩下的就被截掉了,不知是我编程有问题还是 DELPHI 的 BUG; HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI 列出了你的所有 ODBC DRIVER 的详细配置; HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI 列出了你的所有 SYSTEM DSN 以及它们的配置情况; HKEY_CURRENT_USER\Software\ODBC\ODBC.INI 列出了你的所有 USER DSN 以及它们的配置情况; 知道了以上的几个主键后,你就可以在程序中实现 %SystemRoot%\system32\odbcad32.exe 的大部分功能了。 HKEY_LOCAL_MACHINE\SOFTWARE\Borland\Database Engine 下面是你的 DBE 的配置,我就不多说了,大家拿它和 BDE 用户界面一比较就明白了。 2。关于 INTERNET 编程: HKEY_CLASSES_ROOT\htmlfile 系统对 HTMLFILE 的处理定义; HKEY_LOCAL_MACHINE\SOFTWARE\Clients INTERNET Option 中 INTERNET PROGRAM 的设定,尤其重要的是其中的 HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail。 3。关于 WINDOWS 编程 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run 每次该用户启动 WINDOWS 必定执行下面的命令(如果有,当然一般都有), HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Runonce 该用户启动 WINDOWS 必定执行下面的命令(如果有),执行完后由 WINDOWS 把命令删掉,安装软件的时候特别有用, 以上两处是针对特定用户的,在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion 下还有类似的地方,是针对所有用户的,我就不罗嗦了。 2003-11-20 12:16:38 Delphi 中注册表构件TRegistry 的应用 在Delphi3.0 及以上版本中,提供了一个构件TRegistry。在程序中可以利用它来实现对WIN95/98/NT 注册表的操作,可以很方便地在注册表中增加、修改和删除键值。这样可以在程序中完成一些特殊的功能。 ---- TRegistry 常用的属性和方法有(具体作用和用法请参考Delphi 帮 助): RootKey、CreateKey、OpenKey、CloseKey、DeleteKey、ReadXXXX、WriteXXXX (XXXX表示数据类型如String、Integer等) 我们用到的属性和方法有: RootKey:注册表的根键名( 如HKEY_LOCAL_MACHINE等) OpenKey( KeyName:string; CanCreate:boolean ): 使当前键为KeyName,CanCreate 表示当指定的键不存在时是否创建,True 表示创建 SetKey( KeyName,KeyValue : string ):使键KeyName的值为KeyValue ---- 应用之一:让自己的程序随WIN95/98/NT 的启动而运行 当然,你可以在"启动"程序组中加入程序的快捷方式,但这样做好象不大明智,因为大多数程序在安装时不会这样做,而是在通过在注册表增加键值,让WIN95/98/NT 在启动时运行自己的程序。如果打开注册表,找到HKEY_LOCAL_MACHINE \Software \Microsoft\Windows \CurrentVersion \Run,就会发现这个秘密了,原来许多自动运行的程序都在这里。你也可以在这里增加一个键,让你的程序也随着 WIN95/98/NT 的启动而自己运行,成为WINDOWS 下的TSR 程序。实现方法如下: 首先,在Uses 中加上Registry 单元 然后,写下面代码。 {将程序strExeFileName置为自动启动 } function StartUpMyProgram ( strPrompt,strExeFileName : string ) : boolean; var registerTemp : TRegistry; begin registerTemp := TRegistry.Create; //建立一个Registry实例 with registerTemp do begin RootKey:=HKEY_LOCAL_MACHINE; //设置根键值为HKEY_LOCAL_MACHINE //找到Software\Microsoft\Windows\CurrentVersion\Run if OpenKey('Software\Microsoft\Windows\CurrentVersion\Run',True) then //写入自己程序的快捷方式信息 begin WriteString( strPrompt, strExeFileName ); result := true; end else result := false; //善后处理 CloseKey; Free; end; end; {调用StartUpMyProgram, 使Delphi随WINDOWS启动而自动运行 } procedure TForm1.Button1Click(Sender: TObject); begin memo1.lines.add('开始'); if StartUpMyProgram('delphi','C:\Program Files\borland\delphi3\bin\delphi32.exe') then memo1.lines.add('成功') else memo1.lines.add('失败') end; ---- 应用之二:实现文件关联 当MS WORD 安装在你的系统中时,它会把.DOC 文件与自己关联,当你双击一个DOC 文件,就会启动MS WORD,打开你指定的DOC文件。你也可以把一个文件类型与一个程序关联起来,其秘密还是在注册表中。如果打开注册表,找到HKEY_CLASSES_ROOT,就会发现这里已经有很多文件类型。 你也可以在这里增加一个键,建立自己的文件关联。 建立文件关联,一般应有两个步骤: (1)根据文件类型的扩展名,指定对应的键名(如doc 文件对应的键为doc_auto_file) 该键及其子键的值,将定义该类型的文件的类型说明和操作(如打开、编辑)说明 (2)在指定的键名下,建立子键,指明文件类型说明和操作对应的程序信息 例如,我们可以为.DBF 文件建立文件关联,其文件类型说明为"xBase 数据表",使其打开(Open)文件的操作对应程序C:\ProgramFiles\Borland\DBD\DBD32.EXE。首先,应在注册表的根键HKEY_CLASSES_ROOT 下建立一个键,键名为.DBF,默认值为DBF_Auto_File,表示DBF 类型文件的关联操作信息记录在键HKEY_CLASSES_ROOT\DBF_Auto_File 下;然后,建立键 HKEY_CLASSES_ROOT\DBF_Auto_File,并设其默认值为"xBase 数据表",表示文件类型说明;再建立键HKEY_CLASSES_ROOT\DBF_Auto_File\Shell\open\command,设置其默认值为C:\Program Files\Borland\DBD\DBD32.EXE %1(其中"%1 "为命令行参数),表示打开操作对应的程序信息。 具体实现如下:同样,在Uses 中加上Registry 单元, 然后,写下面代码。 {将文件类型strFileExtension与程序 strExeFileName相关联,strDiscription为文件类型说明 } function AssignToProgram(strFileExtension,strDiscription,strExeFileName : string ) : boolean; var registerTemp : TRegistry; begin registerTemp := TRegistry.Create; //建立一个Registry实例 with registerTemp do begin RootKey:=HKEY_CLASSES_ROOT; //设置根键值为HKEY_CLASSES_ROOT //根据文件类型的扩展名,创建或打开对应的键名.FileExt,如DBF对应'.DBF' if OpenKey( '.' + strFileExtension, true ) then begin result := false; exit; end; //设置键.FileExt默认值为FileExt_Auto_File,如'.DBF'对应'DBF_Auto_File' WriteString('',strFileExtension + '_Auto_File'); CloseKey; //写入自己程序的信息 //根据文件类型的扩展名,创建或打开对应的键名 FileExt_Auto_File //'.DBF'对应'DBF_Auto_File' if OpenKey(strFileExtension + '_Auto_File', true ) then begin result := false; exit; end; //设置默认值文件类型说明,如DBF可对应'xBase数据表' WriteString('',strDiscription); CloseKey; //创建或打开键名FileExt_Auto_File\Shell\open\command,该键为表示操作为'打开' //'.DBF'对应'DBF_Auto_File\shell\open\command' if OpenKey(strFileExtension + '_Auto_File\shell\open\command', true ) then begin result := false; exit; end; //设置该键的默认值为打开操作对应的程序信息 //如DBF可对应'C:\Program Files\Borland\DBD\DBD32.EXE' WriteString('',strExeFileName + ' %1'); CloseKey; Free; end; end; {调用AssignToProgram,使DBF文件与DBD32.EXE关联 } procedure TForm1.Button3Click(Sender: TObject); begin memo1.lines.add('开始'); if AssignToProgram('DBF','xBase数据表','C:\Program Files\borland\dbd\dbd32.exe') then memo1.lines.add('成功') else memo1.lines.add('失败') end; ---- 应用之三:检测Win95/98/NT 系统中是否安装了Borland Database Engine 当你的应用程序是一个基于BDE 的数据库应用程序时,如果运行在一个没有安装BDE 的Win95/98/NT 中,会出现让用户迷惑不解的错误。你可能需要在程序正常运行之前,检查系统中是否安装了BDE。由于 BDE 安装后会在注册表进行注册,你可以通过查询注册表来确定系统中是否安装了BDE,然后决定下一步采取什么行动。BDE 在注册表中的位置为: HKEY_LOCAL_MACHINE\Software\Borland\Database Engine,该键存在说明 BDE 已经安装。 具体的例子如下。 同样,在Uses 中加上Registry 单元 然后,写下面代码。 {检测系统中是否安装了BDE } function IsBDEInstalled : boolean; var registerTemp : TRegistry; begin registerTemp := TRegistry.Create; //建立一个Registry实例 with registerTemp do begin RootKey:=HKEY_LOCAL_MACHINE; //设置根键值为HKEY_LOCAL_MACHINE //查询Software\Borland\Database Engine result := OpenKey('Software\Borland\Database Engine',false); //善后处理 CloseKey; Free; end; end; {调用IsBDEInstalled,检测系统中是否安装了BDE } procedure TForm1.Button4Click(Sender: TObject); begin memo1.lines.add('开始'); if IsBDEInstalled then memo1.lines.add('已安装了BDE') else memo1.lines.add('未安装BDE') end; ---- 应用之四:在桌面建立程序的快捷方式 当你的WIN95/98/NT 桌面上整齐地排列着各种程序的快捷方式时,也许你会体会到快捷方式的方便。你也可将自己设计的程序的快捷方式放在别人的桌面上。 桌面上的一个快捷方式,对应Windows 目录下Destop 子目录中的一个ShellLink 文件(.LNK),你只要在这个目录下增加一个.LNK 文件就可以了。 我们的任务,主要是利用TRegistry 从注册表中获取Desktop 的实际路径,默认为Windows 目录下的Desktop 子目录,如C:\PWIN98\Desktop。在注册表中Desktop 的实际路径对应的键为HKEY_CURRENT_USER \Software\MicroSoft \Windows \CurrentVersion \Explorer \Shell Folders \Desktop。 同样,在Uses 中加上Registry 单元 然后,写下面代码。 {为程序strExeFileName在桌面建立快捷方式,运行参数为strParameters } function CreateShortcutOnDesktop( strExeFileName, strParameters : string ) : boolean; var registerTemp : TRegistry; strDesktopDirectory : widestring; shelllinkTemp : IShellLink; persistfileTemp : IPersistFile; begin registerTemp := TRegistry.Create; //建立一个Registry实例 with registerTemp do begin RootKey:=HKEY_CURRENT_USER; //设置根键值为HKEY_CURRENT_USER //找到Software\MicroSoft\Windows\CurrentVersion\Explorer\Shell Folders if not OpenKey('Software\MicroSoft\Windows\CurrentVersion\Explorer\Shell Folders',True) then //写入自己程序的信息 begin result := false; exit; end; //读取项目Desktop的值,即Desktop的实际路径 strDesktopDirectory := ReadString('Desktop'); //善后处理 CloseKey; Free; end; //设置快捷方式的参数 shelllinkTemp := IShellLink( CreateComObject(CLSID_ShellLink)); with shelllinkTemp do begin SetPath( PChar( strExeFileName ) ); //设置程序文件全名 SetArguments( PChar( strParameters) ); //设置程序的命令行参数 //设置程序的工作目录 SetWorkingDirectory( Pchar( ExtractFilePath( strExeFileName ) ) ); end; //构造快捷方式的文件名(.LNK) strDesktopDirectory := strDesktopDirectory + '\' + ExtractFileName( strExeFileName ); strDesktopDirectory := copy( strDesktopDirectory, 1, length( strDesktopDirectory ) - length( ExtractFileExt( strExeFileName ) ) ) + '.LNK'; //保存快捷方式的文件 persistfileTemp := shelllinkTemp as IPersistFile; if S_OK = persistfileTemp.Save( PWChar( strDesktopDirectory ) , false ) then result := true //保存成功,返回True else result := false; end; {调用CreateShortcutOnDesktop,为Delphi在桌面上建立快捷方式 } procedure TForm1.Button2Click(Sender: TObject); begin memo1.lines.add('开始'); if CreateShortcutOnDesktop('C:\Program Files\borland\delphi3\bin\delphi32.exe','%1') then memo1.lines.add('成功') else memo1.lines.add('失败') end; 【结语】:上面几个应用只是TRegistry 一些简单的应用,有了这些知识,你就可以根据自己的需要来定制和改善Winodws 系统了。 ---- 以上程序在PWin98+Delphi3.0 下调试和通过。 2003-11-20 12:21:25 备份部分注册表的代码 Procedure ExportRegistryBranch (rootsection : Integer; regroot:String; filename:String); implementation Function dblBackSlash(t:string):string; var k:longint; begin result:=t; {Strings are not allowed to have} for k:=length(t) downto 1 do {single backslashes} if result[k]='\' then insert('\',result,k); end; Procedure ExportRegistryBranch (rootsection : Integer; regroot:String; filename:String); var reg:tregistry; f:textfile; p:PCHAR; Procedure ProcessBranch(root:string); {recursive sub-procedure} var values, keys:tstringlist; i,j,k:longint; s,t:string; {longstrings are on the heap, not on the stack!} begin writeln(f); {write blank line} case rootsection of HKEY_CLASSES_ROOT : s := 'HKEY_CLASSES_ROOT'; HKEY_CURRENT_USER : s := 'HKEY_CURRENT_USER'; HKEY_LOCAL_MACHINE : s := 'HKEY_LOCAL_MACHINE'; HKEY_USERS : s := 'HKEY_USERS'; HKEY_PERFORMANCE_DATA: s := 'HKEY_PERFORMANCE_DATA'; HKEY_CURRENT_CONFIG : s := 'HKEY_CURRENT_CONFIG'; HKEY_DYN_DATA : s := 'HKEY_DYN_DATA'; end; Writeln(f,'['+s+'\'+root+']'); {write section name in brackets} reg.OpenKey(root,false); values := tstringlist.create; keys:=tstringlist.create; reg.getvaluenames (values); {get all value names} reg.getkeynames (keys); {get all sub-branches} for i:=0 to values.count-1 do {write all the values first} begin s := values[i]; t := s; {s=value name} if s= ''then s:='@' {empty means "default value", write as @} else s:='"' + s + '"'; {else put in quotes} write(f,dblbackslash(s)+ '=' ); {write the name of the key to the file} Case reg.Getdatatype(t) of {What type of data is it?} rdString, rdExpandString: {String-type} Writeln(f,'"' + dblbackslash(reg.readstring(t) + '"')); rdInteger: {32-bit unsigned long integer} Writeln(f,'dword:' + inttohex(reg.readinteger(t),8)); { write an array of hex bytes if data is "binary." Perform a line feed after approx. 25 numbers so the line length stays within limits } rdBinary : begin write(f,'hex:'); j := reg.getdatasize(t); {determine size} getmem(p,j); {Allocate memory} reg.ReadBinaryData(t,p^,J); {read in the data, treat as pchar} for k:=0 to j-1 do begin Write(f,inttohex(byte(p[k]),2)); {Write byte as hex} if k<>j-1 then {not yet last byte?} begin write(f,','); {then write Comma} if (k>0) and ((k mod 25)=0) then {line too long?} writeln(f,'\'); {then write Backslash + lf} end; {if} end; {for} freemem(p,j); {free the memory} writeln(f); {Linefeed} end; ELSE writeln(f,'""'); {write an empty string if datatype illegal/unknown} end; {case} end; {for} reg.closekey; {value names all done, no longer needed} values.free; {Now al values are written, we process all subkeys} {Perform this process RECURSIVELY...} for i := 0 to keys.count -1 do ProcessBranch(root+'\'+keys[i]); keys.free; {this branch is ready} end; begin if regroot[length(regroot)]='\' then {No trailing backslash} setlength(regroot,length(regroot)-1); Assignfile(f,filename); {create a text file} rewrite(f); IF ioresult<>0 then EXIT; Writeln(f,'REGEDIT4'); {"magic key" for regedit} reg:=tregistry.create; try reg.rootkey:=rootsection; ProcessBranch(regroot); {Call the function that writes the branch and all subbranches} finally reg.free; {ready} close(f); end; end; end. 2003-11-20 12:22:54 读写网络上其他计算机注册表的代码 procedure NetReg; var R: TRegistry; S: TStringList; begin R:=TRegistry.Create; S:=TStringList.Create; WriteLn(R.RegistryConnect('\\OtherPC')); WriteLn(R.OpenKeyReadOnly('Software')); R.GetKeyNames(S); WriteLn(S.CommaText); S.Free; R.Free; end; 2003-11-20 12:27:06 关于查看注册表的程序 unit regform; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry; type TForm1 = class(TForm) ListSub: TListBox; ListValues: TListBox; ComboKey: TComboBox; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; ComboLast: TComboBox; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure ListSubClick(Sender: TObject); procedure ComboKeyChange(Sender: TObject); procedure ComboLastChange(Sender: TObject); private Reg: TRegistry; public procedure UpdateAll; end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin Reg := TRegistry.Create; Reg.OpenKey ('\', False); UpdateAll; // select the current root(选择当前的根目录) ComboKey.ItemIndex := 1; ComboLast.Items.Add('\'); /////// ComboLast.ItemIndex := 0; end; //更新 procedure TForm1.UpdateAll; begin Caption := Reg.CurrentPath; if Caption = ' then Caption := '[Root]'; if Reg.HasSubKeys then Reg.GetKeyNames(ListSub.Items) else ListSub.Clear; Reg.GetValueNames(ListValues.Items); end; procedure TForm1.FormDestroy(Sender: TObject); begin Reg.CloseKey; Reg.Free; end; procedure TForm1.ListSubClick(Sender: TObject); var NewKey, Path: string; nItem: Integer; begin // get the selection(获取选择项) NewKey := ListSub.Items [ListSub.ItemIndex]; Reg.OpenKey (NewKey, False); // save the current path (eventually adding a \)(在不列出于列表时保存路径) // only if the it is not already listed Path := Reg.CurrentPath; if Path < '\' then Path := '\' + Path; nItem := ComboLast.Items.IndexOf (Path); if nItem < 0 then begin ComboLast.Items.Insert (0, Path); ComboLast.ItemIndex := 0; end else ComboLast.ItemIndex := nItem; UpdateAll; end; procedure TForm1.ComboKeyChange(Sender: TObject); begin case ComboKey.ItemIndex of 0: Reg.RootKey := HKEY_CLASSES_ROOT; 1: Reg.RootKey := HKEY_CURRENT_USER; 2: Reg.RootKey := HKEY_LOCAL_MACHINE; 3: Reg.RootKey := HKEY_USERS; 4: Reg.RootKey := HKEY_CURRENT_CONFIG; 5: Reg.RootKey := HKEY_DYN_DATA; end; Reg.OpenKey ('\', False); UpdateAll; ComboLast.Items.Clear; end; procedure TForm1.ComboLastChange(Sender: TObject); begin Reg.OpenKey (ComboLast.Text, False); UpdateAll; end; end. 2003-11-20 13:30:00 获得注册表项下的所有值 Var Reg : TRegistry; list : TStrings; i : Integer; Begin Reg:=TRegistry.Create; Reg.RootKey:='HKEY_LOCAL_MACHINE'; If Reg.OpenKey('\Software\Microsoft\CurrentVersion\Run', false) then Begin List:=TStringList.Create; Reg.GetValueNames(List); For i:=0 to list.Count-1 do If Reg.ValueExists(List[i]) then Begin Case Reg.GetDataType(List[i]) of rdInteger: Reg.ReadInteger(List[i]); rdBinary: Reg.ReadBinaryData(List[i]); else Reg.ReadString(List[i]); End; End; End; 2003-11-20 13:38:19 利用Windows API 函数和注册表获取系统信息 在开发应用程序时,增加一项显示计算机系统信息的功能,例如已安装的软盘、硬盘、光驱、网络驱动器,硬盘的容量和剩余空间,显示器分辨率、键盘类型、鼠标的键数,内存大小、CPU 类型,Windows 的版本号、产品标识、注册用户单位名和用户名、当前操作用户名等( 见运行图示),当然还有更多的信息,这样会使你的程序更友好。其实,有很多应用程序就是这样做的。 通过调用Windows 的API 函数和访问Windows 注册表,可以获取大量的系统信息。Delphi 为绝大多数Windows API 函数提供了调用接口( 可参见DELPHI3\SOURCE\RTL\WIN\windows.pas 文件),并提供了一个功能全面的TRegistry 类,使我们可以方便的调用Windows API 函数和访问注册表,例如: 1、function GetDriveType(lpRootPathName: PChar): UINT; 返回指定驱动器的类型。 2、function GetDiskFreeSpace(lpRootPathName: PChar; var lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters: DWORD): BOOL; 返回指定驱动器的总簇数、剩余簇数及每簇扇区数、每扇区字节数,从而可以计算出总容量和剩 余空间。 3、function GetSystemMetrics(SM_CXSCREEN或 SM_CYSCREEN): Integer; 返回显示器分辨率。 4、function GetSystemMetrics(SM_CMOUSEBUTTONS): Integer; 返回鼠标的按键数目。 5、在windows 注册表的HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion \RegisteredOwner 主键下存放着Windows 安装时输入的用户名, 可用以下语句读取。 myreg:=Tregistry.Create; //必须在程序单元的uses部分加入Registry myreg.RootKey:=HKEY_LOCAL_MACHINE; if myreg.openkey('software\microsoft\windows\currentversion',false) then memo1.lines.add(' 注册用户名:'+myreg.readstring('RegisteredOwner')); myreg.closekey; 以上仅举几例,获取其他一些信息的方法与此类似,详见源程序。 本程序在Pwin95、Delphi3 下调试通过。 【附】: 源程序清单。 unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,Registry; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); var i,x,y:integer; ch:char; //驱动器字符'A'~'Z' buffer:string; cpuinfo:TSYSTEMINFO; //存放系统信息的记录类型,在Windows.pas中查到详细内容。 meminfo:TMemoryStatus; //存放系统内存信息的记录类型。 computername,username:pchar; //计算机名称、用户名 spc,bps,nofc,tnoc:longint; //用于存放磁盘容量的变量 myreg:Tregistry; //用于访问注册表的TRegistry变量 begin memo1.Lines.Clear; for ch:='A' to 'Z' do begin i:=getdrivetype(pchar(ch+':\')); buffer:=' '+ch+': '; case i of DRIVE_UNKNOWN : buffer:=buffer+'未知类型'; DRIVE_REMOVABLE: buffer:=buffer+'软盘'; DRIVE_FIXED : begin buffer:=buffer+'硬盘'; if getdiskfreespace(pchar(ch+':\'),spc,bps,nofc,tnoc) then begin buffer:=buffer+'总容量:'+inttostr((spc*bps*tnoc) div (1024*1024))+'MB'; buffer:=buffer+'剩余:'+inttostr((spc*bps*nofc) div (1024*1024))+'MB'; end; end; DRIVE_REMOTE : buffer:=buffer+'网络驱动器'; DRIVE_CDROM :buffer:=buffer+'CD-ROM驱动器'; DRIVE_RAMDISK:buffer:=buffer+'RAM虚拟驱动器'; end; if (ch >'D') and (i=1) then break; if i< >1 then memo1.Lines.Add(buffer); end; case getkeyboardtype(0) of //获取键盘类型 1: buffer:=' 键盘: IBM PC/XT或兼容类型(83键)'; 2: buffer:=' 键盘: Olivetti "ICO"(102键)'; 3: buffer:=' 键盘: IBM PC/AT(84键)'; 4: buffer:=' 键盘: IBM增强型(101或102键)'; 5: buffer:=' 键盘: Nokia 1050'; 6: buffer:=' 键盘: Nokia 9140'; 7: buffer:=' 键盘: Japanese'; end; memo1.lines.add(buffer); //获取键盘功能键数目 memo1.lines.add(' 功能键数目:'+inttostr(getkeyboardtype(2))); memo1.Lines.add('显示器分辨率:'+inttostr(getsystemmetrics(SM_CXSCREEN)) +'x'+inttostr(getsystemmetrics(SM_CYSCREEN))); //获取鼠标按键数目 memo1.Lines.add(' 鼠标:'+inttostr(getsystemmetrics(SM_CMOUSEBUTTONS))+'键'); globalmemorystatus(meminfo); //获取系统内存数量 memo1.lines.add(' 物理内存:'+inttostr(meminfo.dwTotalPhys div 1024)+' KB'); i:=getsystemmetrics(SM_CLEANBOOT); case i of 0:buffer:='系统启动模式:正常模式'; 1:buffer:='系统启动模式:保护模式'; 2:buffer:='系统启动模式:网络保护模式'; end; memo1.lines.add(buffer); x:=getsystemmetrics(SM_ARRANGE); //获取系统最小化窗口的起始位置和排列方式 y:=x; x:=x and 3; y:=y and 12; case x of ARW_BOTTOMLEFT : buffer:=' 最小化窗口:自左下角'; ARW_BOTTOMRIGHT : buffer:=' 最小化窗口:自右下角'; ARW_TOPLEFT : buffer:=' 最小化窗口:自左上角'; ARW_TOPRIGHT : buffer:=' 最小化窗口:自右上角'; end; case y of ARW_LEFT : buffer:=buffer+'横向排列'; ARW_UP : buffer:=buffer+'纵向排列'; ARW_HIDE : buffer:=buffer+'隐藏'; end; memo1.lines.add(buffer); getmem(computername,255); //获取计算机名称和用户名 getmem(username,255); i:=255; getcomputername(computername,i); memo1.lines.add(' 计算机名称: '+computername); getusername(username,i); memo1.lines.add(' 用户名: '+username); freemem(computername); freemem(username); getsysteminfo(cpuinfo); //获取CPU类型 case cpuinfo.dwProcessorType of 386 : buffer:=' CPU类型: 386'; 486 : buffer:=' CPU类型: 486'; 586 : buffer:=' CPU类型: Pentium'; end; memo1.Lines.add(buffer); //从注册表中获取CPU标识,Windows版本,产品标识,注册单位名称及用户名 myreg:=Tregistry.Create; myreg.RootKey:=HKEY_LOCAL_MACHINE; if myreg.OpenKey('hardware\description\system\centralprocessor\0',false) then memo1.lines.add(' CPU标识:'+myreg.ReadString('VendorIdentifier')); myreg.closekey; if myreg.openkey('software\microsoft\windows\currentversion',false) then begin memo1.lines.add(' windows版本:'+myreg.ReadString('Version')); memo1.lines.add(' 版本号:'+myreg.ReadString('VersionNumber')+''+myreg.ReadString('Subversionnumber')); memo1.lines.add(' 产品标识:'+myreg.Readstring('ProductID')); memo1.lines.add('注册单位名称:'+myreg.readstring('RegisteredOrganization')); memo1.lines.add(' 注册用户名:'+myreg.readstring('RegisteredOwner')); end; myreg.CloseKey; myreg.Free; end; end. 2003-11-20 13:44:20 注册表配置ODBC的详细例子 【思路】:先在ODBC中配置然后到注册表中去看有什么增加,然后照样写进去就可以了,但是这样做有一个问题,SQL Server默认是用命名管道,如果要用TCP/IP协议请在注册表中找1433,就能找到它是在那里.照样写进去就OK了。 var reg : TRegistry; begin reg := TRegistry.Create; //建立一个Registry实例 with reg do begin RootKey:=HKEY_LOCAL_MACHINE; //设置根键值为HKEY_LOCAL_MACHINE //找到Software\ODBC\ODBC.INI\ODBC Data Sources if OpenKey('Software\ODBC\ODBC.INI\ODBC Data Sources' True) then begin //注册一个DSN名称 WriteString( 'DSN' 'SQL Server' ); end else begin //创建键值失败 ShowMessage('增加ODBC数据源失败'); exit; end; CloseKey; //找到或创建Software\ODBC\ODBC.INI\masdsn 写入DSN配置信息 if OpenKey('Software\ODBC\ODBC.INI\DSN' True) then begin WriteString( 'Driver' 'C:\Windows\System\sqlsrv32.dll' ); WriteString( 'LastUser' 'Username' ); WriteString( 'Password' 'password' ); WriteString( 'Server' 'ServerName' ); end else //创建键值失败 begin Showmessage('增加ODBC数据源失败'); exit; end; CloseKey; Free; ShowMessage('增加ODBC数据源成功'); end; //以上程序是写到system里的,当然同样可以写到当前用户里! 2003-11-20 13:50:20 通过注册表读取设置字体 unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure WriteFontToRegistry(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ReadFontFromRegistry(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private-Deklarationen } Font : TFont; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.DFM} type TFontRegData = record Name : string[100]; Size : integer; Color : TColor; Style : set of TFontStyle; Charset : byte; Height : integer; Pitch : TFontPitch; PixelsPerInch : integer; end; // Before writing font data to the registry you have to copy all needed data to a record of fixed size procedure PrepareFontDataForRegistry(Font : TFont;var RegData : TFontRegData); begin { Copy font data to record for saving to registry } //复制字体数据到记录并保存到注册表中 with RegData do begin Name:=Font.Name; Size:=Font.Size; Color:=Font.Color; Style:=Font.Style; Charset:=Font.Charset; Height:=Font.Height; Pitch:=Font.Pitch; PixelsperInch:=Font.PixelsPerInch; end; end; procedure PrepareFontfromRegData(Font : TFont;RegData : TFontRegData); begin { Set font data to values read from registry } //设置来自注册表的字体数据的值 with Font do begin Name:=RegData.Name; Size:=RegData.Size; Color:=RegData.Color; Style:=RegData.Style; Charset:=RegData.Charset; Height:=RegData.Height; Pitch:=RegData.Pitch; PixelsperInch:=RegData.PixelsPerInch; end; end; //初始化 procedure TForm1.FormCreate(Sender: TObject); begin Font:=TFont.Create; Font.Name:='Arial'; end; //写入注册表 procedure TForm1.WriteFontToRegistry(Sender: TObject); var rd : TFontRegData; reg : TRegistry; begin PrepareFontDataForRegistry(Font,rd); Reg:=TRegistry.Create; Reg.OpenKey('Software\Test',true); Reg.WriteBinaryData('FontData',rd,Sizeof(rd)); reg.Free; end; //从注册表中读取字体设置值 procedure TForm1.ReadFontFromRegistry(Sender: TObject); var rd : TFontRegData; reg : TRegistry; begin Reg:=TRegistry.Create; Reg.OpenKey('Software\Test',true); if Reg.ValueExists('FontData') then Reg.ReadBinaryData('FontData',rd,Sizeof(rd)); reg.Free; PrepareFontFromRegData(Font,rd); end; procedure TForm1.FormDestroy(Sender: TObject); begin Font.Free; end; end. 2003-11-20 13:56:06 系统注册表读写操作的例子代码 操作注册表需要认识到注册表的六个根键。看看DELPHI的定义: const { Reserved Key Handles. } {$EXTERNALSYM HKEY_CLASSES_ROOT} HKEY_CLASSES_ROOT = DWORD($80000000); {$EXTERNALSYM HKEY_CURRENT_USER} HKEY_CURRENT_USER = DWORD($80000001); {$EXTERNALSYM HKEY_LOCAL_MACHINE} HKEY_LOCAL_MACHINE = DWORD($80000002); {$EXTERNALSYM HKEY_USERS} HKEY_USERS = DWORD($80000003); {$EXTERNALSYM HKEY_PERFORMANCE_DATA} HKEY_PERFORMANCE_DATA = DWORD($80000004); {$EXTERNALSYM HKEY_CURRENT_CONFIG} HKEY_CURRENT_CONFIG = DWORD($80000005); {$EXTERNALSYM HKEY_DYN_DATA} HKEY_DYN_DATA = DWORD($80000006); 它们必须在TRegistry变量的RootKey属性中指定。 要取得某一个路径的某个键值,必须找到某一个主键,例如有如下一个路径存放着WORD97存放的程序路径: \Software\Microsoft\Office\8.0\Word\InstallRoot\Path 其中,PATH是键,在它前面的便是主键(键的路径),而这些键又是放在HKEY_LOCAL_MACHINE这个根键中的。当然,我们想要的是PATH对应的数据,而不是想知道有PATH这个键存在。PATH的类型是一个字符串,所以需要一个字符串变量存放它,例程中使用直接显示的方法表达它。 因此,读出PATH键数据的过程就应该是,确定根键,进入主键(路径),读出键的数据值。为了体现对注册表的写操作,我们还特意创建一个主键\Software\3hsoft和里面一个字符串的键MyData。 下面是一小段关于此过程的程序,虽然内容不多,但基本上已经将读写的操作表现出来了。 unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry; // 记得要加入这个红色的。 type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); Const FPath = '\Software\Microsoft\Office\8.0\Word\InstallRoot'; FKey = 'Path'; FMyPath = '\Software\3hSoft'; FMyKey = 'MyData'; Var Reg : TRegistry; begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_LOCAL_MACHINE; If Reg.OpenKey(FPath, False) then ShowMessage(Reg.ReadString(FKey)); // 读出的 WinWord 的路径就显示出来了。 Reg.CreateKey(FMyPath); // 创建我们的主键 Reg.OpenKey(FMyPath, True); // 进入我们自己的主键中 Reg.WriteString(FMyKey, 'This is a registry operation test program.'); // 写进键值。 finally Reg.Free; // 用 Try..Finally 结构确保 REG 变量能够释放。 end; end; end. 2003-11-20 14:02:11 用注册表对Delphi程序进行加密 本加密方法分三部分: 1. 根据对注册表的搜索结果判定设置对话框的内容。 2. 若初次使用,则设新密码;若是已经设置密码,则进行验证。 3. 一个密码变换小程序(比原来的复杂得多)。当然,如果需要修改密码的功能,只要将设置密码部分改动一下即可。 一、程序启动时,通过搜索注册表,判断是否已有密码,来确定窗口的显示内容。不过事先应有以下的声明然后才能使用: 在user中加入TRegistry,在var声明中加入以下几个窗体变量: var TheReg: TRegistry; KeyName,ValueStr,tempStr:String; procedure TfrmPass.FormShow(Sender: TObject); begin TheReg := TRegistry.Create; try TheReg.RootKey := HKEY-LOCAL-MACHINE; KeyName := ′SOFTWARE\Mypassword′; //有该键则打开,没有则创建 if TheReg.OpenKey(KeyName, True) then begin tempStr:=ExtractFileName(Application.ExeName); //读取密码 ValueStr:=TheReg.ReadString(tempStr); //密码不为空则修改窗体为验证密码 if ValueStr<>′′ then begin edit2.Visible:=false; frmPass.Caption:=′验证密码′; edit1.SetFocus; OK.Caption:=′确定′; end //密码为空则修改窗体为设置密码对话框 else begin showmessage(′第一次使用请设置密码!′); edit2.Visible:=true; frmPass.Caption:=′请设置新密码′; edit1.SetFocus; OK.Caption:=′设置′; end; TheReg.CloseKey; end; finally TheReg.Free; end; end; 二、按钮的响应代码:包括新设密码和验证密码。 procedure TfrmPass.OKClick(Sender: TObject); begin //根据Edit2的显示与否判断已有密码,进行验证 if edit2.Visible=false then begin if pass(edit1.text)=ValueStr then begin showmessage(′密码正确!′); end else begin showmessage(′密码不正确!无权操作!′); halt; end; end //无密码,设置新密码 else begin if edit1.text=edit2.text then begin TheReg := TRegistry.Create; TheReg.RootKey := HKEY-LOCAL-MACHINE; KeyName := ′SOFTWARE\Mypassword′; if TheReg.OpenKey(KeyName, True) then TheReg.WriteString(tempStr,pass(edit1.text)); TheReg.CloseKey; end else begin showmessage(′再次键入的密码不一致,请重输!′); edit1.text:=′′; edit2.text:=′′; edit1.SetFocus; end; //进行下一步操作... end; end; 三、密码变换程序:注意要预先定义。 这个变换小程序在笔者看来还不算很复杂,只进行了两次变换,不过,想要破译也是得费点劲。读者还可以采用其他的数学函数进行更为复杂的变换。 function pass(pstr:string):string; var str,str1:string; i,j:integer; begin str:=pstr; for i:=1 to length(str) do begin //进行第一次变换 j:=(i*i*i mod (i+20))+(i*i mod (i+10))+i*2+1; str1:=str1+chr(ord(str[i])+j); //第二次变换 j:=(i*i*i mod (i+10))+(i*i mod (i+20))+i*2+1; str1:=str1+chr(ord(str[i])+j); end; pass:=str1; end; 2003-11-20 14:06:55 使Delphi程序记忆参数的设置 【王伟】 我们平时用的很多软件都具有一些记忆功能,如foxmail和TheBat等等。这些软件能在启动时自动的保持上一次关闭软件时的一些状态,如窗口的初始位置,用户在软件中设置的一些特性(如窗口风格,横相排列还是竖相排列等等),如果能让我们的程序也具有这样的一些功能可以使我们程序看起来更专业性一些:) 这里我就来讲一下怎样使应用程序能记住上一次关闭时的窗口位置,并在下一次启动时和上一次的位置一样。 既然要保留信息,就一定要涉及到存贮的问题。数据的存贮有好几种办法,可以写.ini 或.inf文件,还可以用Delphi提供的文件类来自定义一个文件,还可以用数据库接口(如ODBC) 引入一种数据库文件,foxpro 的.dbf和Access的.mdb比较常用,还可以直接往Windows的注册表里写。写.ini和.inf文件没有任何的安全性,且不适合win95,还记得在94,95年时用中文的Windows3.2中大量的用到了.ini文件,但Windows95出现后,微软建议尽可能的把信息写到注册表中。用ODBC的话会给程序带来很多不必要的麻烦,如会使程序更加复杂,需要相应的DBMS的驱动程序的支持,如果没有相应数据源的驱动程序,则该数据源就不能使用,还有安全性问题也不能很好的解决。 在这里推荐使用写注册表的方法。因为这种方法很方便,不需太多额外的开销,程序比较简 单,对一般的用户来说在注册表里找到有用的信息比打开.ini文件要麻烦的多。所以注册表的安全性比.ini文件要略强一些。 使应用程序能记住上一次关闭时的窗口位置,并在这一次启动时和上一次的位置一样。总体 思路是这样的:在关闭程序时要记录下本次程序结束时的信息,写入注册表中,在下次程序启动 时读注册表中相应信息,并赋给程序。 对于我们这个程序来说主要需要记录的信息是窗口关闭时的Top,Left,Height,Width。 注意:要想使Delphi可以操作注册表,必须包括registry单元。 以下是源程序和相关注释: unit Unit1; interface uses Windows, Messages,. . . . . . . ,registry; //包括registry单元 type TForm1 = class(TForm) public ww:TRegistry; //声明一个TRegistry对象,我们就通过ww来实现对注册表的操作 //启动窗口时要做的一些工作 procedure TForm1.FormCreate(Sender: TObject); begin ww:=TRegistry.Create; //创建ww对象 ww.RootKey :=HKEY_CURRENT_USER; //注意:通过修改RootKey可以把信息写到注册表的每一个角落 ww.OpenKey('software',FALSE); //打开键software,可以看到Borland,Netscape,还有Microsoft也在这个software键中 ww.CreateKey( '王伟'); //在software键中创建一个名为“王伟“的键值,使自己的名字和Borland,Netscape, //Microsoft并排在一起,是不是很Cool啊:) ww.OpenKey( '王伟',FALSE); //打开键"王伟" ww.CreateKey('XX单位XX管理系统'); //创建应用程序的名称 ww.OpenKey('XX单位XX管理系统',TRUE); ww.CreateKey('位置'); //创建应用程序中某一个要存贮的项目的名称,便于管理 ww.OpenKey('位置',TRUE); if (ww.ReadString('first')<>'1')then //这是值得注意的一个地方,通过“first“来判断程序是否 begin //是第一次写注册表,如果是第一次写则用程序给的默认值来 ww.WriteString('first','1'); //设置窗口的位置和大小。如果不是第一次启动应用程序则说明 Form1.WindowState:=(wsNormal); //注册表中已经写了位置信息,就读这些信息并赋给Form。 Form1.Top:=10; form1.Left:=10; form1.Height:=100; form1.Width:=100; end else begin if(ww.ReadString('max')='y') then //判断上次关闭程序时,窗口是否是最大化的。如果是的话,则 Form1.WindowState:=(wsMaximized) //继续使窗口拥有这一特征。 else begin Form1.top:=StrToInt(ww.ReadString('top')); //如果不是最大化,则取位置和大小数据赋给From Form1.left:=StrToInt(ww.ReadString('left')); Form1.height:=StrToInt(ww.ReadString('height')); Form1.width:=StrToInt(ww.ReadString('width')); end; end; end; //关闭窗口时要做的一些工作 procedure TForm1.FormDestroy(Sender: TObject); begin ww.OpenKey('位置',FALSE); //打开“位置”键 if Form1.WindowState=(wsMaximized) then //如果当前程序是最大化,则把这一信息写入注册表, ww.WriteString('max','y') //便于下一次时使用。 else begin ww.WriteString('max','n'); //如果不是最大化,则把窗口的位置和大小数据写入注册表中。 ww.WriteString('top',IntToStr(Form1.top)); ww.WriteString('left',IntToStr(Form1.left)); ww.WriteString('height',IntToStr(Form1.Height)); ww.writeString('width',IntToStr(Form1.Width)); end; end; 【需要注意的几点】: 1:因为程序不可能在第一次使用时,就从注册表里读数据,所以第一次必须由程序赋一个 初值。然后做上标记,表示已经有过第一次了,以后只要判断出不是第一次了,就可以读数据 了。(这点最重要,由这一点还可以引出一个话题,那就是可以做一个Demo版的软件,每次启动时往注册表里加个1,当>10时,就不许用该软件了,cool吧) 2:往注册表里可以写string型数据,也可以写Integer型数据,但在注册表中的Integer型数据是以16进制形式存在的,而我们在程序中用的都是10进制数,所以干脆写string型,然后用StrToInt或IntToStr转换。 3:写注册表并不是很安全的,它的内容可以用RegEdit一览无佘的看到,所以千万不能将一些重要的信息(如密码)不经加密而直接写入注册表,这样做是非常危险的!! 2003-11-20 14:22:10 在DELPHI程序中动态设置ODBC数据源(使用注册表) 【编辑者说】: 这个咚咚写得不错,比上面的那个更加详细,如果上面的那个看不明白就看这个吧,应该能看懂的吧,要不然.... 在DELPHI数据库应用程序中,我们访问数据库通常有两种方法.一种是通过BDE数据库搜索引擎,即利用DELPHI自带的数据库驱动程序,这种方法的优点是速度快,但应用范围有限,当数据库版本更新时,有可能不能用于操作新的数据库;另一种方法是通过ODBC,这种方法的优点是可以随操作系统(如WINDOWS)提供,作为标准接口能适应多种数据库,缺点是速度慢.在编程时,我们可以根据需要选择其中的一种方法. 在利用ODBC访问数据库时,通常的方法时是在ODBC管理面板中设置一个ODBC系统数据源 (系统DSN),然后在DBD中或在程序中设置一个数据库别名(Alias)对应该DSN,这样就可以如愿以偿地操作数据库了.相信用DELPHI做过数据库应用的程序员对这方面已经很熟悉了,笔者就不多说了.在实际应用中,笔者曾遇到过这样的情况,我们的数据库应用程序是依靠ODBC系统数据源访问和操作数据库的,应用程序运行一直良好,直到某一天,一个对WINDOWS系统较为熟悉但又不太精通的用户不慎修改或删除了我们预先设置的系统DSN...... 于是,笔者就开始研究怎么在程序中动态地设置ODBC系统DSN的内容,这样就可以增加自己程序的坚固性了.经过整整一天对WINDOWS注册表的研究,终于找到了ODBC管理程序设置DSN的秘密("天地自有公道,付出总会回报!",不是做广告!),现写出来与大家共享,也请高手指教. ODBC管理程序设置DSN的秘密在注册表中,不信可以到HKEY_LOCAL_MACHINE\Software\ODBC 去看看,肯定让你感觉已经成功了一半. 首先来看看系统中已安装的ODBC数据库驱动程序.在HKEY_LOCAL_MACHINE\Software\ODBC\ ODBCInst.INI中,存放着已经安装了的ODBC数据库驱动程序的信息,从这里可以查到已安装的 ODBC数据库驱动程序对应的DLL文件等信息.在ODBCInst.INI\ODBC Drivers的各个键值中,键名是驱动程序名称(如Microsoft Access Driver(*.mdb)),键值为“Installed”,表示驱动程序已安装.在 ODBCInst.INI\DriverName(DriverName为一个驱动程序名称,如Microsoft Access Driver(*.mdb)) 中,有驱动程序的详细信息,我们主要从这里获得ODBC驱动程序对应的DLL文件的路径和文件名,即键名Driver的键值,一般为"C:\WINDOWS\SYSTEM\FileName.DLL". 然后来看系统DSN的注册信息,在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI中,存放着系统 DSN的注册信息,我们在ODBC管理面板设置的DSN参数就在这里. 下面来看看创建一个ODBC系统DSN的步骤,即我们在ODBC管理面板中完成参数设置后,ODBC 管理程序是怎么在注册表中注册DSN信息的.以创建一个名称为MyAccess的Ms Access97类型的系统DSN为例,我们指定的参数主要有数据库类型(Microsoft Access Driver(*.mdb))、数据源名称(MyAccess)、数据源描述(我的ACCESS)、数据库路径(C:\Inetpub\wwwroot\Test.mdb),其它参数如用户名称、用户密码、独占、只读、系统数据库、默认目录、缓冲区大小、扫描行数、页超时等采用系统缺省参数.这时,注册系统DSN一般应有以下几个步骤: 1.在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\ODBC Data Sources中增加一个字符串 键值,为MyAccess = Microsoft Access Driver(*.mdb),其中分别为数据源名称和数据库类型. 这是在注册表中注册一个系统DSN名称. 2.在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI中创建一个子键(SubKey)MyAccess,即 创建一个键为HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\MyAccess,然后在其下创建一些键值,详细描述一个系统DSN的配置信息,主要信息有([]中的内容为笔者注释): DBQ=C:\Inetpub\wwwroot\Test.mdb [字符串,表示数据库路径] Description=我的ACCESS [字符串,表示数据库描述] Driver=C:\PWIN98\System\odbcjt32.dll [字符串,表示驱动程序,可见ODBCINST.INI] DriverId=0x00000019(25) [数字,表示驱动程序标识,不能改变] FIL=Ms Access; [字符串,可能与过滤Filter有关] SafeTransaction=0x00000000 [数字,可能表示支持事务性操作的个数] UID="" [字符串,表示用户名称,此处为空字符串] 3.在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\MyAccess中创建一个子键(SubKey) Engines, 再在其下创建子键(SubKey)Jet,即创建一个键为 HKEY_LOCAL_MACHINE\Software \ODBC\ODBC.INI\MyAccess\Engines\Jet,然后在其下创建一些 键值,详细描述一个系统DSN的数据库引擎配置信息,主要信息有([]中的内容为笔者注释): ImplicitCommitSync=Yes [字符串,可能表示是否立即反映数据修改] MaxBufferSize=0x00000200(512) [数字,表示缓冲区大小] PageTimeout=0x00000005(5) [数字,表示页超时] Threads=0x00000003(3) [数字,可能表示支持的最大线程数目] UserCommitSync=Yes [字符串,可能表示是否立即将数据修改反映到用户] 以上是建立一个系统DSN的基本信息(其它信息如选项或高级选项等信息也在这里设置, 只不过因采用默认信息,注册表里没有列出),我们在程序中按上述步骤操作注册表,同样也能增加一个系统DSN或修改其配置.在下面的例子程序中,将按以上步骤建立一个系统DSN,请注意程序中的注释. {******************************************************* 在本程序中,将创建一个ODBC系统数据源(DSN), 数据源名称:MyAccess 数据源描述:我的新数据源 数据库类型:ACCESS97 对应数据库:C:\Inetpub\wwwroot\test.mdb *******************************************************} { 注意应在USES语句中包含Registry } procedure TForm1.Button1Click(Sender: TObject); var registerTemp : TRegistry; bData : array[ 0..0 ] of byte; begin registerTemp := TRegistry.Create; //建立一个Registry实例 with registerTemp do begin RootKey:=HKEY_LOCAL_MACHINE; //设置根键值为HKEY_LOCAL_MACHINE //找到Software\ODBC\ODBC.INI\ODBC Data Sources if OpenKey('Software\ODBC\ODBC.INI\ODBC Data Sources',True) then begin //注册一个DSN名称 WriteString( 'MyAccess', 'Microsoft Access Driver (*.mdb)' ); end else begin//创建键值失败 memo1.lines.add('增加ODBC数据源失败'); exit; end; CloseKey; //找到或创建Software\ODBC\ODBC.INI\MyAccess,写入DSN配置信息 if OpenKey('Software\ODBC\ODBC.INI\MyAccess',True) then begin WriteString( 'DBQ', 'C:\inetpub\wwwroot\test.mdb' );//数据库目录 WriteString( 'Description','我的新数据源' );//数据源描述 WriteString( 'Driver', 'C:\PWIN98\SYSTEM\odbcjt32.dll' );//驱动程序DLL文件 WriteInteger( 'DriverId', 25 ); //驱动程序标识 WriteString( 'FIL', 'Ms Access;' ); //Filter依据 WriteInteger( 'SafeTransaction', 0 ); //支持的事务操作数目 WriteString( 'UID', '' );//用户名称 bData[0] := 0; WriteBinaryData( 'Exclusive', bData, 1 ); //非独占方式 WriteBinaryData( 'ReadOnly', bData, 1 ); //非只读方式 end else//创建键值失败 begin memo1.lines.add('增加ODBC数据源失败'); exit; end; CloseKey; //找到或创建Software\ODBC\ODBC.INI\MyAccess\Engines\Jet //写入DSN数据库引擎配置信息 if OpenKey('Software\ODBC\ODBC.INI\MyAccess\Engines\Jet',True) then begin WriteString( 'ImplicitCommitSync', 'Yes' ); WriteInteger( 'MaxBufferSize', 512 );//缓冲区大小 WriteInteger( 'PageTimeout', 10 );//页超时 WriteInteger( 'Threads', 3 );//支持的线程数目 WriteString( 'UserCommitSync', 'Yes' ); end else//创建键值失败 begin memo1.lines.add('增加ODBC数据源失败'); exit; end; CloseKey; memo1.lines.add('增加新ODBC数据源成功'); Free; end; end; 以上程序在PWIN98+DELPHI3.0下调试通过. 下面是创建常见数据库类型的DSN需要设置的信息([]为注释内容,除特殊注释外,各参数可见前面说明): 1.Access(Microsoft Access Driver(*.mdb)) DBQ、Description、Driver[odbcjt32.dll]、DriverID[25]、FIL[Ms Access;]、SafeTransaction[默认为0]、UID[默认为空]、Engines\Jet\ImplicitCommitSync[默认为Yes]、Engines\Jet\MaxBufferSize[默认512]、Engines\Jet\PageTimeout[默认为512]、Engines\Jet\Threads[默认为3]、Engines\Jet\UserCommitSync[默认为Yes] 可选设置:SystemDb[字符串,系统数据库的路径]、ReadOnly[二进制,是否以只读方式打开,1为是,默认为0]、Exclusive[二进制,是否以独占方式打开,1为是,默认为0]、PWD[字符串,用户密码] 2.EXCEL(Microsoft Excel Driver(*.xls)) DBQ[Excel97(=path\xxx.xls)、5.0/7.0(=path\xxx.xls)、4.0(=path)、3.0(=path)]、Description、Driver[odbcjt32.dll]、DefaultDir[Excel97(< >DBQ)、5.0/7.0(< >DBQ)、4.0(=DBQ)、3.0(=DBQ)]、DriverID[790(Excel97)、22(5.0/7.0)、278(4.0)、534(3.0)]、FIL[Excel5.0;]、ReadOnly、SafeTransaction、UID、Engines\Excel\ImplicitCommitSync、 Engines\Excel\MaxScanRows[数字,扫描行数,默认为8]、Engines\Excel\Threads、Engines\Excel\UserCommitSync、Engines\Excel\FirstRowHasName[二进制,第一行是否是域名,1表示是,默认为1] 【注】: Excel97和Excel7.0/5.0的DBQ对应一个XLS文件,而Excel4.0和Excel3.0则对应一个目录;DefaultDir对应一个目录,在Excel97和Excel7.0/5.0中是DBQ所对应的路径,而在Excel4.0和Excel3.0下则与DBQ相同;各个版本的DriverID不同. 3.dBase(Microsoft dBase Driver(*.dbf)) DefaultDir[字符串,数据库文件所在目录]、Description、Driver[odbcjt32.dll]、 DriverID[277(IV)、533(5.0)]、FIL[dbase III;]、SafeTransaction、UID、Engines\Xbase\ImplicitCommitSync、Engines\Xbase\Collating[字符串,排序依据,可为ASC |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论