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
[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
<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
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); } } }
参考资料:
[1] Windows DWM(Desktop Window Manager): https://learn.microsoft.com/zh-cn/windows/win32/dwm/dwm-overview?redirectedfrom=MSDN
[2] GitHub 源码地址: https://github.com/WPFDevelopersOrg/WPFDevelopers/blob/dev/src/WPFDevelopers.Shared/Core/Helpers/WindowHelpers.cs
[3] Gitee 源码地址: https://gitee.com/WPFDevelopersOrg/WPFDevelopers/blob/dev/src/WPFDevelopers.Shared/Core/Helpers/WindowHelpers.cs