Precisa de um exemplo de trabalho da função extractassociatedicon do Shell32 na .NET

StackOverflow https://stackoverflow.com/questions/1988393

  •  22-09-2019
  •  | 
  •  

Pergunta

Preciso de um exemplo de funcionamento da função Extractassociatedicon no shell32.dll. Não consigo funcionar e estou sem ideias. Eu preciso de outro conjunto de olhos no código a seguir. Quando o formulário carrega, seu ícone deve ser definido para o ícone do Visual Studio, mas tudo o que eu recebo é o ícone do sistema padrão.

Imports System.Runtime.InteropServices

Public Class Form1

    Public Function ExtractIcon(ByVal path As String, ByVal handle As IntPtr) As Icon
        Dim oResult As Icon
        Dim hIcon As IntPtr
        Dim iIndex As Integer
        Dim oPath As New System.Text.StringBuilder(260, 260)

        oPath.Append(path)

        hIcon = ExtractAssociatedIcon(handle, oPath, iIndex)

        'hIcon = ExtractAssociatedIcon(handle, path, iIndex)

        Dim oIcon As Icon = Icon.FromHandle(hIcon)

        oResult = DirectCast(oIcon.Clone, Icon)

        DestroyIcon(hIcon)

        Return oResult
    End Function

    Public Declare Auto Function ExtractAssociatedIcon Lib "shell32" ( _
        ByVal hInst As IntPtr, _
        <MarshalAs(UnmanagedType.LPStr)> ByVal lpIconPath As System.Text.StringBuilder, _
        ByRef lpiIcon As Integer) As IntPtr

    'Public Declare Auto Function ExtractAssociatedIcon Lib "shell32" ( _
    '    ByVal hInst As IntPtr, _
    '    <MarshalAs(UnmanagedType.LPStr)> ByVal lpIconPath As String, _
    '    ByRef lpiIcon As Integer) As IntPtr

    Friend Declare Auto Function DestroyIcon Lib "user32" (<[In]()> ByVal hIcon As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'ExtractAssociatedIcon uses ExtractAssociatedIcon that is in Shell32.dll.
        'This works, so why doesn't mine? What am I missing?
        'Me.Icon = System.Drawing.Icon.ExtractAssociatedIcon("C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe")

        Me.Icon = ExtractIcon("C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe", Me.Handle)

    End Sub

End Class

Corrigido

<MarshalAs(UnmanagedType.LPStr)> foi o problema. Deveria ter sido LPTStr, não LPStr.

Foi útil?

Solução

Passar na alça está definitivamente errado, o 1º argumento para o EAI é uma alça de módulo, não uma alça de ícone. Isso funcionou bem:

Imports System.Runtime.InteropServices
Imports System.ComponentModel
...
  Public Shared Function ExtractIcon(ByVal path As String, Optional ByVal index As Integer = 0) As Icon
    Dim handle As IntPtr = ExtractAssociatedIcon(IntPtr.Zero, path, index)
    If handle = IntPtr.Zero Then Throw New Win32Exception(Marshal.GetLastWin32Error())
    Dim retval As Icon = Nothing
    using temp As Icon = Icon.FromHandle(handle)
      retval = CType(temp.Clone(), Icon)
      DestroyIcon(handle)
    end using
    Return retval      
  End Function

  Private Declare Auto Function ExtractAssociatedIcon Lib "shell32" ( _
      ByVal hInst As IntPtr, ByVal path As String, ByRef index As Integer) As IntPtr
  Private Declare Auto Function DestroyIcon Lib "user32" (ByVal hIcon As IntPtr) As Boolean

Não há necessidade de StringBuilder se o identificador do módulo for nulo. Não use este código se você não não o argumento "índice". Icon.extractastocationicon também funcionará.

Outras dicas

Por que não simplesmente usar o nativo .NET Icon.ExtractAssociatedIcon Método, que parece fazer a mesma coisa?

Me.Icon = Icon.ExtractAssociatedIcon( _
    "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe")

PS: Eu tentei seu código, com o mesmo resultado errado que você descreveu. O trecho de código acima parece funcionar.

Experimente o método .NET nativo menciona o Stakx - tive a sorte de salvar o arquivo da OIC (se você salvar como outro formato, digamos bitmap, ele normalmente funciona)

Para um pinvoke algo como esse deve funcionar: (advertência, não testada) referenciado: http://social.msdn.microsoft.com/forums/en-us/csharpgeneral/thread/ecb6137c-8bda-4468-b5e0-359caeb202b1

[DllImport("Shell32.dll")]
private static extern int SHGetFileInfo( string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbfileInfo, SHGFI uFlags );

[StructLayout(LayoutKind.Sequential)]
private struct SHFILEINFO
{
    public SHFILEINFO(bool b)
    {
        hIcon = IntPtr.Zero; iIcon = 0; dwAttributes = 0; szDisplayName = ""; szTypeName = "";
    }
    public IntPtr hIcon;
    public int iIcon;
    public uint dwAttributes;

    [MarshalAs(UnmanagedType.LPStr, SizeConst = 260)]
    public string szDisplayName;

    [MarshalAs(UnmanagedType.LPStr, SizeConst = 80)]
    public string szTypeName;
};

private ExtractIcon()
{
}

private enum SHGFI
{
    SmallIcon = 0x00000001,
    LargeIcon = 0x00000000,
    Icon = 0x00000100,
    DisplayName = 0x00000200,
    Typename = 0x00000400,
    SysIconIndex = 0x00004000,
    UseFileAttributes = 0x00000010
}

public static Icon GetIcon(string strPath, bool bSmall)
{
    SHFILEINFO info = new SHFILEINFO(true);
    int cbFileInfo = Marshal.SizeOf(info);

    SHGFI flags;
    if (bSmall)
    {
        flags = SHGFI.Icon | SHGFI.SmallIcon | SHGFI.UseFileAttributes;
    }
    else
    {
        flags = SHGFI.Icon | SHGFI.LargeIcon | SHGFI.UseFileAttributes;
    }

    SHGetFileInfo(strPath, 256, out info, (uint)cbFileInfo, flags);

    return Icon.FromHandle(info.hIcon);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top