WPF自定义任务栏缩略图:实现个性化任务栏的魔法

时间:2025-01-13 00:25 分类:其他教程

在Windows操作系统中,任务栏缩略图功能一直备受用户喜爱。从Windows 7开始,微软就引入了这个功能,允许用户在任务栏上预览窗口内容。然而,如果你想自定义任务栏缩略图的内容,比如像网易云那样,就需要一些技术手段。本文将带你深入了解如何使用DWM函数在WPF中自定义任务栏缩略图。

任务栏缩略图预览的演变

在Windows 7系统上,任务栏缩略图预览功能首次亮相。当鼠标悬停在任务栏上的程序图标上时,会打开一个预览窗口,允许用户对整个窗口内容进行预览。这种功能在后续的Windows 8/8.1/10/11系统中得到了延续。但是,这种预览功能仅限于窗口本身内容,无法满足更复杂的需求。

自定义任务栏缩略图的技术手段

要自定义任务栏缩略图,我们需要借助DirectWrite和Direct2D等图形API,以及DWM(Desktop Window Manager)中的几个函数。通过这些工具,我们可以实现高度个性化的任务栏缩略图。

使用DWM函数设置窗口属性

首先,我们需要在窗口的Loaded事件中调用DwmSetWindowAttribute函数来设置相关属性。这个函数允许我们设置窗口管理器(DWM)的非客户端呈现属性的值。

[DllImport("dwmapi.dll")]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, int dwAttribute, IntPtr pvAttribute, int cbAttribute);

private const int DWMWINDOWATTRIBUTE = 0x00000002;
private const int FORCE_ICONIC_REPRESENTATION = 0x00000004;
private const int HAS_ICONIC_BITMAP = 0x00000008;

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    int size = Marshal.SizeOf(typeof(int));
    IntPtr pBool = Marshal.AllocHGlobal(size);
    Marshal.WriteInt32(pBool, 0, 1); // 设置属性为TRUE

    var result = DwmSetWindowAttribute(new WindowInteropHelper(this).Handle, DWM.WINDOW_ATTRIBUTE.FORCE_ICONIC_REPRESENTATION, pBool, size);
    Marshal.FreeHGlobal(pBool);

    HwndSource.FromHwnd(new WindowInteropHelper(this).Handle).AddHook(WndProc);
}
处理WM_DWMSENDICONICTHUMBNAIL消息

当收到WM_DWMSENDICONICTHUMBNAIL消息时,我们需要调用DwmSetIconicThumbnail函数来设置缩略图。这个函数允许我们设置窗口或选项卡上要用作缩略图表示形式的静态图标位图。

[DllImport("dwmapi.dll")]
public static extern int DwmSetIconicThumbnail(IntPtr hwnd, IntPtr hbmp, int dwSITFlags);

private const int DWM_SIT_DISPLAYFRAME = 0x00000001;

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    switch (msg)
    {
        case DWM.WM_DWMSENDICONICTHUMBNAIL:
            var bmp = (Bitmap)Bitmap.FromFile(@"xxx.bmp");
            var hBitmap = bmp.GetHbitmap();
            DwmSetIconicThumbnail(hwnd, hBitmap, DWM.SIT_DISPLAYFRAME);
            handled = true;
            break;
    }
    return IntPtr.Zero;
}
解析lParam参数

为了获取缩略图的尺寸,我们需要解析WM_DWMSENDICONICTHUMBNAIL消息的lParam参数。lParam的高16位表示宽度,低16位表示高度。

private short HIWORD(IntPtr lParam)
{
    return (short)(((ulong)lParam >> 16) & 0xFFFF);
}

private short LOWORD(IntPtr lParam)
{
    return (short)((ulong)lParam & 0xFFFF);
}

private void SetThumbnail(IntPtr hwnd)
{
    var width = HIWORD(lParam);
    var height = LOWORD(lParam);

    // 创建位图并设置缩略图
    using (Bitmap bitmap = new Bitmap(width, height))
    {
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.DrawString("HelloWorld", new Font("Arial", 13), System.Drawing.Brushes.Red, 20, 20);
        }
        var hBitmap = bitmap.GetHbitmap();
        DwmSetIconicThumbnail(hwnd, hBitmap, DWM.SIT_DISPLAYFRAME);
    }
}

实现自定义缩略图的效果

通过上述步骤,我们可以实现一个高度个性化的任务栏缩略图。例如,可以在缩略图中添加自定义的图标、文本或背景颜色。以下是一个完整的示例代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.Loaded += MainWindow_Loaded;
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        SetThumbnail(this.Handle);
    }

    private void SetThumbnail(IntPtr hwnd)
    {
        var width = HIWORD(lParam);
        var height = LOWORD(lParam);

        using (Bitmap bitmap = new Bitmap(width, height))
        {
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                g.DrawString("HelloWorld", new Font("Arial", 13), System.Drawing.Brushes.Red, 20, 20);
            }
            var hBitmap = bitmap.GetHbitmap();
            DwmSetIconicThumbnail(hwnd, hBitmap, DWM.SIT_DISPLAYFRAME);
        }
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        switch (msg)
        {
            case DWM.WM_DWMSENDICONICTHUMBNAIL:
                var bmp = (Bitmap)Bitmap.FromFile(@"xxx.bmp");
                var hBitmap = bmp.GetHbitmap();
                DwmSetIconicThumbnail(hwnd, hBitmap, DWM.SIT_DISPLAYFRAME);
                handled = true;
                break;
        }
        return IntPtr.Zero;
    }
}

通过本文的介绍,相信你已经掌握了如何在WPF中自定义任务栏缩略图的方法。如果你有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入我们的微信公众号[DotNet技术匠]社区,与其他热爱技术的同行一起交流心得,共同成长!

声明:

1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。

2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。

3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。

4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。

本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 0人参与,0条评论
查看更多

Copyright 2005-2024 yuanmayuan.com 源码园 版权所有 备案信息

声明: 本站非腾讯QQ官方网站 所有软件和文章来自互联网 如有异议 请与本站联系 本站为非赢利性网站 不接受任何赞助和广告