Что нового

Не корректное копирование иконки

assch

Новичок
Сообщения
166
Репутация
4
В этом коде для примера взято расширение ".bat"
Функция "_WinAPI_AssocQueryString" с помощью других функций находит "Путь" и "Номер ресурса"
У меня это выглядит так:

Путь: C:\WINDOWS\System32\shell.dll
Индекс: -153

код работает так :
По рассширению (в данном случае ".bat") в окно выводится "Путь" и "Номер ресурса" а также
функцией "GUICtrlCreateIcon" выводится иконка взятая по этому адресу.
Для сравнения рядом с программой (лучше на рабочем столе)
появляется пустой файл ".bat" Дальше функция заточена так что с помощью функции "_FileExtractIcon"
она должна скопировать по этому адресу иконку в формате ".ico" и положить её там же и если иконка скопируется то она
появится в окне чуть правее первой иконки. Только как я понимаю функция "_FileExtractIcon"
не корректно работает с "Номером ресурса -153"
Она воспринимает его как индекс ну и как результат копируется иконка с "индексом -153" . А она совсем другая.
Не подскажете как исправить эту проблему
Код:
#Include <WinAPIEx.au3>

Global $aaa = "bat"

Global $bbb = "." & $aaa

Global $aSad[1] 

$GUI = GUICreate($aaa, 400, 250, 100, 250)
$sIcon = _WinAPI_AssocQueryString($bbb, $ASSOCSTR_DEFAULTICON)
$aIcon = _WinAPI_PathParseIconLocation($sIcon)
$put = _WinAPI_PathUnquoteSpaces($aIcon[0])
$ind = $aIcon[1]

GUICtrlCreateLabel("Путь:   " & $put,10, 150 ,380 ,40)
GUICtrlCreateLabel("Индекс: " & $ind ,10, 190 ,380 ,20)

GUICtrlCreateIcon($put,-($ind + ($ind > -1)), 100, 50, 48, 48)

GUISetState()

$file = FileOpen($bbb,2)

_FileExtractIcon($put,-($ind + ($ind > -1)), $aaa & ".ico")

GUICtrlCreateIcon($aaa & ".ico",0, 250, 50, 48, 48)

While 1	
$iMsg = GUIGetMsg()
Switch $iMsg
	
Case -3
FileDelete ($bbb)
FileDelete ($aaa & ".ico")
Exit

EndSwitch	 
WEnd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Func _FileExtractIcon($sInFile, $iIcon, $sOutIco, $iPath = 0)
	Local Const $LOAD_LIBRARY_AS_DATAFILE = 0x00000002
	Local Const $RT_ICON = 3
	Local Const $RT_GROUP_ICON = 14
	Local $hInst, $iGN = "", $sData, $sDByte, $sHdr, $aHdr, $iCnt, $Offset, $FO, $FW, $iCrt = 18
	If $iPath = 1 Then $iCrt = 26 ;+8, to create directory structure
	If Not FileExists($sInFile) Then Return SetError(1, 0, 0)
	If Not IsInt($iIcon) Then Return SetError(2, 0, 0)
	$hInst = _LoadLibraryEx($sInFile, $LOAD_LIBRARY_AS_DATAFILE)
	If Not $hInst Then Return SetError(3, 0, 0)
	_ResourceEnumNames($hInst, $RT_GROUP_ICON)
	For $i = 1 To $aSad[0]
		If $i = StringReplace($iIcon, "-", "") Then
			$iGN = $aSad[$i]
			ExitLoop
		EndIf
	Next
	Dim $aSad[1]
	If $iGN = "" Then
		_FreeLibrary($hInst)
		Return SetError(4, 0, 0)
	EndIf
	$sData = _GetIconResource($hInst, $iGN, $RT_GROUP_ICON)
	If @error Then
		_FreeLibrary($hInst)
		Return SetError(5, 0, 0)
	EndIf
	$sHdr = BinaryMid($sData, 1, 6)
	$aHdr = StringRegExp(StringTrimLeft(BinaryMid($sData, 7), 2), "(.{28})", 3)
	$iCnt = UBound($aHdr)
	$Offset = ($iCnt * 16) + 6
	For $i = 0 To $iCnt - 1
		$sDByte = Dec(_StringReverseBytes(StringMid($aHdr[$i], 17, 8)))
		$sHdr &= StringTrimRight($aHdr[$i], 4) & _StringReverseBytes(Hex($Offset))
		$Offset += $sDByte
	Next
	For $i = 0 To $iCnt - 1
		$sData = _GetIconResource($hInst, "#" & Dec(_StringReverseBytes(StringRight($aHdr[$i], 4))), $RT_ICON)
		If @error Then
			_FreeLibrary($hInst)
			Return SetError(6, 0, 0)
		EndIf
		$sHdr &= StringTrimLeft($sData, 2)
	Next
	_FreeLibrary($hInst)
	$FO = FileOpen($sOutIco, $iCrt)
	If $FO = -1 Then Return SetError(7, 0, 0)
	$FW = FileWrite($FO, $sHdr)
	If $FW = 0 Then
		FileClose($FO)
		Return SetError(8, 0, 0)
	EndIf
	FileClose($FO)
	Return SetError(0, 0, 1)
