作为一个Steam老玩家,我太懂那种被WIN+R代码淹没的痛苦了。每次在DY上看到"Steam喜加一"的推荐,兴奋地记下一串代码,结果过几天再看到同样的游戏推荐,完全想不起来自己到底领没领过。更糟的是,有些游戏领完发现是个Demo或者根本不好玩,想删又怕以后重复领取,不删又占着库位。
WIN+R输入steam://install/代码的方式确实快捷,但缺乏管理功能。我统计过自己的游戏库,通过这种方式领取的游戏超过200个后,管理就完全失控了。常见问题包括:
这就是为什么我们需要一个本地化的管理工具。AutoHotKey作为Windows平台最轻量的自动化工具,完美契合这个需求。它不需要复杂的开发环境,一个文本编辑器就能写脚本;编译后的exe文件只有几百KB;最重要的是它能直接调用Windows API,与Steam客户端无缝配合。
首先到AutoHotKey官网下载最新版本。建议选择v1.1的稳定版,因为我们的工具不需要v2.0的新特性。安装时注意勾选"添加右键菜单"选项,这样以后新建.ahk文件更方便。
安装完成后,新建一个文本文件,重命名为SteamCodeManager.ahk。右键这个文件选择"Edit Script",系统会用记事本打开它。不过我更推荐使用VS Code加上AutoHotKey插件,会有语法高亮和代码提示。
每个AutoHotKey脚本都需要一些基础配置。在我们的工具开头添加这些代码:
autohotkey复制#SingleInstance, Force ; 确保只运行一个实例
#NoTrayIcon ; 不显示托盘图标
SetWorkingDir, %A_ScriptDir% ; 设置工作目录
; 定义全局变量
global m_Title := "Steam Code Manager"
global m_Version := "v1.2"
global m_ConfigFile := A_ScriptDir "\SteamCodes.cfg"
这些配置确保了工具的单实例运行,隐藏了不必要的托盘图标,并定义了配置文件的存储位置。我建议把配置文件放在脚本同目录下,这样重装系统时不容易丢失数据。
AutoHotKey的GUI系统虽然简单,但足够构建一个实用的界面。我们先创建主窗口和三个功能区:
autohotkey复制Gui, SCM:New, , %m_Title% ; 创建名为SCM的GUI
Gui, SCM:Margin, 10, 10 ; 设置边距
; 代码输入区
Gui, SCM:Add, GroupBox, w220 h70 Section, Steam代码
Gui, SCM:Add, Edit, xp+10 yp+20 w100 vInputCode,
Gui, SCM:Add, Button, x+10 yp-2 gInstallBtn, 安装
Gui, SCM:Add, Button, x+10 yp gCheckBtn, 查询
; 操作区
Gui, SCM:Add, GroupBox, w400 h70 ys, 游戏管理
Gui, SCM:Add, Edit, xp+10 yp+20 w200 vEditField
Gui, SCM:Add, DropDownList, x+10 yp w80 vEditType, ID|名称|标签
Gui, SCM:Add, Button, x+10 yp gModifyBtn, 修改
Gui, SCM:Add, Button, x+10 yp gDeleteBtn, 删除
; 游戏列表区
Gui, SCM:Add, ListView, xs w620 r15 vGameList gListClick, 序号|ID|游戏名称|标签
这个布局包含了:
我特意把列表放在最下方,因为这是主要的信息展示区域。宽度设置为620px可以完整显示大多数游戏名称。
默认的ListView比较简陋,我们需要添加一些美化:
autohotkey复制; 设置列表样式
LV_ModifyCol(1, 50) ; 序号列宽50
LV_ModifyCol(2, 80) ; ID列宽80
LV_ModifyCol(3, 300) ; 名称列宽300
LV_ModifyCol(4, 150) ; 标签列宽150
; 设置交替行颜色
GuiControl, +AltSubmit, GameList
Gui, Color, FFFFFF
这些调整让列表看起来更专业。我还添加了交替行颜色,方便长时间浏览时区分行。实际使用中发现300px的宽度足够显示99%的游戏全名,只有少数超长的独立游戏名称需要悬停查看。
安装功能是工具的核心,需要处理几种情况:
autohotkey复制InstallBtn:
Gui, Submit, NoHide
if (InputCode = "") {
MsgBox, 请输入有效的Steam代码
return
}
; 检查是否已存在
found := 0
Loop % LV_GetCount() {
LV_GetText(id, A_Index, 2)
if (id = InputCode) {
found := A_Index
break
}
}
if (found) {
MsgBox, 4,, 该游戏已存在,是否重新安装?
IfMsgBox, No
return
}
Run, steam://install/%InputCode%
if (!found) {
LV_Add("", LV_GetCount()+1, InputCode, "新安装的游戏", "")
SaveToFile()
}
return
查询功能相对简单,主要是高亮显示已存在的游戏:
autohotkey复制CheckBtn:
Gui, Submit, NoHide
if (InputCode = "") {
MsgBox, 请输入有效的Steam代码
return
}
Loop % LV_GetCount() {
LV_GetText(id, A_Index, 2)
if (id = InputCode) {
LV_Modify(A_Index, "Select Vis")
MsgBox, 已找到游戏:%id%
return
}
}
MsgBox, 未找到该代码对应的游戏
return
我们需要把游戏列表保存到本地文件,这样下次启动工具时能恢复数据。我选择使用简单的文本格式:
code复制921590:DISSIDIA FINAL FANTASY NT Free Edition:格斗
520720:Dear Esther:Landmark Edition:冒险
对应的读写函数:
autohotkey复制LoadFromFile() {
global m_ConfigFile
if !FileExist(m_ConfigFile)
return
FileRead, content, %m_ConfigFile%
Loop, Parse, content, `n, `r
{
if (A_LoopField = "")
continue
parts := StrSplit(A_LoopField, ":")
if (parts.Length() >= 2) {
LV_Add("", LV_GetCount()+1, parts[1], parts[2], parts[3] ? parts[3] : "")
}
}
}
SaveToFile() {
global m_ConfigFile
content := ""
Loop % LV_GetCount() {
LV_GetText(id, A_Index, 2)
LV_GetText(name, A_Index, 3)
LV_GetText(tag, A_Index, 4)
content .= id ":" name ":" tag "`n"
}
FileDelete, %m_ConfigFile%
FileAppend, %content%, %m_ConfigFile%
}
这种格式简单直观,即使直接打开配置文件也能轻松编辑。我在实际使用中还会定期备份这个文件,防止意外丢失数据。
除了手动添加,我们还可以批量导入代码。创建一个ImportCodes.txt,每行一个代码:
code复制921590
520720
730
然后添加导入功能:
autohotkey复制Gui, SCM:Add, Button, xs gImportBtn, 批量导入
Gui, SCM:Add, Button, x+10 gExportBtn, 导出列表
ImportBtn:
FileSelectFile, file,,, 选择导入文件, Text Documents (*.txt)
if (file = "")
return
imported := 0
FileRead, content, %file%
Loop, Parse, content, `n, `r
{
code := Trim(A_LoopField)
if code is not Integer
continue
; 检查是否已存在
exists := 0
Loop % LV_GetCount() {
LV_GetText(id, A_Index, 2)
if (id = code) {
exists := 1
break
}
}
if (!exists) {
LV_Add("", LV_GetCount()+1, code, "待查询游戏", "")
imported++
}
}
if (imported > 0) {
SaveToFile()
MsgBox, 成功导入 %imported% 个游戏代码
} else {
MsgBox, 没有新代码可导入
}
return
导出功能则可以把当前列表保存为CSV格式,方便用Excel打开分析:
autohotkey复制ExportBtn:
FileSelectFile, file, S16,, 导出游戏列表, CSV文件 (*.csv)
if (file = "")
return
if !InStr(file, ".csv")
file .= ".csv"
content := "序号,ID,游戏名称,标签`n"
Loop % LV_GetCount() {
LV_GetText(no, A_Index, 1)
LV_GetText(id, A_Index, 2)
LV_GetText(name, A_Index, 3)
LV_GetText(tag, A_Index, 4)
content .= no "," id "," name "," tag "`n"
}
FileDelete, %file%
FileAppend, %content%, %file%
MsgBox, 已导出 %LV_GetCount% 条记录
return
为了避免重复领取游戏,我们可以增强查询功能:
autohotkey复制; 在查询按钮代码中添加这部分
LV_GetText(name, found, 3)
LV_GetText(tag, found, 4)
MsgBox, 游戏信息:`nID: %InputCode%`n名称: %name%`n标签: %tag%
标签系统可以帮助我们分类游戏。添加标签管理功能:
autohotkey复制Gui, SCM:Add, Button, x+10 gTagBtn, 管理标签
TagBtn:
row := LV_GetNext()
if (!row) {
MsgBox, 请先选择一行
return
}
LV_GetText(id, row, 2)
LV_GetText(name, row, 3)
LV_GetText(curTag, row, 4)
InputBox, newTag, 编辑标签, 为游戏设置标签:`n%name%, , 300, 150, , , , , %curTag%
if (!ErrorLevel && newTag != curTag) {
LV_Modify(row, "", "", "", "", newTag)
SaveToFile()
}
return
有了标签系统后,我们可以快速筛选特定类型的游戏,比如标记所有"限免"游戏,方便后续整理。
虽然.ahk脚本可以直接运行,但编译成exe更方便分发和使用:
编译后的exe可以放在任意位置运行,它会自动在同目录下创建配置文件。我习惯把它固定在任务栏,随时可以调出使用。
典型的使用流程是这样的:
这个工具特别适合以下场景:
经过几个月的使用,我的Steam库终于恢复了秩序。现在看到任何Steam代码,我都能在3秒内确认是否已经拥有,再也不会出现重复领取的尴尬情况了。