You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Steamworks SDK在C++应用中无法接收ScreenshotRequested回调

问题:Steamworks SDK Hook截图后无法接收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; // 替换为原子变量
// ...

额外验证步骤

  1. 单独运行控制台程序(不启动Game1.exe),触发截图热键,确认是否能收到ScreenshotRequested_t回调——若能,说明问题出在Game1.exe抢占事件。
  2. 确认SteamScreenshots()->IsScreenshotsHooked()返回true,确保截图Hook已生效。

内容的提问来源于stack exchange,提问作者Reizenchuu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 08:50:11