WPF自定义任务栏缩略图

news/2025/1/6 7:53:09/

任务栏缩略图预览

在Windows7系统上,微软首次推出任务栏缩略图预览功能。

当鼠标划会任务栏上的程序时,会打开一个预览窗口,可以对整个窗口内容进行预览。

效果如下:

在后面的Windows 8/8.1/10/11系统上,都延续了这个功能。

但是这种预览是基于窗口本身内容的,如果我们想修改这个缩略图的内容,类似网易云这样,就需要一些技术手段。

可以借助dwm里的几个函数来实现。

用到的DWM函数

DwmSetWindowAttribute

设置窗口管理器(DWM)非客户端呈现属性的值

函数声明如下:

1 HRESULT DwmSetWindowAttribute(
2   [in] HWND    hwnd,
3   [in] DWORD   dwAttribute,
4   [in] LPCVOID pvAttribute,
5   [in] DWORD   cbAttribute
6 );

参数说明:

 hwnd :要为其设置属性值的窗口的句柄。

 dwAttribute:描述要设置的值的标志,指定为 DWMWINDOWATTRIBUTE 枚举的值。 此参数指定要设置的属性,pvAttribute 参数指向包含属性值的对象。

 pvAttribute:指向包含要设置的属性值的对象的指针。 值集的类型取决于 dwAttribute 参数的值。 DWMWINDOWATTRIBUTE 枚举主题指示,在每个标志的行中,应向 pvAttribute 参数传递指向的值类型。

 cbAttribute:通过 pvAttribute 参数设置的属性值的大小(以字节为单位)。 值集的类型及其大小(以字节为单位)取决于 dwAttribute 参数的值。

DwmSetIconicThumbnail

设置窗口或选项卡上要用作缩略图表示形式的静态图标位图。

函数声明如下:

1 HRESULT DwmSetIconicThumbnail(
2   [in] HWND    hwnd,
3   [in] HBITMAP hbmp,
4   [in] DWORD   dwSITFlags
5 );

参数说明:

hwnd:窗口或选项卡的句柄。此窗口必须属于调用进程。

hbmp:位图的句柄,用于表示 hwnd 指定的窗口。

dwSITFlags:缩略图的显示选项。 以下值之一:

说明
0 (0x00000000)提供的缩略图周围不显示任何框架
DWM_SIT_DISPLAYFRAME 0x00000001在提供的缩略图周围显示一个框架

在WPF中自定义任务缩略图的步骤

1、在Window.Loaded事件中调用DwmSetWindowAttribute设置相关属性

2、增加一个Windows消息的处理函数

3、当收到WM_DWMSENDICONICTHUMBNAIL(0x0323)消息时,调用DwmSetIconicThumbnail设置缩略图。

注意:缩略图不应超过该消息中指定的最大 x 坐标(宽度)和 y 坐标(高度)。 缩略图还必须具有 32 位颜色深度。

缩略图的大小可以通过消息的lParam参数解析。

lParam的高16位是宽度,低16位是高度。

解析方法如下:

1  private short HIWORD(IntPtr lParam)
2  {
3      return (short)(((ulong)lParam >> 16) & 0xFFFF);
4  }
5 
6  private short LOWORD(IntPtr lParam)
7  {
8      return (short)((ulong)lParam & 0xFFFF);
9  }

1 var width = HIWORD(lParam);
2 var height = LOWORD(lParam);

引入签名

新建一个WPF工程,创建一个DWM.cs,内容如下:

 1     public class DWM2     {3         public const int WM_DWMSENDICONICTHUMBNAIL = 0x0323;4         public const int FORCE_ICONIC_REPRESENTATION = 7;5         public const int HAS_ICONIC_BITMAP = 10;6         public const int DISPLAYFRAME = 1;7 8         [DllImport("dwmapi.dll")]9         public static extern int DwmSetIconicThumbnail(IntPtr hwnd, IntPtr hbmp, int dwSITFlags);
10 
11         [DllImport("dwmapi.dll")]
12         public static extern int DwmSetWindowAttribute(IntPtr hwnd, int dwAttribute, IntPtr pvAttribute, int cbAttribute);
13     }

设置DWM属性并增加窗口的消息处理函数

