Что нового

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

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,716
Вот здесь, я подробно написал о различиях AutoIt и API в работе с иконками.
 
Автор
A

assch

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

Yashied

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

: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

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
: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,716
Застрелите меня кто-нибудь...

:suicide:
 
Автор
A

assch

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
У тебя проблема с функцией _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,716
Здается мне, что ты изначально пошел по неверному пути. Зачем нужно сохранять иконки на диск?
 
Автор
A

assch

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
Так просто укажи в 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,716
А что написано в

HKEY_CLASSES_ROOT\Diagnostic.Perfmon.Document\DefaultIcon

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

HKEY_CLASSES_ROOT\.blg
 
Автор
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,716
Ну так иконки ведь нет, поэтому и путь не возвращает. Все правильно. А то, что ты принимаешь за иконку, это всего навсего происки Explorer'а, да и выглядит она некрасиво.

P.S

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