WPF自定义任务栏缩略图

任务栏缩略图预览

在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 DWM
 2     {
 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

相关推荐
炯哈哈12 小时前
【上位机——WPF】Window标签常用属性
开发语言·c#·wpf·上位机
绿龙术士2 天前
构建现代化WPF应用:数据驱动开发与高级特性解析
c#·wpf
wangnaisheng4 天前
【WPF】Opacity 属性的使用
wpf
姬激薄4 天前
配置Hadoop集群-集群配置
wpf
python算法(魔法师版)4 天前
.NET 在鸿蒙系统上的适配现状
华为od·华为·华为云·.net·wpf·harmonyos
大道随心4 天前
【wpf】11 在WPF中实现父窗口蒙版效果:原理详解与进阶优化
wpf
zizisuo5 天前
9.1.领域驱动设计
wpf
大道随心5 天前
【wpf】10 C#树形控件高效实现:递归构建与路径查找优化详解
开发语言·c#·wpf
离歌漠5 天前
WPF内嵌其他进程的窗口
c#·wpf
沉到海底去吧Go6 天前
【身份证识别表格】批量识别身份证扫描件或照片保存为Excel表格,怎么大批量将身份证图片转为excel表格?基于WPF和腾讯OCR的识别方案
ocr·wpf·excel·身份证识别表格·批量扫描件身份证转表格·图片识别表格·图片识别excel表格