设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2375|回复: 1
打印 上一主题 下一主题

[RMVA发布] [RGSS3]API相关操作 1.0 INI档、注册表、转换编码

[复制链接]

Lv1.梦旅人

梦石
0
星屑
200
在线时间
78 小时
注册时间
2010-7-1
帖子
58
跳转到指定楼层
1
发表于 2015-2-23 17:32:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 abc1236762 于 2015-2-23 17:40 编辑

这是我花4天左右熬夜呕心沥血之作
这脚本可以:
1.转换字串的编码。
2.读取、写入INI档,对应系统编码和Unicode(UTF-16LE)编码。
3.对注册表进行建立、修改、读取、删除键和值项,对应系统编码。
之后还会陆续增加其他的功能,预计有对视窗的操作及取得时间等。

因为牵扯到了String.encode等方法,所以目前只适用于RGSS3。

如果有BUG,请将你用了哪些方法/函数,怎么用的,得到了那些结果回报给我,不然我会很难修正脚本。

也请各位高手指教指教,谢谢。


RUBY 代码复制下载
  1. #==============================================================================
  2. # ■ API相关操作 版本1.0
  3. #------------------------------------------------------------------------------
  4. #  此脚本目前只适用于RGSS3。
  5. #  在使用之前,请详阅使用方法及备注,否则造成系统或档案损坏后果请自行承担。
  6. #------------------------------------------------------------------------------
  7. #  这个脚本可以帮助你:
  8. #  1.转换字串的编码。
  9. #  2.读取、写入INI档,对应系统编码和Unicode编码。
  10. #  3.对注册表进行建立、修改、读取、删除键和值项,对应系统编码。
  11. #  这个脚本的放置位置:main以上,尽量在自订脚本的最高处,原始脚本以下。
  12. #------------------------------------------------------------------------------
  13. #  困难度:极高
  14. #  撰写者:白羽ゆりな(abc1236762)
  15. #  工作室:RMGTW工作室 [url]http://rmgtw.eu.org/[/url]
  16. #------------------------------------------------------------------------------
  17. #  更新日志:
  18. #   1.0 2015/02/23 初版公开。
  19. #------------------------------------------------------------------------------
  20. #  使用方法:
  21. #  ■转换编码的部分
  22. #   ●String.conv(from, to) 将字串从来源编码转换至欲输出的编码。(*1)
  23. #    from :字串来源编码的代码页,资料型别为整数或符号。(*2)
  24. #    to   :欲输出编码的代码页,资料型别为整数或符号。(*2)
  25. #    avoid:为真能降低输出额外乱码的机率,资料型别为布林值,选填项,预设为真。
  26. #    例:
  27. #     "foobar".conv(65001, 932) 等价于
  28. #     "foobar".conv(:UTF_8, :Shift_JIS)
  29. #   ●String.to_uni([usesys]) 将字串从UTF-8转换至UTF-16
  30. #    usesys:是否使用内建功能取代,选填项预设为真。
  31. #    例:
  32. #     "foobar".to_uni 等价于
  33. #     "foobar".conv(:UTF_8, :UTF_16LE)
  34. #   ●String.to_utf8([usesys]) 将字串从UTF-16转换至UTF-8
  35. #    usesys:是否使用内建功能取代,选填项预设为真。
  36. #   ●String.to_ansi() 将字串从UTF-8转换至系统编码
  37. #  ■INI档的操作部分(*3)
  38. #   ●INI.get(lpAppName, lpKeyName, [lpDefault[, nSize]]) 取得指定位置的参数
  39. #    传回取得的值,失败时传回预设值。
  40. #    lpAppName:欲取得参数所在的节,资料型别为字串。
  41. #    lpKeyName:欲取得参数所在的参数名称,资料型别为字串。
  42. #    lpDefault:预设值,欲取得的参数不存在时输出此,资料型别为字串,选填项。
  43. #    nSize    :缓冲区大小,必须不小于参数的长度,资料型别为整数,选填项。
  44. #    例:
  45. #     INI.get("Foo", "Bar")
  46. #   ●INI.set(lpAppName, lpKeyName, lpString) 设定指定位置的参数
  47. #    传回整数,失败时传回0。
  48. #    lpAppName:欲设定参数所在的节,资料型别为字串。
  49. #    lpKeyName:欲设定参数所在的参数名称,资料型别为字串。
  50. #    lpString :欲设定参数值,资料型别为字串。
  51. #    例:
  52. #     INI.set("Foo", "Bar", "Foobar")
  53. #  ■注册表的操作部分(*4)
  54. #   ●Registry.new() 初始化Registry类别,此动作为必要
  55. #   ●Registry.open(hKey, lpSubKey[, dwOptions]) 开启指定的键
  56. #    传回错误代码,成功时传回0。
  57. #    hKey     :键的基底位置,资料型别为符号或整数。(*5)
  58. #    lpSubKey :键的延伸位置,资料型别为字串。(*6)
  59. #    dwOptions:开启键的选项,资料型别为符号或整数,选填项,预设为0。(*7)
  60. #   ●Registry.create(hKey, lpSubKey[, dwOptions]) 新增指定的键
  61. #    成功时传回字串,失败时传回错误代码。
  62. #    成功时,如果原本没有键,是新增的动作,传回"REG_CREATED_NEW_KEY"
  63. #            如果原本存在键,是开启的动作,传回"REG_OPENED_EXISTING_KEY"
  64. #    hKey     :键的基底位置,资料型别为符号或整数。(*5)
  65. #    lpSubKey :键的延伸位置,资料型别为字串。(*6)
  66. #    dwOptions:开启键的选项,资料型别为符号或整数,选填项,预设为0。(*8)
  67. #   ●Registry.remove(hKey, lpSubKey) 删除指定的键
  68. #    传回错误代码,成功时传回0。
  69. #    hKey     :键的基底位置,资料型别为符号或整数。(*5)
  70. #    lpSubKey :键的延伸位置,资料型别为字串。(*6)
  71. #   ●Registry.close  关闭已指定的键
  72. #    传回错误代码,成功时传回0。
  73. #   ●Registry.get(lpValueName) 取得已指定的键中指定的值项
  74. #    传回得到的值,失败时传回空(nil)。(9)
  75. #    lpValueName:欲查询值项的名称,资料型别为字串。
  76. #   ●Registry.set(lpValueName, lpData[, dwType]) 设定已指定的键中指定的值项
  77. #    传回错误代码,成功时传回0。
  78. #    lpValueName:欲设定值项的名称,资料型别为字串。
  79. #    lpData     :欲设定值项的值,资料型别因值项的类型(dwType)不同而不同。(*9)
  80. #    dwType     :欲设定值项的类型,资料型别为符号或整数,选填项,
  81. #                 预设为原本的类型,值项不存在时如没有设定会为:REG_NONE(0)。(*9)
  82. #   ●Registry.delete(lpValueName) 删除已指定的键中指定的值项
  83. #    传回错误代码,成功时传回0。
  84. #    lpValueName:欲删除值项的名称,资料型别为字串。
  85. #   注册表的范例:
  86. #   > reg = Registry.new() # 初始化Registry
  87. #   > reg.open(:HKEY_CURRENT_USER, "Software\\Enterbrain\\RGSS3")
  88. #     # 开启HKEY_CURRENT_USER\Software\Enterbrain\RGSS3键
  89. #   > reg.set("ButtonAssign", [0] * 25) # 设定ButtonAssign为指定的值
  90. #   > value = reg.get("ButtonAssign") # 取得ButtonAssign的值传回value
  91. #     # => [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  92. #   > reg.set("test", "test", :REG_SZ)
  93. #     # 因为在开启的键中没有test值项,所以会建立一个,且其值为"test"
  94. #   > reg.delete("test") # 删除刚刚建立的test值项
  95. #   > reg.close() # 在操作完这键或是要换其他键时,记得关闭此键
  96. #   > reg.create(:HKEY_CURRENT_USER, "Software\\Enterbrain\\RGSS3\\new")
  97. #     # 如果在那位置不存在,则会新增键,否则开启
  98. #   > reg.close() # 建立完键后不进行任何操作,请关闭。
  99. #   > reg.remove(:HKEY_CURRENT_USER, "Software\\Enterbrain\\RGSS3\\new")
  100. #     # 移除刚刚建立的键HKEY_CURRENT_USER\Software\Enterbrain\RGSS3\new
  101. #     # 如果不再用reg操作注册表,可以进行以下动作:
  102. #   > reg = nil; GC.start
  103. #------------------------------------------------------------------------------
  104. #  备注:
  105. #   ●注1:请勿使用UTF-16BE(代码页1201)以及UTF-32等作为来源或输出编码。
  106. #   ●注2:关于代码页:
  107. #    1.所有的代码页可以参考以下网址
  108. #     [url]https://msdn.microsoft.com/library/windows/desktop/dd317756.aspx[/url]
  109. #    2.from和to可用,以预先设定好的符号如下
  110. #     符号       编码名称         对应代码页
  111. #     :ACP       ANSI(系统编码) 0
  112. #     :Shift_JIS Shift-JIS        932
  113. #     :GB2312    GB2312           936
  114. #     :BIG5      BIG5             950
  115. #     :UTF_16LE  UTF-16LE         1200
  116. #     :UTF_8     UTF-8            65001
  117. #   ●注3:关于操作INI档的注意事项
  118. #    1.如果没有特殊需求,请尽量不要使用Unicode当作操作INI档的编码方式。
  119. #     即使在编码转换的部分已经针对了输出多余的垃圾字串做了对应的措施,但在操
  120. #     作INI档时使用Unicode当作编码方式时,可能发生以下状况:
  121. #     (1) 档名不符合预期,例如你想设定的值会储存在与原档名不同的档案中。
  122. #     (2) 节、参数名称、参数值的取得不符合预期,可能会有垃圾字串。
  123. #     (3) 发生无法设定或取得的情况,原因是名称、路径错误,代码123。
  124. #     以上方法皆没有替代方案,唯一只有使用系统编码才可以避免,而相对的:
  125. #     (1) 使用系统编码操作INI档,可以正常读写以系统编码和UTF-16LE的INI档。
  126. #     (2) 在系统编码无法容许的字元,皆会以'?'存在,包含设定或取得。
  127. #     (3) 不过包含在系统编码无法中容许字元的路径也可以正常读写。
  128. #    2.在设定INI档的值时,如果没有找到指定的INI档,则会新增一个。
  129. #    3.关于操昨时传回的错误代码,可以参考以下网址
  130. #     [url]https://msdn.microsoft.com/library/windows/desktop/ms681381.aspx[/url]
  131. #   ●注4:关于操作注册表的注意事项
  132. #    1.此脚本只提供系统编码当作操作注册表的编码方式,因此:
  133. #     (1) 键、值项及其值含系统编码不允许字元的操作可能会找不到名称、路径。
  134. #     (2) 取得值项时,如其值的类别与字串相关,系统编码不允许字元将会表'?'。
  135. #     (3) 新增键或值项时,如果含系统编码不允许字元将会以'?'代替。
  136. #    2.在建立、开启键后,如果对里面的值项操作完毕或不进行任何操昨时,一定要
  137. #     进行关闭动作,否则如果发生问题,后果自行负责!
  138. #    3.更多关于注册表的操作,可以参考以下网址
  139. #     [url]https://msdn.microsoft.com/library/windows/desktop/ms724871.aspx[/url]
  140. #     [url]https://msdn.microsoft.com/library/windows/desktop/ms724875.aspx[/url]
  141. #    3.关于操昨时传回的错误代码,可以参考以下网址
  142. #     [url]https://msdn.microsoft.com/library/windows/desktop/ms681381.aspx[/url]
  143. #   ●注5:此处的hKey可以为
  144. #    符号                     代表值
  145. #    :HKEY_CLASSES_ROOT       0x80000000
  146. #    :HKEY_CURRENT_USER       0x80000001
  147. #    :HKEY_LOCAL_MACHINE      0x80000002
  148. #    :HKEY_USERS              0x80000003
  149. #    :HKEY_CURRENT_CONFIG     0x80000005
  150. #   ●注6:此处的lpSubKey在表示位置字串时,'\'必须标示为'\\'。
  151. #   ●注7:此处的dwOptions可以为
  152. #    符号                     对应值
  153. #    :REG_OPTION_NON_VOLATILE 0x0000
  154. #    :REG_OPTION_OPEN_LINK    0x0008
  155. #    详阅:[url]https://msdn.microsoft.com/library/windows/desktop/ms724897.aspx[/url]
  156. #   ●注8:此处的dwOptions可以为
  157. #    符号                       对应值
  158. #    :REG_OPTION_NON_VOLATILE   0x0000
  159. #    :REG_OPTION_VOLATILE       0x0001
  160. #    :REG_OPTION_CREATE_LINK    0x0002
  161. #    :REG_OPTION_BACKUP_RESTORE 0x0004
  162. #    详阅:[url]https://msdn.microsoft.com/library/windows/desktop/ms724897.aspx[/url]
  163. #   ●注9:对应值项的类型(dwType),需设定或取得的值的资料型别如下
  164. #    dwType的符号                    对应值 值的资料型别
  165. #    :REG_NONE                       0      另外说明
  166. #    :REG_SZ                         1      String
  167. #    :REG_EXPAND_SZ                  2      String
  168. #    :REG_BINARY                     3      Array(Integer(0~255))
  169. #    :REG_DWORD                      4      Integer(0~4294967295)
  170. #    :REG_DWORD_LITTLE_ENDIAN        4      Integer(0~4294967295)
  171. #    :REG_DWORD_BIG_ENDIAN           5      Integer(0~4294967295)
  172. #    :REG_LINK                       6      String
  173. #    :REG_MULTI_SZ                   7      Array(String)
  174. #    :REG_RESOURCE_LIST              8      Array(Integer(0~255))
  175. #    :REG_FULL_RESOURCE_DESCRIPTOR   9      Array(Integer(0~255))
  176. #    :REG_RESOURCE_REQUIREMENTS_LIST 10     Array(Integer(0~255))
  177. #    :REG_QWORD                      11     Integer(0~18446744073709551615)
  178. #    :REG_QWORD_LITTLE_ENDIAN        11     Integer(0~18446744073709551615)
  179. #    :REG_NONE的值的资料型别:输入为以上出现过的,输出为Array(Integer(0~255))
  180. #    详阅:[url]https://msdn.microsoft.com/library/windows/desktop/ms724884.aspx[/url]
  181. #------------------------------------------------------------------------------
  182. #  本脚本以创用CC 姓名标示-非商业性-禁止改作 4.0 国际 授权条款释出。
  183. #==============================================================================
  184.  
  185. #==============================================================================
  186. # ■ 预先设定
  187. #==============================================================================
  188. module RMGTW
  189.   # 预设参数(在未指定预设参数时,输入或输出此参数,必须是字串)
  190.   DefaultValue = ""
  191.   # 预设缓冲区大小(在未指定缓冲区大小时,使用这数值来当作缓冲区大小)
  192.   DefaultnSize = 400
  193.   # INI档的位置
  194.   INIPath = "./Game.ini"
  195.   # INI档使用的编法方式是否为Unicode(UTF-16LE)
  196.   #  只有VX Ace的INI档用的了UTF-16LE当作编码方式。
  197.   #  为true的风险请阅备注的注4。
  198.   INIUseUni = false
  199.   # 当功能失败时时是否回报错误。
  200.   Debug = true
  201.   # 当回报错误时,是否弹出错误讯息,否则在主控台显示。
  202.   RaiseError = true
  203. end
  204.  
  205. #==============================================================================
  206. # ■ NativeMethods
  207. #------------------------------------------------------------------------------
  208. #  这个模组用来定义原生方法。
  209. # 没有用到的都是之后新增功能时会用到的。
  210. #==============================================================================
  211. module NativeMethods
  212.   #--------------------------------------------------------------------------
  213.   # ● 处理视窗的API
  214.   #--------------------------------------------------------------------------
  215.   FindWindow    =
  216.     Win32API.new('user32',    'FindWindow',  'PP', 'L')
  217.   GetSystemMenu =
  218.     Win32API.new('user32', 'GetSystemMenu',  'LL', 'L')
  219.   RemoveMenu    =
  220.     Win32API.new('user32',    'RemoveMenu', 'LLL', 'L')
  221.   #--------------------------------------------------------------------------
  222.   # ● 转换编码的API
  223.   #--------------------------------------------------------------------------
  224.   MultiByteToWideChar =
  225.     Win32API.new('kernel32', 'MultiByteToWideChar',   'LLPLPL', 'L')
  226.   WideCharToMultiByte =
  227.     Win32API.new('kernel32', 'WideCharToMultiByte', 'LLPLPLPP', 'L')
  228.   #--------------------------------------------------------------------------
  229.   # ● 控制INI档的API
  230.   #--------------------------------------------------------------------------
  231.   GetPrivateProfileStringA   =
  232.     Win32API.new('kernel32',    'GetPrivateProfileStringA', 'PPPPLP', 'L')
  233.   GetPrivateProfileStringW   =
  234.     Win32API.new('kernel32',    'GetPrivateProfileStringW', 'PPPPLP', 'L')
  235.   WritePrivateProfileStringA =
  236.     Win32API.new('kernel32',  'WritePrivateProfileStringA',   'PPPP', 'L')
  237.   WritePrivateProfileStringW =
  238.     Win32API.new('kernel32',  'WritePrivateProfileStringW',   'PPPP', 'L')
  239.   #--------------------------------------------------------------------------
  240.   # ● 控制注册表的键的API
  241.   #--------------------------------------------------------------------------
  242.     RegOpenKeyEx   =
  243.     Win32API.new('advapi32',   'RegOpenKeyEx',     'LPLLP', 'L')
  244.   RegCreateKeyEx =
  245.     Win32API.new('advapi32', 'RegCreateKeyEx', 'LPLPLLPPP', 'L')
  246.   RegDeleteKeyEx =
  247.     Win32API.new('advapi32', 'RegDeleteKeyEx',      'LPLL', 'L')
  248.   RegCloseKey    =
  249.     Win32API.new('advapi32',    'RegCloseKey',         'L', 'L')
  250.   #--------------------------------------------------------------------------
  251.   # ● 控制注册表的值项的API
  252.   #--------------------------------------------------------------------------
  253.   RegQueryValueEx =
  254.     Win32API.new('advapi32', 'RegQueryValueEx', 'LPPPPP', 'L')
  255.   RegSetValueEx   =
  256.     Win32API.new('advapi32',   'RegSetValueEx', 'LPLLPL', 'L')
  257.   RegDeleteValue  =
  258.     Win32API.new('advapi32',  'RegDeleteValue',     'LP', 'L')
  259.   #--------------------------------------------------------------------------
  260.   # ● 其他API
  261.   #--------------------------------------------------------------------------
  262.   GetLocalTime =
  263.     Win32API.new('kernel32', 'GetLocalTime', 'P', 'V')
  264.   GetLastError =
  265.     Win32API.new('kernel32', 'GetLastError', 'V', 'L')
  266. end
  267.  
  268. #==============================================================================
  269. # ■ String
  270. #------------------------------------------------------------------------------
  271. #  这个类别定义了资料型别String。
  272. #==============================================================================
  273. class String
  274.   #--------------------------------------------------------------------------
  275.   # ● 防范NativeMethods
  276.   #--------------------------------------------------------------------------
  277.   include NativeMethods
  278.   #--------------------------------------------------------------------------
  279.   # ● 定义常用的编码代码
  280.   #--------------------------------------------------------------------------
  281.   CP = {
  282.   :ACP      =>    0, :Shift_JIS =>   932, :GB2312 => 936, :BIG5 => 950,
  283.   :UTF_16LE => 1200, :UTF_8     => 65001
  284.   }
  285.   #--------------------------------------------------------------------------
  286.   # ● 定义转换字串编码的输出
  287.   #--------------------------------------------------------------------------
  288.   def conv(from, to, avoid = true)
  289.     str0 = _conv(from, to)
  290.     str1 = _conv(from, to)
  291.     str2 = _conv(from, to)
  292.     while (str0 != str1 || str0 != str2) && avoid do
  293.       str0 = _conv(from, to)
  294.       str1 = _conv(from, to)
  295.       str2 = _conv(from, to)
  296.     end
  297.     return str0
  298.   end
  299.   #--------------------------------------------------------------------------
  300.   # ● 定义转换字串编码
  301.   #--------------------------------------------------------------------------
  302.   def _conv(from, to)
  303.     from = from.is_a?(Symbol) ? CP[from] : from
  304.     to   =   to.is_a?(Symbol) ? CP[to]   : to
  305.     if from != CP[:UTF_16LE]
  306.       length = MultiByteToWideChar.call(from, 0, self, -1, nil, 0)
  307.       buffer = "\0".encode("UTF-16LE") * length
  308.       MultiByteToWideChar.call(from, 0, self, -1, buffer, length)
  309.       wide_str = buffer.chop
  310.       return wide_str if to == CP[:UTF_16LE]
  311.     end
  312.     wide_str = self if wide_str.nil?
  313.     encoding = to == CP[:UTF_8] ? "UTF-8" : "ASCII-8BIT"
  314.     length = WideCharToMultiByte.call(to, 0, wide_str, -1, nil, 0, nil, nil)
  315.     buffer = "\0".encode(encoding) * length
  316.     WideCharToMultiByte.call(to, 0, wide_str, -1, buffer, length, nil, nil)
  317.     multi_str = buffer.chop
  318.     return multi_str
  319.   end
  320.   #--------------------------------------------------------------------------
  321.   # ● 定义转换字串从UTF-8至UTF-16LE
  322.   #--------------------------------------------------------------------------
  323.   def to_uni(usesys = true)
  324.     return conv(:UTF_8, :UTF_16LE) unless usesys
  325.     self.encode("UTF-16LE")
  326.   end
  327.   #--------------------------------------------------------------------------
  328.   # ● 定义转换字串从UTF-16LE至UTF-8
  329.   #--------------------------------------------------------------------------
  330.   def to_utf8(usesys = true)
  331.     return conv(:UTF_16LE, :UTF_8) unless usesys
  332.     self.encode("UTF-8")
  333.   end
  334.   #--------------------------------------------------------------------------
  335.   # ● 定义转换字串从UTF-8至系统编码
  336.   #--------------------------------------------------------------------------
  337.   def to_ansi
  338.     return conv(:UTF_8, :ACP)
  339.   end
  340.   #--------------------------------------------------------------------------
  341.   # ● 设定权限
  342.   #--------------------------------------------------------------------------
  343.   private :_conv
  344. end
  345.  
  346. #==============================================================================
  347. # ■ INI
  348. #------------------------------------------------------------------------------
  349. #  这个模组用来操作INI档。
  350. #==============================================================================
  351. module INI
  352.   #--------------------------------------------------------------------------
  353.   # ● 防范NativeMethods
  354.   #--------------------------------------------------------------------------
  355.   include NativeMethods
  356.   #--------------------------------------------------------------------------
  357.   # ● 定义取得在INI档中指定的值
  358.   #--------------------------------------------------------------------------
  359.   def self.get(lpAppName, lpKeyName,
  360.     lpDefault = RMGTW::DefaultValue, nSize = RMGTW::DefaultnSize)
  361.     if RMGTW::INIUseUni
  362.       zero = "\0".encode("UTF-16LE")
  363.       lpReturnedString = zero * nSize
  364.       error = GetPrivateProfileStringW.call(
  365.         lpAppName.to_uni, lpKeyName.to_uni,
  366.         lpDefault.to_uni, lpReturnedString, nSize,
  367.         RMGTW::INIPath.to_uni)
  368.       Error.show("INI取得值", error) if error == 0 && RMGTW::Debug
  369.       return lpReturnedString.delete(zero).to_utf8
  370.     else
  371.       zero = "\0".encode("ASCII-8BIT")
  372.       lpReturnedString = zero * nSize
  373.       error = GetPrivateProfileStringA.call(
  374.         lpAppName.to_ansi, lpKeyName.to_ansi,
  375.         lpDefault.to_ansi, lpReturnedString, nSize,
  376.         RMGTW::INIPath.to_ansi)
  377.       Error.show("INI取得值", error) if error == 0 && RMGTW::Debug
  378.       return lpReturnedString.delete(zero).conv(:ACP, :UTF_8)
  379.     end
  380.   end
  381.   #--------------------------------------------------------------------------
  382.   # ● 定义设定在INI档中指定的值
  383.   #--------------------------------------------------------------------------
  384.   def self.set(lpAppName, lpKeyName, lpString)
  385.     if RMGTW::INIUseUni
  386.       error = WritePrivateProfileStringW.call(
  387.         lpAppName.to_uni, lpKeyName.to_uni,
  388.         lpString.to_uni, RMGTW::INIPath.to_uni)
  389.     else
  390.       error = WritePrivateProfileStringA.call(
  391.         lpAppName.to_ansi, lpKeyName.to_ansi,
  392.         lpString.to_ansi, RMGTW::INIPath.to_ansi)
  393.     end
  394.     Error.show("INI设定值", error) if error == 0 && RMGTW::Debug
  395.     return error
  396.   end
  397. end
  398.  
  399. #==============================================================================
  400. # ■ Registry
  401. #------------------------------------------------------------------------------
  402. #  这个类别用来操作注册表。
  403. #==============================================================================
  404. class Registry
  405.   #--------------------------------------------------------------------------
  406.   # ● 防范NativeMethods
  407.   #--------------------------------------------------------------------------
  408.   include NativeMethods
  409.   #--------------------------------------------------------------------------
  410.   # ● 物件初始化
  411.   #--------------------------------------------------------------------------
  412.   def initialize
  413.     @hKey = nil
  414.     @lpType = nil
  415.     @lpcbData = nil
  416.   end
  417.   #--------------------------------------------------------------------------
  418.   # ● 键的操作:开启指定的键并取得其控制代码
  419.   #--------------------------------------------------------------------------
  420.   def open(hKey, lpSubKey, dwOptions = :REG_OPTION_NON_VOLATILE)
  421.     phkResult = [0].pack('L')
  422.     hKey = hKey.is_a?(Symbol) ? H[hKey] : hKey
  423.     dwOptions = dwOptions.is_a?(Symbol) ? H[dwOptions] : dwOptions
  424.     error = RegOpenKeyEx.call(hKey, lpSubKey.to_ansi, dwOptions,
  425.       H[:KEY_ALL_ACCESS] | H[:KEY_WOW64_32KEY], phkResult)
  426.     @hKey = phkResult.unpack('L')[0]
  427.     Error.show("注册表开启键", error) if error != 0 && RMGTW::Debug
  428.     return error
  429.   end
  430.   #--------------------------------------------------------------------------
  431.   # ● 键的操作:建立新的键并取得其控制代码
  432.   #--------------------------------------------------------------------------
  433.   def create(hKey, lpSubKey, dwOptions = :REG_OPTION_NON_VOLATILE)
  434.     phkResult = [0].pack('L')
  435.     lpdwDisposition = [0].pack('L')
  436.     hKey = hKey.is_a?(Symbol) ? H[hKey] : hKey
  437.     dwOptions = dwOptions.is_a?(Symbol) ? H[dwOptions] : dwOptions
  438.     error = RegCreateKeyEx.call(hKey, lpSubKey.to_ansi, 0, nil, dwOptions,
  439.       H[:KEY_ALL_ACCESS] | H[:KEY_WOW64_32KEY], nil, phkResult,
  440.       lpdwDisposition)
  441.     @hKey = phkResult.unpack('L')[0]
  442.     lpdwDisposition = lpdwDisposition.unpack('L')[0]
  443.     if error == 0
  444.       if lpdwDisposition = H[:REG_CREATED_NEW_KEY]
  445.         return :REG_CREATED_NEW_KEY.id2name
  446.       elsif lpdwDisposition = H[:REG_OPENED_EXISTING_KEY]
  447.         return :REG_OPENED_EXISTING_KEY.id2name
  448.       end
  449.     else
  450.       Error.show("注册表新增键", error) if error != 0 && RMGTW::Debug
  451.       return error
  452.     end
  453.   end
  454.   #--------------------------------------------------------------------------
  455.   # ● 键的操作:删除指定的的键
  456.   #--------------------------------------------------------------------------
  457.   def remove(hKey, lpSubKey)
  458.     hKey = hKey.is_a?(Symbol) ? H[hKey] : hKey
  459.     error = RegDeleteKeyEx.call(hKey, lpSubKey.to_ansi,
  460.       H[:KEY_WOW64_32KEY], 0)
  461.     Error.show("注册表删除键", error) if error != 0 && RMGTW::Debug
  462.     return error
  463.   end
  464.   #--------------------------------------------------------------------------
  465.   # ● 键的操作:关闭已开启的键
  466.   #--------------------------------------------------------------------------
  467.   def close
  468.     error = RegCloseKey.call(@hKey)
  469.     @hKey = nil
  470.     @lpType = nil
  471.     @lpcbData = nil
  472.     Error.show("注册表关闭键", error) if error != 0 && RMGTW::Debug
  473.     return error
  474.   end
  475.   #--------------------------------------------------------------------------
  476.   # ● 值项的操作:取得已指定的键中指定值项的种类和长度
  477.   #--------------------------------------------------------------------------
  478.   def query(lpValueName)
  479.     lpType = [0].pack('L')
  480.     lpcbData = [0].pack('L')
  481.     error = RegQueryValueEx.call(@hKey, lpValueName.to_ansi, 0,
  482.       lpType, 0, lpcbData)
  483.     @lpType = lpType
  484.     @lpcbData = lpcbData
  485.     Error.show("注册表的键中取得值项", error) if error != 0 && RMGTW::Debug
  486.   end
  487.   #--------------------------------------------------------------------------
  488.   # ● 值项的操作:从已指定的键中取得指定值项的值
  489.   #--------------------------------------------------------------------------
  490.   def get(lpValueName)
  491.     query(lpValueName)
  492.     lpData = "\0".encode("ASCII-8BIT") * @lpcbData.unpack('L')[0]
  493.     error = RegQueryValueEx.call(@hKey, lpValueName.to_ansi,
  494.       0, @lpType, lpData, @lpcbData)
  495.     Error.show("注册表的键中取得值项的值", error) if error != 0 && RMGTW::Debug
  496.     return nil if error != 0
  497.     case @lpType.unpack('V')[0]
  498.     when H[:REG_DWORD], H[:REG_DWORD_LITTLE_ENDIAN]
  499.       return lpData.unpack('V')[0]
  500.     when H[:REG_DWORD_BIG_ENDIAN]
  501.       return lpData.unpack('N')[0]
  502.     when H[:REG_QWORD], H[:REG_QWORD_LITTLE_ENDIAN]
  503.       return lpData.unpack('Q')[0]
  504.     when H[:REG_SZ], H[:REG_EXPAND_SZ], H[:REG_LINK]
  505.       return lpData.chop.conv(:ACP, :UTF_8)
  506.     when H[:REG_MULTI_SZ]
  507.       return lpData.chop.split(%r{(\0)})
  508.         .delete_if { |s| s == "\0" }
  509.         .collect { |s| s.conv(:ACP, :UTF_8) }
  510.     else
  511.       return lpData.unpack('C*')
  512.     end
  513.   end
  514.   #--------------------------------------------------------------------------
  515.   # ● 值项的操作:从已指定的键中设定指定值项的值
  516.   #--------------------------------------------------------------------------
  517.   def set(lpValueName, lpData, dwType = 0)
  518.     if dwType == 0
  519.       query(lpValueName) if @lpType == nil
  520.       dwType = @lpType.unpack('V')[0]
  521.     else
  522.       dwType = dwType.is_a?(Symbol) ? H[dwType] : dwType
  523.     end
  524.     if dwType == H[:REG_NONE]
  525.       if lpData.is_a?(Integer)
  526.         if lpData >= 0 && lpData <= 0xFFFFFFFF
  527.           dwType = H[:REG_DWORD]
  528.         elsif lpData >= 0 && lpData <= 0xFFFFFFFFFFFFFFFF
  529.           dwType = H[:REG_QWORD]
  530.         elsif lpData < 0 || lpData > 0xFFFFFFFFFFFFFFFF
  531.           raise("lpData Value Error")
  532.         end
  533.       elsif lpData.is_a?(String)
  534.         dwType = H[:REG_SZ]
  535.       elsif lpData.is_a?(Array)
  536.         if lpData[0].is_a?(Integer)
  537.           dwType = H[:REG_BINARY]
  538.         elsif lpData[0].is_a?(String)
  539.           dwType = H[:REG_MULTI_SZ]
  540.         else
  541.           raise("lpData Type Error")
  542.         end
  543.       elsif lpData != nil
  544.         raise("lpData Type Error")
  545.       end
  546.       dwType_none = true
  547.     end
  548.     case dwType
  549.     when H[:REG_DWORD], H[:REG_DWORD_LITTLE_ENDIAN], H[:REG_DWORD_BIG_ENDIAN]
  550.       raise("lpData Type Error") unless lpData.is_a?(Integer)
  551.       if lpData < 0 || lpData > 0xFFFFFFFF
  552.         raise("lpData Value Error")
  553.       end
  554.       _lpData = [
  555.         lpData / 0x1 % 0x100,
  556.         lpData / 0x100 % 0x100,
  557.         lpData / 0x10000 % 0x100,
  558.         lpData / 0x1000000 % 0x100
  559.       ]
  560.       _lpData.reverse if dwType == H[:REG_DWORD_LITTLE_ENDIAN]
  561.       lpData = _lpData.pack("CCCC").force_encoding("ASCII-8BIT")
  562.     when H[:REG_QWORD], H[:REG_QWORD_LITTLE_ENDIAN]
  563.       raise("lpData Type Error") unless lpData.is_a?(Integer)
  564.       if lpData < 0 || lpData > 0xFFFFFFFFFFFFFFFF
  565.         raise("lpData Value Error")
  566.       end
  567.       _lpData = [
  568.         lpData / 0x1 % 0x100,
  569.         lpData / 0x100 % 0x100,
  570.         lpData / 0x10000 % 0x100,
  571.         lpData / 0x1000000 % 0x100,
  572.         lpData / 0x100000000 % 0x100,
  573.         lpData / 0x10000000000 % 0x100,
  574.         lpData / 0x1000000000000 % 0x100,
  575.         lpData / 0x100000000000000 % 0x100
  576.       ]
  577.       lpData = _lpData.pack("CCCCCCCC").force_encoding("ASCII-8BIT")
  578.     when H[:REG_SZ], H[:REG_EXPAND_SZ], H[:REG_LINK]
  579.       raise("lpData Type Error") unless lpData.is_a?(String)
  580.       lpData = lpData.conv(:UTF_8, :ACP)
  581.       lpData += "\0".encode("ASCII-8BIT")
  582.     when H[:REG_MULTI_SZ]
  583.       raise("lpData Type Error") unless lpData.is_a?(Array)
  584.       _lpData = ""
  585.       for i in 0..(lpData.length - 1)
  586.         raise("lpData Type Error") unless lpData[i].is_a?(String)
  587.         _lpData += lpData[i].conv(:UTF_8, :ACP)
  588.         _lpData += "\0".encode("ASCII-8BIT")
  589.       end
  590.       lpData = _lpData + "\0".encode("ASCII-8BIT")
  591.     else
  592.       if lpData != nil
  593.         for i in 0..(lpData.length - 1)
  594.           raise("lpData Type Error") unless lpData[i].is_a?(Integer)
  595.           raise("lpData Value Error") if lpData[i] < 0 || lpData[i] > 0xFF
  596.         end
  597.         lpData = lpData.pack('C*').force_encoding("ASCII-8BIT")
  598.       end
  599.     end
  600.     cbData = lpData.nil? ? 0 : lpData.size
  601.     dwType = H[:REG_NONE] if dwType_none
  602.     error = RegSetValueEx.call(@hKey, lpValueName.to_ansi, 0,
  603.       dwType, lpData, cbData)
  604.     Error.show("注册表的键中设定值项", error) if error != 0 && RMGTW::Debug
  605.     return error
  606.   end
  607.   #--------------------------------------------------------------------------
  608.   # ● 值项的操作:从已指定的键中删除指定的值项
  609.   #--------------------------------------------------------------------------
  610.   def delete(lpValueName)
  611.     error = RegDeleteValue.call(@hKey, lpValueName)
  612.     Error.show("注册表的键中删除值项", error) if error != 0 && RMGTW::Debug
  613.     return error
  614.   end
  615.   #--------------------------------------------------------------------------
  616.   # ● 设定权限
  617.   #--------------------------------------------------------------------------
  618.   private :query
  619.   #--------------------------------------------------------------------------
  620.   # ● 定义常数
  621.   #--------------------------------------------------------------------------
  622.   H = {
  623.     :HKEY_CLASSES_ROOT        => 0x80000000,
  624.     :HKEY_CURRENT_USER        => 0x80000001,
  625.     :HKEY_LOCAL_MACHINE       => 0x80000002,
  626.     :HKEY_USERS               => 0x80000003,
  627.     :HKEY_PERFORMANCE_DATA    => 0x80000004,
  628.     :HKEY_CURRENT_CONFIG      => 0x80000005,
  629.  
  630.     :REG_NONE                       => 0,
  631.     :REG_SZ                         => 1,
  632.     :REG_EXPAND_SZ                  => 2,
  633.     :REG_BINARY                     => 3,
  634.     :REG_DWORD                      => 4,
  635.     :REG_DWORD_LITTLE_ENDIAN        => 4,
  636.     :REG_DWORD_BIG_ENDIAN           => 5,
  637.     :REG_LINK                       => 6,
  638.     :REG_MULTI_SZ                   => 7,
  639.     :REG_RESOURCE_LIST              => 8,
  640.     :REG_FULL_RESOURCE_DESCRIPTOR   => 9,
  641.     :REG_RESOURCE_REQUIREMENTS_LIST => 10,
  642.     :REG_QWORD                      => 11,
  643.     :REG_QWORD_LITTLE_ENDIAN        => 11,
  644.  
  645.     :KEY_QUERY_VALUE        => 0x0001,
  646.     :KEY_SET_VALUE          => 0x0002,
  647.     :KEY_CREATE_SUB_KEY     => 0x0004,
  648.     :KEY_ENUMERATE_SUB_KEYS => 0x0008,
  649.     :KEY_NOTIFY             => 0x0010,
  650.     :KEY_CREATE_LINK        => 0x0020,
  651.     :KEY_READ               => 0x20019,
  652.     :KEY_WRITE              => 0x20006,
  653.     :KEY_EXECUTE            => 0x20019,
  654.     :KEY_ALL_ACCESS         => 0xF003F,
  655.     :KEY_WOW64_32KEY        => 0x0200,
  656.     :KEY_WOW64_64KEY        => 0x0100,
  657.  
  658.     :REG_OPTION_NON_VOLATILE   => 0x0000,
  659.     :REG_OPTION_VOLATILE       => 0x0001,
  660.     :REG_OPTION_CREATE_LINK    => 0x0002,
  661.     :REG_OPTION_BACKUP_RESTORE => 0x0004,
  662.     :REG_OPTION_OPEN_LINK      => 0x0008,
  663.  
  664.     :REG_CREATED_NEW_KEY     => 1,
  665.     :REG_OPENED_EXISTING_KEY => 2
  666.   }
  667. end
  668.  
  669. #==============================================================================
  670. # ■ Error
  671. #------------------------------------------------------------------------------
  672. #  这个模组用来显示错误讯息。
  673. #==============================================================================
  674. module Error
  675.   #--------------------------------------------------------------------------
  676.   # ● 防范NativeMethods
  677.   #--------------------------------------------------------------------------
  678.   include NativeMethods
  679.   #--------------------------------------------------------------------------
  680.   # ● 定义显示错误讯息
  681.   #--------------------------------------------------------------------------
  682.   def self.show(errstr, errcode)
  683.     url = "https://msdn.microsoft.com/library/windows/desktop/ms681381.aspx"
  684.     errcode = GetLastError.call() if errcode == 0
  685.     msg = sprintf("在%s发生错误,错误代码:%i,请至下列网址查询",
  686.       errstr, errcode)
  687.     if RMGTW::RaiseError
  688.       raise(sprintf("%s\n%s", msg, url))
  689.     else
  690.       p(msg); p(url)
  691.     end
  692.   end
  693. end

点评

GetLastError反馈的错误信息可以用FormatMessage的,不过这样也很清楚-  发表于 2015-2-23 21:54
LZ你去重写一个ruby附加库的注册表不就行了, 而且还有源代码参考  发表于 2015-2-23 17:55

Lv1.梦旅人

梦石
0
星屑
200
在线时间
78 小时
注册时间
2010-7-1
帖子
58
2
 楼主| 发表于 2015-2-23 21:08:04 | 只看该作者
我的程度還沒到那,而且其實需要的功能不會是全部的API,不過還是有參考一下啦
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-6-8 05:32

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表