Sign in to follow this  
Followers 0
Terenz

[SOLVED] Double click multiple tray icon

3 posts in this topic

#1 ·  Posted (edited)

The code:

; orginal code by johnmcloud
HotKeySet("{ESC}", "_Exit")

Opt("TrayMenuMode", 3)

OnAutoItExitRegister('OnAutoItExit')
TraySetIcon("Shell32.dll", 4)
TraySetToolTip("ToolTip_Main")

Global $aTray[11], $iTray = 2

Global $hWnd = WinGetHandle(AutoItWinGetTitle())
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;'
Global $tNOTIFYICONDATA = DllStructCreate($tagNOTIFYICONDATA)
Global Const $NIF_ICON = 0x00000002
Global Const $NIM_ADD = 0x00000000
Global Const $NIM_DELETE = 0x00000002
Global Const $NIM_MODIFY = 0x00000001
Global Const $NIF_TIP = 0x00000004
DllStructSetData($tNOTIFYICONDATA, 'Size', DllStructGetSize($tNOTIFYICONDATA))
DllStructSetData($tNOTIFYICONDATA, 'hWnd', WinGetHandle(AutoItWinGetTitle()))
DllStructSetData($tNOTIFYICONDATA, 'Flags', $NIF_ICON)

_AddIcon(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 166, 16, 16), "ToolTip_2")
_AddIcon(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 130, 16, 16), "ToolTip_3")
_AddIcon(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 125, 16, 16), "ToolTip_4")

Func _AddIcon($hIcon, $sTooltip)
    If $iTray >= UBound($aTray) Then ReDim $aTray[UBound($aTray) + 11]
    $aTray[$iTray] = 1
    ;Icon
    DllStructSetData($tNOTIFYICONDATA, 'ID', $iTray)
    DllStructSetData($tNOTIFYICONDATA, 'hIcon', $hIcon)
    _WinAPI_ShellNotifyIcon($NIM_ADD, $tNOTIFYICONDATA)
    ;Tooltip
    $NID = DllStructCreate($tagNOTIFYICONDATA)
    DllStructSetData($NID, "Size", DllStructGetSize($NID))
    DllStructSetData($NID, "hWnd", $hWnd)
    DllStructSetData($NID, "ID", $iTray)
    DllStructSetData($NID, "Flags", $NIF_TIP)
    DllStructSetData($NID, "Tip", $sTooltip)
    _WinAPI_ShellNotifyIcon($NIM_MODIFY, $NID)
    $iTray += 1
EndFunc   ;==>_AddIcon

While 1
    $tMsg = TrayGetMsg()
    Switch $tMsg
        Case -13 ; is $TRAY_EVENT_PRIMARYDOUBLE, sorry for the magic number is just a test
            ConsoleWrite(1 & @CRLF)
    EndSwitch
WEnd

Func OnAutoItExit()
    For $i = 0 To UBound($aTray)
        If $aTray[$i] = 1 Then
            _DeleteIcon($i)
        EndIf
    Next
EndFunc   ;==>OnAutoItExit

Func _DeleteIcon($iID)
    DllStructSetData($tNOTIFYICONDATA, 'ID', $iID)
    _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNOTIFYICONDATA)
EndFunc   ;==>_DeleteIcon

Func _Exit()
    Exit
EndFunc

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

Func _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
    Local $Ret = DllCall('shell32.dll', 'int', 'SHExtractIconsW', 'wstr', $sIcon, 'int', $iIndex, 'int', $iWidth, 'int', $iHeight, 'ptr*', 0, 'ptr*', 0, 'int', 1, 'int', 0)
    If (@error) Or (Not $Ret[0]) Or (Not $Ret[5]) Then
        Return SetError(1, 0, 0)
    EndIf
    Return $Ret[5]
EndFunc   ;==>_WinAPI_ShellExtractIcon

I'd like to know how to detect the $TRAY_EVENT_PRIMARYDOUBLE also for the new icon and from what ID. There is another thread about create icons but is too old so was suggested to create a new one. Thanks

Edited by Terenz

Nothing is so strong as gentleness. Nothing is so gentle as real strength

 

Share this post


Link to post
Share on other sites



Guys i need an help with this :(

Reading here,  Shell Notify Icon,  seems need a callback for get the doubleclick. I have added it and...not work. Or better work for the native autoit tray icon but not for the new once, incredible. And that is only the first part, i need also to understand from what icon is clicked! Without help i can't do it by myself

; orginal code by johnmcloud
HotKeySet("{ESC}", "_Exit")

Opt("TrayMenuMode", 3)

OnAutoItExitRegister('OnAutoItExit')
TraySetIcon("Shell32.dll", 4)
TraySetToolTip("ToolTip_Main")

Global $aTray[11], $iTray = 2

Global $hWnd = WinGetHandle(AutoItWinGetTitle())
Global Const $TRAY_CALLBACK = 0x400 + 1 ; $WM_USER
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;'
Global $tNOTIFYICONDATA = DllStructCreate($tagNOTIFYICONDATA)
Global Const $NIF_ICON = 0x00000002
Global Const $NIM_ADD = 0x00000000
Global Const $NIM_DELETE = 0x00000002
Global Const $NIM_MODIFY = 0x00000001
Global Const $NIF_TIP = 0x00000004
DllStructSetData($tNOTIFYICONDATA, 'Size', DllStructGetSize($tNOTIFYICONDATA))
DllStructSetData($tNOTIFYICONDATA, 'hWnd', $hWnd)
DllStructSetData($tNOTIFYICONDATA, 'Flags', $NIF_ICON)

Global $hProcNew = DllCallbackRegister("_TrayProc", "int", "hwnd;uint;wparam;lparam")
Global $hProcOld = _WinAPI_SetWindowLong($hWnd, 0xFFFFFFFC, DllCallbackGetPtr($hProcNew)) ; $GWL_WNDPROC

_AddIcon(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 166, 16, 16), "ToolTip_2")
_AddIcon(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 130, 16, 16), "ToolTip_3")
_AddIcon(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 125, 16, 16), "ToolTip_4")

