如何从 C# 或 VB.Net 使用 Win32 'DwmSetIconicThumbnail'?

2023-12-10

我想使用DwmSetIconicThumbnail函数为我的应用程序的缩略图预览设置静态图像。

正如上面的参考链接中指出的,首先需要调用Dwm设置窗口属性启用DWMWA_FORCE_ICONIC_REPRESENTATION and DWMWA_HAS_ICONIC_BITMAP属性。

我已经做了这一切。我已经从以下位置获取了所有定义WindowsAPI代码包源代码here,并且我正在遵循相同的步骤(或者我认为是这样)。

问题是,当我尝试为我的 WinForms 窗口调整示例时,我得到了一个E_INVALIDARG调用时的 HRESULT 代码DwmSetIconicThumbnail下面代码末尾的函数,我不确定有问题的参数是 hwnd 还是 hBitmap。

我做错了什么?


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

根据MSDN 文档:

应用程序通常在收到其窗口的 WM_DWMSENDICONICTHUMBNAIL 消息后调用 DwmSetIconicThumbnail 函数。缩略图不应超过该消息中指定的最大 x 坐标和 y 坐标。缩略图还必须具有 32 位颜色深度。

因此,使用以下具有 32 位颜色深度的 32×32 位图,它可以工作:

enter image description here

异常消失了。但是,它并没有完全取代应用程序图标缩略图,而是附加了它。

使用 ALT+TAB 的效果如下:

enter image description here

当鼠标悬停在它上面时:

enter image description here

请注意,我根本没有修改您的代码并完全按照原样运行它,而只是使用合适的Bitmap。这些是 Windows 10 计算机的结果。


UPDATE

究其原因,是因为DwmSetIconicThumbnail函数返回错误是因为图像超出了缩略图的最大尺寸,就是这样,Windows本身不处理调整大小,所以我们需要做更多的工作。

我不确定哪个因素决定了我们可以为图像建立的最大可能缩略图大小,这是猜测,但我认为这取决于确定缩略图预览的宽度和高度的 Windows 注册表值(我完全不知道)记住该值的注册表位置,抱歉,但可以轻松通过 Google 搜索)。

嗯,正如上面指出的,我们需要处理WM_DWMSENDICONICTHUMBNAIL (0x323) 消息,因此我们需要重写基本窗口过程(又名)WNDPROC我们的 Win32 窗口(一个表单),最后我们可以从消息参数中检索缩略图创建的最大宽度和高度。

这是一个工作代码示例:

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

