草庐IT

windows - WM_GETICON 有时不返回图标句柄

coder 2024-06-05 原文

我正在尝试显示所有窗口标题,包括相应的图标,就像 Windows 任务管理器所做的那样。这仅在一定程度上有效 - 虽然我能够获得窗口的标题栏文本,但该图标并不总是可用。

为了获取图标,我将 WM_GETICON 消息传递给 SendMessage ( source ):

Public Const WM_GETICON As UInteger = &H7F
Public Function GetWindowIcon(ByVal WindowHandle As IntPtr) As Icon
    Dim IconHandle As IntPtr = SendMessage(WindowHandle, WM_GETICON, 0, 0)
    If Not IconHandle = IntPtr.Zero Then
        Return Icon.FromHandle(IconHandle)
    Else
        Return Nothing
    End If
End Function

对于某些窗口,这只会返回正确的图标。对于其他人,它返回 Nothing,因为 IconHandle 等于 0。在 Windows 任务管理器和任务栏中,它们显示得很好。

这可能是什么原因造成的,我应该如何解决这个问题?

最佳答案

使用一些复制粘贴和乱搞,我最终得到了以下代码......但它现在适用于所有窗口。

基本上,它会尝试 WM_GETICON 来获得一个大图标。如果失败,它会调用 GetClassLong,有时会包含图标。否则,WM_GETICON 用于获取小图标。在前两种情况下,我必须将其转换为 Bitmap,将其调整为 16x16(我需要该大小),然后再将其转换回 Icon

