Systémové ikony   zodpovězená otázka

VB.NET, WinForms

Dobrý den,

jak mohu ze systému vytahat ikony pro určité typy souborů a požít je do listview ve své aplikaci?

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Jde o celkem rozsáhlé téme, podívejte se se na tuto adresu, tak je to vše popsané:

http://www.devarticles.com/c/a/Visual-Ba...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Snad žádám příliš, ale přesto Vás poprosím, abyste mi pomohl pochopit ten kód. Visual Studio mi tam vyhodilo 20 errorů. Mockrát děkuji

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Tak napište kód a jaké chyby to píše.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
Option Explicit
'For looking at registry keys
'To: Open key ready to look at
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
'To: Look at key
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As Any, lpcbData As Long) As Long
'To: Close the key when it's finished with
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long

Private Const HKEY_CLASSES_ROOT = &H80000000
Private Const KEY_READ = &H20019 'To allow us to READ the registry keys

'For Drawing the icon
'To: Retrieve the icon from the .EXE, .DLL or .ICO
Private Declare Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" (ByVal hInst As Long, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As Long
'To: Draw the icon into our picture box
Private Declare Function DrawIcon Lib "user32.dll" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal hIcon As Long) As Long
'To: Clean up after our selves (destroy the icon that "ExtractIcon" created)
Private Declare Function DestroyIcon Lib "user32.dll" (ByVal hIcon As Long) As Long

'For Finding the System folder
Private Declare Function GetSystemDirectory Lib "kernel32.dll" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long

Private Sub GetDefaultIcon(FileName As String, Picture_hDC As Long )
Dim TempFileName As String 'Never manipulate an input unless it doubles as an output
Dim lngError As Long 'For receiving error numbers
Dim lngRegKeyHandle As Long 'Stores the "handle" of the registry key that is currently open
Dim strProgramName As String 'Stores the contents of the first registry key
Dim strDefaultIcon As String 'Stores the contents of the second registry key
Dim lngStringLength As Long 'Sets / Returns the length of the output string
Dim lngIconNumber As Long 'Stores the icon number within a file
Dim lngIcon As Long 'Stores the "Icon Handle" for the default icon
Dim intN As Integer 'For any temporary numbers

TempFileName = Right(FileName, Len(FileName) - InStrRev(FileName, ".") + 1)

If LCase(TempFileName) = ".exe" Then
strDefaultIcon = Space(260)
lngStringLength = GetSystemDirectory(strDefaultIcon, 260)
strDefaultIcon = Left(strDefaultIcon, lngStringLength) & "\SHELL32.DLL"
lngIconNumber = 2
GoTo Draw_Icon
End If

lngError = RegOpenKey(HKEY_CLASSES_ROOT, TempFileName, lngRegKeyHandle)
If lngError Then GoTo No_Icon 'we do not even have a valid extension so lets NOT try to find an icon!
lngStringLength = 260
strProgramName = Space$(260) 'Make space for the incoming string
'Get the key value:
lngError = RegQueryValueEx(lngRegKeyHandle, vbNullString, 0, 0, strProgramName, lngStringLength)
If lngError Then 'if there's an error then BIG TROUBLE so lets use the normal "windows" icon
lngError = RegCloseKey(lngRegKeyHandle) 'the world may be about to end (or just an error) but we'll clean up anyway
GoTo No_Icon
End If
lngError = RegCloseKey(lngRegKeyHandle) 'if this generates an error then we can't do anything about it anyway
strProgramName = Left(strProgramName, lngStringLength - 1) 'Cut the name down to size

'Use the value of the last key in the name of the next one (strProgramName)
lngError = RegOpenKey(HKEY_CLASSES_ROOT, strProgramName & "\DefaultIcon", lngRegKeyHandle)
If lngError Then GoTo No_Icon 'there is no icon for this extension so lets NOT try to load what doesn't exist!
'The rest is just the same as before
lngStringLength = 260
strDefaultIcon = Space$(260)
lngError = RegQueryValueEx(lngRegKeyHandle, vbNullString, 0, 0, strDefaultIcon, lngStringLength)
If lngError Then
lngError = RegCloseKey(lngRegKeyHandle)
GoTo No_Icon
End If
lngError = RegCloseKey(lngRegKeyHandle)
strDefaultIcon = Trim$(Left(strDefaultIcon, lngStringLength - 1))

