#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <Constants.au3>
#include <WinAPI.au3>

; -Author: name22 (www.autoit.de)

;Auszug aus WinAPIEx.au3:
Global Const $NIM_ADD = 0x00
Global Const $NIM_MODIFY = 0x01
Global Const $NIM_DELETE = 0x02
Global Const $NIM_SETFOCUS = 0x03
Global Const $NIM_SETVERSION = 0x04

Global Const $NIF_MESSAGE = 0x01
Global Const $NIF_ICON = 0x02
Global Const $NIF_TIP = 0x04
Global Const $NIF_STATE = 0x08
Global Const $NIF_INFO = 0x10
Global Const $NIF_GUID = 0x20
Global Const $NIF_REALTIME = 0x40
Global Const $NIF_SHOWTIP = 0x80

Global Const $NIS_HIDDEN = 0x01
Global Const $NIS_SHAREDICON = 0x02

Global Const $NIIF_NONE = 0x00
Global Const $NIIF_INFO = 0x01
Global Const $NIIF_WARNING = 0x02
Global Const $NIIF_ERROR = 0x03
Global Const $NIIF_USER = 0x04
Global Const $NIIF_NOSOUND = 0x10
Global Const $NIIF_LARGE_ICON = 0x10
Global Const $NIIF_RESPECT_QUIET_TIME = 0x80
Global Const $NIIF_ICON_MASK = 0x0F

