Что нового

Разработка UDF для добавления ресурсов в исполняющий файл

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Написал функцию которая добавляет в EXE файл ресурсы типа RT_ICON, RT_BITMAP, RT_RCDATA, RT_VERSION, RT_MANIFEST, User-defined, при этом оставляет исполняющий файл написанный на AutoIt рабочим, так же имеется возможность включить/отключить Backup при добавлении ресурса, всё бы хорошо, но не радует то что в RT_ICON нужно указывать файл типа *.ico, если взять *.png то функция слетает, хотелось бы преобразовывать любой тип картинки в формат *.ico в памяти без сохранения на диск, то же самое и RT_BITMAP, так же буду признателен если кто нибудь даст инфу по работе с ресурсами RT_MESSAGETABLE и RT_STRING, ну и конечно же обсудить здесь работу скрипта.

Для работы скрипта требуется WinAPI UDF v3.7 для AutoIt v3.3.6.1

UDF
Код:
#include <WinAPIEx.au3>
#include <APIConstants.au3>
#include <ResStructure.au3>


AddResource(@ScriptDir & '\1.exe', @ScriptDir & '\10.ico', 'ICON', 99)
If @error Then
	MsgBox(16, 'Error', 'Failed to add resource to executable file, error = ' & @error)
EndIf	

Func AddResource($sFile, $sResFile, $sResType, $sResName, $iResLang = -1, $iBackup = 1)	
	
	If ($iResLang = -1) Then
		$iResLang = 2057
	EndIf	

	Local $sBackup = __rc_Backup($sFile)
    __rc_Relocation($sFile, $sBackup)
	
	$hFile = _WinAPI_CreateFile($sFile, 2, 2)
	If (Not $hFile) Then
		Return SetError(1, 0, 0)
	EndIf	
	_WinAPI_SetFilePointerEx($hFile, FileGetSize($sBackup), $FILE_BEGIN)
	$tBuffer = DllStructCreate('byte[' & FileGetSize($sFile) & ']')
	$pBuffer = DllStructGetPtr($tBuffer)
	$iBuffer = DllStructGetSize($tBuffer)
	If Not _WinAPI_ReadFile($hFile, $pBuffer, $iBuffer, $iBuffer) Then
		Return SetError(2, 0, 0)
	EndIf	
	_WinAPI_CloseHandle($hFile)
	
	If IsString($sResType) Then $sResType = StringUpper($sResType)
	
	Switch $sResType
	    Case 2, 'BITMAP'
		    __rc_AddBitmap($sBackup, $sResFile, $sResName, $iResLang)
	    Case 3, 'ICON'; RT_ICON
		    __rc_AddIcon($sBackup, $sResFile, $sResName, $iResLang)
	    Case Else ; RT_RCDATA, RT_VERSION, RT_MANIFEST, User-defined
		    __rc_AddRCData($sBackup, $sResFile, $sResType, $sResName, $iResLang)
	EndSwitch		
	If @error Then
	    Return SetError(3, 0, 0)
	EndIf
	If Not __rc_WriteData($sBackup, $pBuffer, $iBuffer) Then
		Return SetError(4, 0, 0)
	EndIf	
	If Not __rc_SelectBackup($sFile, $sBackup, $iBackup) Then
		Return SetError(5, 0, 0)
	EndIf
	Return True
EndFunc

Func __rc_WriteData($sBackup, $pBuffer, $iBuffer)
	$hFile = _WinAPI_CreateFile($sBackup, 2, 4)
	If (Not $hFile) Then
		Return SetError(1, 0, 0)
	EndIf	
	_WinAPI_SetFilePointerEx($hFile, 0, $FILE_END)
	If Not _WinAPI_WriteFile($hFile, $pBuffer, $iBuffer, $iBuffer) Then
		Return SetError(2, 0, 0)
	EndIf	
	_WinAPI_CloseHandle($hFile)
	Return 1
EndFunc	

Func __rc_Backup($sFile)
	Return StringRegExpReplace($sFile, '(?s)(.*)\.(.*)', '$1') & '.TMP'
EnDFunc	