EndFunc   ;==>_FileExtractIcon
; ========================================================================================================
; Internal Helper Functions from this point on
; ========================================================================================================
Func _GetIconResource($hModule, $sResName, $iResType)
	Local $hFind, $aSize, $hLoad, $hLock, $tRes, $sRet
	$hFind = DllCall("kernel32.dll", "int", "FindResource", "int", $hModule, "str", $sResName, "long", $iResType)
	If @error Or Not $hFind[0] Then Return SetError(1, 0, 0)
	$aSize = DllCall("kernel32.dll", "dword", "SizeofResource", "int", $hModule, "int", $hFind[0])
	If @error Or Not $aSize[0] Then Return SetError(2, 0, 0)
	$hLoad = DllCall("kernel32.dll", "int", "LoadResource", "int", $hModule, "int", $hFind[0])
	If @error Or Not $hLoad[0] Then Return SetError(3, 0, 0)
	$hLock = DllCall("kernel32.dll", "int", "LockResource", "int", $hLoad[0])
	If @error Or Not $hLock[0] Then
		_FreeResource($hLoad[0])
		Return SetError(4, 0, 0)
	EndIf
	$tRes = DllStructCreate("byte[" & $aSize[0] & "]", $hLock[0])
	If Not IsDllStruct($tRes) Then
		_FreeResource($hLoad[0])
		Return SetError(5, 0, 0)
	EndIf
	$sRet = DllStructGetData($tRes, 1)
	If $sRet = "" Then
		_FreeResource($hLoad[0])
		Return SetError(6, 0, 0)
	EndIf
	_FreeResource($hLoad[0])
	Return $sRet
EndFunc   ;==>_GetIconResource

Func _LoadLibraryEx($sFile, $iFlag)
	Local $aRet = DllCall("Kernel32.dll", "hwnd", "LoadLibraryExW", "wstr", $sFile, "hwnd", 0, "int", $iFlag)
	Return $aRet[0]
EndFunc   ;==>_LoadLibraryEx

Func _FreeLibrary($hModule)
	DllCall("Kernel32.dll", "hwnd", "FreeLibrary", "hwnd", $hModule)
EndFunc   ;==>_FreeLibrary

Func _FreeResource($hglbResource)
	DllCall("kernel32.dll", "int", "FreeResource", "int", $hglbResource)
EndFunc   ;==>_FreeResource

; Just a Reverse string byte function (smashly style..lol)
Func _StringReverseBytes($sByte)
	Local $aX = StringRegExp($sByte, "(.{2})", 3), $sX = ''
	For $i = UBound($aX) - 1 To 0 Step -1
		$sX &= $aX[$i]
	Next
	Return $sX
EndFunc   ;==>_StringReverseBytes

