WM_GETICON有时不返回图标句柄

我试图显示所有的窗口标题,包括相应的图标,很像Windows任务pipe理器。 这只能在一定程度上 – 虽然我能够得到Windows的标题栏文本,图标并不总是可用的。

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

 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 

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

这可能是什么原因呢,我该怎么解决呢?

使用一些复制粘贴和混乱,我结束了以下代码…但现在适用于所有窗口。

基本上,它试图WM_GETICON得到一个大的图标。 如果失败,它调用GetClassLong ,有时包含图标。 否则,使用WM_GETICON来获取小图标。 在前两种情况下,我必须将其转换为Bitmap ,将其大小调整为16×16(我需要这种大小),然后将其转换回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