Автор Тема: Получение уведомлений от Tray Tip  (Прочитано 4668 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379
  • Репутация: 2693
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
AutoIt: 3.3.6.1
Версия: 1.0

Категория: Окна и диалоги

Описание: Я думаю, что многие из вас хотели бы произвести какие-либо действия (например вызвать диалоговое окно), когда пользователь кликает на Tray Tip. Вот простой способ реализовать это. К сожалению, написать алгоритм без .dll не представляется возможным. Важно, только AutoIt окно может быть зарегистрировано в качестве исходного окна для получения уведомлений (см. пример).

Файл(ы): AITray.zip

Пример:
(нажмите для показа/скрытия)

Скриншот:


Источник: Tray notifications redirector (оффициальный форум)
Автор: Yashied


Думай, прежде чем говорить.

Русское сообщество AutoIt

Получение уведомлений от Tray Tip
« Отправлен: Май 19, 2012, 15:39:52 »

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7806
  • Репутация: 2279
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Получение уведомлений от Tray Tip
« Ответ #1, Отправлен: Май 21, 2012, 03:58:59 »
Yashied  [?]
Цитировать
К сожалению, написать алгоритм без .dll не представляется возможным.
Ну почему, вот первый набросок, грубый, но вроде работает:

Код: AutoIt [Выделить]
#include <Misc.au3>
#include <Array.au3>

Global $hTrayTip_Wnd
Global $iTrayTip_Close = 0
Global $iTrayTip_Click = 0
Global $iTrayTip_Hide = 0

_TrayTipEx('Tip', 'This is a tray tip, click here.', 5, 1)
Sleep(15000)

Func _TrayTipEx($sTitle, $sText, $iTimeOut, $iOptions = 0, $sEventFunc = '_TrayTipEvent')
    Local  $aBefore_WL, $aAfter_WL
   
    $aBefore_WL = _WinListVisible('[CLASS:tooltips_class32]')
    TrayTip($sTitle, $sText, $iTimeOut, $iOptions)
    WinWait('[CLASS:tooltips_class32]')
    $aAfter_WL = _WinListVisible('[CLASS:tooltips_class32]')
   
    For $i = 1 To $aAfter_WL[0][0]
        If _ArraySearch($aBefore_WL, $aAfter_WL[$i][1], 1, 0, 0, 0, 1, 1) = -1 Then
            $hTrayTip_Wnd = $aAfter_WL[$i][1]
            AdlibRegister($sEventFunc, 10)
            Return 1
        EndIf
    Next
   
    Return 0
EndFunc

Func _TrayTipEvent()
    Local $iOld_Opt_MCM = Opt("MouseCoordMode", 1)
    Local $aWinPos = WinGetPos($hTrayTip_Wnd)
    Local $aMousePos = MouseGetPos()
    Local $ahWnd = DllCall("user32.dll", "int", "WindowFromPoint", "long", $aMousePos[0], "long", $aMousePos[1])
    Local $iEvent = 0
   
    Opt("MouseCoordMode", $iOld_Opt_MCM)
   
    If $ahWnd[0] = $hTrayTip_Wnd And _IsPressed(1) Then
        If $aMousePos[0] > ($aWinPos[0]+$aWinPos[2] - 25) And $aMousePos[0] < ($aWinPos[0]+$aWinPos[2] - 10) And $aMousePos[1] < ($aWinPos[1] + 25) And $aMousePos[1] > ($aWinPos[1] + 10) Then
            $iTrayTip_Close = 1
            $iEvent = 1
        Else
            $iTrayTip_Click = 1
            $iEvent = 2
        EndIf
    ElseIf Not $iTrayTip_Close And Not $iTrayTip_Click And Not $iTrayTip_Hide And Not BitAND(WinGetState($hTrayTip_Wnd), 2) Then
        $iTrayTip_Hide = 1
        $iEvent = 3
    EndIf
   
    Switch $iEvent
        Case 1 ;TrayTip close
            ConsoleWrite('TrayTip close' & @LF)
            Exit
        Case 2 ;TrayTip click
            ConsoleWrite('TrayTip click' & @LF)
        Case 3 ;TrayTip hide
            ConsoleWrite('TrayTip hide' & @LF)
    EndSwitch
EndFunc

Func _WinListVisible($sTitle, $sText = '')
    Local $aWinList = WinList($sTitle, $sText)
    Local $aRetList[UBound($aWinList)][2]
   
    For $i = 1 To UBound($aWinList)-1
        If BitAND(WinGetState($aWinList[$i][1]), 2) Then
            $aRetList[0][0] += 1
            $aRetList[$aRetList[0][0]][0] = $aWinList[$i][0]
            $aRetList[$aRetList[0][0]][1] = $aWinList[$i][1]
        EndIf
    Next
   
    ReDim $aRetList[$aRetList[0][0]+1][2]
    Return $aRetList
EndFunc



Правила, Поиск, Супер тема


AutoIt is simple, subtle, elegant.


«Не оказываю тех. поддержку через ПМ/ICQ, и по электронной почте - для этого есть форум. (C)»
«Законы Мэрфи неоспоримы!»


Мои работы

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7806
  • Репутация: 2279
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Re: Получение уведомлений от Tray Tip
« Ответ #2, Отправлен: Май 21, 2012, 04:27:09 »
Нашёл решение на оф. форуме, с использованием subclass (немного изменил для упрощения):

Код: AutoIt [Выделить]
;Author: rover 07/04/09
;MSDN reference:
;Shell_NotifyIcon Function
;http://msdn.microsoft.com/en-us/library/bb762159(VS.85).aspx

#include <Constants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global $hProcNew = 0, $hProcOld = 0

Global Const $NIN_BALLOONSHOW = $WM_USER + 2
Global Const $NIN_BALLOONHIDE = $WM_USER + 3
Global Const $NIN_BALLOONUSERCLICK = $WM_USER + 5
Global Const $NIN_BALLOONTIMEOUT = $WM_USER + 4

TrayTip('Tip', 'This is a tray tip, click here.', 10, 1)

;get handle to AutoIt v3 hidden gui
$hAutoIt = WinGetHandle(AutoItWinGetTitle())
_SubclassWin($hAutoIt, $hProcNew, $hProcOld)

While 1
    Sleep(100)
WEnd

;NOTE: _WinAPI_SetWindowLong() in WinAPI.au3 consistently returns 'The specified procedure could not be found' error 127
;error is due to the call being SetWindowLong instead of SetWindowLongW,
;using SetWindowLongW the error message is 'The operation completed successfully.
Func _SubclassWin($hWnd, ByRef $hProcNew, ByRef $hProcOld)
    If $hProcNew <> 0 Or $hProcOld <> 0 Then Return SetError(1, 0, 0)
   
    $hProcNew = DllCallbackRegister("WM_TRAYNOTIFY", "int", "hwnd;uint;wparam;lparam")
    If @error Or $hProcNew = 0 Then Return SetError(2, 0, 0)
   
    $hProcOld = DllCall("User32.dll", "int", "SetWindowLongW", "hwnd", $hWnd, "int", $GWL_WNDPROC, "ptr", DllCallbackGetPtr($hProcNew))
   
    If @error Or $hProcOld[0] = 0 Then
        $hProcOld = 0
        Return SetError(3, 0, 0)
    EndIf
   
    $hProcOld = $hProcOld[0]
    Return SetError(0, 0, 1)
EndFunc

Func _RestoreWndProc($hWnd, ByRef $hProcNew, ByRef $hProcOld)
    If $hProcOld <> 0 Then _WinAPI_SetWindowLong($hWnd, $GWL_WNDPROC, $hProcOld)
    If $hProcNew <> 0 Then DllCallbackFree($hProcNew)
   
    $hProcNew = 0
    $hProcOld = 0
EndFunc

Func WM_TRAYNOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Switch $iMsg
        Case $WM_USER + 1 ;AutoIt callback message value for tray icon (1025), can be retrieved with ReadProcessMemory and TRAYDATA struct
             Switch $lParam
                Case $NIN_BALLOONSHOW
                    ConsoleWrite('Balloon tip show.' & @CR)
                Case $NIN_BALLOONHIDE
                    ConsoleWrite('Balloon tip hide.' & @CR)
                Case $NIN_BALLOONUSERCLICK
                    ConsoleWrite('Balloon tip click.' & @CR)
                Case $NIN_BALLOONTIMEOUT
                    ConsoleWrite('Balloon tip close/timeout.' & @CR)
                    Exit
            EndSwitch
    EndSwitch
   
    ; pass the unhandled messages to default WindowProc
    Return _WinAPI_CallWindowProc($hProcOld, $hWnd, $iMsg, $wParam, $lParam)
EndFunc

Func OnAutoItExit()
    _RestoreWndProc($hAutoIt, $hProcNew, $hProcOld)
EndFunc


Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2693
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: Получение уведомлений от Tray Tip
« Ответ #3, Отправлен: Май 21, 2012, 10:27:42 »
CreatoR, ты думаешь я не пробывал DllCallbackRegister()?

:)

