2015-09-16 3 views
0

Я пытаюсь загрузить значок приложений '(ы) с помощью функции LoadImage WinAPI, но по какой-то причине он всегда возвращает 0.Попытка загрузить отображается иконка приложения (ы) с помощью LoadImage, но функция возвращает 0

Я прочитал documentation, но я не могу понять, что я сделал неправильно. Я не получаю исключений, кроме тех случаев, когда вы пытаетесь преобразовать 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}}) 
+0

Фро m документация (даже от имени метода), кажется, что возвращенный дескриптор связан с изображением, а не с значком.Вы пытались преобразовать вывод в изображение/растровое изображение (и эту переменную в значок)? – varocarbas

+0

EXE-файл обычно содержит несколько значков. Обратите внимание, как вы никогда не указали, какой из них вы хотите. И это не так просто узнать, идентификаторы ресурса значков произвольны. Таким образом, вы просто используете неправильную функцию winapi для выполнения этой работы. Вместо этого используйте Icon.ExtractAssociatedIcon(). –

+1

@varocarbas: Это не имеет значения, так как функция возвращает 0 в любом случае. –

ответ

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 
2

Вы собираетесь об этом неправильном пути. Вы передаете имя исполняемого файла в аргумент lpszNameLoadImage. Этот параметр не принимает имя исполняемого файла. Он принимает имя ресурса в модуле, указанном первым параметром, hinst. Это объясняется в документации.

Обратите внимание, что вы не сталкиваетесь с исключениями. Этого следовало ожидать. API Win32 не будет создавать исключения. Вновь документация описывает, как сообщаются ошибки. Сообщается, что возвращаемое значение составляет NULL. И когда это произойдет, вы вызываете GetLastError, чтобы получить код ошибки. Это будет Marshal.GetLastWin32Error от .net.

Чтобы сделать то, что вы пытаетесь с помощью LoadImage вам нужно сделать следующее:

  1. Получить дескриптор экземпляра с помощью вызова LoadLibraryEx передавая имя исполняемого файла. Используйте флаг LOAD_LIBRARY_AS_DATAFILE, как описано в документации.
  2. Передайте этот экземпляр дескриптору LoadImage. Вам также нужно знать имя ресурса изображения, которое вы хотите извлечь.
  3. Если вы не знаете имя ресурса, вам нужно будет использовать функции перечисления ресурсов, например. EnumResourceNames. Вы ищете первый ресурс в исполняемом файле.
+0

Ох ... Так что я неправильно понял документацию :). Я посмотрю, что вы предлагаете. Вам просто сложно извлечь значки требуемого размера из .exe, не так ли? (: –

+0

@VisualVincent: Это не сложно, просто утомительно. [Иконки] (https://msdn.microsoft.com/en-us/library/ms997538.aspx) содержит всю необходимую информацию (* Icon API: Raw Байт ресурсов *). Чтобы найти идентификатор значка нужного размера, вызовите [LookupIconIdFromDirectory] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms648074.aspx) и вручную создайте значок Или используйте [CreateIconFromResourceEx] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms648061.aspx). – IInspectable

+0

Спасибо за помощь. Мне удалось решить ее с помощью 'ExtractIconEx'. Вы научили меня некоторым ценным вещам. :) –

Смежные вопросы