Func __rc_SelectBackup($sFile, $sBackup, $iFlag = 0)
	Local $sPath = StringRegExpReplace($sFile, '(?s)(.*)\.(.*)', '$1')
	Local $sExp = StringRegExpReplace($sFile, '(?s)(.*)\.(.*)', '$2')
	If $iFlag Then
	    If Not _WinAPI_CopyFileEx($sFile, $sPath & ' Backup.' & $sExp) Then
	        Return SetError(1, 0, 0)
	    EndIf	
	EndIf	
	If Not _WinAPI_CopyFileEx($sBackup, $sFile) Then
		Return SetError(2, 0, 0)
	EndIf	
	If Not _WinAPI_DeleteFile($sBackup) Then
		Return SetError(3, 0, 0)
	EndIf	
	Return 1
EndFunc	

Func __rc_AddIcon($sBackup, $sResFile, $sResName, $iResLang)
	Local $iBytes, $hUpdate, $tMODULESTRUCTURE[1][1][1], $tINPUTICONHEADER, $tGROUPICONDATA, $iEnumIconName

    $hUpdate = _WinAPI_BeginUpdateResource($sBackup, 0)
	If (Not $hUpdate) Then
		Return SetError(0, 0, 0)
	EndIf	
	$hFile = _WinAPI_CreateFile($sResFile, 2, 2)
	If Not $hFile Then
		Return SetError(1, 0, 0)
	EndIf	
	$iSize = _WinAPI_GetFileSizeEx($hFile)
	$tBuffer = DllStructCreate('byte[' & $iSize & ']')
	$pBuffer = DllStructGetPtr($tBuffer)
	$iBuffer = DllStructGetSize($tBuffer)
	If Not _WinAPI_ReadFile($hFile, $pBuffer, $iBuffer, $iBytes) Then
		Return SetError(2, 0, 0)
	EndIf	
	_WinAPI_CloseHandle($hFile)
	$tICONRESOURCE = DllStructCreate($tagRESOURCEICON & 'byte Body[' & $iBuffer - 6 & ']', $pBuffer)
	$iIconCount = DllStructGetData($tICONRESOURCE, 'ImageCount')
	If Not $iIconCount Then
		Return SetError(3, 0, 0)
	EndIf
	$tICONGROUPHEADER = DllStructCreate($tagRESOURCEICON & 'byte Body[' & $iIconCount * 14 & ']')
	DllStructSetData($tICONGROUPHEADER, 1, DllStructGetData($tICONRESOURCE, 1))
	DllStructSetData($tICONGROUPHEADER, 'Type', DllStructGetData($tICONRESOURCE, 'Type'))
	DllStructSetData($tICONGROUPHEADER, 'ImageCount', DllStructGetData($tICONRESOURCE, 'ImageCount'))
    For $i = 1 To $iIconCount
		$tINPUTICONHEADER = DllStructCreate($tagINPUTICONHEADER, DllStructGetPtr($tICONRESOURCE, 'Body') + ($i - 1) * 16)
		$tGROUPICONDATA = DllStructCreate($tagGROUPICONDATA, DllStructGetPtr($tICONGROUPHEADER, 'Body') + ($i - 1) * 14)
	    DllStructSetData($tGROUPICONDATA, 'Width', DllStructGetData($tINPUTICONHEADER, 'Width'))
	    DllStructSetData($tGROUPICONDATA, 'Height', DllStructGetData($tINPUTICONHEADER, 'Height'))
		DllStructSetData($tGROUPICONDATA, 'Colors', DllStructGetData($tINPUTICONHEADER, 'Colors'))
		DllStructSetData($tGROUPICONDATA, 4, DllStructGetData($tINPUTICONHEADER, 4))
		DllStructSetData($tGROUPICONDATA, 'Planes', DllStructGetData($tINPUTICONHEADER, 'Planes'))
		DllStructSetData($tGROUPICONDATA, 'BitPerPixel', DllStructGetData($tINPUTICONHEADER, 'BitPerPixel'))
		DllStructSetData($tGROUPICONDATA, 'BitmapSize', DllStructGetData($tINPUTICONHEADER, 'BitmapSize'))
		$iEnumIconName += 1
		For $y = 0 To UBound($tMODULESTRUCTURE, 1) - 1
			If $tMODULESTRUCTURE[$y][0][0] = $RT_ICON Then
				For $z = 1 To UBound($tMODULESTRUCTURE, 2) - 1
					If $iEnumIconName = $tMODULESTRUCTURE[$y][$z][0] Then
					    $iEnumIconName += 1
					EndIf	
				Next
                ExitLoop				
			EndIf
        Next
        DllStructSetData($tGROUPICONDATA, 'OrdinalName', $iEnumIconName)
		$iResult = _WinAPI_UpdateResource($hUpdate, $RT_ICON, $iEnumIconName, $iResLang, DllStructGetPtr($tICONRESOURCE) + DllStructGetData($tINPUTICONHEADER, 'BitmapOffset'), DllStructGetData($tINPUTICONHEADER, 'BitmapSize'))
		If ((@error) Or (Not $iResult)) Then
			_WinAPI_EndUpdateResource($hUpdate, 0)
			Return SetError(4, 0, 0)
	    EndIf
	Next	
	Switch IsNumber($sResName)
		Case True
			$iResult = _WinAPI_UpdateResource($hUpdate, $RT_GROUP_ICON, $sResName, $iResLang, DllStructGetPtr($tICONGROUPHEADER), DllStructGetSize($tICONGROUPHEADER))
		Case Else
			$iResult = _WinAPI_UpdateResource($hUpdate, $RT_GROUP_ICON, StringUpper($sResName), $iResLang, DllStructGetPtr($tICONGROUPHEADER), DllStructGetSize($tICONGROUPHEADER))	
	EndSwitch
    If ((@error) Or (Not $iResult)) Then
		_WinAPI_EndUpdateResource($hUpdate, 0)
		Return SetError(5, 0, 0)
	EndIf
	_WinAPI_EndUpdateResource($hUpdate, 0)
    Return 1
