安全开发专题

5、屏幕截屏

1、课程目标

  1. 理解Windows图形设备接口(GDI)
  2. 掌握屏幕截图技术实现
  3. 实现高效的屏幕捕获功能
  4. 了解图像格式转换和保存

2、名词解释

术语 全称 解释
GDI Graphics Device Interface Windows图形设备接口
BitBlt Bit Block Transfer 位块传输
HDC Handle to Device Context 设备上下文句柄
Bitmap 位图 图像数据结构

3、技术原理

1. Windows图形系统

Windows图形架构:
┌─────────────────────────────────────┐
│           应用程序                  │
├─────────────────────────────────────┤
│           GDI/GDI+                  │
├─────────────────────────────────────┤
│         Device Drivers              │
├─────────────────────────────────────┤
│         Graphics Hardware           │
└─────────────────────────────────────┘

屏幕截图原理:
1. 获取屏幕设备上下文(HDC)
2. 创建兼容的内存设备上下文
3. 创建位图对象
4. 将屏幕内容复制到位图
5. 保存位图数据

2. 屏幕截图技术

主要API:
GetDC()          - 获取设备上下文
CreateCompatibleDC() - 创建兼容DC
CreateCompatibleBitmap() - 创建兼容位图
BitBlt()         - 位块传输
GetDIBits()      - 获取位图数据

3、代码实现

1. 基础屏幕截图实现

// screen_capture.cpp
// 基础屏幕截图实现

#include <windows.h>
#include <stdio.h>
#include <string>
#include <vector>

// BMP文件头结构
#pragma pack(push, 1)
typedef struct {
    WORD    bfType;
    DWORD   bfSize;
    WORD    bfReserved1;
    WORD    bfReserved2;
    DWORD   bfOffBits;
} BITMAPFILEHEADER_COMPAT;
#pragma pack(pop)

// 屏幕截图类
class ScreenCapture {
public:
    // 截取全屏
    static bool CaptureScreen(const char* filename) {
        // 获取屏幕尺寸
        int screenWidth = GetSystemMetrics(SM_CXSCREEN);
        int screenHeight = GetSystemMetrics(SM_CYSCREEN);
        
        // 获取屏幕DC
        HDC hScreenDC = GetDC(NULL);
        if (!hScreenDC) {
            printf("[-] Failed to get screen DC\n");
            return false;
        }
        
        // 创建兼容的内存DC
        HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
        if (!hMemoryDC) {
            ReleaseDC(NULL, hScreenDC);
            printf("[-] Failed to create memory DC\n");
            return false;
        }
        
        // 创建兼容位图
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
        if (!hBitmap) {
            DeleteDC(hMemoryDC);
            ReleaseDC(NULL, hScreenDC);
            printf("[-] Failed to create bitmap\n");
            return false;
        }
        
        // 选择位图到内存DC
        HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);
        
        // 复制屏幕到内存DC
        if (!BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, 
                   hScreenDC, 0, 0, SRCCOPY)) {
            printf("[-] BitBlt failed\n");
            SelectObject(hMemoryDC, hOldBitmap);
            DeleteObject(hBitmap);
            DeleteDC(hMemoryDC);
            ReleaseDC(NULL, hScreenDC);
            return false;
        }
        
        // 保存位图到文件
        bool result = SaveBitmapToFile(hBitmap, hMemoryDC, filename);
        
        // 清理资源
        SelectObject(hMemoryDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(NULL, hScreenDC);
        
        return result;
    }
    
    // 截取指定区域
    static bool CaptureRegion(int x, int y, int width, int height, const char* filename) {
        // 获取屏幕DC
        HDC hScreenDC = GetDC(NULL);
        if (!hScreenDC) return false;
        
        // 创建内存DC
        HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
        if (!hMemoryDC) {
            ReleaseDC(NULL, hScreenDC);
            return false;
        }
        
        // 创建位图
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
        if (!hBitmap) {
            DeleteDC(hMemoryDC);
            ReleaseDC(NULL, hScreenDC);
            return false;
        }
        
        // 选择位图
        HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);
        
        // 复制指定区域
        if (!BitBlt(hMemoryDC, 0, 0, width, height, 
                   hScreenDC, x, y, SRCCOPY)) {
            SelectObject(hMemoryDC, hOldBitmap);
            DeleteObject(hBitmap);
            DeleteDC(hMemoryDC);
            ReleaseDC(NULL, hScreenDC);
            return false;
        }
        
        // 保存位图
        bool result = SaveBitmapToFile(hBitmap, hMemoryDC, filename);
        
        // 清理
        SelectObject(hMemoryDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(NULL, hScreenDC);
        
        return result;
    }
    