为主窗口增加一个Loaded事件,在Loaded事件中,增加如下代码:

 1         private void Window_Loaded(object sender, RoutedEventArgs e)2         {3             int size = Marshal.SizeOf(typeof(Int32));4             IntPtr pBool = Marshal.AllocHGlobal(size);5             Marshal.WriteInt32(pBool, 0, 1);  // last parameter 0 (FALSE), 1 (TRUE)6 7             //设置属性8             var result = DWM.DwmSetWindowAttribute(new WindowInteropHelper(this).Handle, DWM.FORCE_ICONIC_REPRESENTATION, pBool, sizeof(int));9             result = DWM.DwmSetWindowAttribute(new WindowInteropHelper(this).Handle, DWM.HAS_ICONIC_BITMAP, pBool, sizeof(int));
10 
11             Marshal.FreeHGlobal(pBool);
12 
13             //Windows消息处理函数
14             HwndSource.FromHwnd(new WindowInteropHelper(this).Handle).AddHook(WndProc);
15         }

设置缩略图

 1      private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)2      {3          switch (msg)4          {5              case DWM.WM_DWMSENDICONICTHUMBNAIL:6                  var bmp = (Bitmap)Bitmap.FromFile(@"xxx.bmp");7                  var hBitmap = bmp.GetHbitmap();8                  DWM.DwmSetIconicThumbnail(hwnd, hBitmap, DWM.DISPLAYFRAME);9                  handled = true;
10                  break;
11          }
12          return IntPtr.Zero;
13      }

效果如下:

也可以自行绘制

 1         private IntPtr CreateBitmap(int width,int height)2         {3             Bitmap bitmap = new Bitmap(width, height);4             using (Graphics g = Graphics.FromImage(bitmap))5             {6                 g.DrawString("HelloWorld", new Font("Arial",13), System.Drawing.Brushes.Red, 20, 20);7             }8 9             return bitmap.GetHbitmap();
10         }

运行效果如下:

示例代码

下载

参考资料

DWM 缩略图概述 - Win32 apps | Microsoft Learn


http://www.ppmy.cn/news/1560661.html

相关文章

【MyBatis-Plus 条件构造器】全面解析 Wrapper

在 MyBatis-Plus 中, 条件构造器 是一个强大的工具,能够帮助我们灵活地构建 SQL 查询条件,而无需手写繁琐的 SQL 语句。本文将从基础到高级,带你全面了解条件构造器的使用方法及其链式构造能力。 一、什么是条件构造器&#xff1f…

vim、watch、cp和mv

一、vim使用技巧 vim主配置文件:/etc/vimrc (对所有用户都生效) vim子配置文件:vim ~/.vimrc (只对当前用户生效) 可写入: set nu 显示行号 ts2 tab键长度为两个空格(默认为8个空格…

【Rust练习】26.Package and Crate

练习题来自:https://practice-zh.course.rs/crate-module/crate.html 建议在命令行下操作完成本节内容,Windows 11/10 首选 Windows 终端,好看,支持渲染中文字体,缺点是功能太少了;其次推荐 mobaxterm&…

pytorch中nn.Conv2d详解及参数设置原则

文章目录 基础参数1. in_channels (输入通道数)2. out_channels (输出通道数)3. kernel_size (卷积核大小)4. stride (步幅)5. padding (填充)6. dilation (膨胀)7. groups (分组卷积)8. bias (偏置) 如何设置参数?1. **in_channels 和 out_channels(输入…

5G终端串口AT命令 FM650 常用命令

5G终端串口AT命令 FM650 常用命令 5G终端串口AT命令 FM650 常用命令 #状态查询 MODULE_PORT/dev/ttyUSB0echo -e "ATE0\r\n" > $MODULE_PORT echo -e "ATGTUSBMODE?\r\n" > $MODULE_PORT echo -e "ATGTRAT?" > $MODULE_PORT ec…

【JMeter详解】

JMeter详解 Apache JMeter 是一个开源的、100%纯Java应用程序,设计用于负载测试和性能测量。它最初是为测试Web应用程序而设计的,但后来扩展到其他测试功能。JMeter可以用来对静态和动态资源(如静态文件、Servlets、Perl脚本、Java对象、数据…

多分类的损失函数

在多分类任务中,常用的损失函数能够衡量模型输出的类别分布与目标类别之间的差异,帮助模型学习更准确的分类能力。以下是多分类任务中常用的损失函数: 1. 交叉熵损失(Cross-Entropy Loss) 公式: CrossEntropyLoss = − 1 N ∑ i =

logback日志文件多环境配置路径

项目中遇到问题,springboot项目 本地jar包部署到现场后,经常遇到现场的日志存放的路径会更改,经过查阅,有两种方式,下面简单说明一下。 一、第一种 启动jar包时 添加参数 --logging.configF:\hgtest\config\logback.x…