Func _ResourceEnumNames($hModule, $iType)
	Local $aRet, $xCB
	If Not $hModule Then Return SetError(1, 0, 0)
	$xCB = DllCallbackRegister('__ResourceEnumNamesProc', 'int', 'int_ptr;int_ptr;int_ptr;int_ptr')
	$aRet = DllCall('kernel32.dll', 'int', 'EnumResourceNamesW', 'ptr', $hModule, 'int', $iType, 'ptr', DllCallbackGetPtr($xCB), 'ptr', 0)
	DllCallbackFree($xCB)
	If $aRet[0] <> 1 Then Return SetError(2, 0, 0)
	Return SetError(0, 0, 1)
EndFunc   ;==>_ResourceEnumNames

Func __ResourceEnumNamesProc($hModule, $pType, $pName, $lParam)
	Local $aSize = DllCall('kernel32.dll', 'int', 'GlobalSize', 'ptr', $pName), $tBuf
	If $aSize[0] Then
		$tBuf = DllStructCreate('wchar[' & $aSize[0] & ']', $pName)
		ReDim $aSad[UBound($aSad) + 1]
		$aSad[0] += 1
		$aSad[UBound($aSad) - 1] = DllStructGetData($tBuf, 1)
	Else
		ReDim $aSad[UBound($aSad) + 1]
		$aSad[0] += 1
		$aSad[UBound($aSad) - 1] = "#" & $pName
	EndIf
	Return 1
EndFunc   ;==>__ResourceEnumNamesProc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Вот здесь, я подробно написал о различиях AutoIt и API в работе с иконками.
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Yashied Как я понимаю это много ходовая комбинация
Нужно сначала найти какие номера ресурсов содержит файл
потом под нужный номер ресурса подставить порядкорвый индекс
Или я что то путаю?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Я же там все подробно расписал...

:blink:

Код:
Func _Index($iIndex)
	Select 
		Case $iIndex > 0
			Return -$iIndex - 1
		Case $iIndex < 0
			Return -$iIndex
		Case Else
			Return 0
	EndSelect
EndFunc   ;==>_Index


В своем коде пишешь так:

Код:
GUICtrlCreateIcon($put, _Index($ind), 100, 50, 48, 48)


P.S

"Не корректное" пишется слитно.
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Попробую
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
:wacko:

Тебе не нужно сопоставлять ресурсы и индексы. Если иконка представлена ресурсом (знак "-"), то и в GUICtrl... функциях их нужно использовать как ресурсы, и наоборот, если указан именно индекс иконки в файле (знак "+"), то в AutoIt указываешь индекс. Загвоздка только в том, что в API ресурс указывается знаком "-", а индекс - "+". В AutoIt все с точностью до наоборот: "-" - индекс, а "+" - ресурс. Например, если у тебя иконка, полученная с помощью API функции, определена, как "-152", то это означает ресурс "152", т.к. стоит знак "-". И соответственно в AutoIt тебе тоже нужно использовать ресурс, но здесь ресурсы нужно указывать как положительные числа, т.е. просто "152". Именно это и делает функция _Index(), конвертирует API индексы или ID ресурсов в их AutoIt представление.
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Мне кажется здесь некоторое недопонимание (я наверно плохо объяснил)
Первая иконка отображается правильно
Это вторая иконка которая не правильно копируется
Функция "_FileExtractIcon" принимает номер ресурса за индекс и копирует её по индексу -153 а на самом деле эта иконка
Лежит по индексу -72 (если от нуля)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Застрелите меня кто-нибудь...

:suicide:
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Извини я просто наверно тупой
Просто если я напрямую подставлю вместо -153 просто 153 это не чего не меняет
Скопируется та же не правильная иконка
Большая просьба измени мой код как надо а то я тупею на глазах
Перед форумчанами стыдно и особенно перед тобой
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
У тебя проблема с функцией _FileExtractIcon(), которая воспринимает именно индексы, а у тебя ресурс (знак "-"). Так просто из одного другое не получишь... Переписал полностью твой код.

Код:
#Include <WinAPIEx.au3>

Global $aaa = "bat"
Global $bbb = "." & $aaa
Global $aSad[1]

