Что нового

как сохранить иконки из Listview или ImageList в файл

damien2008

Осваивающий
Сообщения
178
Репутация
34
добрый день, подскажите, пожалуйста, как можно сохранить иконки первого столбика из Listview или ImageList в файл.
я так понимаю нужно получить индекс иконки с помощью
Код:
_GUICtrlListView_GetItemImage

а как указатель потом использовать?

вот пример создания списка, с англ. форума:
Код:
;coded by rover 2k11
#NoTrayIcon
#include <WinAPIEx.au3>
#include <WinAPI.au3>
#include <Process.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>
#include <Constants.au3>
#include <APIConstants.au3>
#include <WindowsConstants.au3>
#include <ToolBarConstants.au3>
#include <ProcessConstants.au3>
#include <MemoryConstants.au3>

Opt("MustDeclareVars", 1)

Global Const $PROCESS_ACCESS = BitOR($PROCESS_VM_OPERATION, $PROCESS_VM_READ)
Global $iTbar = 0
Global $hOwnerWin, $hTrayWnd, $hTrayNotifyWnd, $hSysPager, $hToolbar, _
		$iDLLUser32 = DllOpen("user32.dll"), $iDLLKrnl32 = DllOpen("kernel32.dll"), _
		$tTBBUTTON, $pTBBUTTON, $iTBBUTTON, $tTRAYDATA, $pTRAYDATA, $iTRAYDATA, _
		$iImg = 0, $iIdx = 0, $iCount, $iPIDExp, $hProcess, $pAddress, $iPID, $aRet, $sRet, $hIconTray, $hIcon
$hTrayWnd = WinGetHandle("[CLASS:Shell_TrayWnd]")
$hTrayNotifyWnd = ControlGetHandle($hTrayWnd, "", "[CLASS:TrayNotifyWnd]")
$hSysPager = ControlGetHandle($hTrayNotifyWnd, "", "[CLASS:SysPager]")
$hToolbar = ControlGetHandle($hSysPager, "", "[CLASS:ToolbarWindow32; INSTANCE:1]");User Promoted Notification Area/Notification Area/SysTray

Switch @OSVersion
	Case "WIN_2008R2", "WIN_7"
		Switch $iTbar
			Case 1 ;Overflow Notification Area
				$hToolbar = ControlGetHandle(WinGetHandle("[CLASS:NotifyIconOverflowWindow]"), "", "[CLASS:ToolbarWindow32; INSTANCE:1]")
			Case 2 ;System Promoted Notification Area
				$hToolbar = ControlGetHandle($hTrayNotifyWnd, "", "[CLASS:ToolbarWindow32; INSTANCE:2]")
		EndSwitch
EndSwitch

$tTBBUTTON = DllStructCreate("int Bitmap;int Command;byte State;byte Style;align;dword_ptr Param;int_ptr String")
$pTBBUTTON = DllStructGetPtr($tTBBUTTON)
$iTBBUTTON = DllStructGetSize($tTBBUTTON)
$tTRAYDATA = DllStructCreate("hwnd hwnd;uint uID;uint uCallbackMessage;dword Reserved[2];ptr hIcon")
$pTRAYDATA = DllStructGetPtr($tTRAYDATA)
$iTRAYDATA = DllStructGetSize($tTRAYDATA)
$iPIDExp = WinGetProcess($hToolbar)
If @error Or $iPIDExp = -1 Then Exit
$aRet = DllCall($iDLLKrnl32, "ptr", "OpenProcess", "dword", _
		$PROCESS_ACCESS, "int", 0, "int", $iPIDExp)
If @error Or $aRet[0] = 0 Then Exit
$hProcess = $aRet[0]
$aRet = DllCall($iDLLUser32, "lparam", "SendMessageW", "hwnd", _
		$hToolbar, "int", $TB_BUTTONCOUNT, "wparam", 0, "lparam", 0)
If @error Or $aRet[0] < 1 Then
	DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProcess)
	Exit
EndIf
$iCount = $aRet[0] - 1
$aRet = DllCall($iDLLKrnl32, "ptr", "VirtualAllocEx", "ptr", $hProcess, "ptr", 0, "ulong_ptr", _
		$iTBBUTTON, "dword", BitOR($MEM_RESERVE, $MEM_COMMIT), "dword", $PAGE_READWRITE)
If @error Or $aRet[0] = 0 Then
	DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProcess)
	Exit
EndIf
$pAddress = $aRet[0]

