使用Steamworks SDK在C++应用中无法接收ScreenshotRequested回调
ScreenshotRequested_t回调 我写了一个C++控制台程序,用来测试Steamworks SDK——它会启动我的Steam游戏(Game1.exe),同时集成Steam SDK接收回调。代码如下:
#include <iostream> #include "../HeaderFiles/steam_api.h" #include <thread> #include <cstdlib> class MyGameClass { public: MyGameClass() : m_ScreenshotReadyCallback(this, &MyGameClass::OnScreenshotReady), m_ScreenshotRequestedCallback(this, &MyGameClass::OnScreenshotRequested) { running = true; } ~MyGameClass() { running = false; if (gameThread.joinable()) { gameThread.join(); } } void OnScreenshotRequested(ScreenshotRequested_t* pParam) { std::cerr << "Screenshot requested!" << std::endl; std::cout << "Screenshot hooked: " << pParam << std::endl; } void OnScreenshotReady(ScreenshotReady_t* pParam) { if (pParam->m_eResult == k_EResultOK) { std::cerr << "Screenshot ready!" << std::endl; } } void StartGameExecutable() { gameThread = std::thread(&MyGameClass::RunGameExecutable, this); } void RunSteamCallbacks() { while (running) { SteamAPI_RunCallbacks(); std::this_thread::sleep_for(std::chrono::milliseconds(16)); } } private: std::thread gameThread; bool running; void RunGameExecutable() { std::system("Game1.exe"); } CCallback<MyGameClass, ScreenshotRequested_t> m_ScreenshotRequestedCallback; CCallback<MyGameClass, ScreenshotReady_t> m_ScreenshotReadyCallback; }; int main() { if (!SteamAPI_Init()) { std::cerr << "SteamAPI initialization failed" << std::endl; return 1; } SteamScreenshots()->HookScreenshots(true); MyGameClass myGame; myGame.StartGameExecutable(); bool hooked = SteamScreenshots()->IsScreenshotsHooked(); std::cout << "Screenshot hooked: " << hooked << std::endl; myGame.RunSteamCallbacks(); SteamAPI_Shutdown(); return 0; }
问题是:明明调用了SteamScreenshots()->HookScreenshots(true),却收不到ScreenshotRequested_t回调,但能正常收到ScreenshotReady_t。根据Steam官方文档:
By default Steam will handle taking screenshots, but you can take over control by hooking the screenshots using ISteamScreenshots::HookScreenshots. If you're hooking the screenshots you'll be getting a ScreenshotRequested_t callback when the user presses the screenshot hotkey. You can check if you're currently hooking screenshots with ISteamScreenshots::IsScreenshotsHooked.
我需要完全接管截图流程,不想让Steam处理,求问题原因和解决办法。
可能的原因及解决办法
1. 回调注册时机晚于Hook调用
当前代码的执行顺序是:初始化SteamAPI → 开启截图Hook → 注册回调。但Steam要求回调必须在Hook操作之前完成注册,否则Hook生效后触发的事件无法被后续注册的回调捕获。
修复方案:
调整代码顺序,先创建MyGameClass(完成回调注册),再调用HookScreenshots(true):
int main() { if (!SteamAPI_Init()) { std::cerr << "SteamAPI initialization failed" << std::endl; return 1; } MyGameClass myGame; // 先完成回调注册 SteamScreenshots()->HookScreenshots(true); // 再开启截图Hook myGame.StartGameExecutable(); bool hooked = SteamScreenshots()->IsScreenshotsHooked(); std::cout << "Screenshot hooked: " << hooked << std::endl; myGame.RunSteamCallbacks(); SteamAPI_Shutdown(); return 0; }
2. 前台游戏进程抢占了截图事件
如果你的Game1.exe本身也集成了Steamworks SDK,Steam客户端会默认把截图热键事件发送给当前处于前台的游戏进程(即Game1.exe),而非后台运行的控制台程序。
修复方案:
- 测试时先关闭Game1.exe的Steamworks集成,或者切换控制台程序到前台后触发截图热键,验证是否能收到回调。
- 若需控制台程序接管游戏截图,需确保控制台程序与Game1.exe使用同一个AppID:在控制台程序的运行目录下创建
steam_appid.txt并写入对应AppID,启动程序时Steam需登录该AppID的关联账号。
3. AppID未正确配置
如果控制台程序没有正确设置Steam AppID,SteamAPI_Init()可能只是表面初始化,无法正常接收回调。
修复方案:
- 在控制台程序运行目录创建
steam_appid.txt,写入你的游戏AppID。 - 或在
SteamAPI_Init()前手动设置AppID:
SteamAPI_SetAppID(你的游戏AppID); if (!SteamAPI_Init()) { std::cerr << "SteamAPI initialization failed" << std::endl; return 1; }
4. 线程安全问题
running变量是普通bool,多线程环境下可能出现竞争问题,导致回调循环提前退出。
修复方案:
将running改为std::atomic<bool>:
#include <atomic> // ... private: std::thread gameThread; std::atomic<bool> running; // 替换为原子变量 // ...
额外验证步骤
- 单独运行控制台程序(不启动Game1.exe),触发截图热键,确认是否能收到
ScreenshotRequested_t回调——若能,说明问题出在Game1.exe抢占事件。 - 确认
SteamScreenshots()->IsScreenshotsHooked()返回true,确保截图Hook已生效。
内容的提问来源于stack exchange,提问作者Reizenchuu