Сабклассинг окна AutoIt делает скрипт практически неработоспособным, что и наблюдается в твоем примере. Попробуй выйти из программы с первого раза... Если добавить GUI, то количество глюков только увеличится, вплоть до полного зависания скрипта. Это реакция на DllCallbackRegister(), она очень медленная, т.к. не является .dll в полном смысле этого слова. Подобные глюки можно наблюдать, если делать сабклассинг ListView, TreeView и др. элементов GUI, в зависимости от сложности функции обработки.



Добавлено: Май 21, 2012, 10:30:08
По поводу первого примера, я думаю, что ты и сам понимаешь, что это "неправильный" подход.


Добавлено: Май 21, 2012, 10:37:45
Можно обойтись без .dll, если функцию сабклассинга написать в машинных кодах.
« Последнее редактирование: Май 21, 2012, 10:37:45 от Yashied, Причина: Объединение сообщений »

Русское сообщество AutoIt

Re: Получение уведомлений от Tray Tip
« Ответ #3 Отправлен: Май 21, 2012, 10:27:42 »

Оффлайн musicstashall [?]

  • Новичок
  • *
  • Сообщений: 127
  • Репутация: 0
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.14.0
Re: Получение уведомлений от Tray Tip
« Ответ #4, Отправлен: Апрель 21, 2017, 10:47:24 »
Как сделать то же самое, но без иконки в трее?? Если ставить #NoTrayIcon, то функция перестает выполняться.