private:
    // 保存位图为BMP文件
    static bool SaveBitmapToFile(HBITMAP hBitmap, HDC hDC, const char* filename) {
        // 获取位图信息
        BITMAP bmp;
        if (!GetObject(hBitmap, sizeof(BITMAP), &bmp)) {
            return false;
        }
        
        // 准备BITMAPINFO结构
        BITMAPINFOHEADER bi = {0};
        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = bmp.bmWidth;
        bi.biHeight = bmp.bmHeight;
        bi.biPlanes = 1;
        bi.biBitCount = 24;
        bi.biCompression = BI_RGB;
        bi.biSizeImage = 0;
        
        // 计算行大小(4字节对齐)
        DWORD dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
        
        // 分配内存存储位图数据
        std::vector<BYTE> bmpData(dwBmpSize);
        
        // 获取位图数据
        if (!GetDIBits(hDC, hBitmap, 0, bmp.bmHeight, 
                      bmpData.data(), (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
            return false;
        }
        
        // 创建文件
        HANDLE hFile = CreateFileA(
            filename,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
        );
        
        if (hFile == INVALID_HANDLE_VALUE) {
            return false;
        }
        
        // 写入文件头
        BITMAPFILEHEADER_COMPAT bmfHeader = {0};
        bmfHeader.bfType = 0x4D42; // "BM"
        bmfHeader.bfSize = sizeof(BITMAPFILEHEADER_COMPAT) + sizeof(BITMAPINFOHEADER) + dwBmpSize;
        bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER_COMPAT) + sizeof(BITMAPINFOHEADER);
        
        DWORD written;
        WriteFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER_COMPAT), &written, NULL);
        WriteFile(hFile, &bi, sizeof(BITMAPINFOHEADER), &written, NULL);
        WriteFile(hFile, bmpData.data(), dwBmpSize, &written, NULL);
        
        CloseHandle(hFile);
        
        printf("[+] Screenshot saved: %s (%dx%d)\n", filename, bmp.bmWidth, bmp.bmHeight);
        return true;
    }
};

// 测试函数
void TestScreenCapture() {
    printf("=== Screen Capture Test ===\n");
    
    // 截取全屏
    if (ScreenCapture::CaptureScreen("screenshot_full.bmp")) {
        printf("[+] Full screen captured\n");
    }
    
    // 截取指定区域
    if (ScreenCapture::CaptureRegion(100, 100, 800, 600, "screenshot_region.bmp")) {
        printf("[+] Region captured\n");
    }
}

2. 高级屏幕截图技术

// advanced_screen_capture.cpp
// 高级屏幕截图技术

#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
#include <string>
#include <vector>

#pragma comment(lib, "gdiplus.lib")

// 高级屏幕截图类
class AdvancedScreenCapture {
private:
    static ULONG_PTR gdiplusToken;
    
public:
    // 初始化GDI+
    static bool InitializeGDIPlus() {
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        return (Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Gdiplus::Ok);
    }
    
    // 清理GDI+
    static void ShutdownGDIPlus() {
        Gdiplus::GdiplusShutdown(gdiplusToken);
    }
    