$GUI = GUICreate($aaa, 400, 250, 100, 250)
$sIcon = _WinAPI_AssocQueryString($bbb, $ASSOCSTR_DEFAULTICON)
$aIcon = _WinAPI_PathParseIconLocation($sIcon)
$put = _WinAPI_PathUnquoteSpaces($aIcon[0])
$ind = $aIcon[1]

GUICtrlCreateLabel("Путь:   " & $put, 10, 150, 380, 40)
GUICtrlCreateLabel("Индекс: " & $ind, 10, 190, 380, 20)
GUICtrlCreateIcon($put, _Index($ind), 100, 50, 48, 48)

#Region Yashied

Dim $aIcon[3]
$aIcon[0] = _WinAPI_Create32BitHICON(_WinAPI_ShellExtractIcon($put, $ind, 48, 48), 1)
$aIcon[1] = _WinAPI_Create32BitHICON(_WinAPI_ShellExtractIcon($put, $ind, 32, 32), 1)
$aIcon[2] = _WinAPI_Create32BitHICON(_WinAPI_ShellExtractIcon($put, $ind, 16, 16), 1)
_WinAPI_SaveHICONToFile($aaa & '.ico', $aIcon)
For $i = 0 To 2
	_WinAPI_DestroyIcon($aIcon[$i])
Next

#EndRegion Yashied

GUICtrlCreateIcon($aaa & ".ico", 0, 250, 50, 48, 48)

GUISetState()

While 1
	$iMsg = GUIGetMsg()
	Switch $iMsg

		Case -3
			FileDelete($bbb)
			FileDelete($aaa & ".ico")
			Exit

	EndSwitch
WEnd

Func  _Index($iIndex)
    Select
        Case $iIndex > 0
            Return -$iIndex - 1
        Case $iIndex < 0
            Return -$iIndex
        Case Else
            Return 0
    EndSelect
EndFunc   ;==>_Index

; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_SaveHICONToFile
; Description....: Saves a 32 bits-per-pixel single or multiple icon (HICON) to the specified icon (.ico) file.
; Syntax.........: _WinAPI_SaveHICONToFile ( $sFile, $aIcon [, $iStart [, $iEnd]] )
; Parameters.....: $sFile  - The name of the icon file.
;                  $aIcon  - Handle to the icon or array of the icon handles to be save.
;                  $iStart - The index of array to start saving at.
;                  $iEnd   - The index of array to stop saving at.
; Return values..: Success - 1.
;                  Failure - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: This function only works with 32 bits-per-pixel (RGB + Alpha) icons. If you do not know exactly which color
;                  depth is there an icon, use the _WinAPI_Create32BitHICON() function to convert its.
; Related........:
; Link...........: None
; Example........: Yes
; ===============================================================================================================================