作为最后一条评论,如果将来我需要记住这一点,我将分享我在 MSDN 上找到的这个问题,这对于遇到问题的人可能会有所帮助WM_DWMSENDICONICTHUMBNAIL信息:

  • 当我请求图标表示时,为什么我的程序没有收到 WM_DWMSENDICONICTHUMBNAIL 消息?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 C# 或 VB.Net 使用 Win32 'DwmSetIconicThumbnail'? 的相关文章

  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 函数参数的默认参数是否被视为该参数的初始值设定项?

    假设我有这样的函数声明 static const int R 0 static const int I 0 void f const int r R void g int i I 根据 dcl fct default 1 如果在参数声明中指
  • Visual Studio 在构建后显示假错误

    我使用的是 Visual Studio 2017 构建后 sln在调试模式下 我收到错误 但是 当我通过双击错误列表选项卡中的错误来访问错误时 错误会从页面中消失 并且错误数量也会减少 我不太确定这种行为以及为什么会发生这种情况 有超过 2
  • unordered_map 中字符串的 C++ 哈希函数

    看起来 C 标准库中没有字符串的哈希函数 这是真的 在任何 c 编译器上使用字符串作为 unordered map 中的键的工作示例是什么 C STL提供模板专业化 http en cppreference com w cpp string
  • Python 属性和 Swig

    我正在尝试使用 swig 为一些 C 代码创建 python 绑定 我似乎遇到了一个问题 试图从我拥有的一些访问器函数创建 python 属性 方法如下 class Player public void entity Entity enti
  • File.AppendText 尝试写入错误的位置

    我有一个 C 控制台应用程序 它作为 Windows 任务计划程序中的计划任务运行 此控制台应用程序写入日志文件 该日志文件在调试模式下运行时会创建并写入应用程序文件夹本身内的文件 但是 当它在任务计划程序中运行时 它会抛出一个错误 指出访
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • C++ int 前面加 0 会改变整个值

    我有一个非常奇怪的问题 如果我像这样声明一个 int int time 0110 然后将其显示到控制台返回的值为72 但是当我删除前面的 0 时int time 110 然后控制台显示110正如预期的那样 我想知道两件事 首先 为什么它在
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • 在屏幕上获取字符

    我浏览了 NCurses 函数列表 似乎找不到返回已打印在屏幕上的字符的函数 每个字符单元格中存储的字符是否有可访问的值 如果没有的话Windows终端有类似的功能吗 我想用它来替换屏幕上某个值的所有字符 例如 所有a s 具有不同的特征
  • DataTable.GetChanges() 不断返回 NULL

    我正在尝试获取存在于的所有行allData但不在removeData public static DataTable RemoveDuplicateRows DataTable allData DataTable removeData re
  • 使用 omp_set_num_threads() 将线程数设置为 2,但 omp_get_num_threads() 返回 1

    我有以下使用 OpenMP 的 C C 代码 int nProcessors omp get max threads if argv 4 NULL printf argv 4 s n argv 4 nProcessors atoi argv
  • 如何在richtextbox中使用多颜色[重复]

    这个问题在这里已经有答案了 我使用 C windows 窗体 并且有 richtextbox 我想将一些文本设置为红色 一些设置为绿色 一些设置为黑色 怎么办呢 附图片 System Windows Forms RichTextBox有一个
  • 使用 C 在 OS X 中获取其他进程的 argv

    我想获得其他进程的argv 例如ps 我使用的是在 Intel 或 PowerPC 上运行的 Mac OS X 10 4 11 首先 我阅读了 ps 和 man kvm 的代码 然后编写了一些 C 代码 include