    // 截取屏幕并保存为PNG
    static bool CaptureScreenToPNG(const char* filename) {
        // 获取屏幕尺寸
        int screenWidth = GetSystemMetrics(SM_CXSCREEN);
        int screenHeight = GetSystemMetrics(SM_CYSCREEN);
        
        // 获取屏幕DC
        HDC hScreenDC = GetDC(NULL);
        if (!hScreenDC) return false;
        
        // 创建内存DC
        HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
        if (!hMemoryDC) {
            ReleaseDC(NULL, hScreenDC);
            return false;
        }
        
        // 创建DIB段
        BITMAPINFO bmi = {0};
        bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biWidth = screenWidth;
        bmi.bmiHeader.biHeight = -screenHeight; // 负值表示顶-down DIB
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = 32;
        bmi.bmiHeader.biCompression = BI_RGB;
        
        VOID* bits = nullptr;
        HBITMAP hBitmap = CreateDIBSection(hMemoryDC, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
        if (!hBitmap) {
            DeleteDC(hMemoryDC);
            ReleaseDC(NULL, hScreenDC);
            return false;
        }
        
        // 选择位图
        HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);
        
        // 复制屏幕内容
        BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 0, 0, SRCCOPY);
        
        // 创建GDI+ Bitmap
        Gdiplus::Bitmap* pBitmap = new Gdiplus::Bitmap(screenWidth, screenHeight, 
                                                       screenWidth * 4, PixelFormat32bppARGB, 
                                                       (BYTE*)bits);
        
        // 保存为PNG
        CLSID clsid;
        GetEncoderClsid(L"image/png", &clsid);
        
        std::wstring wFilename(filename, filename + strlen(filename));
        Gdiplus::Status status = pBitmap->Save(wFilename.c_str(), &clsid, NULL);
        
        // 清理
        delete pBitmap;
        SelectObject(hMemoryDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(NULL, hScreenDC);
        
        return (status == Gdiplus::Ok);
    }
    
    // 截取活动窗口
    static bool CaptureActiveWindow(const char* filename) {
        // 获取活动窗口
        HWND hWnd = GetForegroundWindow();
        if (!hWnd) return false;
        
        // 获取窗口位置和大小
        RECT rect;
        GetWindowRect(hWnd, &rect);
        
        int width = rect.right - rect.left;
        int height = rect.bottom - rect.top;
        
        // 获取窗口DC
        HDC hWindowDC = GetDC(hWnd);
        if (!hWindowDC) return false;
        
        // 创建内存DC
        HDC hMemoryDC = CreateCompatibleDC(hWindowDC);
        if (!hMemoryDC) {
            ReleaseDC(hWnd, hWindowDC);
            return false;
        }
        
        // 创建位图
        HBITMAP hBitmap = CreateCompatibleBitmap(hWindowDC, width, height);
        if (!hBitmap) {
            DeleteDC(hMemoryDC);
            ReleaseDC(hWnd, hWindowDC);
            return false;
        }
        
        // 选择位图
        HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);
        
        // 复制窗口内容
        PrintWindow(hWnd, hMemoryDC, PW_CLIENTONLY);
        
        // 保存位图
        bool result = SaveBitmapToJPEG(hBitmap, hMemoryDC, filename);
        
        // 清理
        SelectObject(hMemoryDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(hWnd, hWindowDC);
        
        return result;
    }
    
private:
    // 获取图像编码器CLSID
    static int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
        UINT num = 0;
        UINT size = 0;
        
        Gdiplus::GetImageEncodersSize(&num, &size);
        if (size == 0) return -1;
        
