DWM 相关实现代码 [自用]

· 1. DWM 缩略图和模糊隐藏实现半透明

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

// 检查 UWP 窗口是否可见
bool IsUWPWindowVisible(HWND hwnd) {
    DWORD cloaked = 0;
    DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, &cloaked, sizeof(cloaked));
    return (cloaked == 0);
}

bool IsBadWindow(HWND hwnd) {
    wchar_t title[256];
    wchar_t className[256];
    GetWindowTextW(hwnd, title, 256);
    GetClassNameW(hwnd, className, 256);

    LPCWSTR badTitleList[] = { L"NVIDIA", L"Xaml" };

    for (LPCWSTR badTitle : badTitleList) {
        if (wcsstr(title, badTitle) != nullptr) {
            return true;
        }
    }

    return false;
}

void UpdateInfoWindow(HWND infoHwnd, HWND mainHwnd) {
    if (infoHwnd) {
        RECT mdrc;
        GetWindowRect(mainHwnd, &mdrc);

        // 获取屏幕工作区和任务栏的位置信息
        RECT rcWorkArea = { 0 };
        SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcWorkArea, 0);
        HWND hTrayWnd = FindWindowW(L"Shell_TrayWnd", nullptr);

        // 计算任务栏是否遮挡信息窗口
        bool taskbarVisible = false;
        if (IsWindow(hTrayWnd)
            && IsWindowVisible(hTrayWnd)) {
            RECT tbrc;
            GetWindowRect(hTrayWnd, &tbrc);

            if (tbrc.top >= rcWorkArea.bottom && mdrc.bottom + 50 > tbrc.top) {
                // 任务栏在底部且信息窗口底部超出工作区域底部
                taskbarVisible = true;
            }
        }

        if (taskbarVisible) {
            // 将信息窗口移动到窗口上方
            SetWindowPos(infoHwnd, nullptr, mdrc.left + 10, mdrc.top - 110,
                mdrc.right - mdrc.left - 25,
                100, SWP_NOZORDER | SWP_SHOWWINDOW);
        }
        else {
            // 将信息窗口移动到窗口底部
            SetWindowPos(infoHwnd, nullptr, mdrc.left + 10, mdrc.bottom,
                mdrc.right - mdrc.left - 25,
                100, SWP_NOZORDER | SWP_SHOWWINDOW);
        }
    }
}

