我正在尝试显示所有窗口标题,包括相应的图标,就像Windows任务管理器一样。这只在某种程度上起作用 - 尽管我能够获得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任务管理器和任务栏上,它们显示正常。
这可能是什么原因,我怎么能解决这个问题?
答案 0 :(得分:3)
使用一些复制粘贴和乱码,我最终得到了以下代码......但它现在适用于所有窗口。
基本上,它会尝试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