随机推荐

  • 如何首先按值排序 std::map,然后按键排序?

    我需要排序一个std map按值 然后按键 该地图包含如下数据 1 realistically 8 really 4 reason 3 reasonable 1 reasonably 1 reassemble 1 reassembled 2
  • 有什么办法可以链接到我的应用程序的 Android 通知设置吗?

    有什么方法可以启动意图来访问我的应用程序的 Android 通知设置屏幕 如下图所示 或者有一种简单的方法可以制作一个只需单击即可引导至此处的 PreferenceScreen 项目 以下内容适用于 Android 5 0 Lollipop
  • 查找二维数组或直方图的两个主要峰以及峰之间的谷

    for int i 0 i lt c length i for int j 0 j
  • 无法将 Firebase cocoapod 添加到 kotlin 多平台共享模块

    我正在将 Android iOS 应用程序迁移到 Kotlin 多平台框架 这个过程或多或少进展顺利 但是所有与从 iOS 框架 pod 导入以在共享代码模块中使用它们相关的事情都不容易 这次 我在尝试在通用模块中开发共享类来处理与分析和崩
  • 意外的字符串常量[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 目前不接受答案 我的数据库有问题 我想在R中输入数据库 但出现此消息 错误意外的字符串常量 我写了这个命令 read csv prova1 sep header 20 有什么问题 我想我的数
  • 在具有透明背景的 Octave 中保存绘图

    我使用 Octave 绘制了一些 GPS 轨迹和航向矢量 我想将绘图覆盖在卫星图像上 但是当我保存绘图时 它具有白色背景 有没有办法保存为透明背景 我认为将 print 与 pngalpha 设备一起使用可以满足您的需求 例如 print
  • Android ActionBar/Toolbar 颜色在浅色主题和深色主题中不同

    我试图理解为什么ActionBar浅色主题与深色主题的风格不同 下面是一个简单的设置屏幕 可以在具有相同主题的浅色和深色主题之间切换 值 主题 xml
  • php日期和夏令时混淆

    我遇到了一个问题 我 99 确信它与昨天开始的夏令时有关 以下脚本 其中 86400 是一天的秒数 给出以下输出 1383451200 2013 11 03 1 1383537600 2013 11 03 0 2 个时间戳 以一天中的秒数分
  • 使用 jQuery 从 URL 获取查询字符串 [重复]

    这个问题在这里已经有答案了 我有以下网址 http www mysite co uk location mylocation1 我需要得到的值location将 URL 转换为变量 然后在 jQuery 代码中使用它 var thequer
  • 在 ruby​​ 中如何判断输入的字符串是大写还是小写?

    我正在尝试编写一个程序 当输入单个字母时 如果它是大写字母 则将其保留为大写字母并返回它 如果它是小写字母 则将其转换为大写字母 我该如何编写才能判断字符串最初是大写还是小写 只需将字符串转换为大写并与原始字符串进行比较 string st
  • 设置 SCORM 课程进度

    我只是想知道 是否可以在运行时在 SCORM 文件中设置课程进度 我应该检查哪种方法 进度将根据 SCO 开发人员的学习要求来定义 一般来说 达到的目标 cmi objectives 数量或学习者访问的页面数量 要存储进度 如果 SCORM
  • Shiny 中 fillPage 的基本示例 - 它是如何工作的?

    我不明白如何获得一个图来完全填充我的仪表板 除了标题之外 我想我必须使用 fillPage 但我无法让它工作 这是我的例子 我很感谢任何提示 ipak lt function pkg new pkg lt pkg pkg in instal
  • 为什么这个并行代码比类似的非并行版本慢?

    我有以下代码 从 LINQPad 复制到此处 显然 我似乎不明白 TPL 是如何工作的 或者代码是垃圾 为什么并行版本比非并行版本运行得慢 for int i 0 i lt 100 i ParallelOptions ops new Par
  • Firebase 未将 CORS 标头添加到 REST 请求

    有没有办法为 REST 端点启用 CORS 如上所述here and here Firebase 似乎不再默认添加它们 对于不需要实时连接或无法使用 Websocket 的应用程序来说 这将很有帮助 这是对 Firebase 的 REST
  • R:尽可能均匀地分配数量 II

    我们有一定的数量 例如300 单位 该数量应尽可能均匀地分布在 40 个 槽 或 箱 中 如果每个槽都相同 那就很容易了 所以每个槽都是 7 5 然而 插槽的大小各不相同 我们不能 填充 超过其 大小 允许的范围 例如如果只有 4 个 我们
  • 仅将 HTML、CSS 网页部署到 Tomcat

    我刚刚开始开发website 我现在所拥有的就是HTML 页面由几个人支持CSS 样式表 我可以创建吗来自 HTML 和 CSS 页面的 WAR 文件 我如何将它们部署到 Tomcat 服务器上 Thanks 没有真正需要创建一场战争来从
  • 如何在同一页面上的 Angular 应用程序和非 Angular 应用程序之间进行通信?

    我正在通过 Angular bootstrapping 使用 Angular 模块将一段非 Angular 网页转换为 Angular 版本 它工作得很好 除了它需要与页面的其他部分进行通信这一事实之外 不幸的是 我目前无法将页面的其余部分
  • 简单的计算由于某种原因不起作用

    好吧 我正在尝试计算两个值的百分比 这应该非常简单 但由于某些奇怪的原因它不起作用 我太累了 太笨了 无法弄清楚 这是我的代码 它一直返回 0 我在调试时检查了这些值 FilesCompleted 为 295 TotalFilesCount
  • 如何将小数四舍五入到小数点后 2 位 (Java)

    我对java相当陌生 我必须创建这个程序 但我不知道从哪里开始 有人可以帮助我做什么以及如何编写代码来开始吗 编写一个模拟收银机的程序 提示用户输入三件商品的价格 将它们加在一起即可得到小计 确定小计的税费 6 求销售小计加税的总金额 显示
  • 如何从 C# 或 VB.Net 使用 Win32 'DwmSetIconicThumbnail'?

    我想使用DwmSetIconicThumbnail函数为我的应用程序的缩略图预览设置静态图像 正如上面的参考链接中指出的 首先需要调用Dwm设置窗口属性启用DWMWA FORCE ICONIC REPRESENTATION and DWMW