I would like to use the DwmSetIconicThumbnail function to set a static image for the thumbnail preview of my app.
As pointed in the reference link above, firstly is necessary to call DwmSetWindowAttribute to enable DWMWA_FORCE_ICONIC_REPRESENTATION and DWMWA_HAS_ICONIC_BITMAP attributes.
I already did all that. I've taken all the definitions from WindowsAPICodePack source code here, and I'm following the same steps (or I think so).
The problem is that when I try to adapt the example for my WinForms Window, I get a E_INVALIDARG HRESULT code when calling DwmSetIconicThumbnail function at the end of the code below, I'm not sure whether the problematic argument is the hwnd, or the hBitmap.
What I'm doing wrong?.
C#:
Bitmap bmp;
IntPtr hBitmap;
IntPtr hwnd;
int hresult;
const int DisplayThumbnailFrame = 0x1;
public enum DwmWindowAttribute : uint
{
    NcRenderingEnabled = 1,
    NcRenderingPolicy,
    TransitionsForceDisabled,
    AllowNcPaint,
    CaptionButtonBounds,
    NonClientRtlLayout,
    ForceIconicRepresentation,
    Flip3DPolicy,
    ExtendedFrameBounds,
    HasIconicBitmap,
    DisallowPeek,
    ExcludedFromPeek,
    Cloak,
    Cloaked,
    FreezeRepresentation,
    Last
}
[DllImport("dwmapi.dll", PreserveSig = true)]
static internal extern int DwmSetWindowAttribute(IntPtr hwnd, 
                                                 DwmWindowAttribute dwAttributeToSet, 
                                                 IntPtr pvAttributeValue, 
                                                 uint cbAttribute);
[DllImport("Dwmapi.dll")]
public static extern int DwmSetIconicThumbnail(IntPtr hwnd, 
                                               IntPtr hBitmap, 
                                               int flags);
private void Form1_Shown() {
    bmp = (Bitmap)Bitmap.FromFile("C:\\Image.jpg");
    hBitmap = bmp.GetHbitmap();
    hwnd = Process.GetCurrentProcess.MainWindowHandle;
    IntPtr block = Marshal.AllocHGlobal(4);
    int value = Math.Abs(Convert.ToInt32(true)); // or 1
    Marshal.WriteInt32(block, value);
    try {
        hresult = DwmSetWindowAttribute(hwnd, DwmWindowAttribute.HasIconicBitmap, block, 4);
        if ((hresult != 0)) {
            throw Marshal.GetExceptionForHR(hresult);
        }
        hresult = DwmSetWindowAttribute(hwnd, DwmWindowAttribute.ForceIconicRepresentation, block, 4);
        if ((hresult != 0)) {
            throw Marshal.GetExceptionForHR(hresult);
        }
    } finally {
        Marshal.FreeHGlobal(block);
    }
    hresult = DwmSetIconicThumbnail(hwnd, hBitmap, DisplayThumbnailFrame);
    if ((hresult != 0)) {
        throw Marshal.GetExceptionForHR(hresult);
    }
}
VB.NET:
Dim bmp As Bitmap
Dim hBitmap As IntPtr
Dim hwnd As IntPtr
Dim hresult As Integer
Const DisplayThumbnailFrame As Integer = &H1
Enum DwmWindowAttribute As UInteger
    NcRenderingEnabled = 1
    NcRenderingPolicy
    TransitionsForceDisabled
    AllowNcPaint
    CaptionButtonBounds
    NonClientRtlLayout
    ForceIconicRepresentation
    Flip3DPolicy
    ExtendedFrameBounds
    HasIconicBitmap
    DisallowPeek
    ExcludedFromPeek
    Cloak
    Cloaked
    FreezeRepresentation
    Last
End Enum
<DllImport("dwmapi.dll", PreserveSig:=True)>
Friend Shared Function DwmSetWindowAttribute(hwnd As IntPtr,
                                             dwAttributeToSet As DwmWindowAttribute,
                                             pvAttributeValue As IntPtr,
                                             cbAttribute As UInteger
) As Integer
End Function
<DllImport("Dwmapi.dll")>
Public Shared Function DwmSetIconicThumbnail(ByVal hwnd As IntPtr,
                                             ByVal hBitmap As IntPtr,
                                             ByVal flags As Integer
) As Integer
End Function
Private Sub Form1_Shown() Handles MyBase.Shown
    bmp = DirectCast(Bitmap.FromFile("C:\Image.jpg"), Bitmap)
    hBitmap = bmp.GetHbitmap()
    hwnd = Process.GetCurrentProcess.MainWindowHandle
    Dim block As IntPtr = Marshal.AllocHGlobal(4)
    Dim value As Integer = Math.Abs(CInt(True)) ' or 1
    Marshal.WriteInt32(block, value)
    Try
        hresult = DwmSetWindowAttribute(hwnd, DwmWindowAttribute.HasIconicBitmap, block, 4)
        If (hresult <> 0) Then
            Throw Marshal.GetExceptionForHR(hresult)
        End If
        hresult = DwmSetWindowAttribute(hwnd, DwmWindowAttribute.ForceIconicRepresentation, block, 4)
        If (hresult <> 0) Then
            Throw Marshal.GetExceptionForHR(hresult)
        End If
    Finally
        Marshal.FreeHGlobal(block)
    End Try
    hresult = DwmSetIconicThumbnail(hwnd, hBitmap, DisplayThumbnailFrame)
    If (hresult <> 0) Then
        Throw Marshal.GetExceptionForHR(hresult)
    End If
