windows 窗口全屏绘制,全程置顶,不可远程捕捉,不被预览影响,无标题无边框

windows 窗口全屏绘制,全程置顶,不可远程捕捉,不被预览影响,无标题无边框,所有屏幕全部绘制。

#include <windows.h>
#include <vector>
#include <string>
#include <chrono>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")

// 显示器信息结构体
struct MonitorInfo {
    HMONITOR hMonitor;   // 显示器句柄
    RECT     rect;       // 显示器位置和尺寸
};

// 窗口上下文结构体(每个窗口独立)
struct WindowContext {
    HDC     hdcMem = nullptr;    // 内存设备上下文
    HBITMAP hbmMem = nullptr;    // 兼容位图
    int     width = 0;          // 窗口宽度
    int     height = 0;          // 窗口高度
    int     lastSecond = -1;     // 上次刷新秒数(用于每秒更新)
    bool    isPrimary = false;   // 标识是否主显示器
};

std::vector<MonitorInfo> g_monitorInfos;  // 保存所有显示器信息
HWND g_hwndPrimary = nullptr;             // 主显示器窗口句柄

// 显示器枚举回调函数
BOOL CALLBACK MonitorEnumProc(
    HMONITOR hMonitor,      // 当前显示器句柄
    HDC      hdcMonitor,    // 显示器设备上下文(未使用)
    LPRECT   lprcMonitor,    // 显示器区域
    LPARAM   dwData          // 自定义数据(未使用)
) {
    g_monitorInfos.push_back({ hMonitor, *lprcMonitor }); // 存储显示器信息
    return TRUE; // 继续枚举
}