LRESULT CALLBACK InfoWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        RECT rc;
        GetClientRect(hwnd, &rc);

        // 获取目标窗口信息
        HWND targetHwnd = (HWND)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
        if (targetHwnd) {
            wchar_t title[256];
            wchar_t className[256];
            GetWindowTextW(targetHwnd, title, 256);
            GetClassNameW(targetHwnd, className, 256);
            wchar_t info[512];
            swprintf(info, 512, L"Title: %s\nClass: %s\nHandle: 0x%llX",
                title, className, (UINT_PTR)targetHwnd);

            // 绘制信息文本
            SetBkMode(hdc, TRANSPARENT);
            SetTextColor(hdc, RGB(0, 0, 0));
            DrawTextW(hdc, info, -1, &rc, DT_LEFT | DT_TOP | DT_NOPREFIX);
        }

        EndPaint(hwnd, &ps);
        return 0;
    }
    default:
        break;
    }
    return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    static HTHUMBNAIL thumbnail = NULL;
    static HWND infoHwnd = NULL;
    static HWND oldBehindWnd = NULL;

    // 最小窗口尺寸
    const int MIN_WIDTH = 100;
    const int MIN_HEIGHT = 100;

    switch (uMsg) {
    case WM_CREATE: {
        // 创建子窗口用于显示信息
        HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
        const wchar_t INFO_CLASS_NAME[] = L"InfoWindowClass";

        WNDCLASS wc = {};
        wc.lpfnWndProc = InfoWindowProc;
        wc.hInstance = hInstance;
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);  // 白色背景
        wc.lpszClassName = INFO_CLASS_NAME;

        RegisterClassW(&wc);

        infoHwnd = CreateWindowExW(
            WS_EX_TRANSPARENT | WS_EX_NOACTIVATE,  // 扩展窗口样式
            INFO_CLASS_NAME,                 // 窗口类名
            nullptr,                         // 窗口标题
            WS_POPUP,                        // 窗口样式
            0, 0, 800, 100,                  // 窗口尺寸
            hwnd, nullptr, hInstance, nullptr
        );

        if (infoHwnd == nullptr) {
            return 0;
        }

        SetLayeredWindowAttributes(infoHwnd, RGB(0,0,0), 0, LWA_COLORKEY);

        // 初始化信息窗口的位置
        RECT rc;
        GetWindowRect(hwnd, &rc);
        SetWindowPos(infoHwnd, nullptr, rc.left + 10, rc.bottom, 0, 0,
            SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
    }
    case WM_ACTIVATE: {
        // 查找第一个可见且尺寸不小于最小尺寸的后台窗口
        HWND hwndBehind = GetWindow(hwnd, GW_HWNDNEXT);
        while (hwndBehind) {
            if (IsWindowVisible(hwndBehind)
                && IsUWPWindowVisible(hwndBehind)
                 && !IsBadWindow(hwndBehind)) {
                RECT rcBehind;
                GetWindowRect(hwndBehind, &rcBehind);
                int width = rcBehind.right - rcBehind.left;
                int height = rcBehind.bottom - rcBehind.top;
                
                if (width >= MIN_WIDTH && height >= MIN_HEIGHT) {
                    break;
                }
            }
            hwndBehind = GetWindow(hwndBehind, GW_HWNDNEXT);
        }


        if (oldBehindWnd != hwndBehind) {

            // 注销当前缩略图
            if (thumbnail) {
                DwmUnregisterThumbnail(thumbnail);
                thumbnail = NULL;
            }

            if (hwndBehind) {
                oldBehindWnd = hwndBehind;

                // 注册后台窗口的缩略图
                DwmRegisterThumbnail(hwnd, hwndBehind, &thumbnail);

                RECT rcBehindWnd;
                GetWindowRect(hwndBehind, &rcBehindWnd);
                SetWindowPos(hwnd, nullptr,
                    0, 0,
                    rcBehindWnd.right - rcBehindWnd.left,
                    rcBehindWnd.bottom - rcBehindWnd.top + 50,
                    SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);

                // 更新缩略图属性
                RECT rcClient;
                GetClientRect(hwnd, &rcClient);
                DWM_THUMBNAIL_PROPERTIES dpt;
                dpt.dwFlags = DWM_TNP_RECTDESTINATION | DWM_TNP_OPACITY;
                dpt.rcDestination = rcClient;
                dpt.opacity = (BYTE)(255 * 0.7);  // 设置透明度为70%
                DwmUpdateThumbnailProperties(thumbnail, &dpt);

                // 设置子窗口的用户数据为目标窗口句柄
                SetWindowLongPtrW(infoHwnd, GWLP_USERDATA, (LONG_PTR)hwndBehind);

                InvalidateRect(infoHwnd, NULL, TRUE);  // 重新绘制子窗口
            }
            else {
                // 设置子窗口的用户数据为目标窗口句柄
                SetWindowLongPtrW(infoHwnd, GWLP_USERDATA, (LONG_PTR)NULL);

                MessageBoxW(NULL,
                    L"没有找到合适窗口", L"提示",
                    MB_OK | MB_ICONINFORMATION |
                    MB_APPLMODAL | MB_TOPMOST);
            }
        }
        return 0;
    }
    case WM_DESTROY:
        if (thumbnail) {
            DwmUnregisterThumbnail(thumbnail);
        }
        PostQuitMessage(0);
        return 0;
    case WM_SIZE: {
        if (thumbnail) {
            RECT rcClient;
            GetClientRect(hwnd, &rcClient);

            // 窗口大小改变时重新扩展DWM框架到客户区
            MARGINS margins = { 0, 0, 0, rcClient.bottom - rcClient.top };
            DwmExtendFrameIntoClientArea(hwnd, &margins);

            // 更新缩略图属性
            DWM_THUMBNAIL_PROPERTIES dpt;
            dpt.dwFlags = DWM_TNP_RECTDESTINATION | DWM_TNP_OPACITY;
            dpt.rcDestination = rcClient;
            dpt.opacity = (BYTE)(255 * 0.7);  // 设置透明度为70%
            DwmUpdateThumbnailProperties(thumbnail, &dpt);
        }

        // 更新信息窗口的位置
        UpdateInfoWindow(infoHwnd, hwnd);
        return 0;
    }
    case WM_MOVE: {
        // 更新信息窗口的位置
        UpdateInfoWindow(infoHwnd, hwnd);
        return 0;
    }
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        RECT rc;
        GetClientRect(hwnd, &rc);

        // 绘制半透明背景
        HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
        SetBkMode(hdc, TRANSPARENT);
        FillRect(hdc, &rc, hBrush);
        DeleteObject(hBrush);

        EndPaint(hwnd, &ps);
        return 0;
    }
    default:
        return DefWindowProcW(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) {
    // 注册窗口类
    const wchar_t CLASS_NAME[] = L"TransparentWindowClass";
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);  // 防止背景重绘
    wc.lpszClassName = CLASS_NAME;

    RegisterClassW(&wc);

    // 创建窗口
    HWND hwnd = CreateWindowExW(
        WS_EX_NOREDIRECTIONBITMAP,  // 扩展窗口样式
        CLASS_NAME,                 // 窗口类名
        L"Transparent Window",      // 窗口标题
        WS_OVERLAPPEDWINDOW,        // 窗口样式
        CW_USEDEFAULT, CW_USEDEFAULT, 1000, 600,
        nullptr, nullptr, hInstance, nullptr
    );

    if (hwnd == nullptr) {
        return 0;
    }

    // 使用 DWM API 设置毛玻璃效果
    DWM_BLURBEHIND bb = { 0 };
    bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
    bb.fEnable = TRUE;
    bb.hRgnBlur = NULL;
    DwmEnableBlurBehindWindow(hwnd, &bb);

    // 设置标题栏颜色为深色(示例为灰色)
    COLORREF grey = RGB(30, 30, 30);
    DwmSetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, &grey, sizeof(grey));

    // 显示窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 消息循环
    MSG msg = {};
    while (GetMessageW(&msg, nullptr, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    return 0;
}

效果图:

窗口缩略图实现背景墙(自动识别窗口切换)

窗口切换和大小跟随: 

演示截图 2

· 2. 更多代码......

(...)


本文发布于:2024.07.08

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/785002.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

matplotlib颜色对照表

matplotlib的色彩设置: #------------------------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------…

【linux服务器】大语言模型实战教程:LLMS大模型快速部署到个人服务器

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言 说到大语言模型相信大家都不会陌生&#xff0c;大型语言模型(LLMs)是人工智能文本处理的主要类型,也现在最流行的人工智能…

【AI大模型】赋能儿童安全:楼层与室内定位实践与未来发展

文章目录 引言第一章&#xff1a;AI与室内定位技术1.1 AI技术概述1.2 室内定位技术概述1.3 楼层定位的挑战与解决方案 第二章&#xff1a;儿童定位与安全监控的需求2.1 儿童安全问题的现状2.2 智能穿戴设备的兴起 第三章&#xff1a;技术实现细节3.1 硬件设计与选择传感器选择与…

报修小程序论文(设计)开题报告

一、课题的背景和意义 近些年来&#xff0c;随着移动互联网巅峰时期的来临&#xff0c;互联网产业逐渐趋于“小、轻、微”的方向发展&#xff0c;符合轻应用时代特点的各类技术受到了不同领域的广泛关注。在诸多产品中&#xff0c;被誉为“运行着程序的网站”之名的微信小程序…

Java | Leetcode Java题解之第224题基本计算器

题目&#xff1a; 题解&#xff1a; class Solution {public int calculate(String s) {Deque<Integer> ops new LinkedList<Integer>();ops.push(1);int sign 1;int ret 0;int n s.length();int i 0;while (i < n) {if (s.charAt(i) ) {i;} else if (s…

(十一) Docker compose 部署 Mysql 和 其它容器

文章目录 1、前言1.1、部署 MySQL 容器的 3 种类型1.2、M2芯片类型问题 2、具体实现2.1、单独部署 mysql 供宿主机访问2.1.1、文件夹结构2.1.2、docker-compose.yml 内容2.1.3、运行 2.2、单独部署 mysql 容器供其它容器访问&#xff08;以 apollo 为例&#xff09;2.2.1、文件…

allWebPlugin中间件实现ActiveX插件在谷歌、火狐、Edge浏览器使用

下载并安装allWebPlugin中间件 1、请从下面地址下载allWebPlugin中间件产品&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1xUyQDzOabh7mU7J7TYhtig?pwdz3q0 提取码&#xff1a;z3q0 如下图所示&#xff0c;下载最新allWebPlugin_x86_v2.0.0.14_stable_20240707…

Flutter【组件】标签

简介 flutter 标签组件。标签组件是一种常见的 UI 元素&#xff0c;用于显示和管理多个标签&#xff08;或标签集合&#xff09;。 github地址&#xff1a; https://github.com/ThinkerJack/jac_uikit pub地址&#xff1a;https://pub.dev/packages/jac_uikit 使用方式&…

机器学习:预测评估8类指标

机器学习&#xff1a;8类预测评估指标 R方值、平均值绝对误差值MAE、均方误差MSE、均方误差根EMSE、中位数绝对误差MAD、平均绝对百分误差MAPE、可解释方差分EVS、均方根对数误差MLSE。 一、R方值 1、说明&#xff1a; R方值&#xff0c;也称为确定系数或拟合优度&#xff…

Python 基础知识:为什么使用 __init__.py ?

大家好&#xff01;今天&#xff0c;我们将深入了解 Python 中的 __init__.py 文件&#xff0c;这个小文件却能干大事。让我们抛开任何专业术语&#xff0c;直接进入正题。 什么是 __init__.py &#xff1f; 假设你有一个 Python 目录&#xff0c;里面有一堆 Python 文件&…

从零开始做题:My_lllp

题目 给出一张png图片 解题 ┌──(holyeyes㉿kali2023)-[~/Misc/题目/zulu/My_lllp] └─$ python2 lsb.py extract my_lllp.png out.txt my_lllp [] Image size: 1080x1079 pixels. [] Written extracted data to out.txt. ┌──(holyeyes㉿kali2023)-[~/Misc/题目/zul…

绝区伍--2024年AI发展路线图

2024 年将是人工智能具有里程碑意义的一年。随着新模式、融资轮次和进步以惊人的速度出现&#xff0c;很难跟上人工智能世界发生的一切。让我们深入了解 2024 年可能定义人工智能的关键事件、产品发布、研究突破和趋势。 2024 年第一季度 2024 年第一季度将推出一些主要车型并…

AI绘画Stable Diffusion:ControlNet组件—Scribble(涂鸦)赋予用户精细控制权,让涂鸦草图焕发生命力

大家好&#xff0c;我是画画的小强 今天给大家分享一下AI绘画Stable Diffusion当中的&#xff1a;ControlNet Scribble组件&#xff0c;**Scribble&#xff08;涂鸦&#xff09;**技术是一种能够为用户提供独特的手动注释或标记图像&#xff08;如&#xff1a;涂鸦、简笔画等&…

变阻器的阻值范围是多少?

变阻器&#xff0c;又称可变电阻器或电位器&#xff0c;是一种可以改变电阻值的电子元件。它通常由一个滑动臂、一个固定电阻体和一个滑动触点组成。通过滑动臂在固定电阻体上的位置变化&#xff0c;可以实现对电阻值的连续调整。变阻器广泛应用于各种电子设备中&#xff0c;如…

2024 ACT汽车软件与安全技术周 | 龙智携全方位汽车软件开发解决方案亮相,助力应对汽车软件开发功能安全、合规等挑战

2024年7月18-19日&#xff08;周四-周五&#xff09;&#xff0c;2024第三届ACT汽车软件与安全技术周将在上海佘山翰悦阁酒店举办。 龙智即将携汽车开发及管理解决方案创新亮相&#xff0c;并在汽车信息安全技术峰会主会场上发表主题演讲&#xff0c;分享推动汽车软件开发与功…

Java-Redis-Clickhouse-Jenkins-MybatisPlus-Zookeeper-vscode-Docker

文章目录 Clickhouse基础实操windows docker desktop 下载clickhousespringboot项目配置clickhouse Redis谈下你对Redis的了解&#xff1f;Redis一般都有哪些使用的场景&#xff1f;Redis有哪些常见的功能&#xff1f;Redis支持的数据类型有哪些&#xff1f;Redis为什么这么快…

电源中电感底部需要铺地平面吗?

感有交变电流&#xff0c;电感底部铺铜会在地平面上产生涡流&#xff0c;涡流效应会影响功率电感的电感量&#xff0c;涡流也会增加系统的损耗&#xff0c;同时交变电流产生的噪声会增加地平面的噪声&#xff0c;会影响其他信号的稳定性。 在EMC方面来看&#xff0c;在电感底部…

DSSM双塔特征交互

传统的DSSM双塔无法在早期进行user和item侧的特征交互&#xff0c;这在一定程度上降低了模型性能。我们想要对双塔模型进行细粒度的特征交互&#xff0c;同时又不失双塔模型离线建向量索引的解耦性。下面介绍两篇这方面的工作。 美团-Dual Augmented Two-tower 在user和item的特…

基于stm32开发的红外循迹小车

本项目算是接触32来开发的第一个小项目了&#xff0c;虽然前期用51写过一个循迹小车&#xff0c;以为直接转到32会比较简单&#xff0c;结果还是花了大几天才把小车的参数完全调完&#xff0c;以此来记录下自己的学习历程&#xff08;注&#xff1a;循迹算法并未加入PID算法&am…

AI网络爬虫016:用deepseek批量提取coze扣子的智能体数据

文章目录 一、介绍二、输入内容三、输出内容一、介绍 动态加载页面,返回json数据: 翻页规律: https://www.coze.cn/api/marketplace 这两个URL在多个方面有所不同,主要差异如下: **查询参数(Query Parameters)**: - 第一个URL的查询参数包括: - `entity_type=1` - `…