EndFunc	

Func __rc_AddRCData($sBackup, $sResFile, $sResType, $sResName, $iResLang)
	$hUpdate = _WinAPI_BeginUpdateResource($sBackup, 0)
	If (Not $hUpdate) Then
		ConsoleWrite(0 & @CRLF)
		Return SetError(0, 0, 0)
	EndIf	
	$hFile = _WinAPI_CreateFileEx($sResFile, $OPEN_EXISTING, $GENERIC_READ)
	If Not $hFile Then
		Return SetError(1, 0, 0)
	EndIf	
	$iSize = _WinAPI_GetFileSizeEx($hFile)
	$tByte = DllStructCreate('byte[' & $iSize & ']')
	$pByte = DllStructGetPtr($tByte)
	$iByte = DllStructGetSize($tByte)
	If Not _WinAPI_ReadFile($hFile, $pByte, $iByte, $iByte) Then
		Return SetError(2, 0, 0)
	EndIf	
	$iResult = _WinAPI_UpdateResource($hUpdate, $sResType, $sResName, $iResLang, $pByte, $iByte)
	If (@error) Or (Not $iResult) Then
		Return SetError(3, 0, 0)
	EndIf	
	_WinAPI_EndUpdateResource($hUpdate, 0)
	Return 1
EndFunc	

Func __rc_AddBitmap($sBackup, $sResFile, $sResName, $iResLang)
	Local $iBytes
	$hUpdate = _WinAPI_BeginUpdateResource($sBackup, 0)
	If Not $hUpdate Then
		Return SetError(0, 0, 0)
	EndIf
	$hFile = _WinAPI_CreateFile($sResFile, 2, 2)
	If (Not $hFile) Then
		Return SetError(1, 0, 0)
	EndIf
	$iSize = _WinAPI_GetFileSizeEx($hFile) - 14 
	$tBuffer = DllStructCreate('char Text[' & $iSize & ']')
	$pBuffer = DllStructGetPtr($tBuffer)
	_WinAPI_SetFilePointer($hFile, 14)
	If Not _WinAPI_ReadFile($hFile, $pBuffer, $iSize, $iBytes) Then
		Return SetError(2, 0, 0)
	EndIf	
	_WinAPI_CloseHandle($hFile)
    $iResult = _WinAPI_UpdateResource($hUpdate, $RT_BITMAP, $sResName, $iResLang, $pBuffer, $iSize)
    If (@error) Or (Not $iResult) Then
		Return SetError(3, 0, 0)
	EndIf
	_WinAPI_EndUpdateResource($hUpdate, 0)
	Return 1
EndFunc	

Func DelResource($sFile, $sResType, $sResName, $sResLang = 0)

    ;~ Удаляет ресурсы типа RC_DATA

	Local $hFile, $tBuffer, $pBuffer, $iBuffer, $hUpdate, $hModule, $iEnumLang
	Local $sOutFile = ($sFile & '.tmp')

	__rc_Relocation($sFile, $sOutFile)

	$hFile = _WinAPI_CreateFile($sFile, 2, 2)
	If $hFile Then
		_WinAPI_SetFilePointerEx($hFile, FileGetSize($sOutFile), 0)
		$tBuffer = DllStructCreate('byte[' & FileGetSize($sFile) & ']')
		$pBuffer = DllStructGetPtr($tBuffer)
		$iBuffer = DllStructGetSize($tBuffer)
		If _WinAPI_ReadFile($hFile, $pBuffer, $iBuffer, $iBuffer) Then
			_WinAPI_CloseHandle($hFile)
			$hUpdate = _WinAPI_BeginUpdateResource($sOutFile, False)
			If $hUpdate Then
				If $sResLang Then
					If _WinAPI_UpdateResource($hUpdate, $sResType, $sResName, $sResLang, 0, 0) Then
						_WinAPI_EndUpdateResource($hUpdate, False)
					EndIf
				Else
					$hModule = _WinAPI_LoadLibrary($sFile)
					$iEnumLang = _WinAPI_EnumResourceLanguages($hModule, $sResType, $sResName)
					For $I = 1 To UBound($iEnumLang) - 1
						_WinAPI_UpdateResource($hUpdate, $sResType, $sResName, $iEnumLang[$I], 0, 0)
					Next
					_WinAPI_EndUpdateResource($hUpdate, False)
					_WinAPI_FreeLibrary($hModule)
				EndIf
				$hFile = _WinAPI_CreateFile($sOutFile, 2, 4)
				If $hFile Then
					_WinAPI_SetFilePointerEx($hFile, 0, 2)
					If _WinAPI_WriteFile($hFile, $pBuffer, $iBuffer, $iBuffer) Then
						_WinAPI_CloseHandle($hFile)
						_WinAPI_DeleteFile($sFile)
						$hFile = FileOpen($sOutFile)
						FileWrite($sFile, FileRead($hFile))
						FileClose($hFile)
						_WinAPI_DeleteFile($sOutFile)
						Return True
					Else
						_WinAPI_CloseHandle($hFile)
						Return SetError(5, 0, 0)
					EndIf
				Else
					_WinAPI_CloseHandle($hFile)
					Return SetError(4, 0, 0)
				EndIf
			Else
				_WinAPI_EndUpdateResource($hUpdate, False)
				Return SetError(3, 0, 0)
			EndIf
		Else
			_WinAPI_CloseHandle($hFile)
			Return SetError(2, 0, 0)
		EndIf
	Else
		_WinAPI_CloseHandle($hFile)
		Return SetError(1, 0, 0)
	EndIf
EndFunc

Func ExtractResource($hInstance, $sExtractPath, $sResType, $sResName, $iResLanguage = 0x0400)
	Local $hResource, $aResSize, $aResLoad, $pMemRes
	$hResource = _WinAPI_FindResourceEx($hInstance, $sResType, $sResName, $iResLanguage)
	$iSize = _WinAPI_SizeOfResource($hInstance, $hResource)
	$aResLoad = _WinAPI_LoadResource($hInstance, $hResource)
	$pMemRes = _WinAPI_LockResource($aResLoad)
	If @error Then
		Return SetError(@error, @extended, 0)
	EndIf
	$tByte = DllStructCreate('byte[' & $iSize & ']', $pMemRes)
	$hFile = _WinAPI_CreateFileEx($sExtractPath, $CREATE_ALWAYS, $GENERIC_WRITE)
	_WinAPI_WriteFile($hFile, DllStructGetPtr($tByte), DllStructGetSize($tByte), $tByte)
	If $hFile Then
		_WinAPI_CloseHandle($hFile)
	EndIf
EndFunc