intN = InStrRev(strDefaultIcon, ",") 'Find the commer
If intN < 1 Then GoTo No_Icon 'We MUST have an icon number and it will be after the ",": NO COMMA NO DEFAULT ICON
lngIconNumber = Trim$(Right(strDefaultIcon, Len(strDefaultIcon) - intN)) 'What number is after the comma
strDefaultIcon = Trim$(Left(strDefaultIcon, intN - 1)) 'We only want what's before the comma in the file name

Draw_Icon:
lngIcon = ExtractIcon(App.hInstance, strDefaultIcon, lngIconNumber) 'Extract the Icon
If lngIcon = 1 Or lngIcon = 0 Then GoTo No_Icon 'if 1 or 0 then after all that the Icon Could not be retrieved

lngError = DrawIcon(Picture_hDC, 0, 0, lngIcon) 'Draw the icon in the box
'If that was unsucessful then we can't do anything about it now!
lngError = DestroyIcon(lngIcon)
'Again we can't correct any errors now
Exit Sub
No_Icon:
'No icon could be found so we use the normal windows icon
'This icon is held in shell32.dll in the system directory, Icon 0
strDefaultIcon = Space(260)
lngStringLength = GetSystemDirectory(strDefaultIcon, 260)
strDefaultIcon = Left(strDefaultIcon, lngStringLength) & "\SHELL32.DLL"
lngIconNumber = 0
GoTo Draw_Icon
End Sub

Just incase it's not obvious, here's how to use this subroutine (Remember that you need a picture box and text box on your form). Make sure that "AutoRedraw" is set to true on your picture box:

Private Sub Command1_Click()
Picture1.Cls
GetDefaultIcon Text1.Text, Picture1.hDC
End Sub

mimo to, že se v kódu nevyznám mi to hází chyby (dal jsem tento kód do třídy Form1):

Error 1 'Option' statements must precede any declarations or 'Imports' statements. 2 1 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 2 'As Any' is not supported in 'Declare' statements. 7 204 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 3 'Public ReadOnly Property Right() As Integer' has no parameters and its return type cannot be indexed. 36 24 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 4 'Public Property Left() As Integer' has no parameters and its return type cannot be indexed. 41 30 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 5 'Public Property Left() As Integer' has no parameters and its return type cannot be indexed. 57 26 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 6 'Public Property Left() As Integer' has no parameters and its return type cannot be indexed. 71 32 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 7 'Public ReadOnly Property Right() As Integer' has no parameters and its return type cannot be indexed. 75 31 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 8 'Public Property Left() As Integer' has no parameters and its return type cannot be indexed. 76 32 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 9 Name 'App' is not declared. 79 31 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 10 'Public Property Left() As Integer' has no parameters and its return type cannot be indexed. 92 26 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 11 Declaration expected. 97 1 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 12 'Cls' is not a member of 'System.Windows.Forms.PictureBox'. 100 9 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Error 13 'hDC' is not a member of 'System.Windows.Forms.PictureBox'. 101 36 C:\Documents and Settings\Tomas\Local Settings\Data aplikací\Temporary Projects\WindowsApplication2\Form1.vb WindowsApplication2

Testvoal jsem to na VB2005EE, protože 2008 má špatný den, a nechce mi povolit kliknou na tlačítko OK v dialogu New Project.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Snad Vás tím moc neobtěžuji

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Omlouvám se - nebyl jsem přihlášen.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

On bude nejspíš problém v tom, že si myslím, že uvedený kód je pro VB6.

Když Vás pan Jecha odkazoval na uvedenou stránku, měl patrně na mysli ne zde uvedený kód, ale postup, jak se k ikonám dopídit - a ten je zde popsán celkem podrobně.