Func _WinAPI_SaveHICONToFile($sFile, $aIcon, $iStart = 0, $iEnd = -1)

    Local $Icon, $Count = 1

    If IsArray($aIcon) Then
        If UBound($aIcon, 2) Then
            Return SetError(2, 0, 0)
        EndIf
        If $iStart < 0 Then
            $iStart = 0
        EndIf
        If ($iEnd < 0) Or ($iEnd > UBound($aIcon) - 1) Then
            $iEnd = UBound($aIcon) - 1
        EndIf
        $Count = $iEnd - $iStart + 1
        If $Count < 1 Then
            Return SetError(1, 0, 0)
        EndIf
        Dim $Icon[$Count]
        For $i = 0 To $Count - 1
            $Icon[$i] = $aIcon[$iStart + $i]
        Next
    Else
        Dim $Icon[1] = [$aIcon]
    EndIf

    Local $hFile = _WinAPI_CreateFileEx($sFile, 2, 0x40000000, 0)

    If @error Then
        Return SetError(1, 0, 0)
    EndIf

    Local $tData, $W, $H, $Info, $Bytes, $Error, $Result = 0
    Local $tIco = DllStructCreate('ushort Reserved;ushort Type;ushort Count;byte Data[' & (16 * $Count) & ']')
    Local $Lenght = DllStructGetSize($tIco)
    Local $pIco = DllStructGetPtr($tIco)
    Local $tBI = DllStructCreate($tagBITMAPINFOHEADER)
    Local $pBI = DllStructGetPtr($tBI)
    Local $tDIB = DllStructCreate($tagDIBSECTION)
    Local $Size = DllStructGetSize($tDIB)
    Local $pDIB = DllStructGetPtr($tDIB)
    Local $Offset = $Lenght

    DllStructSetData($tIco, 'Reserved', 0)
    DllStructSetData($tIco, 'Type', 1)
    DllStructSetData($tIco, 'Count', $Count)

    DllStructSetData($tBI, 'biSize', 40)
    DllStructSetData($tBI, 'biPlanes', 1)
    DllStructSetData($tBI, 'biBitCount', 32)
    DllStructSetData($tBI, 'biCompression', 0)
    DllStructSetData($tBI, 'biXPelsPerMeter', 0)
    DllStructSetData($tBI, 'biYPelsPerMeter', 0)
    DllStructSetData($tBI, 'biClrUsed', 0)
    DllStructSetData($tBI, 'biClrImportant', 0)

    Do
        If Not _WinAPI_WriteFile($hFile, $pIco, $Lenght, $Bytes) Then
            ExitLoop
        EndIf
        For $i = 0 To $Count - 1
            $Info = _WinAPI_GetIconInfo($Icon[$i])
            If Not IsArray($Info) Then
                ExitLoop 2
            EndIf
            For $j = 4 To 5
                $Info[$j] = _WinAPI_CopyImage($Info[$j], 0, 0, 0, BitOR(0x2000, 0x0008))
                If _WinAPI_GetObject($Info[$j], $Size, $pDIB) Then
                    $Info[$j - 4] = DllStructGetData($tDIB, 'biSizeImage')
                    $Info[$j - 2] = DllStructGetData($tDIB, 'bmBits')
                Else
                    $Info[$j - 4] = 0
                    $Info[$j - 2] = 0
                EndIf
            Next
            $W = DllStructGetData($tDIB, 'bmWidth')
            $H = DllStructGetData($tDIB, 'bmHeight')
            $tData = DllStructCreate('byte Width;byte Height;byte Colors;byte Reserved;word Planes;word BPP;long Size;long Offset', $pIco + 6 + 16 * $i)
            DllStructSetData($tData, 'Width', $W)
            DllStructSetData($tData, 'Height', $H)
            DllStructSetData($tData, 'Colors', 0)
            DllStructSetData($tData, 'Reserved', 0)
            DllStructSetData($tData, 'Planes', 1)
            DllStructSetData($tData, 'BPP', 32)
            DllStructSetData($tData, 'Size', 40 + $Info[0] + $Info[1])
            DllStructSetData($tData, 'Offset', $Offset)
            DllStructSetData($tBI, 'biWidth', $W)
            DllStructSetData($tBI, 'biHeight', 2 * $H)
            DllStructSetData($tBI, 'biSizeImage', $Info[0] + $Info[1])
            $Offset += 40 + $Info[0] + $Info[1]
            Do
                $Error = 1
                If Not _WinAPI_WriteFile($hFile, $pBI, 40, $Bytes) Then
                    ExitLoop
                EndIf
                For $j = 1 To 0 Step -1
                    If Not _WinAPI_WriteFile($hFile, $Info[$j + 2], $Info[$j], $Bytes) Then
                        ExitLoop 2
                    EndIf
                Next
                $Error = 0
            Until 1
            For $j = 4 To 5
                _WinAPI_DeleteObject($Info[$j])
            Next
            If $Error Then
                ExitLoop 2
            EndIf
        Next
        _WinAPI_SetFilePointer($hFile, 0)
        If Not _WinAPI_WriteFile($hFile, $pIco, $Lenght, $Bytes) Then
            ExitLoop
        EndIf
        $Result = 1
    Until 1
    _WinAPI_CloseHandle($hFile)
    If Not $Result Then
        FileDelete($sFile)
    EndIf
    Return SetError(Number(Not $Result), 0, $Result)
EndFunc   ;==>_WinAPI_SaveHICONToFile
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Yashied
Ты заслуженный учитель России
Большое спасибо
Буду изучать
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Здается мне, что ты изначально пошел по неверному пути. Зачем нужно сохранять иконки на диск?
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Дополнение для моей программы
чтобы потом эти иконки запихивать в папки для изменения их вида (папок)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Так просто укажи в Desktop.ini путь к тому же Shell32.dll и индекс. Зачем пользователю лишний мусор в папке. Кроме того, извлечение иконок из файлов ОС будет нарушением лицензионного соглашения (я думаю).
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Такая же родная утилита есть в виндах
Только в моей проге зашивается сама иконка в папку вместе с файлом Desktop.ini
Папка становится автономной то есть при переносе на другой комп папка имеет
изменённый вид. Да мусор в папке будет, только я эти файлы делаю системно невидимыми. В конечном счёте это чистое баловство, просто занимаюсь этим проектом
просто ради интереса .Я выкладавал свою прогу на сайте
Ты её не смотрел? Если есть желание посмотри её и ты увидишь что хоть примерно
это такое
http://narod.ru/disk/8140778001/Stilist.rar.html
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Re: Некорректное копирование иконки

Yashied
Я протестировал этот код
Эта функция отображает большинство рассширений , но некоторые (например ".blg") не хочет (хотя не исключено что это моя системная проблема)
Но правда она правильно определила что это "Файл системного монитора" а вот путь к ресурсу она не знает.
Например Функция "_WinAPI_ShellExtractAssociatedIcon" правильно отображает иконку ".blg" , но мне нужен именно путь к этому ресурсу (где находится иконка
заточенная в системе под это рассширение) Попытался по шаманить с функцией "_WinAPI_ShellExtractAssociatedIcon" но так не чего и не добился .
Интересно где может находится этот ресурс (для расширения ".blg") который функция "_WinAPI_AssocQueryString" не оределяет.
Код:
#Include <WinAPIEx.au3>

Global $aaa = "blg"
Global $bbb = "." & $aaa

FileOpen($bbb,2)

$GUI = GUICreate($aaa, 400, 270, 100, 250)
$sIcon = _WinAPI_AssocQueryString($bbb, $ASSOCSTR_DEFAULTICON) 
$aIcon = _WinAPI_PathParseIconLocation($sIcon)
$put = _WinAPI_PathUnquoteSpaces($aIcon[0])
$ind = $aIcon[1]

#Region Yashied

Dim $aIcon[3]
$aIcon[0] = _WinAPI_Create32BitHICON(_WinAPI_ShellExtractIcon($put, $ind, 48, 48), 1)
$aIcon[1] = _WinAPI_Create32BitHICON(_WinAPI_ShellExtractIcon($put, $ind, 32, 32), 1)
$aIcon[2] = _WinAPI_Create32BitHICON(_WinAPI_ShellExtractIcon($put, $ind, 16, 16), 1)
_WinAPI_SaveHICONToFile($aaa & '.ico', $aIcon)
For $i = 0 To 2
    _WinAPI_DestroyIcon($aIcon[$i])
Next

#EndRegion Yashied

GUICtrlCreateLabel("Путь:   " & $put, 10, 150, 380, 40)
GUICtrlCreateLabel("Индекс: " & $ind, 10, 190, 380, 20)

$sfrien = _WinAPI_AssocQueryString($bbb, $ASSOCSTR_FRIENDLYDOCNAME)
GUICtrlCreateLabel($sfrien, 10, 230, 380, 20)

GUICtrlCreateIcon($put, _Index($ind), 100, 50, 48, 48)

GUICtrlCreateIcon($aaa & ".ico", 0, 250, 50, 48, 48)

GUISetState()

While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg

        Case -3
            FileDelete($bbb)
            FileDelete($aaa & ".ico")
            Exit

    EndSwitch
WEnd

