使用WPF在Windows實(shí)現(xiàn)任務(wù)欄縮略圖效果
WPF 在 Windows 實(shí)現(xiàn)任務(wù)欄縮略圖
- 框架支持
.NET4 至 .NET8; Visual Studio 2022;
在 Windows Vista 系統(tǒng)上,微軟首次推出任務(wù)欄縮略圖預(yù)覽功能。
Windows 任務(wù)欄中,當(dāng)我們將窗口最小化并將鼠標(biāo)懸停在圖標(biāo)上,會(huì)顯示一個(gè)窗口預(yù)覽縮略圖。通過 Windows DWM(Desktop Window Manager)[3]提供的 API,我們可以自定義這個(gè)縮略圖的內(nèi)容,實(shí)現(xiàn)類似音樂播放器當(dāng)前播放的音樂封面圖。

1. 修改 WindowHelpers.cs
先檢查 window 是否為 null 或 imagePath 是否為空。
使用 WindowInteropHelper 獲取 window 的句柄 (hwnd);
注冊(cè)窗口消息鉤子,監(jiān)聽 DWM 消息;
window.ShowInTaskbar = true;設(shè)置 Window 有任務(wù)欄圖標(biāo),否則無法顯示預(yù)覽縮略圖。
public static void SetIconicThumbnail(this Window window, string imagePath)
{
if (window == null || string.IsNullOrWhiteSpace(imagePath)) return;
if (!File.Exists(imagePath)) return;
IntPtr hwnd = new WindowInteropHelper(window).Handle;
int size = Marshal.SizeOf(typeof(int));
IntPtr pBool = Marshal.AllocHGlobal(size);
try
{
Marshal.WriteInt32(pBool, 1);
Win32.DwmSetWindowAttribute(hwnd, DwmWindowAttributes.FORCE_ICONIC_REPRESENTATION, pBool, size);
Win32.DwmSetWindowAttribute(hwnd, DwmWindowAttributes.HAS_ICONIC_BITMAP, pBool, size);
}
finally
{
Marshal.FreeHGlobal(pBool);
}
var source = HwndSource.FromHwnd(hwnd);
if (source != null)
{
source.AddHook(new HwndSourceHook((IntPtr hwnd2, int msg, IntPtr wParam, IntPtr lParam, refbool handled) =>
{
if (msg == WindowsMessageCodes.WM_DWMSENDICONICTHUMBNAIL)
{
int width = ((int)((((long)lParam) >> 16) & 0xFFFF));
int height = ((int)((long)lParam & 0xFFFF));
try
{
using (var bmp = new Bitmap(imagePath))
using (var resized = new Bitmap(bmp, new Size(width, height)))
{
IntPtr hBitmap = resized.GetHbitmap();
Win32.DwmSetIconicThumbnail(hwnd2, hBitmap, (int)DwmWindowAttributes.None);
Win32.DeleteObject(hBitmap);
}
}
catch (Exception ex)
{
thrownew Exception($"DwmSetIconicThumbnail error :{ex.Message}!");
}
handled = true;
}
return IntPtr.Zero;
}));
}
Win32.DwmInvalidateIconicBitmaps(hwnd);
window.ShowInTaskbar = true;
}
2. 修改 Win32.cs
DwmSetWindowAttribute 設(shè)置打開縮略圖顯示圖片;
DwmSetIconicThumbnail 設(shè)置自定義縮略圖給任務(wù)欄;
DwmInvalidateIconicBitmaps 通知 DWM 當(dāng)前的縮略圖無效,重新請(qǐng)求;
WM_DWMSENDICONICTHUMBNAILDWM 向窗口發(fā)送消息,請(qǐng)求新的縮略圖;
DeleteObject() 手動(dòng)釋放 GDI ,避免內(nèi)存泄漏;
[DllImport(Gdi32)]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport(DwmApi)]
public static extern int DwmSetIconicThumbnail(IntPtr hwnd, IntPtr hbmp, int dwSITFlags);
[DllImport(DwmApi)]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttributes dwAttribute, IntPtr pvAttribute, int cbAttribute);
[DllImport(DwmApi)]
public static extern int DwmInvalidateIconicBitmaps(IntPtr hwnd);
internalclassWindowsMessageCodes
{
publicconstint WM_DWMSENDICONICTHUMBNAIL = 0x0323;
}
[Flags]
publicenum DwmWindowAttributes : uint
{
None = 0,
DISPLAYFRAME = 1,
FORCE_ICONIC_REPRESENTATION = 7,
HAS_ICONIC_BITMAP = 10
}
3. 新增 IconicThumbnailWindowExample.xaml
新增兩個(gè)按鈕切換圖片,BtnPrevious_Click 和 BtnNext_Click。
Image 控件用于顯示任務(wù)欄的縮略圖。
<wd:Window
x:Class="WPFDevelopers.Sample.ExampleViews.IconicThumbnailWindowExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converts="clr-namespace:WPFDevelopers.Sample.Converts"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFDevelopers.Sample.ExampleViews"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="clr-namespace:WPFDevelopers.Sample.Models"
xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
Title="IconicThumbnailWindowExample"
Width="600"
Height="450"
Icon="pack://application:,,,/WPFDevelopers.Samples;component/WPFDevelopers.ico"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="7*" />
<RowDefinition Height="3*" />
</Grid.RowDefinitions>
<Image
x:Name="ImagePreview"
Width="200"
Height="200"
VerticalAlignment="Bottom" />
<StackPanel
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
wd:PanelHelper.Spacing="3"
Orientation="Horizontal">
<Button
x:Name="BtnPrevious"
Width="50"
Height="50"
Click="BtnPrevious_Click">
<wd:PathIcon Width="10" Kind="Previous" />
</Button>
<Button
x:Name="BtnNext"
Width="50"
Height="50"
Click="BtnNext_Click">
<wd:PathIcon Width="10" Kind="Next" />
</Button>
</StackPanel>
</Grid>
</wd:Window>
4. 新增 IconicThumbnailWindowExample.xaml.cs
BtnNext_ClickcurrentFileIndex = (currentFileIndex + 1) % fileList.Count; 通過代碼實(shí)現(xiàn)圖片循環(huán)切換:每次點(diǎn)擊按鈕時(shí),currentFileIndex 會(huì)增加 1,如果超過了 fileList 的最大索引,回到第一個(gè)圖片。。
BtnPrevious_ClickcurrentFileIndex = (currentFileIndex - 1 + fileList.Count) % fileList.Count; 通過代碼實(shí)現(xiàn)圖片循環(huán)切換:每次點(diǎn)擊按鈕時(shí),currentFileIndex 會(huì)減少 1,并且如果當(dāng)前索引小于 0,回到最后一張圖片。
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Media.Imaging;
using WPFDevelopers.Helpers;
namespaceWPFDevelopers.Sample.ExampleViews
{
/// <summary>
/// IconicThumbnailWindowExample.xaml 的交互邏輯
/// </summary>
publicpartialclassIconicThumbnailWindowExample
{
private List<string> fileList = new List<string>();
privateint currentFileIndex = -1;
public IconicThumbnailWindowExample()
{
InitializeComponent();
Loaded += IconicThumbnailWindowExample_Loaded;
}
private void IconicThumbnailWindowExample_Loaded(object sender, RoutedEventArgs e)
{
fileList.Clear();
currentFileIndex = -1;
var directorys = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "IconicThumbnail");
if (!Directory.Exists(directorys)) return;
string[] files = Directory.GetFiles(directorys);
fileList.AddRange(files);
}
private void BtnPrevious_Click(object sender, RoutedEventArgs e)
{
if (fileList.Count == 0) return;
currentFileIndex = (currentFileIndex + 1) % fileList.Count;
var img = fileList[currentFileIndex];
ImagePreview.Source = new BitmapImage(new Uri(img));
this.SetIconicThumbnail(img);
}
private void BtnNext_Click(object sender, RoutedEventArgs e)
{
if (fileList.Count == 0) return;
currentFileIndex = (currentFileIndex - 1 + fileList.Count) % fileList.Count;
var img = fileList[currentFileIndex];
ImagePreview.Source = new BitmapImage(new Uri(img));
this.SetIconicThumbnail(img);
}
}
}效果如下

到此這篇關(guān)于使用WPF在Windows實(shí)現(xiàn)任務(wù)欄縮略圖效果的文章就介紹到這了,更多相關(guān)WPF任務(wù)欄縮略圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#方法中調(diào)用參數(shù)的值傳遞方式和引用傳遞方式以及ref與out的區(qū)別深入解析
以下是對(duì)c#方法中調(diào)用參數(shù)的值傳遞方式和引用傳遞方式,以及ref與out的區(qū)進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-07-07
C#實(shí)現(xiàn)遞歸算法經(jīng)典實(shí)例
這篇文章主要為大家介紹了C#實(shí)現(xiàn)遞歸算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01
基于C#實(shí)現(xiàn)SM2加簽驗(yàn)簽工具
這篇文章主要為大家詳細(xì)介紹了如何基于C#實(shí)現(xiàn)一個(gè)SM2加簽驗(yàn)簽工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-10-10
C# Double轉(zhuǎn)化為String時(shí)的保留位數(shù)及格式方式
這篇文章主要介紹了C# Double轉(zhuǎn)化為String時(shí)的保留位數(shù)及格式方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02