Dobrou zprávou pak je to, že hlavní složitost uvedeného kódu tkví v tom, že (alespoň mi to tak připadá, neb VB6 neznám), že asi tento jazyk neměl, na rozdíl od VB2005, tak jednoduchou práci s registrem.

Zkoušel jsem včera podle popisu v uvedeném článku kousek kódu postavit a dostal jsem se až sem:

1. do nového projektu si přidejte referenci na Microsoft.win32

2. na form si hoďte jeden textbox, jeden label a jedno tlačítko.

3. do kódu si dejte:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim reg, subreg As RegistryKey
        Dim pripona As String
        Dim jmenoAplikace As String
        Dim platnaverze As String
        Dim ikona As String


        Do
            pripona = TextBox1.Text

            ' najdeme v registru pro zadanou příponu (vč. tečky) klíč popisující vlastnosti odpovídajících souborů:
            reg = Registry.ClassesRoot.OpenSubKey(pripona, False)
            If IsNothing(reg) Then
                MsgBox("Pro příponu " & pripona & " není zaregistrována žádná aplikace", MsgBoxStyle.Critical, "Chyba zadání")
                Exit Do
            End If

            ' z daného klíče vytáhneme "výchozí" hodnotu, ve které je uložen název spřažené aplikace
            jmenoAplikace = reg.GetValue("")

            ' 1) najdeme v registru pro nalezený název aplikace klíč popisující tuto aplikaci:
            reg = Registry.ClassesRoot.OpenSubKey(jmenoAplikace, False)
            If IsNothing(reg) Then
                MsgBox("Pro aplikaci " & jmenoAplikace & " nebyla v registru nalezena odpovídající položka", MsgBoxStyle.Critical, "Chyba zadání")
                Exit Do
            End If


            ' najdeme "podklíč" (subkey) s názvem DefaultIcon
            subreg = reg.OpenSubKey("DefaultIcon", False)

            If Not IsNothing(subreg) Then
                ' pokud podklíč existuje, pořečteme hodnotu jeho výchozí vlastnosti
                ikona = subreg.GetValue("", "0")

            Else
                ' pokud podklíč neexistuje, zkusíme nalézt informaci o aktuální verzi (stejným postupem)
                subreg = reg.OpenSubKey("CurVer", False)
                If IsNothing(subreg) Then
                    MsgBox("Pro příponu " & pripona & " se v aplikaci nepodařilo nalézt odpovídající údaje", MsgBoxStyle.Critical, "Chyba zadání")
                    Exit Do
                End If

                platnaverze = subreg.GetValue("")

                ' a opakujeme postup hledání od bodu 1), ale tentokrát pro platnou verzi aplikace:
                reg = Registry.ClassesRoot.OpenSubKey(platnaverze, False)
                If IsNothing(reg) Then
                    MsgBox("Pro aplikaci " & jmenoAplikace & " nebyla v registru nalezena odpovídající položka", MsgBoxStyle.Critical, "Chyba zadání")
                    Exit Do
                End If

                ' najdeme "podklíč" (subkey) s názvem DefaultIcon
                subreg = reg.OpenSubKey("DefaultIcon", False)

                If IsNothing(subreg) Then
                    MsgBox("Pro aplikaci " & jmenoAplikace & " nebyla v registru nalezena odpovídající položka", MsgBoxStyle.Critical, "Chyba zadání")
                    Exit Do
                End If

                ikona = subreg.GetValue("", "0")
            End If

            If ikona = "0" Then
                MsgBox("Pro příponu " & pripona & " se nepodařilo nalézt odpovídající ikonu", MsgBoxStyle.Critical, "Chyba zadání")
                Exit Do
            End If
            
            'kresliIkonu(ikona)
            Label1.Text = ikona
        Loop While False
    End Sub

Vypadá to složitě, ale důležité (funkční) jsou ty okomentované řádky, to ostatní je tam kvůli odchycení výjimek.

Skládal jsem to v noci podle postupu v článku (co kde a jak v registru najít), takže je to hrozně neučesané (pouze jako námět na přemýšlení) - chtělo by to inteligentněji ošetřit výjimky, určitě by bylo dobré separovat to na podprogramy, pokud si s tím budete hrát, určitě přijdete i na jednodušší postupy (byl to skutečně první nástřel).