Func __rc_Relocation($sFile, $sOutFile)
	Local $iBytes
	Local $hFile = _WinAPI_CreateFile($sFile, 2, 2)
	If (@error) Or (Not $hFile) Then
		Return SetError(-1, 0, 0)
	EndIf
	Local $hFileOut = _WinAPI_CreateFileEx($sOutFile, 2, 2)
	If (Not $hFileOut) Then
		Return SetError(-2, 0, 0)
	EndIf
	$IMAGE_DOS_HEADER = DllStructCreate($tagIMAGE_DOS_HEADER)
	_WinAPI_SetFilePointerEx($hFile, 0)
	_WinAPI_ReadFile($hFile, DllStructGetPtr($IMAGE_DOS_HEADER), DllStructGetSize($IMAGE_DOS_HEADER), $iBytes)
    _WinAPI_SetFilePointerEx($hFileOut, 0)
	_WinAPI_WriteFile($hFileOut, DllStructGetPtr($IMAGE_DOS_HEADER), DllStructGetSize($IMAGE_DOS_HEADER), $iBytes)
	$iAddress = DllStructGetData($IMAGE_DOS_HEADER, 'lfanew')
	$Signature = DllStructCreate('dword Signature')
	_WinAPI_SetFilePointerEx($hFile, $iAddress)
	_WinAPI_ReadFile($hFile, DllStructGetPtr($Signature), DllStructGetSize($Signature), $iBytes)
	If DllStructGetData($Signature, 'Signature') <> 0x00004550 And DllStructGetData($Signature, 'Signature') <> 0x50450000 Then
		Return SetError(-3, 0, 0)
	EndIf
	_WinAPI_SetFilePointerEx($hFileOut, $iAddress)
	_WinAPI_WriteFile($hFileOut, DllStructGetPtr($Signature), DllStructGetSize($Signature), $iBytes)
	$iAddress += DllStructGetSize($Signature)
	$IMAGE_FILE_HEADER = DllStructCreate($tagIMAGE_FILE_HEADER)
	_WinAPI_SetFilePointerEx($hFile, $iAddress)
	_WinAPI_ReadFile($hFile, DllStructGetPtr($IMAGE_FILE_HEADER), DllStructGetSize($IMAGE_FILE_HEADER), $iBytes)
    _WinAPI_SetFilePointerEx($hFileOut, $iAddress)
	_WinAPI_WriteFile($hFileOut, DllStructGetPtr($IMAGE_FILE_HEADER), DllStructGetSize($IMAGE_FILE_HEADER), $iBytes)
	$iAddress += DllStructGetSize($IMAGE_FILE_HEADER)
	$IMAGE_OPTIONAL_HEADER = DllStructCreate($tagIMAGE_OPTIONAL_HEADER)
	_WinAPI_SetFilePointerEx($hFile, $iAddress)
	_WinAPI_ReadFile($hFile, DllStructGetPtr($IMAGE_OPTIONAL_HEADER), DllStructGetSize($IMAGE_OPTIONAL_HEADER), $iBytes)
	If DllStructGetData($IMAGE_OPTIONAL_HEADER, 'Magic') <> 0x10b And DllStructGetData($IMAGE_OPTIONAL_HEADER, 'Magic') <> 0x20b Then
		Return SetError(-4, 0, 0)
	EndIf
	_WinAPI_SetFilePointerEx($hFileOut, $iAddress)
	_WinAPI_WriteFile($hFileOut, DllStructGetPtr($IMAGE_OPTIONAL_HEADER), DllStructGetSize($IMAGE_OPTIONAL_HEADER), $iBytes)
	$NumberOfSections = DllStructGetData($IMAGE_FILE_HEADER, 'NumberOfSections')
	$iAddress += DllStructGetSize($IMAGE_OPTIONAL_HEADER)
	$SizeOfHeaders = DllStructGetData($IMAGE_OPTIONAL_HEADER, 'SizeOfHeaders')
	$RemainderSize = $SizeOfHeaders - ($iAddress + $NumberOfSections * 40)
	$DataPos = ($iAddress + $NumberOfSections * 40)
	$DataStruct = DllStructCreate("byte[" & $RemainderSize & "]")
	_WinAPI_SetFilePointerEx($hFile, $DataPos)
	_WinAPI_ReadFile($hFile, DllStructGetPtr($DataStruct), $RemainderSize, $iBytes)
    _WinAPI_SetFilePointerEx($hFileOut, $DataPos)
	_WinAPI_WriteFile($hFileOut, DllStructGetPtr($DataStruct), DllStructGetSize($DataStruct), $iBytes)
	For $I = 1 To $NumberOfSections
		$IMAGE_SECTION_HEADER = DllStructCreate($tagIMAGE_SECTION_HEADER)
	    _WinAPI_SetFilePointerEx($hFile, $iAddress)
	    _WinAPI_ReadFile($hFile, DllStructGetPtr($IMAGE_SECTION_HEADER), DllStructGetSize($IMAGE_SECTION_HEADER), $iBytes)
		If $iAddress <> 0 Then _WinAPI_SetFilePointerEx($hFileOut, $iAddress)
	    _WinAPI_WriteFile($hFileOut, DllStructGetPtr($IMAGE_SECTION_HEADER), DllStructGetSize($IMAGE_SECTION_HEADER), $iBytes)
		$PointerToRawData = DllStructGetData($IMAGE_SECTION_HEADER, 'PointerToRawData')
		$SizeOfRawData = DllStructGetData($IMAGE_SECTION_HEADER, 'SizeOfRawData')
		$VirtualAddress = DllStructGetData($IMAGE_SECTION_HEADER, 'VirtualAddress')
		$byteStruct = DllStructCreate('byte[' & $SizeOfRawData & ']')
	    _WinAPI_SetFilePointerEx($hFile, $PointerToRawData)
	    _WinAPI_ReadFile($hFile, DllStructGetPtr($byteStruct), $SizeOfRawData, $iBytes)
       _WinAPI_SetFilePointerEx($hFileOut, $PointerToRawData)
	    _WinAPI_WriteFile($hFileOut, DllStructGetPtr($byteStruct), DllStructGetSize($byteStruct), $iBytes)
		$iAddress += DllStructGetSize($IMAGE_SECTION_HEADER)
	Next
	_WinAPI_CloseHandle($hFile)
	_WinAPI_CloseHandle($hFileOut)