Func _AddIcon($hIcon, $sTooltip)
    If $iTray >= UBound($aTray) Then ReDim $aTray[UBound($aTray) + 11]
    $aTray[$iTray] = 1
    ;Icon
    DllStructSetData($tNOTIFYICONDATA, 'ID', $iTray)
    DllStructSetData($tNOTIFYICONDATA, 'hIcon', $hIcon)
    _WinAPI_ShellNotifyIcon($NIM_ADD, $tNOTIFYICONDATA)
    ;Tooltip
    $NID = DllStructCreate($tagNOTIFYICONDATA)
    DllStructSetData($NID, "Size", DllStructGetSize($NID))
    DllStructSetData($NID, "hWnd", $hWnd)
    DllStructSetData($NID, "ID", $iTray)
    DllStructSetData($NID, "Flags", $NIF_TIP)
    DllStructSetData($NID, "Tip", $sTooltip)
    _WinAPI_ShellNotifyIcon($NIM_MODIFY, $NID)
    $iTray += 1
EndFunc   ;==>_AddIcon

While 1
    $tMsg = TrayGetMsg()
    Switch $tMsg
        Case -13 ; is $TRAY_EVENT_PRIMARYDOUBLE, sorry for the magic number is just a test
            ConsoleWrite("From TrayGetMsg" & @CRLF)
    EndSwitch
WEnd

Func OnAutoItExit()
    For $i = 0 To UBound($aTray) - 1
        If $aTray[$i] = 1 Then
            _DeleteIcon($i)
        EndIf
    Next
    If $hProcOld > 0 Then _WinAPI_SetWindowLong($hWnd, 0xFFFFFFFC, $hProcOld) ; $GWL_WNDPROC
    If $hProcNew > 0 Then DllCallbackFree($hProcNew)
EndFunc   ;==>OnAutoItExit

Func _DeleteIcon($iID)
    DllStructSetData($tNOTIFYICONDATA, 'ID', $iID)
    _WinAPI_ShellNotifyIcon($NIM_DELETE, $tNOTIFYICONDATA)
EndFunc   ;==>_DeleteIcon

Func _TrayProc($hWnd, $iMsg, $wParam, $lParam)
    ;#forceref $hWnd, $iMsg, $wParam, $lParam
    Switch $iMsg
        Case $TRAY_CALLBACK
            Switch $lParam
                Case 0x0203 ; $WM_LBUTTONDBLCLK
                    ConsoleWrite("From $TRAY_CALLBACK" & @CRLF)
            EndSwitch
    EndSwitch
    Local $aResult = DllCall("user32.dll", "lresult", "CallWindowProcW", "ptr", $hProcOld, "hwnd", $hWnd, "uint", $Msg, "wparam", $wParam, "lparam", $lParam)
    If @error Then Return -1
    Return $aResult[0]
EndFunc   ;==>_TrayProc

Func _Exit()
    Exit
EndFunc

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

Func _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
    Local $Ret = DllCall('shell32.dll', 'int', 'SHExtractIconsW', 'wstr', $sIcon, 'int', $iIndex, 'int', $iWidth, 'int', $iHeight, 'ptr*', 0, 'ptr*', 0, 'int', 1, 'int', 0)
    If (@error) Or (Not $Ret[0]) Or (Not $Ret[5]) Then
        Return SetError(1, 0, 0)
    EndIf
    Return $Ret[5]
EndFunc   ;==>_WinAPI_ShellExtractIcon

Func _WinAPI_SetWindowLong($hWnd, $iIndex, $iValue)
    _WinAPI_SetLastError(0) ; as suggested in MSDN
    Local $sFuncName = "SetWindowLongW"
    If @AutoItX64 Then $sFuncName = "SetWindowLongPtrW"
    Local $aResult = DllCall("user32.dll", "long_ptr", $sFuncName, "hwnd", $hWnd, "int", $iIndex, "long_ptr", $iValue)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_SetWindowLong

Func _WinAPI_SetLastError($iErrCode, $curErr = @error, $curExt = @extended)
    DllCall("kernel32.dll", "none", "SetLastError", "dword", $iErrCode)
    Return SetError($curErr, $curExt)
EndFunc   ;==>_WinAPI_SetLastError

 


Nothing is so strong as gentleness. Nothing is so gentle as real strength

 

Share this post


Link to post
Share on other sites

Solved! The problem was a missing parameter in DllStructSetData of $tNOTIFYICONDATA, "CallbackMessage". After added that you don't need all that stuff of DllCallbackRegister, _WinAPI_SetWindowLong and so on but just a function for intercept the message. Thanks anyway

1 person likes this

Nothing is so strong as gentleness. Nothing is so gentle as real strength

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0