A taky to není celé - je to jen první polovina - na základě zadané přípony souboru (do textboxu - včetně tečky, např. ".bmp") by Vám to z registru mělo vytáhnout soubor, ve kterém je nutno hledat systémovou ikonu.

Dál to chce už "jenom" tu ikonu z uvedeného souboru separovat a je hotovo :-) To jenom jsem dal do uvozovek proto, že ani tento krok zcela triviální nebude, protože pro málokterý program dostanete soubor .ico, ale většinou soubor .exe či .dll + posici, kolikátou ikonu z něj použít.

A ještě je to trošku zkomplikované tím, že u některých typů souborů jako výstup dostanete pouce jméno bez cesty - a je tedy nutné přišít k tomu systémový adresář (u mne třeba ".bmp"), no a ještě další problém je, že u některých přípon dostanete něco ještě úplně jiného (???), což momentálně skutečně nevím, co s tím-chtělo by to naštudovat obsah registru (Např. ".html" mi vrací "%1" (???)). Ale u většiny přípon mi to vrací rozumnou hodnotu.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Výborný příspěvek.

Jinak máte pravdu, ten link byl jen na článek o tom jakým způsobem to udělat.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Dík - a když už jsme u toho, Vy nemáte ideu, jak se poprat s tím "%1", které mi jako hodnotu klíče DefaultIcon vrátí třeba to ".html" ? Ne že bych to potřeboval, ale vím, že mi to bude vrtat hlavou (když už jsem se do toho jednou postil), a zase přes noc budu bádat :-/

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Tak jsem našel jednu chybu. Najde se ikona, která je pro všechny uživatele, já mám ve svém uživatelském účtu nastaven pro JPG IrfanView, a najde mi to program od Nera, který má nastaven admin účet.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pak musíte zkusit hledat v jiných částech registru - tady, dle výše uvedeného článku, jsem se zaměřil pouze na větev HKEY_CLASSES_ROOT, kde jsou, samozřejmě, ta nastavení společná. Zkuste prohledat jiné větve (curent_user?), určitě by to tam někde mělo být.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Setkal jsem se s cestami jako "%windir%" nebo "%temp%", ale "%1" vidím poprvé.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ono %1 apod. se kdysi používalo jako označení parametrů příkazové řádky, když se programovalo přímo v shelu systému (v DOSu - ale to Vy, vzhledem ke svému věku, snad už ani nemůžete vědět, co bylo :-), tam by to dle některých interpretací znamenalo první parametr na řádce, tedy samotný spouštěcí program, podle některých interpretací první parametr až za tímto programem, nicméně v kontextu registru netuším, co by to mohlo být (a těch procentních vyjádření je tam povícero, asi to bude chtít něco si přešíst o registru jako takovém, ale k tomu jsem se zatím nedostal).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Mnohokrát Vám děkuji.

Napadlo mne, že je ten kód na VB6, protože jsou tam použité WinAPI. Ale sám jsem jaksi nedokázal složit ten kód. Ikdyž mám na svých 14let angličtinu na hovorové úrovni, ještě se někde plácám. Ještě jednou děkuji za Váš příspěvek.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Omlouvám se, Opět jsem nebyl přihlášen. Předchotí příspěvek je ode mne.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Není zač, hlavně jestli Vám to nějak pomohlo. Jinak co já bych za to dal mít "angličtinu na hovorové úrovni"! Pěkný den.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Opravdu mi to velice pomohlo. Ted už stačí domyslet jak extrahovat ty ikony, ale na tom již zapracuji sám. Přeji hezký den.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Až to udoláte, pochlubte se (ať se taky něco přiučím).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak jsem to udělal takto a funguje to:

Dim FileIcon As System.Drawing.Icon = Drawing.Icon.ExtractAssociatedIcon(ikona.Substring(0, ikona.LastIndexOf(",")))
PictureBox1.Image = FileIcon.ToBitmap()
nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ale to není zdaleka dokonalé, protože to (asi) umí extrahovat jen ikonu s indexem 1.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback