用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;
}

效果:

相关推荐
UIU11436 分钟前
递归算法与汉诺塔
c++·学习·算法·c#·递归
Fruit_Caller1 小时前
static
开发语言·c++
codigger6 小时前
ObjectSense:一门千行内核、把可靠性写进骨子里的面向对象脚本语言
开发语言·编程·编程语言
小小龙学IT7 小时前
Boost.Interprocess 开源 C++ 进程间通信库深度解析
c++·开源
倒头就睡的小比特6 天前
算法竞赛C++常用的STL
c++·算法
weilx12346 天前
C++笔记-文件IO-<fcntl.h>
c++
小羊没烦恼!6 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读6 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
Smileyqp沛沛6 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车6 天前
C/C++ 为什么需要编译器?
开发语言·c++