        Gdiplus::ImageCodecInfo* pImageCodecInfo = (Gdiplus::ImageCodecInfo*)malloc(size);
        if (!pImageCodecInfo) return -1;
        
        Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);
        
        for (UINT i = 0; i < num; ++i) {
            if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0) {
                *pClsid = pImageCodecInfo[i].Clsid;
                free(pImageCodecInfo);
                return i;
            }
        }
        
        free(pImageCodecInfo);
        return -1;
    }
    
    // 保存位图为JPEG
    static bool SaveBitmapToJPEG(HBITMAP hBitmap, HDC hDC, const char* filename) {
        // 获取位图信息
        BITMAP bmp;
        GetObject(hBitmap, sizeof(BITMAP), &bmp);
        
        // 创建GDI+ Bitmap
        Gdiplus::Bitmap* pBitmap = Gdiplus::Bitmap::FromHBITMAP(hBitmap, NULL);
        if (!pBitmap) return false;
        
        // 设置JPEG质量参数
        Gdiplus::EncoderParameters encoderParams;
        encoderParams.Count = 1;
        encoderParams.Parameter[0].Guid = Gdiplus::EncoderQuality;
        encoderParams.Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong;
        encoderParams.Parameter[0].NumberOfValues = 1;
        
        ULONG quality = 90;
        encoderParams.Parameter[0].Value = &quality;
        
        // 获取JPEG编码器
        CLSID clsid;
        GetEncoderClsid(L"image/jpeg", &clsid);
        
        // 转换文件名为宽字符
        std::wstring wFilename(filename, filename + strlen(filename));
        
        // 保存
        Gdiplus::Status status = pBitmap->Save(wFilename.c_str(), &clsid, &encoderParams);
        
        delete pBitmap;
        return (status == Gdiplus::Ok);
    }
};

// GDI+ Token
ULONG_PTR AdvancedScreenCapture::gdiplusToken = 0;

// 测试高级截图功能
void TestAdvancedCapture() {
    printf("=== Advanced Screen Capture Test ===\n");
    
    // 初始化GDI+
    if (!AdvancedScreenCapture::InitializeGDIPlus()) {
        printf("[-] Failed to initialize GDI+\n");
        return;
    }
    
    // 截取屏幕保存为PNG
    if (AdvancedScreenCapture::CaptureScreenToPNG("advanced_screenshot.png")) {
        printf("[+] Screen captured to PNG\n");
    }
    
    // 截取活动窗口保存为JPEG
    if (AdvancedScreenCapture::CaptureActiveWindow("active_window.jpg")) {
        printf("[+] Active window captured to JPEG\n");
    }
    
    // 清理GDI+
    AdvancedScreenCapture::ShutdownGDIPlus();
}

3. 隐蔽屏幕截图实现

// stealth_screen_capture.cpp
// 隐蔽屏幕截图实现

#include <windows.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <thread>
#include <chrono>

// 隐蔽屏幕截图类
class StealthScreenCapture {
private:
    bool m_enabled;
    std::string m_outputDir;
    int m_interval; // 截图间隔(秒)
    
public:
    StealthScreenCapture() : m_enabled(false), m_interval(30) {}
    
    // 设置输出目录
    void SetOutputDirectory(const char* dir) {
        m_outputDir = dir;
        CreateDirectoryA(dir, NULL);
    }
    
    // 设置截图间隔
    void SetInterval(int seconds) {
        m_interval = seconds;
    }
    
    // 启动隐蔽截图
    void Start() {
        if (m_enabled) return;
        
        m_enabled = true;
        printf("[+] Stealth screen capture started\n");
        
        // 启动截图线程
        std::thread captureThread(&StealthScreenCapture::CaptureThread, this);
        captureThread.detach();
    }
    
    // 停止隐蔽截图
    void Stop() {
        m_enabled = false;
        printf("[+] Stealth screen capture stopped\n");
    }
    
