用C++编写屏幕准星

c 复制代码
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib,"gdiplus.lib")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")

using namespace Gdiplus;

// 高DPI感知定义
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE)-4)
#endif

static int     g_x = 1920; // 圆点的坐标位置,主要看你的显示器分辨率,如果是3840x2160,那么分别填写1920和1080
static int     g_y = 1080; // 圆点的坐标位置
static float   g_centerDotRadius = 4.8f; // 圆点半径
static float   g_lineLen = 20.0f; // 十字准星线条长度
static float   g_lineWidth = 1.0f; // 十字准星线条厚度
static BYTE    g_alpha = 255; // 不透明度

HBITMAP DrawCrosshairBitmap(int width, int height) {
    Bitmap bmp(width, height, PixelFormat32bppARGB);
    Graphics g(&bmp);
    g.Clear(Color(0, 0, 0, 0));

    REAL cx = width / 2.0f;
    REAL cy = height / 2.0f;

    SolidBrush redBrush(Color(g_alpha, 255, 63, 63));
    Pen redPen(Color(g_alpha, 255, 63, 63), g_lineWidth);

    g.FillEllipse(&redBrush,
        cx - g_centerDotRadius,
        cy - g_centerDotRadius,
        g_centerDotRadius * 2,
        g_centerDotRadius * 2);

    g.DrawLine(&redPen, cx - g_lineLen, cy, cx + g_lineLen, cy);
    g.DrawLine(&redPen, cx, cy - g_lineLen, cx, cy + g_lineLen);

    HBITMAP hBmp = nullptr;
    bmp.GetHBITMAP(Color(0, 0, 0, 0), &hBmp);
    return hBmp;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if (msg == WM_DESTROY)
    {
        PostQuitMessage(0);
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

int main() {
    // ==========开启每显示器DPI感知,必须放在main最前面!==========
    SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);

    GdiplusStartupInput gdiInput{};
    ULONG_PTR gdiToken;
    GdiplusStartup(&gdiToken, &gdiInput, nullptr);

    const wchar_t* clsName = L"CrosshairULW";
    WNDCLASSEXW wc{ 0 };
    wc.cbSize = sizeof(WNDCLASSEXW);
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandleW(NULL);
    wc.lpszClassName = clsName;
    RegisterClassExW(&wc);

    int winHalf = (int)(g_lineLen + 12.0f);
    int winSize = winHalf * 2;

    HWND hwnd = CreateWindowExW(
        WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_NOACTIVATE | WS_EX_TRANSPARENT,
        clsName,
        L"",
        WS_POPUP,
        0, 0, winSize, winSize,
        NULL,
        NULL,
        GetModuleHandleW(NULL),
        NULL
    );

    HBITMAP hCrossBmp = DrawCrosshairBitmap(winSize, winSize);

    HDC hdcScreen = GetDC(NULL);
    HDC hdcMem = CreateCompatibleDC(hdcScreen);
    HBITMAP hOld = (HBITMAP)SelectObject(hdcMem, hCrossBmp);

    SIZE winSz = { winSize, winSize };
    POINT ptSrc = { 0,0 };
    POINT ptDst = { g_x - winHalf, g_y - winHalf };
    BLENDFUNCTION bf{};
    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 255;
    bf.AlphaFormat = AC_SRC_ALPHA;

    UpdateLayeredWindow(
        hwnd,
        hdcScreen,
        &ptDst,
        &winSz,
        hdcMem,
        &ptSrc,
        0,
        &bf,
        ULW_ALPHA
    );

    SelectObject(hdcMem, hOld);
    DeleteDC(hdcMem);
    ReleaseDC(NULL, hdcScreen);
    DeleteObject(hCrossBmp);

    ShowWindow(hwnd, SW_SHOWNOACTIVATE);

    MSG msg{};
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    GdiplusShutdown(gdiToken);
    return (int)msg.wParam;
}

效果:

相关推荐
孤存5221 小时前
c语言动态内存管理
c语言·开发语言·算法
冰暮流星1 小时前
javascript之webstorage用法
开发语言·javascript·ecmascript
我一定会有钱1 小时前
打造完美工作流:Git 配置”一次推送,三端同步”(Gitee/GitCode/GitHub)
开发语言·windows·vscode·搜索引擎·gitlab·github·visual studio code
matlab代码1 小时前
基于matlab肤色人脸标记检测系统 GUI界面【源码53期】
开发语言·matlab·人脸标记
KhalilRuan2 小时前
UnityCsReference——笔记
java·开发语言·笔记
电子云与长程纠缠2 小时前
UE5 Lyra PocketWorld进行3D内容UI预览 - 上
开发语言·学习·3d·ue5·游戏引擎
码农大叔的博客2 小时前
golang示例:for九九乘法表
开发语言·算法·golang
星恒随风2 小时前
C++ 哈希详解(二):开放定址、哈希桶与 C++ 哈希表底层实现
c++·笔记·学习·哈希算法·散列表
长谷深风1112 小时前
Agent 何时该 Replan:五个关键判断
java·大数据·开发语言·ai agent·ai智能体·agent设计·clarify机制