GUICreate("Notification Icons", 600, 600)
GUISetBkColor(0x494949)
Global $hListView = GUICtrlCreateListView("", 2, 2, 596, 596)
_GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES))
Global $hImage = _GUIImageList_Create(16, 16, 5, 5)
_GUICtrlListView_SetImageList($hListView, $hImage, 1)
_GUICtrlListView_AddColumn($hListView, "Tray", 38)
_GUICtrlListView_AddColumn($hListView, "Proc", 38)
_GUICtrlListView_AddColumn($hListView, "Process", 138)
_GUICtrlListView_AddColumn($hListView, "Module", 138)
_GUICtrlListView_SetColumnWidth($hListView, 3, $LVSCW_AUTOSIZE_USEHEADER)
GUISetState()

For $iID = 0 To $iCount
	If IsHWnd($hToolbar) = False Then ExitLoop
	$aRet = DllCall($iDLLUser32, "lparam", "SendMessageW", "hwnd", $hToolbar, _
			"int", $TB_GETBUTTON, "wparam", $iID, "lparam", $pAddress)
	If @error Or $aRet[0] <> 1 Then ContinueLoop
	$aRet = DllCall($iDLLKrnl32, "int", "ReadProcessMemory", "ptr", $hProcess, _
			"ptr", $pAddress, "ptr", $pTBBUTTON, "ulong_ptr", $iTBBUTTON, "ulong_ptr*", -1)
	If @error Or $aRet[5] <> $iTBBUTTON Then ContinueLoop
	;If BitAND(DllStructGetData($tTBBUTTON, "State"), $TBSTATE_HIDDEN) = $TBSTATE_HIDDEN Then ContinueLoop
	$aRet = DllCall($iDLLKrnl32, "int", "ReadProcessMemory", "ptr", $hProcess, _
			"dword_ptr", DllStructGetData($tTBBUTTON, "Param"), "ptr", $pTRAYDATA, "ulong_ptr", $iTRAYDATA, "ulong_ptr*", -1)
	If @error Or $aRet[5] <> $iTRAYDATA Then ContinueLoop
	$hOwnerWin = DllStructGetData($tTRAYDATA, 1)
	If @error Or $hOwnerWin = 0 Then ContinueLoop
	$iPID = WinGetProcess($hOwnerWin)
	If @error Or $iPID = -1 Then ContinueLoop
	$hIconTray = DllStructGetData($tTRAYDATA, 5) ;returned icon handles shared
	$sRet = ""
	If Not _IsIconHandle($hIconTray, $sRet) Then
		;ConsoleWrite('!VarGetType($hIconTray) = ' & VarGetType($hIconTray) & @CRLF)
		If IsPtr($hIconTray) Then $hIconTray = _WinAPI_Create32BitHICON($hIconTray)
		;some icons like HDDLife's temp icons return an invalid icon handle, and won't display, but will when formatted by _WinAPI_Create32BitHICON
		If Not _IsIconHandle($hIconTray, $sRet) Then
			$hIconTray = _GetTrayIconHandle($hOwnerWin)
			ConsoleWrite("- Invalid Icon handle: OwnerWin: " & _WinAPI_GetClassName($hOwnerWin) & "  Process Name: " & _ProcessGetName($iPID) & @CRLF)
		EndIf
	EndIf
	;$hIconTray = _WinAPI_CopyImage($hIconTray, $IMAGE_ICON, 16, 16)
	_GUIImageList_ReplaceIcon($hImage, -1, $hIconTray)
	$hIcon = _WinAPI_ShellExtractAssociatedIcon(_WinAPI_GetProcessFileName($iPID), 1)
	$iImg = _GUIImageList_ReplaceIcon($hImage, -1, $hIcon)
	_GUICtrlListView_InsertItem($hListView, "", -1, $iImg - 1)
	_GUICtrlListView_AddSubItem($hListView, $iIdx, "", 1, $iImg)
	_GUICtrlListView_AddSubItem($hListView, $iIdx, _ProcessGetName($iPID), 2)
	If $sRet = "" Then $sRet = _WinAPI_GetProcessFileName($iPID)
	_GUICtrlListView_AddSubItem($hListView, $iIdx, $sRet, 3)
	ConsoleWrite($sRet & @CRLF)
	$iIdx += 1
	;ToolTip(_WinAPI_GetClassName($hOwnerWin), 1030, 850, $sRet, $hIconTray, 5)
	;Sleep(500)
	_WinAPI_DestroyIcon($hIcon)
	_WinAPI_DestroyIcon($hIconTray) ;does not destroy traydata handles
Next