    // 检查是否启用
    bool IsEnabled() const {
        return m_enabled;
    }
    
private:
    // 截图线程
    void CaptureThread() {
        int counter = 0;
        
        while (m_enabled) {
            // 生成文件名
            char filename[MAX_PATH];
            sprintf_s(filename, "%s\\capture_%04d.bmp", m_outputDir.c_str(), counter++);
            
            // 截图
            if (CaptureSilent(filename)) {
                printf("[+] Screenshot saved: %s\n", filename);
            }
            
            // 等待下一次截图
            for (int i = 0; i < m_interval && m_enabled; i++) {
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        }
    }
    
    // 隐蔽截图(无提示)
    bool CaptureSilent(const char* filename) {
        // 隐藏光标
        ShowCursor(FALSE);
        
        // 获取屏幕尺寸
        int screenWidth = GetSystemMetrics(SM_CXSCREEN);
        int screenHeight = GetSystemMetrics(SM_CYSCREEN);
        
        // 获取屏幕DC
        HDC hScreenDC = GetDC(NULL);
        if (!hScreenDC) {
            ShowCursor(TRUE);
            return false;
        }
        
        // 创建内存DC
        HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
        if (!hMemoryDC) {
            ReleaseDC(NULL, hScreenDC);
            ShowCursor(TRUE);
            return false;
        }
        
        // 创建位图
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
        if (!hBitmap) {
            DeleteDC(hMemoryDC);
            ReleaseDC(NULL, hScreenDC);
            ShowCursor(TRUE);
            return false;
        }
        
        // 选择位图
        HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);
        
        // 复制屏幕内容
        BOOL result = BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight,
                            hScreenDC, 0, 0, SRCCOPY);
        
        // 恢复光标
        ShowCursor(TRUE);
        
        if (result) {
            // 保存位图
            result = SaveBitmapToFile(hBitmap, hMemoryDC, filename);
        }
        
        // 清理资源
        SelectObject(hMemoryDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(NULL, hScreenDC);
        
        return (result != FALSE);
    }
    
    // 保存位图文件(静默)
    bool SaveBitmapToFile(HBITMAP hBitmap, HDC hDC, const char* filename) {
        BITMAP bmp;
        GetObject(hBitmap, sizeof(BITMAP), &bmp);
        
        BITMAPINFOHEADER bi = {0};
        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = bmp.bmWidth;
        bi.biHeight = bmp.bmHeight;
        bi.biPlanes = 1;
        bi.biBitCount = 24;
        bi.biCompression = BI_RGB;
        
        DWORD dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
        std::vector<BYTE> bmpData(dwBmpSize);
        
        if (!GetDIBits(hDC, hBitmap, 0, bmp.bmHeight, 
                      bmpData.data(), (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
            return false;
        }
        
        // 创建隐藏文件
        HANDLE hFile = CreateFileA(
            filename,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_HIDDEN,
            NULL
        );
        
        if (hFile == INVALID_HANDLE_VALUE) {
            return false;
        }
        
        BITMAPFILEHEADER_COMPAT bmfHeader = {0};
        bmfHeader.bfType = 0x4D42;
        bmfHeader.bfSize = sizeof(BITMAPFILEHEADER_COMPAT) + sizeof(BITMAPINFOHEADER) + dwBmpSize;
        bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER_COMPAT) + sizeof(BITMAPINFOHEADER);
        
        DWORD written;
        WriteFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER_COMPAT), &written, NULL);
        WriteFile(hFile, &bi, sizeof(BITMAPINFOHEADER), &written, NULL);
        WriteFile(hFile, bmpData.data(), dwBmpSize, &written, NULL);
        
        CloseHandle(hFile);
        return true;
    }
};

// 测试隐蔽截图
void TestStealthCapture() {
    printf("=== Stealth Screen Capture Test ===\n");
    
    StealthScreenCapture capture;
    capture.SetOutputDirectory("captures");
    capture.SetInterval(10); // 10秒间隔
    
    capture.Start();
    
    printf("[*] Stealth capture running for 60 seconds...\n");
    Sleep(60000); // 运行1分钟
    
    capture.Stop();
    printf("[*] Stealth capture test completed\n");
}

4. 屏幕截图管理器

// screenshot_manager.cpp
// 屏幕截图管理器

#include <windows.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>

// 截图格式枚举
enum class CaptureFormat {
    BMP,
    JPEG,
    PNG
};

// 截图区域类型
enum class CaptureArea {
    FullScreen,
    ActiveWindow,
    CustomRegion
};

// 截图管理器
class ScreenshotManager {
private:
    std::string m_outputDir;
    CaptureFormat m_format;
    int m_quality; // JPEG/PNG质量 (1-100)
    bool m_timestamp; // 是否添加时间戳
    
public:
    ScreenshotManager() : m_format(CaptureFormat::BMP), 
                         m_quality(90), m_timestamp(true) {
        SetOutputDirectory(".");
    }
    
