0

我正在尝试使用LoadImageWinAPI 函数加载应用程序的图标,但由于某种原因它总是返回 0。

我已阅读文档,但我无法理解我做错了什么。IconPtr除了尝试转换为Icon(因为IconPtr为 0)时,我没有任何例外。

Public Shared Function ExtractAssociatedIconArray(ByVal File As String, ByVal Sizes() As Size) As Icon()
    Dim ReturnArray(Sizes.Length) As Icon
    Dim Index As Integer = 0

    For Each s As Size In Sizes
        'IconPtr is always zero for some reason.
        Dim IconPtr As IntPtr = NativeMethods.LoadImage(Nothing, File, NativeMethods.Enumrations.IMAGE_ICON, s.Width, s.Height, NativeMethods.Enumrations.LR_DEFAULTCOLOR Or NativeMethods.Enumrations.LR_LOADFROMFILE)
        ReturnArray(Index) = Icon.FromHandle(IconPtr)
        Index += 1
    Next

    Return ReturnArray
End Function

NativeMethods班级:

Public Class NativeMethods
    <DllImport("user32.dll", SetLastError:=True)> _
    Public Shared Function LoadImage(ByVal hInst As IntPtr, _
                     ByVal lpszName As String,
                     ByVal uType As UInt32, _
                     ByVal cxDesired As Integer, _
                     ByVal cyDesired As Integer, _
                     ByVal fuLoad As UInt32) As IntPtr
    End Function

    Public Enum Enumrations As UInteger
        '' LoadImage ''
        IMAGE_BITMAP = 0
        IMAGE_ICON = 1
        IMAGE_CURSOR = 2
        LR_CREATEDIBSECTION = &H2000
        LR_DEFAULTCOLOR = &H0
        LR_DEFAULTSIZE = &H40
        LR_LOADFROMFILE = &H10
        LR_LOADMAP3DCOLORS = &H1000
        LR_LOADTRANSPARENT = &H20
        LR_MONOCHROME = &H1
        LR_SHARED = &H8000
        LR_VGACOLOR = &H80
    End Enum
End Class

使用示例:

Dim Icons() As Icon = ExtractAssociatedIconArray("C:\MyApp.exe", New Size() {New Size() {48, 48}})
4

2 回答 2

2

你正在以错误的方式解决这个问题。您正在将可执行文件名传递lpszNameLoadImage. 该参数不接受可执行文件名。它接受第一个参数指定的模块内的资源名称,hinst。这在文档中进行了解释。

您注意到您没有遇到异常。这是可以预料的。Win32 API 不会引发异常。文档再次描述了如何报告错误。它们由返回值报告NULL。发生这种情况时,您调用GetLastError以获取错误代码。那将Marshal.GetLastWin32Error来自.net。

要执行您尝试使用的操作LoadImage,您需要执行以下操作:

  1. LoadLibraryEx通过调用传递可执行文件名来获取实例句柄。使用该LOAD_LIBRARY_AS_DATAFILE标志,如文档所述。
  2. 将该实例句柄传递给LoadImage. 您还需要知道要提取的图像资源的名称。
  3. 如果您不知道资源的名称,则需要使用资源枚举函数,例如EnumResourceNames. 您正在寻找可执行文件中的第一个资源。
于 2015-09-16T11:27:20.010 回答
1

感谢您的帮助和建议。

ExtractIconEx我设法通过使用该函数来解决我自己的问题。

Public Shared Function ExtractAssociatedIcons(ByVal File As String) As AssemblyIconCollection
    Dim IconCount As Integer = NativeMethods.ExtractIconEx(File, -1, Nothing, Nothing, 0)
    Dim AssemblyIcons As New AssemblyIconCollection

    'The 'Icon handle' arrays.
    Dim LargeIcons(IconCount) As IntPtr
    Dim SmallIcons(IconCount) As IntPtr

    'Extract icons into the two arrays of handles.
    NativeMethods.ExtractIconEx(File, 0, LargeIcons, SmallIcons, IconCount)

    'Add each large icon to the "LargeIcons" list.
    For Each ptr As IntPtr In LargeIcons
        If ptr = IntPtr.Zero Then Continue For

        Dim Ico As Icon = Icon.FromHandle(ptr)
        If Ico.Width < 25 Or Ico.Height < 25 Then Continue For
        AssemblyIcons.LargeIcons.Add(Ico)
    Next

    'Add each small icon to the "SmallIcons" list.
    For Each ptr As IntPtr In SmallIcons
        If ptr = IntPtr.Zero Then Continue For

        Dim Ico As Icon = Icon.FromHandle(ptr)
        If Ico.Width > 24 Or Ico.Height > 24 Then Continue For
        AssemblyIcons.SmallIcons.Add(Ico)
    Next

    'Return the output class.
    Return AssemblyIcons
End Function

我的AssemblyIconCollection班级:

Public NotInheritable Class AssemblyIconCollection
    ''' <summary>
    ''' Gets or sets the large icons found in the assembly.
    ''' </summary>
    ''' <remarks></remarks>
    Public Property LargeIcons As List(Of Icon)

    ''' <summary>
    ''' Gets or sets the small icons found in the assembly.
    ''' </summary>
    ''' <remarks></remarks>
    Public Property SmallIcons As List(Of Icon)

    Public Sub New()
        Me.LargeIcons = New List(Of Icon)
        Me.SmallIcons = New List(Of Icon)
    End Sub
End Class

ExtractIconEx声明:

Public Class NativeMethods
    <DllImport("shell32.dll", CharSet:=CharSet.Auto)> _
    Public Shared Function ExtractIconEx(ByVal szFileName As String, _
         ByVal nIconIndex As Integer, _
         ByVal phiconLarge() As IntPtr, _
         ByVal phiconSmall() As IntPtr, _
         ByVal nIcons As UInteger) As UInteger
    End Function
End Class

用法:

Dim Icons As AssemblyIconCollection = ExtractAssociatedIcons("C:\myfile.exe")

'Iterating every large icon.
For Each LargeIcon As Icon In Icons.LargeIcons
    'Do stuff.
Next

'Iterating every small icon.
For Each SmallIcon As Icon In Icons.SmallIcons
    'Do stuff.
Next
于 2015-09-16T14:56:48.937 回答