EndFunc

Так же здесь имеются функции DelResource() и ExtractResource(), но пока что они работают с ресурсами типа RT_RCDATA и User-defined.

ResStructure.au3
Код:
#Region Executable File Structure
Global Const $tagIMAGE_DOS_HEADER = '' & _
	'ushort magic;' & _        ;// Сигнатура заголовка
	'ushort cblp;' & _         ;// количество байт на последней странице файла
	'ushort cp;' & _           ;// количество страниц в файле
	'ushort crlc;' & _         ;// Relocations
	'ushort cparhdr;' & _      ;// Размер заголовка в параграфах
	'ushort minalloc;' & _     ;// Минимальные дополнительные параграфы
	'ushort maxalloc;' & _     ;// Максимальные дополнительные параграфы
	'ushort ss;' & _           ;// начальное относительное значение регистра SS
	'ushort sp;' & _           ;// начальное значение регистра SP
	'ushort csum;' & _         ;// контрольная сумма
	'ushort ip;' & _           ;// начальное значение регистра IP
	'ushort cs;' & _           ;// начальное относительное значение регистра CS
	'ushort lfarlc;' & _       ;// адрес в файле на таблицу переадресации
	'ushort ovno;' & _         ;// количество оверлеев
	'ushort res[4];' & _       ;// Зарезервировано
	'ushort oemid;' & _        ;// OEM идентифкатор
	'ushort oeminfo;' & _      ;// OEM информация
	'ushort res2[10];' & _     ;// Зарезервировано
	'dword lfanew'             ;// адрес в файле нового .exe заголовка (PE)

Global Const $tagIMAGE_FILE_HEADER = '' & _
	'ushort Machine;' & _                 ;// Машина
	'ushort NumberOfSections;' & _        ;// Колличество секторов
	'dword TimeDateStamp;' & _            ;// Временной штамп
	'dword PointerToSymbolTable;' & _     ;// Указатель на таблицу символов
	'dword NumberOfSymbols;' & _          ;// Колличество символов
	'ushort SizeOfOptionalHeader;' & _    ;// Размер дополнительного заголовка
	'ushort Characteristics'              ;// Характеристики
	