    // 设置输出目录
    void SetOutputDirectory(const char* dir) {
        m_outputDir = dir;
        CreateDirectoryA(dir, NULL);
    }
    
    // 设置截图格式
    void SetFormat(CaptureFormat format) {
        m_format = format;
    }
    
    // 设置图像质量
    void SetQuality(int quality) {
        m_quality = std::max(1, std::min(100, quality));
    }
    
    // 设置时间戳
    void SetTimestamp(bool enable) {
        m_timestamp = enable;
    }
    
    // 截取屏幕
    bool CaptureScreen(CaptureArea area = CaptureArea::FullScreen, 
                      int x = 0, int y = 0, int width = 0, int height = 0) {
        std::string filename = GenerateFilename();
        
        switch (area) {
            case CaptureArea::FullScreen:
                return CaptureFullScreen(filename.c_str());
                
            case CaptureArea::ActiveWindow:
                return CaptureActiveWindow(filename.c_str());
                
            case CaptureArea::CustomRegion:
                return CaptureRegion(x, y, width, height, filename.c_str());
                
            default:
                return false;
        }
    }
    
    // 批量截图
    int BatchCapture(int count, int intervalMs) {
        int successCount = 0;
        
        for (int i = 0; i < count; i++) {
            if (CaptureScreen()) {
                successCount++;
            }
            
            if (i < count - 1) {
                Sleep(intervalMs);
            }
        }
        
        return successCount;
    }
    
private:
    // 生成文件名
    std::string GenerateFilename() {
        char filename[MAX_PATH];
        
        if (m_timestamp) {
            SYSTEMTIME st;
            GetLocalTime(&st);
            sprintf_s(filename, "%s\\screenshot_%04d%02d%02d_%02d%02d%02d.%s",
                     m_outputDir.c_str(),
                     st.wYear, st.wMonth, st.wDay,
                     st.wHour, st.wMinute, st.wSecond,
                     GetExtension());
        } else {
            static int counter = 0;
            sprintf_s(filename, "%s\\screenshot_%04d.%s",
                     m_outputDir.c_str(), counter++, GetExtension());
        }
        
        return std::string(filename);
    }
    
    // 获取文件扩展名
    const char* GetExtension() {
        switch (m_format) {
            case CaptureFormat::BMP: return "bmp";
            case CaptureFormat::JPEG: return "jpg";
            case CaptureFormat::PNG: return "png";
            default: return "bmp";
        }
    }
    