DllCall($iDLLKrnl32, "int", "VirtualFreeEx", "ptr", $hProcess, "ptr", $pAddress, "ulong_ptr", 0, "dword", $MEM_RELEASE)
DllCall($iDLLKrnl32, "int", "CloseHandle", "ptr", $hProcess)
DllClose($iDLLUser32)
DllClose($iDLLKrnl32)
ToolTip("")

While GUIGetMsg() <> -3
WEnd
_GUIImageList_Destroy($hImage)
Exit

Func _GetTrayIconHandle($hWnd, $hDLLUser32 = "User32.dll")
	If Not IsHWnd($hWnd) Then Return SetError(1, 1, -1)
	Local $iPID, $ParentPID, $aWinList
	$hIcon = _GetIcon($hWnd, $hDLLUser32)
	If Not @error And $hIcon <> -1 Then Return SetError(0, 0, $hIcon)
	$ParentPID = WinGetProcess($hWnd)
	If @error Or $ParentPID = -1 Then Return SetError(2, 2, -1)
	$aWinList = WinList()
	For $i = 1 To $aWinList[0][0]
		$iPID = WinGetProcess($aWinList[$i][1])
		If @error Or $iPID = -1 Then ContinueLoop
		If $iPID = $ParentPID Then
			$hIcon = _GetIcon($aWinList[$i][1], $hDLLUser32)
			If Not @error And $hIcon <> -1 Then Return SetError(0, 0, $hIcon)
		EndIf
	Next
	Return SetError(2, 2, -1)
EndFunc   ;==>_GetTrayIconHandle

;modified from ModernMenu Win2Tray - by Holger Kotsch
Func _GetIcon(ByRef $hWnd, $hDLLUser32 = "User32.dll")
	If Not IsHWnd($hWnd) Then Return SetError(1, 1, -1)
	Local Const $GCL_HICON = -14
	Local Const $GCL_HICONSM = -34
	Local $hIcon
	$hIcon = _SendMessage($hWnd, $WM_GETICON, 2, 0)
	If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon))
	$hIcon = _SendMessage($hWnd, $WM_GETICON, 0, 0)
	If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon))
	$hIcon = _WinAPI_GetClassLongEx($hWnd, $GCL_HICONSM)
	If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon))
	$hIcon = _WinAPI_GetClassLongEx($hWnd, $GCL_HICON)
	If Not @error And _IsIconHandle($hIcon, $sRet) = True Then Return SetError(0, 0, Ptr($hIcon))
	Return SetError(2, 2, -1)
EndFunc   ;==>_GetIcon

Func _IsIconHandle($hIcon, ByRef $sMod)
	;rover 2k11
	Local $aRet
	Switch @OSVersion
		Case "WIN_2008R2", "WIN_7", "WIN_2008", "WIN_VISTA"
			$aRet = _WinAPI_GetIconInfoEx($hIcon)
			If @error Then Return SetError(1, 1, False)
			DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", $aRet[3])
			DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", $aRet[4])
			If $aRet[0] = 0 Then Return SetError(2, 2, False)
			$sMod = $aRet[6]
			Return SetError(0, 0, True)
		Case "WIN_2003", "WIN_XP"
			Local $tIconInfo = DllStructCreate("int fIcon;int xHotspot;int yHotspot;ptr hbmMask;ptr hbmColor")
			Local $aRet = DllCall("User32.dll", "int", "GetIconInfo", "ptr", $hIcon, "ptr", DllStructGetPtr($tIconInfo))
			If @error Or UBound($aRet) <> 3 Or $aRet[0] = 0 Then Return SetError(1, 1, False)
			DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", DllStructGetData($tIconInfo, 4))
			DllCall("gdi32.dll", "bool", "DeleteObject", "ptr", DllStructGetData($tIconInfo, 5))
			If Not DllStructGetData($tIconInfo, 1) Then Return SetError(2, 2, False)
			Return SetError(0, 0, True)
	EndSwitch
EndFunc   ;==>_IsIconHandle

autoit 3.3.8.1
 
Автор
damien2008

damien2008

Осваивающий
Сообщения
178
Репутация
34
Yashied

сделал вот так:
Код:
_WinAPI_SaveHICONToFile(@ScriptDir & '\MyIcon'&$iID&'.ico', $hIconTray)

после
Код:
$hIconTray = DllStructGetData($tTRAYDATA, 5) ;returned icon handles shared


работает, но все-равно, как сохранять из Listview или ImageList не понял.

не знаю, помечать тему решенной?
50/50
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
ImageList представляет собой обычный bitmap, в котором друг за другом располагаются изображения. Сохранить этот bitmap можно с помощью вышепредставленной функции. Правда не непосредственно в файл, а посредством потока.
 
Верх