Public Function GetClassLongPtr(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As IntPtr
    If IntPtr.Size > 4 Then
        Return GetClassLongPtr64(hWnd, nIndex)
    Else
        Return New IntPtr(GetClassLongPtr32(hWnd, nIndex))
    End If
End Function

<DllImport("user32.dll", EntryPoint:="GetClassLong")> _
Public Function GetClassLongPtr32(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As UInteger
End Function

<DllImport("user32.dll", EntryPoint:="GetClassLongPtr")> _
Public Function GetClassLongPtr64(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As IntPtr
End Function

<DllImport("user32.dll")> _
Public Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Int32, ByVal wParam As Boolean, ByVal lParam As Int32) As Integer
End Function


Public Const WM_GETICON As UInteger = &H7F
Public Function GetWindowIcon(ByVal WindowHandle As IntPtr) As Icon
    Dim IconHandle As IntPtr = SendMessage(WindowHandle, WM_GETICON, 1, 0)
    If Not IconHandle = IntPtr.Zero Then
        Dim _icon = Icon.FromHandle(IconHandle)
        Dim bmp = _icon.ToBitmap
        Dim scale_factor As Single = 16 / _icon.Size.Width

        ' Make a bitmap for the result.
        Dim bm_dest As New Bitmap( _
            CInt(bmp.Width * scale_factor), _
            CInt(bmp.Height * scale_factor))

        ' Make a Graphics object for the result Bitmap.
        Dim gr_dest As Graphics = Graphics.FromImage(bm_dest)

        ' Copy the source image into the destination bitmap.
        gr_dest.DrawImage(bmp, 0, 0, _
            bm_dest.Width + 1, _
            bm_dest.Height + 1)

        Return MakeIcon(bm_dest, 16, False)
        'Return Icon.FromHandle(IconHandle)
    Else
        IconHandle = GetClassLongPtr(WindowHandle, -34)
        If Not IconHandle = IntPtr.Zero Then
            Dim _icon = Icon.FromHandle(IconHandle)

            Dim bmp = _icon.ToBitmap
            Dim scale_factor As Single = 16 / _icon.Size.Width

            ' Make a bitmap for the result.
            Dim bm_dest As New Bitmap( _
                CInt(bmp.Width * scale_factor), _
                CInt(bmp.Height * scale_factor))

            ' Make a Graphics object for the result Bitmap.
            Dim gr_dest As Graphics = Graphics.FromImage(bm_dest)

            ' Copy the source image into the destination bitmap.
            gr_dest.DrawImage(bmp, 0, 0, _
                bm_dest.Width + 1, _
                bm_dest.Height + 1)

            Return MakeIcon(bm_dest, 16, False)
        Else
            IconHandle = SendMessage(WindowHandle, WM_GETICON, 1, 0)
            If Not IconHandle = IntPtr.Zero Then
                Dim _icon = Icon.FromHandle(IconHandle)
                Dim bmp = _icon.ToBitmap
                Dim scale_factor As Single = 16 / _icon.Size.Width

                ' Make a bitmap for the result.
                Dim bm_dest As New Bitmap( _
                    CInt(bmp.Width * scale_factor), _
                    CInt(bmp.Height * scale_factor))

                ' Make a Graphics object for the result Bitmap.
                Dim gr_dest As Graphics = Graphics.FromImage(bm_dest)

                ' Copy the source image into the destination bitmap.
                gr_dest.DrawImage(bmp, 0, 0, _
                    bm_dest.Width + 1, _
                    bm_dest.Height + 1)

                Return MakeIcon(bm_dest, 16, False)
            Else
                Return Nothing
            End If
        End If
    End If
End Function



''' <summary>
''' Converts an image into an icon.
''' </summary>
''' <param name="img">The image that shall become an icon</param>
''' <param name="size">The width and height of the icon. Standard
''' sizes are 16x16, 32x32, 48x48, 64x64.</param>
''' <param name="keepAspectRatio">Whether the image should be squashed into a
''' square or whether whitespace should be put around it.</param>
''' <returns>An icon!!</returns>
Private Function MakeIcon(ByVal img As Image, ByVal size As Integer, ByVal keepAspectRatio As Boolean) As Icon
    Dim square As New Bitmap(size, size)
    ' create new bitmap
    Dim g As Graphics = Graphics.FromImage(square)
    ' allow drawing to it
    Dim x As Integer, y As Integer, w As Integer, h As Integer
    ' dimensions for new image
    If Not keepAspectRatio OrElse img.Height = img.Width Then
        ' just fill the square
        x = 0
        y = 0
        ' set x and y to 0
        ' set width and height to size
        w = size
        h = size
    Else
        ' work out the aspect ratio
        Dim r As Single = CSng(img.Width) / CSng(img.Height)

        ' set dimensions accordingly to fit inside size^2 square
        If r > 1 Then
            ' w is bigger, so divide h by r
            w = size
            h = CInt(Math.Truncate(CSng(size) / r))
            x = 0
            ' center the image
            y = (size - h) \ 2
        Else
            ' h is bigger, so multiply w by r
            w = CInt(Math.Truncate(CSng(size) * r))
            h = size
            y = 0
            ' center the image
            x = (size - w) \ 2
        End If
    End If

    ' make the image shrink nicely by using HighQualityBicubic mode
    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default
    g.DrawImage(img, x, y, w, h)
    ' draw image with specified dimensions
    'g.Flush()
    ' make sure all drawing operations complete before we get the icon
    ' following line would work directly on any image, but then
    ' it wouldn't look as nice.
    Return Icon.FromHandle(square.GetHicon())
End Function

关于windows - WM_GETICON 有时不返回图标句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5542423/

有关windows - WM_GETICON 有时不返回图标句柄的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  3. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  4. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  5. ruby - Ruby 中的隐式返回值是怎么回事? - 2

    所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

  6. ruby-on-rails - ruby 日期方程不返回预期的真值 - 2

    为什么以下不同?Time.now.end_of_day==Time.now.end_of_day-0.days#falseTime.now.end_of_day.to_s==Time.now.end_of_day-0.days.to_s#true 最佳答案 因为纳秒数不同:ruby-1.9.2-p180:014>(Time.now.end_of_day-0.days).nsec=>999999000ruby-1.9.2-p180:015>Time.now.end_of_day.nsec=>999999998

  7. ruby - 从 String#split 返回的零长度字符串 - 2

    在Ruby1.9.3(可能还有更早的版本,不确定)中,我试图弄清楚为什么Ruby的String#split方法会给我某些结果。我得到的结果似乎与我的预期相反。这是一个例子:"abcabc".split("b")#=>["a","ca","c"]"abcabc".split("a")#=>["","bc","bc"]"abcabc".split("c")#=>["ab","ab"]在这里,第一个示例返回的正是我所期望的。但在第二个示例中,我很困惑为什么#split返回零长度字符串作为返回数组的第一个值。这是什么原因呢?这是我所期望的:"abcabc".split("a")#=>["bc"

  8. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  9. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  10. ruby - 为什么 Integer.respond_to?( :even? ) 返回 false? - 2

    我一直在研究RubyKoans,我发现about_open_classes.rbkoan很有趣。特别是他们修改Integer#even?方法的最后一个测试。我想尝试一下这个概念,所以我打开了Irb并尝试运行Integer.respond_to?(:even?),但令我惊讶的是我得到了错误。然后我尝试了Fixnum.respond_to?(:even?)并得到了错误。我还尝试了Integer.respond_to?(:respond_to?)并得到了true,当我执行2.even?时,我也得到了true。我不知道发生了什么。谁能告诉我缺少什么? 最佳答案

随机推荐