    // 截取全屏
    bool CaptureFullScreen(const char* filename) {
        int screenWidth = GetSystemMetrics(SM_CXSCREEN);
        int screenHeight = GetSystemMetrics(SM_CYSCREEN);
        
        HDC hScreenDC = GetDC(NULL);
        HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
        
        HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);
        BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 0, 0, SRCCOPY);
        
        bool result = SaveBitmap(hBitmap, hMemoryDC, filename);
        
        SelectObject(hMemoryDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(NULL, hScreenDC);
        
        return result;
    }
    
    // 截取活动窗口
    bool CaptureActiveWindow(const char* filename) {
        HWND hWnd = GetForegroundWindow();
        if (!hWnd) return false;
        
        RECT rect;
        GetWindowRect(hWnd, &rect);
        
        int width = rect.right - rect.left;
        int height = rect.bottom - rect.top;
        
        HDC hWindowDC = GetDC(hWnd);
        HDC hMemoryDC = CreateCompatibleDC(hWindowDC);
        HBITMAP hBitmap = CreateCompatibleBitmap(hWindowDC, width, height);
        
        HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);
        PrintWindow(hWnd, hMemoryDC, PW_CLIENTONLY);
        
        bool result = SaveBitmap(hBitmap, hMemoryDC, filename);
        
        SelectObject(hMemoryDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(hWnd, hWindowDC);
        
        return result;
    }
    
    // 截取指定区域
    bool CaptureRegion(int x, int y, int width, int height, const char* filename) {
        HDC hScreenDC = GetDC(NULL);
        HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
        
        HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);
        BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, x, y, SRCCOPY);
        
        bool result = SaveBitmap(hBitmap, hMemoryDC, filename);
        
        SelectObject(hMemoryDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(NULL, hScreenDC);
        
        return result;
    }
    
    // 保存位图
    bool SaveBitmap(HBITMAP hBitmap, HDC hDC, const char* filename) {
        switch (m_format) {
            case CaptureFormat::BMP:
                return SaveAsBMP(hBitmap, hDC, filename);
                
            case CaptureFormat::JPEG:
                return SaveAsJPEG(hBitmap, hDC, filename);
                
            case CaptureFormat::PNG:
                return SaveAsPNG(hBitmap, hDC, filename);
                
            default:
                return SaveAsBMP(hBitmap, hDC, filename);
        }
    }
    
    // 保存为BMP
    bool SaveAsBMP(HBITMAP hBitmap, HDC hDC, const char* filename) {
        BITMAP bmp;
        GetObject(hBitmap, sizeof(BITMAP), &bmp);
        
        BITMAPINFOHEADER bi = {0};
        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = bmp.bmWidth;
        bi.biHeight = bmp.bmHeight;
        bi.biPlanes = 1;
        bi.biBitCount = 24;
        bi.biCompression = BI_RGB;
        
        DWORD dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
        std::vector<BYTE> bmpData(dwBmpSize);
        
        if (!GetDIBits(hDC, hBitmap, 0, bmp.bmHeight, 
                      bmpData.data(), (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
            return false;
        }
        
        HANDLE hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
                                  CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        
        if (hFile == INVALID_HANDLE_VALUE) {
            return false;
        }
        
        BITMAPFILEHEADER_COMPAT bmfHeader = {0};
        bmfHeader.bfType = 0x4D42;
        bmfHeader.bfSize = sizeof(BITMAPFILEHEADER_COMPAT) + sizeof(BITMAPINFOHEADER) + dwBmpSize;
        bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER_COMPAT) + sizeof(BITMAPINFOHEADER);
        
        DWORD written;
        WriteFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER_COMPAT), &written, NULL);
        WriteFile(hFile, &bi, sizeof(BITMAPINFOHEADER), &written, NULL);
        WriteFile(hFile, bmpData.data(), dwBmpSize, &written, NULL);
        
        CloseHandle(hFile);
        return true;
    }
    
    // 保存为JPEG(简化实现)
    bool SaveAsJPEG(HBITMAP hBitmap, HDC hDC, const char* filename) {
        // 简化实现,实际需要使用GDI+或其他库
        return SaveAsBMP(hBitmap, hDC, filename);
    }
    
    // 保存为PNG(简化实现)
    bool SaveAsPNG(HBITMAP hBitmap, HDC hDC, const char* filename) {
        // 简化实现,实际需要使用GDI+或其他库
        return SaveAsBMP(hBitmap, hDC, filename);
    }
};

// 测试截图管理器
void TestScreenshotManager() {
    printf("=== Screenshot Manager Test ===\n");
    
    ScreenshotManager manager;
    manager.SetOutputDirectory("screenshots");
    manager.SetFormat(CaptureFormat::BMP);
    manager.SetTimestamp(true);
    
    // 单次截图
    if (manager.CaptureScreen()) {
        printf("[+] Single screenshot captured\n");
    }
    
    // 批量截图
    int captured = manager.BatchCapture(3, 2000); // 3张截图,间隔2秒
    printf("[+] Batch captured %d screenshots\n", captured);
}

5、课后作业

5.1、作业1:实现视频录制功能

扩展屏幕截图功能,实现连续截图并合成视频的功能。

5.2、作业2:添加图像压缩功能

实现截图的压缩存储,减小文件大小。

5.3、作业3:实现远程传输功能

添加将截图实时传输到远程服务器的功能。