Global Const $tagNOTIFYICONDATA = 'dword Size;hwnd hWnd;uint ID;uint Flags;uint CallbackMessage;ptr hIcon;wchar Tip[128];dword State;dword StateMask;wchar Info[256];uint Version;wchar InfoTitle[64];dword InfoFlags;' ;aus WinAPIEx.au3
Global Const $tagNOTIFYICONIDENTIFIER = "DWORD cbSize;HWND hWnd;UINT uID;BYTE guidItem[16]" ;Struktur um ein TrayIcon eindeutig zu identifizieren (http://msdn.microsoft.com/en-us/library/dd391553%28v=vs.85%29.aspx)
Global Const $WM_NOTIFYICONCALLBACK = _WinAPI_RegisterWindowMessage("WM_NOTIFYICONCALLBACK") ;Registriert eine WM mit dem angegebenen String die garantiert noch frei ist.

Global $hIcon, $hGUI, $cLabel_Pos, $tIconData, $tIconData_Delete, $tIconIdentifier
Global $iNotifyIconID = 1 ;Beliebige ID für das neue TrayIcon (darf noch nicht in Benutzung sein)

GUIRegisterMsg($WM_NOTIFYICONCALLBACK, "_IconCallback") ;Registriert den MessageHandler über unsere eigene WM

$hIcon = _WinAPI_ExtractIcon(@AutoItExe, 0, True) ;Lädt das AutoIt Icon aus der AutoIt3.exe

$hGUI = GUICreate("IconParent", 200, 100) ;Ein Fenster muss vorhanden sein um TrayIcon zu registrieren.
$cLabel_Pos = GUICtrlCreateLabel("", 5, 5, 190, 25)
GUISetState()

$tIconData = DllStructCreate($tagNOTIFYICONDATA) ;Enthält alle Daten um TrayIcons zu erstellen/modifizieren/löschen (http://msdn.microsoft.com/en-us/library/bb773352%28v=vs.85%29.aspx)
DllStructSetData($tIconData, "Size", DllStructGetSize($tIconData))
DllStructSetData($tIconData, "hWnd", $hGUI)
DllStructSetData($tIconData, "ID", $iNotifyIconID)
DllStructSetData($tIconData, "Flags", BitOR($NIF_ICON, $NIF_MESSAGE)) ;Flags um Icon zu setzen und eine CallbackMessage zu registrieren
DllStructSetData($tIconData, "CallbackMessage", $WM_NOTIFYICONCALLBACK)
DllStructSetData($tIconData, "hIcon", $hIcon) ;Iconhandle für das Icon des TrayItems

$tIconIdentifier = DllStructCreate($tagNOTIFYICONIDENTIFIER)
DllStructSetData($tIconIdentifier, "cbSize", DllStructGetSize($tIconIdentifier))
DllStructSetData($tIconIdentifier, "hWnd", $hGUI)
DllStructSetData($tIconIdentifier, "uID", $iNotifyIconID)
DllStructSetData($tIconIdentifier, "guidItem", 0)

_WinAPI_ShellNotifyIcon($NIM_ADD, $tIconData) ;Erstellt unser TrayIcon

AdlibRegister("_GetPosition", 500)

While True
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			;Struktur mit Daten um TrayIcon zu löschen
			$tIconData_Delete = DllStructCreate($tagNOTIFYICONDATA)
			DllStructSetData($tIconData_Delete, "Size", DllStructGetSize($tIconData))
			DllStructSetData($tIconData, "hWnd", $hGUI)
			DllStructSetData($tIconData, "ID", $iNotifyIconID)

			_WinAPI_ShellNotifyIcon($NIM_DELETE, $tIconData_Delete) ;Löscht unser TrayIcon
			_WinAPI_DestroyIcon($hIcon) ;Icon aus RAM entfernen
			Exit
	EndSwitch
WEnd

Func _IconCallback($hWnd, $iMsg, $wParam, $lParam) ;Callback Funktion
	ConsoleWrite($iMsg & @TAB & $lParam & @CRLF)
EndFunc

Func _GetPosition()
	$tRect = DllStructCreate($tagRECT) ;Rect Struktur die Position erhalten wird
	_Shell_NotifyIconGetRect(DllStructGetPtr($tIconIdentifier), DllStructGetPtr($tRect)) ;Identifier identifiziert das TrayIcon, Rect empfängt die Positionsdaten
	GUICtrlSetData($cLabel_Pos, "X: " & DllStructGetData($tRect, "left") & @TAB & @TAB & "Y: " & DllStructGetData($tRect, "top"))
EndFunc


Func _Shell_NotifyIconGetRect($pIdentifier, $pRect)
	;Liest die Postition eines TrayIcons aus und schreibt sie in eine RECT Struktur (http://msdn.microsoft.com/en-us/library/dd378426%28v=vs.85%29.aspx)
	;Rückgabewert: Bei Erfolg = 0, sonst HRESULT Error Code (http://blogs.msdn.com/b/eldar/archive/2007/04/03/a-lot-of-hresult-codes.aspx)
	; -Author: name22 (www.autoit.de)

	$aRet = DllCall("shell32.dll", "LONG", "Shell_NotifyIconGetRect", "PTR", $pIdentifier, "PTR", $pRect)
	Return $aRet[0]
EndFunc


; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_ShellNotifyIcon
; Description....: Sends a message to the taskbar's status area.
; Syntax.........: _WinAPI_ShellNotifyIcon ( $iMessage, $tNOTIFYICONDATA )
; Parameters.....: $iMessage        - The variable that specifies the action to be taken. It can have one of the following values.
;
;                                     $NIM_ADD
;                                     $NIM_MODIFY
;                                     $NIM_DELETE
;                                     $NIM_SETFOCUS
;                                     $NIM_SETVERSION
;
;                  $tNOTIFYICONDATA - $tagNOTIFYICONDATA structure. The content and size of this structure depends on the value
;                                     of the $iMessage and version of the operating system.
; Return values..: Success          - 1.
;                  Failure          - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: None
; Related........:
; Link...........: @@MsdnLink@@ Shell_NotifyIcon
; Example........: Yes
; ===============================================================================================================================

Func _WinAPI_ShellNotifyIcon($iMessage, $tNOTIFYICONDATA)

	Local $Ret = DllCall('shell32.dll', 'int', 'Shell_NotifyIconW', 'dword', $iMessage, 'ptr', DllStructGetPtr($tNOTIFYICONDATA))

	If (@error) Or (Not $Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	Return 1
EndFunc   ;==>_WinAPI_ShellNotifyIcon


; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_ExtractIcon
; Description....: Extracts an icon from the specified executable file, DLL, or icon file.
; Syntax.........: _WinAPI_ExtractIcon ( $sIcon, $iIndex [, $fSmall] )
; Parameters.....: $sIcon  - The name of an executable file, DLL, or icon file from which icons will be extracted.
;                  $iIndex - The zero-based index of the icon to extract. If this value is a negative number, the function extracts
;                            the icon whose resource identifier is equal to the absolute value of $iIndex.
;                  $fSmall - Specifies whether extract a small icon, valid values:
;                  |TRUE   - Extract a small icon.
;                  |FALSE  - Extract a large icon. (Default)
; Return values..: Success - Handle to the extracted icon.
;                  Failure - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: When you are finished using the icon, destroy it using the _WinAPI_DestroyIcon() function.
; Related........:
; Link...........: @@MsdnLink@@ ExtractIconEx
; Example........: Yes
; ===============================================================================================================================

Func _WinAPI_ExtractIcon($sIcon, $iIndex, $fSmall = 0)

	Local $pLarge, $pSmall, $tPtr = DllStructCreate('ptr')

	If $fSmall Then
		$pLarge = 0
		$pSmall = DllStructGetPtr($tPtr)
	Else
		$pLarge = DllStructGetPtr($tPtr)
		$pSmall = 0
	Endif

	Local $Ret = DllCall('shell32.dll', 'uint', 'ExtractIconExW', 'wstr', $sIcon, 'int', $iIndex, 'ptr', $pLarge, 'ptr', $pSmall, 'uint', 1)

	If (@error) Or (Not $Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	Return DllStructGetData($tPtr, 1)
EndFunc   ;==>_WinAPI_ExtractIcon