// 更新内存缓冲区的绘制内容
void UpdateBuffer(WindowContext& ctx, HWND hwnd) {
    RECT rc;
    GetClientRect(hwnd, &rc); // 获取窗口客户区尺寸

    // 如果窗口尺寸变化则重建缓冲
    if (ctx.width != rc.right || ctx.height != rc.bottom) {
        // 释放旧资源
        if (ctx.hdcMem) DeleteDC(ctx.hdcMem);
        if (ctx.hbmMem) DeleteObject(ctx.hbmMem);

        HDC hdc = GetDC(hwnd); // 获取窗口设备上下文
        // 创建兼容内存DC
        ctx.hdcMem = CreateCompatibleDC(hdc);
        // 创建兼容位图
        ctx.hbmMem = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
        SelectObject(ctx.hdcMem, ctx.hbmMem); // 选入内存DC
        ReleaseDC(hwnd, hdc); // 释放原始DC

        ctx.width = rc.right;
        ctx.height = rc.bottom;
    }

    // 用深灰色填充背景
    HBRUSH bgBrush = CreateSolidBrush(RGB(30, 30, 30));
    FillRect(ctx.hdcMem, &rc, bgBrush);
    DeleteObject(bgBrush);

    // 获取当前时间
    SYSTEMTIME st;
    GetLocalTime(&st);
    std::wstring timeStr = std::to_wstring(st.wHour) + L":"
        + (st.wMinute < 10 ? L"0" : L"") + std::to_wstring(st.wMinute) + L":"
        + (st.wSecond < 10 ? L"0" : L"") + std::to_wstring(st.wSecond);

    // 设置文字透明背景
    SetBkMode(ctx.hdcMem, TRANSPARENT);
    // 主屏用红色文字,其他用黄色
    SetTextColor(ctx.hdcMem, ctx.isPrimary ? RGB(255, 0, 0) : RGB(255, 255, 0));

    // 创建字体
    HFONT hFont = CreateFont(
        48, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
        DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial");
    HFONT hOldFont = (HFONT)SelectObject(ctx.hdcMem, hFont);

    // 居中绘制时间文字
    DrawText(ctx.hdcMem, timeStr.c_str(), -1, &rc,
        DT_CENTER | DT_VCENTER | DT_SINGLELINE);

    // 恢复旧字体并删除新字体
    SelectObject(ctx.hdcMem, hOldFont);
    DeleteObject(hFont);
}

// 窗口过程函数
LRESULT CALLBACK WindowProc(
    HWND   hwnd,
    UINT   uMsg,
    WPARAM wParam,
    LPARAM lParam
) {
    // 从窗口附加数据中获取上下文
    WindowContext* ctx = reinterpret_cast<WindowContext*>(
        GetWindowLongPtr(hwnd, GWLP_USERDATA));

    switch (uMsg) {
    case WM_CREATE: {
        // 创建窗口时初始化上下文
        auto* newCtx = new WindowContext;
        SetWindowLongPtr(hwnd, GWLP_USERDATA,
            reinterpret_cast<LONG_PTR>(newCtx));
        return 0;
    }

    case WM_ERASEBKGND: // 拦截背景擦除避免闪烁
        return 1;

    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        if (ctx && ctx->hdcMem) {
            // 将内存DC内容拷贝到屏幕
            BitBlt(hdc, 0, 0, ctx->width, ctx->height,
                ctx->hdcMem, 0, 0, SRCCOPY);
        }

        EndPaint(hwnd, &ps);
        return 0;
    }

    case WM_TIMER: { // 定时器消息(每秒更新)
        if (!ctx) return 0;

        SYSTEMTIME st;
        GetLocalTime(&st);
        if (st.wSecond != ctx->lastSecond) { // 秒变化时更新
            ctx->lastSecond = st.wSecond;
            UpdateBuffer(*ctx, hwnd);    // 重绘缓冲区
            InvalidateRect(hwnd, nullptr, FALSE); // 请求重绘
            UpdateWindow(hwnd);          // 立即更新
        }
        return 0;
    }

    case WM_DESTROY: { // 窗口销毁时清理资源
        KillTimer(hwnd, 1);
        if (ctx) {
            if (ctx->hdcMem) DeleteDC(ctx->hdcMem);
            if (ctx->hbmMem) DeleteObject(ctx->hbmMem);
            delete ctx;
        }
        if (hwnd == g_hwndPrimary)
            g_hwndPrimary = nullptr; // 清除主屏句柄
        PostQuitMessage(0);
        return 0;
    }

    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

// 程序入口
int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nCmdShow
) {
    // 注册窗口类
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WindowProc;       // 窗口过程
    wc.hInstance = hInstance;        // 实例句柄
    wc.lpszClassName = L"MultiDisplayWindow"; // 类名
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 背景画刷(实际未使用)
    RegisterClass(&wc);

    // 枚举所有显示器
    EnumDisplayMonitors(
        nullptr,          // 所有显示器
        nullptr,          // 无裁剪区域
        MonitorEnumProc,  // 回调函数
        0);               // 无额外数据

    // 获取主显示器句柄(使用默认点(0,0)和主屏标志)
    HMONITOR hPrimary = MonitorFromPoint(
        POINT{ 0, 0 },
        MONITOR_DEFAULTTOPRIMARY);
    DWORD dwExStyle = WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW;
    // 为每个显示器创建窗口
    for (const auto& mi : g_monitorInfos) {
        // 创建全屏窗口
        HWND hwnd = CreateWindowEx(
            WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_NOACTIVATE, // 顶层透明窗口
            L"MultiDisplayWindow",      // 类名
            nullptr,                    // 无标题
            WS_POPUP | WS_VISIBLE,      // 无边框可见窗口
            mi.rect.left,               // 显示器左边界
            mi.rect.top,                // 显示器上边界
            mi.rect.right - mi.rect.left,  // 宽度
            mi.rect.bottom - mi.rect.top,  // 高度
            nullptr,                    // 无父窗口
            nullptr,                    // 无菜单
            hInstance,                  // 实例句柄
            nullptr);                   // 无额外数据

        if (hwnd) {
            // 判断是否是主显示器
            if (mi.hMonitor == hPrimary) {
                g_hwndPrimary = hwnd; // 保存主屏句柄
                WindowContext* ctx = reinterpret_cast<WindowContext*>(
                    GetWindowLongPtr(hwnd, GWLP_USERDATA));
                if (ctx)
                    ctx->isPrimary = true; // 设置主屏标志
            }

            // 设置窗口透明度(完全不透明)
            SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA);

            //设置远程不可捕获
            BOOL affinityResult = SetWindowDisplayAffinity(hwnd, WDA_EXCLUDEFROMCAPTURE);
            if (!affinityResult) {
                // Failed to set window display affinity, handle error
            }

            // 设置不受Windows 11的窥视功能影响
            BOOL excluded = TRUE;
            if (SUCCEEDED(DwmSetWindowAttribute(hwnd, DWMWA_EXCLUDED_FROM_PEEK, &excluded, sizeof(BOOL)))) {
                // Exclude the window from the Windows 11 peek feature
                printf(__FILE__, __FUNCTION__, __LINE__, "Failed to DwmSetWindowAttribute DWMWA_EXCLUDED_FROM_PEEK.Error: " + std::to_string(GetLastError()));
            }

            SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

            // 启动定时器(每100ms触发)
            SetTimer(hwnd, 1, 100, nullptr);
        }
    }
    // 消息循环
    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值