WIN32汇编语言教程:第15章 注册表和INI文件 · 15.2 INI文件的操作(4)
2. 获取键值
获取键值的操作比较方便,因为这时既可以用GetPrivateProfileString函数获取键值字符串,也可以使用GetPrivateProfileInt函数让Windows将键值字符串转换成数值后再返回,就像使用GetDlgItemInt函数转换对话框子窗口中的字符串一样。(比较奇怪的是保存键值的时候并没有一个WritePrivateProfileInt函数,结果每次还要首先使用wsprintf函数!)
GetPrivateProfileString函数的用法是:
invoke GetPrivateProfileString,lpAppName,lpKeyName,lpDefault,\
lpReturnedString,nSize,lpFileName
该函数的几个参数与WritePrivateProfileString的参数类似,也是使用lpAppName,lpKeyName和lpFileName参数分别指定小节名称、键名和INI文件名,但是其余几个参数则有所不同:
lpReturnedString参数指向一个缓冲区,函数在这里返回获取的键值字符串,缓冲区的长度用nSize参数指定,当缓冲区的长度太小以至于无法容纳返回的字符串时,字符串会被截止到nSize−1的长度后返回,余下的一个字节用来存放一个0字符用做结尾。
lpDefault参数指向一个默认字符串,当指定的键无法找到的时候,函数将这个字符串拷贝到返回缓冲区中。
GetPrivateProfileString还有两种特殊用法:首先,当lpAppName参数指定为NULL的时候,函数在缓冲区中返回的是全部小节名称的列表,每个小节名以0结尾,全部的名称列表再以一个附加的0结束,返回到缓冲区中的数据格式如下所示:
小节名称1,0,小节名称2,0,...,小节名称n,0,0
另外,当lpAppName参数指定了小节名称,而lpKeyName参数指定为NULL的时候,函数在缓冲区中返回该小节的全部键名列表,每个键名以0结尾,全部列表后面再以一个附加的0结束,如下所示:
键名1,0,键名2,0,...,键名n,0,0
所以用这两种方法调用GetPrivateProfileString函数可以实现枚举小节名称和枚举键名的功能。
不管用何种方式使用GetPrivateProfileString函数,函数的返回值是返回到缓冲区中的字符串长度(长度中并不包括结尾的0字符)。
如果保存的键值是全部由数字字符组成的话(比如例子程序的_SavePosition子程序中用wsprintf函数从窗口位置的坐标值转换过来的字符串),那么可以使用GetPrivateProfileInt函数直接将字符串转换成数值后再返回:
invoke GetPrivateProfileInt,lpAppName,lpKeyName,nDefault,lpFileName
其中lpAppName,lpKeyName和lpFileName参数的使用方法同上,函数将指定的键值字符串转换成数值类型以后返回,但是函数不支持负数,如果键值字符串是“−1234”格式的负数,那么函数的返回值是0。nDefault指定一个默认数值,如果指定的键名不存在的话,函数返回nDefault指定的数值。
例子程序在初始化的时候,在_GetPosition子程序中使用GetPrivateProfileInt函数读出上次退出时保存的窗口位置,并使用SetWindowPos函数将窗口移动到这个位置上。
15.2.3 管理小节
在键名已知的情况下固然可以使用GetPrivateProfileString等函数获取键值,但在某些情况下并不是所有的键名都是已知的,比如一个编辑文件需要保存近来编辑过的文件名列表,它可以建立一个小节如下:
[History]
file1=C:\My documents\Readme.txt
file2=D:\MyApp\Help.txt
file3=C:\download\win32asm.txt
...
这时小节中键的数量和名称就是不定的。另外,也有小节的数量和名称不定的情况,这时就需要对小节或键进行枚举。上一节中已经介绍了在GetPrivateProfileString函数中通过将lpAppName或lpKeyName参数设置为NULL来获取小节名称列表和键名列表的方法。实际上,Windows中还有专门用来实现此功能的函数,这些函数不仅可用来枚举小节和键,也可以用来一次性修改整个小节的内容。
GetPrivateProfileSectionNames函数可以用来返回全部小节名称的列表:
invoke GetPrivateProfileSectionNames,lpBuffer,nSize,lpFileName
lpFileName参数指向INI文件名,lpBuffer参数是一个指针,指向用来返回小节名称列表的缓冲区,nSize参数指定缓冲区的长度。返回到缓冲区中的数据格式也是:“小节名称1,0,小节名称2,0,...,小节名称n,0,0”的格式。当缓冲区太小以至于不能容纳全部数据的时候,后面的数据被丢弃,全部数据被截尾到nSize−2的长度,剩下的两个字节用来保存两个表示结束的0字符。函数的返回值是返回到缓冲区中的数据长度(不包括结尾的0字符)。
GetPrivateProfileSection函数则可以用来返回整个小节的键定义,与上一节介绍的调用GetPrivateProfileString函数时将lpKeyName参数设置为NULL以获取键名列表不同,GetPrivateProfileSection函数返回的是键定义列表。函数的用法是:
invoke GetPrivateProfileSection,lpAppName,lpBuffer,nSize,lpFileName
函数的lpAppName指向一个包含小节名称的字符串,返回到缓冲区中的数据格式为:
键名1=键值1,0,键名2=键值2,0,...,键名n=键值n,0,0
所以,使用这个函数可以同时完成枚举键名和键值的功能。例子程序中就是使用它来枚举键值的,但使用中如果觉得自己处理“键名=键值”字符串来分解键名和键值比较麻烦的话,可以用GetPrivateProfileString函数枚举键名并再次调用它获取指定键的键值。
在Windows 9x中,缓冲区最大不能超过32 767 B,而在Windows NT中则没有限制,函数的返回值是返回到缓存区中的数据长度(不包括结尾的0字符)。
WritePrivateProfileSection函数则将“键名1=键值1,0,键名2=键值2,0,...,键名n=键值n,0,0”格式的小节数据一次性全部写入。函数的用法是:
invoke WritePrivateProfileSection,lpAppName,lpString,lpFileName
lpString参数指向包含键值定义列表的缓冲区,函数执行后,指定小节原来的键定义被全部删除,然后加入新的键定义。如果执行成功,函数返回非0值,否则返回0。
15.2.4 使用不同的INI文件
在前面介绍的这些INI文件函数中,当lpFileName参数指定的文件名字符串中不包括路径时,系统将认为文件位于Windows安装目录下,这样当函数创建INI文件的时候,就会把文件创建于Windows安装目录下。但是大部分情况下,希望INI文件位于程序的运行目录下,这样拷贝文件的时候可以连同INI文件一起拷贝,另外,在卸载或删除程序的时候可以避免在Windows目录中留下一个“垃圾”INI文件。
如果希望在程序的运行目录而非Windows目录中建立INI文件,那么最简单的方法就是在INI文件名前面加上“.\”路径,也就是说把文件名写成“.\MyIniFile.ini”的格式,这样系统会在当前目录下建立INI文件。这种方法的缺陷是如果程序运行中需要不断切换当前目录的话,系统就会在不同的地方乱建INI文件。一个常见的情况就是使用“打开文件”通用对话框的时候,系统会将当前目录切换到对话框中浏览的那个目录,这样写INI文件时就会造成INI文件的位置根本无法确定。最保险的办法就是像例子程序中所示的那样,在程序一开始运行的时候就使用GetCurrentDirectory函数获取当前目录,然后将INI文件名添加到目录后组成一个全路径的文件名,以后在所有的操作中都使用这个文件名。
如果要操作的是Windows安装目录下的Win.ini文件而非其他INI文件时,那么既可以使用上面这些函数,也可以使用另一组专门用于操作Win.ini文件的函数,这组函数是:
invoke GetProfileString,lpAppName,lpKeyName,lpDefault,lpBuffer,nSize
invoke GetProfileInt,lpAppName,lpKeyName,nDefault
invoke WriteProfileString,lpAppName,lpKeyName,lpString
invoke GetProfileSection,lpAppName,lpBuffer,nSize
invoke WriteProfileSection,lpAppName,lpString
可以看出,与操作通用INI文件的函数相比,这组函数的函数名中少了“Private”单词,参数中少了lpFileName参数(因为操作的INI文件名就是Win.ini,并不需要单独指定),所有其他参数的用法都是相同的。
读者可以注意到这些函数中似乎少了一个GetProfileSectionNames函数,实际上并没有这个函数,如果要枚举Win.ini文件中的小节列表的话,只需把GetPrivateProfileSectionNames函数的lpFileName参数指定为NULL就行了,并不需要单独设置一个类似于GetProfileSectionNames的函数。
上页:第15章 注册表和INI文件 · 15.2 INI文件的操作(3) 下页:第15章 注册表和INI文件 · 15.3 对注册表的操作(1)