Добавлено: Апрель 21, 2017, 13:45:29
И еще, скрипт, запущенный в x64 битном исполнении, не работает, автовыход:
AutoIt3.exe ended.rc:-1073741819
« Последнее редактирование: Апрель 21, 2017, 14:35:44 от musicstashall »

Русское сообщество AutoIt

Re: Получение уведомлений от Tray Tip
« Ответ #4 Отправлен: Апрель 21, 2017, 10:47:24 »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
1 Ответов
4230 Просмотров
Последний ответ Октябрь 12, 2009, 01:31:02
от CreatoR
2 Ответов
2134 Просмотров
Последний ответ Февраль 05, 2011, 16:17:14
от CreatoR
7 Ответов
3563 Просмотров
Последний ответ Октябрь 05, 2011, 09:30:10
от Driver
2 Ответов
2095 Просмотров
Последний ответ Декабрь 29, 2011, 02:18:01
от Kaster
2 Ответов
2289 Просмотров
Последний ответ Январь 15, 2012, 16:19:25
от C2H5OH
3 Ответов
2367 Просмотров
Последний ответ Август 30, 2012, 09:55:20
от CreatoR
1 Ответов
3070 Просмотров
Последний ответ Октябрь 10, 2012, 21:28:17
от Viktor1703
5 Ответов
2596 Просмотров
Последний ответ Сентябрь 09, 2013, 12:25:25
от inververs
3 Ответов
1109 Просмотров
Последний ответ Июль 02, 2015, 19:21:15
от Yashied
1 Ответов
213 Просмотров
Последний ответ Апрель 21, 2017, 18:52:34
от musicstashall