Func  _Index($iIndex)
    Select
        Case $iIndex > 0
            Return -$iIndex - 1
        Case $iIndex < 0
            Return -$iIndex
        Case Else
            Return 0
    EndSelect
EndFunc   ;==>_Index

; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_SaveHICONToFile
; Description....: Saves a 32 bits-per-pixel single or multiple icon (HICON) to the specified icon (.ico) file.
; Syntax.........: _WinAPI_SaveHICONToFile ( $sFile, $aIcon [, $iStart [, $iEnd]] )
; Parameters.....: $sFile  - The name of the icon file.
;                  $aIcon  - Handle to the icon or array of the icon handles to be save.
;                  $iStart - The index of array to start saving at.
;                  $iEnd   - The index of array to stop saving at.
; Return values..: Success - 1.
;                  Failure - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: This function only works with 32 bits-per-pixel (RGB + Alpha) icons. If you do not know exactly which color
;                  depth is there an icon, use the _WinAPI_Create32BitHICON() function to convert its.
; Related........:
; Link...........: None
; Example........: Yes
; ===============================================================================================================================

Func _WinAPI_SaveHICONToFile($sFile, $aIcon, $iStart = 0, $iEnd = -1)

    Local $Icon, $Count = 1

    If IsArray($aIcon) Then
        If UBound($aIcon, 2) Then
            Return SetError(2, 0, 0)
        EndIf
        If $iStart < 0 Then
            $iStart = 0
        EndIf
        If ($iEnd < 0) Or ($iEnd > UBound($aIcon) - 1) Then
            $iEnd = UBound($aIcon) - 1
        EndIf
        $Count = $iEnd - $iStart + 1
        If $Count < 1 Then
            Return SetError(1, 0, 0)
        EndIf
        Dim $Icon[$Count]
        For $i = 0 To $Count - 1
            $Icon[$i] = $aIcon[$iStart + $i]
        Next
    Else
        Dim $Icon[1] = [$aIcon]
    EndIf

    Local $hFile = _WinAPI_CreateFileEx($sFile, 2, 0x40000000, 0)

    If @error Then
        Return SetError(1, 0, 0)
    EndIf

    Local $tData, $W, $H, $Info, $Bytes, $Error, $Result = 0
    Local $tIco = DllStructCreate('ushort Reserved;ushort Type;ushort Count;byte Data[' & (16 * $Count) & ']')
    Local $Lenght = DllStructGetSize($tIco)
    Local $pIco = DllStructGetPtr($tIco)
    Local $tBI = DllStructCreate($tagBITMAPINFOHEADER)
    Local $pBI = DllStructGetPtr($tBI)
    Local $tDIB = DllStructCreate($tagDIBSECTION)
    Local $Size = DllStructGetSize($tDIB)
    Local $pDIB = DllStructGetPtr($tDIB)
    Local $Offset = $Lenght

    DllStructSetData($tIco, 'Reserved', 0)
    DllStructSetData($tIco, 'Type', 1)
    DllStructSetData($tIco, 'Count', $Count)

    DllStructSetData($tBI, 'biSize', 40)
    DllStructSetData($tBI, 'biPlanes', 1)
    DllStructSetData($tBI, 'biBitCount', 32)
    DllStructSetData($tBI, 'biCompression', 0)
    DllStructSetData($tBI, 'biXPelsPerMeter', 0)
    DllStructSetData($tBI, 'biYPelsPerMeter', 0)
    DllStructSetData($tBI, 'biClrUsed', 0)
    DllStructSetData($tBI, 'biClrImportant', 0)

    Do
        If Not _WinAPI_WriteFile($hFile, $pIco, $Lenght, $Bytes) Then
            ExitLoop
        EndIf
        For $i = 0 To $Count - 1
            $Info = _WinAPI_GetIconInfo($Icon[$i])
            If Not IsArray($Info) Then
                ExitLoop 2
            EndIf
            For $j = 4 To 5
                $Info[$j] = _WinAPI_CopyImage($Info[$j], 0, 0, 0, BitOR(0x2000, 0x0008))
                If _WinAPI_GetObject($Info[$j], $Size, $pDIB) Then
                    $Info[$j - 4] = DllStructGetData($tDIB, 'biSizeImage')
                    $Info[$j - 2] = DllStructGetData($tDIB, 'bmBits')
                Else
                    $Info[$j - 4] = 0
                    $Info[$j - 2] = 0
                EndIf
            Next
            $W = DllStructGetData($tDIB, 'bmWidth')
            $H = DllStructGetData($tDIB, 'bmHeight')
            $tData = DllStructCreate('byte Width;byte Height;byte Colors;byte Reserved;word Planes;word BPP;long Size;long Offset', $pIco + 6 + 16 * $i)
            DllStructSetData($tData, 'Width', $W)
            DllStructSetData($tData, 'Height', $H)
            DllStructSetData($tData, 'Colors', 0)
            DllStructSetData($tData, 'Reserved', 0)
            DllStructSetData($tData, 'Planes', 1)
            DllStructSetData($tData, 'BPP', 32)
            DllStructSetData($tData, 'Size', 40 + $Info[0] + $Info[1])
            DllStructSetData($tData, 'Offset', $Offset)
            DllStructSetData($tBI, 'biWidth', $W)
            DllStructSetData($tBI, 'biHeight', 2 * $H)
            DllStructSetData($tBI, 'biSizeImage', $Info[0] + $Info[1])
            $Offset += 40 + $Info[0] + $Info[1]
            Do
                $Error = 1
                If Not _WinAPI_WriteFile($hFile, $pBI, 40, $Bytes) Then
                    ExitLoop
                EndIf
                For $j = 1 To 0 Step -1
                    If Not _WinAPI_WriteFile($hFile, $Info[$j + 2], $Info[$j], $Bytes) Then
                        ExitLoop 2
                    EndIf
                Next
                $Error = 0
            Until 1
            For $j = 4 To 5
                _WinAPI_DeleteObject($Info[$j])
            Next
            If $Error Then
                ExitLoop 2
            EndIf
        Next
        _WinAPI_SetFilePointer($hFile, 0)
        If Not _WinAPI_WriteFile($hFile, $pIco, $Lenght, $Bytes) Then
            ExitLoop
        EndIf
        $Result = 1
    Until 1
    _WinAPI_CloseHandle($hFile)
    If Not $Result Then
        FileDelete($sFile)
    EndIf
    Return SetError(Number(Not $Result), 0, $Result)