Global Const $tagIMAGE_OPTIONAL_HEADER = '' & _
	'ushort Magic;' & _                       ;// Тип файла
	'ubyte MajorLinkerVersion;' & _           ;// Основной номер версии компоновщика
	'ubyte MinorLinkerVersion;' & _           ;// Дополнительный номер версии компоновщика
	'dword SizeOfCode;' & _                   ;// Размер кода раздела, в байтах, или сумма всех таких участков, если есть несколько разделов кода.
	'dword SizeOfInitializedData;' & _        ;// Размер инициализированных данных раздела, в байтах, или сумма всех таких участков, если есть несколько разделов инициализируется данными.
	'dword SizeOfUninitializedData;' & _      ;// Размер неинициализированных данных раздела, в байтах, или сумма всех таких участков, если есть несколько неинициализированных данных разделов.
	'dword AddressOfEntryPoint;' & _          ;// Указатель на точку входа
	'dword BaseOfCode;' & _                   ;// Указатель на начало секции кода
	'dword BaseOfData;' & _                   ;// Указатель на начало секции данных
	'dword ImageBase;' & _                    ;// Предпочтительный адрес первого байта изображения при загрузке в память. Это значение является кратной 64 байт. Значение по умолчанию для библиотек DLL 0x10000000. Значение по умолчанию для приложений 0x00400000, за исключением Windows CE, где 0x00010000.
	'dword SectionAlignment;' & _             ;// Выравнивание разделов загруженых в память, в байтах (Должно быть больше или равна FileAlignment)
	'dword FileAlignment;' & _                ;// Согласование исходных данных разделов в файл изображения в байтах.
	'ushort MajorOperatingSystemVersion;' & _ ;// Основной номер версии необходимых операционной системы.
	'ushort MinorOperatingSystemVersion;' & _ ;// Дополнительный номер версии необходимых операционной системы.
	'ushort MajorImageVersion;' & _           ;// Основной номер версии изображения.
	'ushort MinorImageVersion;' & _           ;// Младший номер версии изображения.
	'ushort MajorSubsystemVersion;' & _       ;// Основной номер версии подсистемы.
	'ushort MinorSubsystemVersion;' & _       ;// Дополнительный номер версии подсистемы.
	'dword Win32VersionValue;' & _            ;// Зарезервирован и и должен быть 0.
	'dword SizeOfImage;' & _                  ;// Размер изображения в байтах, включая все заголовки. Должна быть кратна SectionAlignment.
	'dword SizeOfHeaders;' & _                ;// Общий размер из пунктов, округляется до кратного значения, указанного в FileAlignment
	'dword CheckSum;' & _                     ;// Контрольная сумма файла изображения.
	'ushort Subsystem;' & _                   ;// Подсистемы, необходимые для запуска этого образа.
	'ushort DllCharacteristics;' & _          ;// DLL характеристики изображения.
	'dword SizeOfStackReserve;' & _           ;// Количество байт, резерв для стека.
	'dword SizeOfStackCommit;' & _            ;// Количество байт для совершения в стеке.
	'dword SizeOfHeapReserve;' & _            ;// Количество байт, резерв для локальной массы
	'dword SizeOfHeapCommit;' & _             ;// Количество байт для совершения в локальной массе
	'dword LoaderFlags;' & _                  ;// Этот элемент является устаревшим.
	'dword NumberOfRvaAndSizes;' & _          ;// Количество каталогов в оставшейся части дополнительного заголовка. Каждая запись описывает расположение и размер.
	'byte byteData[128]'                      ;// Unknown	
	
Global Const $tagIMAGE_SECTION_HEADER = '' & _
	'byte Name[8];' & _                       ;// Имя секции
	'dword Misc;' & _                         ;// Виртуальный размер
	'dword VirtualAddress;' & _               ;// Виртуальный адресс
	'dword SizeOfRawData;' & _                ;// Размер RAW данных
	'dword PointerToRawData;' & _             ;// Указатель на RAW данные
	'dword PointerToRelocations;' & _         ;// Указатель на релокейшены
	'dword PointerToLinenumbers;' & _         ;// Указатель на номера строк
	'ushort NumberOfRelocations;' & _         ;// Колличество релокейшенов
	'ushort NumberOfLinenumbers;' & _         ;// Колличество номеров строк
	'dword Characteristics'                   ;// Характеристики	
#EndRegion Executable File Structure

#Region (Icon Resource) Structure
Global Const $tagRESOURCEICON = '' & _
    'ushort;' & _
	'ushort Type;' & _
	'ushort ImageCount;'

Global Const $tagINPUTICONHEADER = '' & _
    'ubyte Width;' & _
	'ubyte Height;' & _
	'ubyte Colors;' & _
	'ubyte;' & _
	'ushort Planes;' & _
	'ushort BitPerPixel;' & _
	'dword BitmapSize;' & _
	'dword BitmapOffset;'

Global Const $tagGROUPICONDATA = '' & _
    'ubyte Width;' & _
	'ubyte Height;' & _
	'ubyte Colors;' & _
	'ubyte;' & _
	'ushort Planes;' & _
	'ushort BitPerPixel;' & _
	'dword BitmapSize;' & _
	'ushort OrdinalName;'