End Sub
According to MSDN Documentation:
An application typically calls the DwmSetIconicThumbnail function after it receives a WM_DWMSENDICONICTHUMBNAIL message for its window. The thumbnail should not exceed the maximum x-coordinate and y-coordinate that are specified in that message. The thumbnail must also have a 32-bit color depth.
So, using the following 32-by-32 bitmap, with 32-bit color depth, it worked:

The exception was gone. However, it didn't quite replace the application icon thumbnail, but appended it.
This is what it looks like using ALT+TAB:

And this when hovering over it:

Note that I did not modify your code at all and ran it exactly as it is, but just using a suitable Bitmap. These are results for a Windows 10 machine.
The reason because the DwmSetIconicThumbnail function returns an error is because the image exceeds the maximum size for the thumbnail, that's it, a resize is not handled by Windows itself, so we need to do a little bit more of work.
I'm not sure about which factor determines the maximum possible thumbnail size that we can establish for our image, this is speculation but I think it depends on a Windows registry value that determines the width and height for thumbnail previews (I exactlly don't remember the registry location of that value, sorry, but it can be Googled easy).
Well, as pointed above, we need to handle the WM_DWMSENDICONICTHUMBNAIL (0x323) message, so we need to override the base Window procedure a.k.a WNDPROC of our Win32 window (a Form), then finally we can retrieve the maximum width and height for the thumbnail creation from the message parameters.
This is a working code sample:
Private Const WM_DWMSENDICONICTHUMBNAIL As Integer = &H323
Protected Overrides Sub WndProc(ByRef m As Windows.Forms.Message)
    Select Case m.Msg
        Case WM_DWMSENDICONICTHUMBNAIL
            Dim hwnd As IntPtr = Process.GetCurrentProcess().MainWindowHandle
            Dim dWord As Integer = m.LParam.ToInt32()
            Dim maxWidth As Short = BitConverter.ToInt16(BitConverter.GetBytes(dWord), 2)
            Dim maxHeight As Short = BitConverter.ToInt16(BitConverter.GetBytes(dWord), 0)
            Using img As Image = Bitmap.FromFile("C:\Image.jpg")
                Using thumb As Bitmap = CType(img.GetThumbnailImage(maxWidth, maxHeight, Nothing, Nothing), Bitmap)
                    Dim hBitmap As IntPtr = thumb.GetHbitmap()
                    Dim hresult As Integer = NativeMethods.DwmSetIconicThumbnail(hwnd, hBitmap, 0)
                    If (hresult <> 0) Then
                        ' Handle error...
                        ' Throw Marshal.GetExceptionForHR(hresult)
                    End If
                    NativeMethods.DeleteObject(hBitmap)
                End Using
            End Using
    End Select
    ' Return Message to base message handler.
    MyBase.WndProc(m)
End Sub
As last comment, and if in the future I need to remember this, I will share this question that I found on MSDN, which can be helpful for someone having problems with WM_DWMSENDICONICTHUMBNAIL message:
Using slightly-modified declarations from Microsoft Reference Source (to provide a return value), I'm able to get this to function as expected.
internal static class NativeMethods
{
    [DllImport("dwmapi.dll")]
    public static extern int DwmSetIconicThumbnail(IntPtr hwnd, IntPtr hbmp, DWM_SIT dwSITFlags);
    [DllImport("dwmapi.dll")]
    public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWA dwAttribute, ref int pvAttribute, int cbAttribute);
    public enum DWM_SIT
    {
        None,
        DISPLAYFRAME = 1
    }
    public enum DWMWA
    {
        NCRENDERING_ENABLED = 1,
        NCRENDERING_POLICY,
        TRANSITIONS_FORCEDISABLED,
        ALLOW_NCPAINT,
        CAPTION_BUTTON_BOUNDS,
        NONCLIENT_RTL_LAYOUT,
        FORCE_ICONIC_REPRESENTATION,
        FLIP3D_POLICY,
        EXTENDED_FRAME_BOUNDS,
        // New to Windows 7:
        HAS_ICONIC_BITMAP,
        DISALLOW_PEEK,
        EXCLUDED_FROM_PEEK
        // LAST
    }
    public const uint TRUE = 1;
}
Then, I just modified your existing C# code to fit these signatures.
    private void Form1_Shown(object sender, EventArgs e)
    {
        bmp = (Bitmap)Bitmap.FromFile("C:\\Image.jpg");
        hBitmap = bmp.GetHbitmap();
        hwnd = Process.GetCurrentProcess().MainWindowHandle;
        int attributeTrue = (int)NativeMethods.TRUE;
        hresult = NativeMethods.DwmSetWindowAttribute(hwnd, NativeMethods.DWMWA.HAS_ICONIC_BITMAP, ref attributeTrue, sizeof(int));
        if ((hresult != 0))
            throw Marshal.GetExceptionForHR(hresult);
        hresult = NativeMethods.DwmSetWindowAttribute(hwnd, NativeMethods.DWMWA.FORCE_ICONIC_REPRESENTATION, ref attributeTrue, sizeof(int));
        if ((hresult != 0))
            throw Marshal.GetExceptionForHR(hresult);
        hresult = NativeMethods.DwmSetIconicThumbnail(hwnd, hBitmap, NativeMethods.DWM_SIT.DISPLAYFRAME);
        if ((hresult != 0))
            throw Marshal.GetExceptionForHR(hresult);
    }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With