EndFunc   ;==>_WinAPI_SaveHICONToFile
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
А что написано в

HKEY_CLASSES_ROOT\Diagnostic.Perfmon.Document\DefaultIcon

или в том разделе, на котрый указывает

HKEY_CLASSES_ROOT\.blg
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Сейчас посмотрю
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Ветку HKEY_CLASSES_ROOT\Diagnostic.Perfmon.Document\DefaultIcon я у себя не нашёл

А по адресу HKEY_CLASSES_ROOT\.blg

HKEY_CLASSES_ROOT\.blg ------- По умолчанию --- PerfFile
HKEY_CLASSES_ROOT\PerfFile ------- FriendlyTypeName --- @%SystemRoot%\System32\pdh.dll,-10023
HKEY_CLASSES_ROOT\PerfFile\shell\open\command ------- По умолчанию --- %SystemRoot%\system32\perfmon.exe %1

Скопировал - pdh.dll --- иконок там вообще нет
Скопировал - perfmon.exe --- там только одна иконка (как это чаще всего бывает у экзешников)
Только она выглядит рисунком (в полном объёме) , а иконка которую делает система выглядит как:
на фоне листочка с отогнутом уголком а в ней уже находится этот (но уже маленький рисунок)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Ну так иконки ведь нет, поэтому и путь не возвращает. Все правильно. А то, что ты принимаешь за иконку, это всего навсего происки Explorer'а, да и выглядит она некрасиво.

P.S

Можно конечно самому состряпать такую иконку с помощью функции _WinAPI_AddIconOverlay(), кстати, выглядеть будет лучше, но оно тебе надо?
 
Верх