#EndRegion (Icon Resource) Structure
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Иконки в ресурсах представлены так же, как и в .ico файлах. Структура .ico файла достаточно подробно описана здесь (читать нужно очень внимательно). Для того, чтобы создать иконку из картинки, например .png, нужно сначала создать битмап (DIB), см. здесь, и маску, см. _WinAPI_CreateANDBitmap(). Далее сформировать из этого блок данных с общим заголовком (BITMAPINFOHEADER), так же, как это делается в .ico файле.

А еще лучше использовать PNG компрессию для больших (256x256 и выше) иконок. PNG компрессия, это просто файл PNG без всяких заголовков.
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Спасибо Yashied, посмотрю.


Добавлено:
Сообщение автоматически объединено:

Вот нашёл пример как преобразовать любую картинку в *.ico, но не пойму как получить в памяти данные уже преобразованной картинки в *.ico в виде DllStructCreate('byte[' & $iSize & ']')

Код:
#Include <GDIPlus.au3>
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global Const $sPng = @ScriptDir & '\1.bmp'

Global Const $STM_SETIMAGE = 0x0172

Global $hForm, $Pic[2], $hBitmap[2], $hPng, $hIcon, $Width, $Height, $Path

; Create 32 bits-per-pixel bitmap from a PNG image
_GDIPlus_Startup()
$hPng = _GDIPlus_ImageLoadFromFile($sPng)
$hBitmap[0] = _GDIPlus_BitmapCreateDIBFromBitmap($hPng)
$Width = _GDIPlus_ImageGetWidth($hPng)
$Height = _GDIPlus_ImageGetHeight($hPng)
_GDIPlus_ImageDispose($hPng)
_GDIPlus_Shutdown()

; Create 1 bits-per-pixel AND bitmask bitmap
$hBitmap[1] = _WinAPI_CreateANDBitmap($hBitmap[0])

; Create GUI
$hForm = GUICreate('MyGUI', 200, 200)
$Pic[0] = GUICtrlCreatePic('', 0, 0, $Width, $Height)
$Pic[1] = GUICtrlCreatePic('', $Width, 0, $Width, $Height)

; Set both bitmaps to controls
For $i = 0 To 1
	GUICtrlSendMsg($Pic[$i], $STM_SETIMAGE, 0, $hBitmap[$i])
Next

; Show GUI
GUISetState()

; Create and save icon to .ico file
$Path = FileSaveDialog('Save Icon', @ScriptDir, 'Icon Files (*.ico)', 2 + 16, _WinAPI_PathStripPath(_WinAPI_PathRenameExtension($sPng, '.ico')), $hForm)
If $Path Then
	$hIcon = _WinAPI_CreateIconIndirect($hBitmap[0], $hBitmap[1])
	If Not @error Then
		_WinAPI_SaveHICONToFile($Path, $hIcon)
		_WinAPI_DestroyIcon($hIcon)
	EndIf
EndIf

Do
Until GUIGetMsg() = -3

; Unlike _GDIPlus_BitmapCreateHBITMAPFromBitmap() that creates a device-dependent bitmap (DDB), this function creates a device-independent bitmap (DIB) which may be used for semi-transparent images

Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)

	Local $hDIB = 0, $aSize, $tData, $pBits

	$aSize = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)
	If (@error) Or ($aSize[0]) Then
		Return 0
	EndIf
	$tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $aSize[2], $aSize[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	$pBits = DllStructGetData($tData, 'Scan0')
	If Not $pBits Then
		Return 0
	EndIf
	$hDIB = _WinAPI_CreateDIB($aSize[2], $aSize[3])
	If Not @error Then
		_WinAPI_SetBitmapBits($hDIB, $aSize[2] * $aSize[3] * 4, $pBits)
	EndIf
	_GDIPlus_BitmapUnlockBits($hBitmap, $tData)
	Return $hDIB
EndFunc   ;==>_GDIPlus_BitmapCreateDIBFromBitmap
 

Yashied

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

HBITMAP => HICON => HBITMAP => .ico

Viktor1703 сказал(а):
...но не пойму как получить в памяти данные уже преобразованной картинки в *.ico в виде DllStructCreate('byte[' & $iSize & ']')

И не найдешь, т.к. все это проделывает _WinAPI_SaveHICONToFile(), а она сильно оптимизирована и малопонятна для разбора... Лучше делай так, как я написал выше.
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Не, не пойму как это реализовать :-X
 
Верх