• [c++] gdiplus绘制透明异型窗口


    本来是想使用 GDI+ 制作一个透明窗口,然后使用 SetWindowDisplayAffinity 来实现反截屏的目的,但是遗憾的是针对 WS_EX_LAYERED 属性的窗口,SetWindowDisplayAffinity 的调用总是会失败,返回错误码 :8 。

    但是写都写了,就记录下来备忘吧。
    (代码参考自网络,结构上做了一些小修改,侵删)

    
    #include <iostream>
    #include <Windows.h>
    #include <gdiplus.h>
    
    #pragma comment(lib,"gdiplus.lib")
    
    typedef BOOL(*UPDATELAYEREDWINDOWFUNCTION)(HWND, HDC, POINT*, SIZE*, HDC, POINT*, COLORREF, BLENDFUNCTION*, DWORD);
    
    LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_DESTROY:
            PostQuitMessage(0);       
            break;
        case WM_LBUTTONDOWN:
            break;
        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    }
    
    int main()
    {
        //
        // 变量定义
        //
    
        ULONG_PTR gdiplusStartupToken;
        Gdiplus::GdiplusStartupInput gdiInput;
        HWND hwnd;
        MSG messages;
        WNDCLASSEX wincl;
        HINSTANCE hThisInstance = GetModuleHandle(0);
        char szClassName[] = "PNGDialog";
        RECT wndRect;
        SIZE wndSize;
        HDC hdc;
        HDC memDC;
        HBITMAP memBitmap;
        HMODULE hUser32;
        UPDATELAYEREDWINDOWFUNCTION UpdateLayeredWindow;
        HDC screenDC;
        POINT ptSrc;
        BLENDFUNCTION blendFunction;
    
        //
        // 初始化 GDI+
        //
    
        Gdiplus::GdiplusStartup(&gdiplusStartupToken, &gdiInput, NULL);
    
        //
        // 定义窗口结构
        //
    
        wincl.hInstance = hThisInstance; 
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;
        wincl.style = CS_DBLCLKS;
        wincl.cbSize = sizeof(WNDCLASSEX);
        wincl.hIcon = NULL;
        wincl.hIconSm = NULL;
        wincl.hCursor = NULL;
        wincl.lpszMenuName = NULL;
        wincl.cbClsExtra = 0;
        wincl.cbWndExtra = 0;
        wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
    
        //
        // 注册窗口类
        //
    
        if (!RegisterClassEx(&wincl))
        {
            printf("RegisterClassEx error : %d \n", GetLastError());
            return 0;
        }
    
        //
        // 创建窗口
        //
        
        hwnd = CreateWindowEx(
            WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
            szClassName,
            "PNGDialog Example Application",    
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT, 
            500,                
            500,                 
            HWND_DESKTOP,       
            NULL,               
            hThisInstance,      
            NULL              
        );
    
        //
        // 使窗口在屏幕上可见
        //
    
        ShowWindow(hwnd, SW_SHOW);
        LONG style = ::GetWindowLong(hwnd, GWL_STYLE);
        if (style & WS_CAPTION)
            style ^= WS_CAPTION;
        if (style & WS_THICKFRAME)
            style ^= WS_THICKFRAME;
        if (style & WS_SYSMENU)
            style ^= WS_SYSMENU;
        ::SetWindowLong(hwnd, GWL_STYLE, style);
        style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
        if (style & WS_EX_APPWINDOW)
            style ^= WS_EX_APPWINDOW;
        ::SetWindowLong(hwnd, GWL_EXSTYLE, style);
    
        //
        // 使用 GDI+ 加载图片
        //
    
        ::GetWindowRect(hwnd, &wndRect);
        wndSize = { wndRect.right - wndRect.left,wndRect.bottom - wndRect.top };
        hdc = ::GetDC(hwnd);
        memDC = ::CreateCompatibleDC(hdc);
        memBitmap = ::CreateCompatibleBitmap(hdc, wndSize.cx, wndSize.cy);
        ::SelectObject(memDC, memBitmap);
        Gdiplus::Image image(L"pic.png");
        Gdiplus::Graphics graphics(memDC);
        graphics.DrawImage(&image, 0, 0, wndSize.cx, wndSize.cy);
    
        //
        // 获取 UpdateLayeredWindow 函数地址
        //
    
        hUser32 = ::LoadLibrary("User32.dll");
        if (!hUser32)
        {
            return FALSE;
        }
        UpdateLayeredWindow = (UPDATELAYEREDWINDOWFUNCTION)::GetProcAddress(hUser32, "UpdateLayeredWindow");
        if (!UpdateLayeredWindow)
        {
            return FALSE;
        }
    
        //
        // 获取屏幕 DC
        //
    
        screenDC = GetDC(NULL);
        ptSrc = { 0,0 };
    
        //
        // 绘制窗口
        //
    
        blendFunction.AlphaFormat = AC_SRC_ALPHA;
        blendFunction.BlendFlags = 0;
        blendFunction.BlendOp = AC_SRC_OVER;
        blendFunction.SourceConstantAlpha = 255;
        UpdateLayeredWindow(hwnd, screenDC, &ptSrc, &wndSize, memDC, &ptSrc, 0, &blendFunction, 2);
        ::DeleteDC(memDC);
        ::DeleteObject(memBitmap);
    
      
        //
        // 反截屏(会失败,原因是只能对 WS_EX_TOPMOST 类型的窗口使用)
        //
    
        /*if (!SetWindowDisplayAffinity(hwnd, WDA_MONITOR))
        {
            printf("SetWindowDisplayAffinity error : %d \n", GetLastError());
        }*/
    
        //
        // 进入消息循环
        //
    
        while (GetMessage(&messages, NULL, 0, 0))
        {
            TranslateMessage(&messages);
            DispatchMessage(&messages);
        }
        Gdiplus::GdiplusShutdown(gdiplusStartupToken);
    
    
        (void)getchar();
        return 0;
    }
    
    
    
    

    效果图:
    在这里插入图片描述

  • 相关阅读:
    二分插入排序
    LEETCODE 返回两个正序数组的 中位数
    4的幂 算法
    leetcode 两个单链表两数相加
    KMP(The Knuth-Morris-Pratt Algorithm)
    Java Case Interview one
    AWK SED命令 简单入门
    Problem Fix List(always update)
    mysql存储过程快速上手
    java while和switch-case循环
  • 原文地址:https://www.cnblogs.com/csnd/p/15613292.html
Copyright © 2020-2023  润新知