Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Notify() - multiple easy tray area notifications - v0.4991


  • Please log in to reply
319 replies to this topic
gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
hey hugov:

try this out and let me know what you think... use Options=

GR=0 ;sets gui radius off
BR=0 ;sets background radius off
BT=255 ;sets background transparency off
BW=1 ;sets thickness to 1 like a tooltip

to make it look like a tooltip, and negative duration kills app again (and is per notify, so a newer notify that doesnt have exit won't kill until the first is clicked or times out... so yo ucan haveone up that says "click me to exit" and others can come and go in the meantime

edit: latest version in original post, this version here for detailed comments
; Notify() Version 0.29 - made by gwarble - sept 09
; for displaying multiple customizable tray area notifications
;
;    Notify([Message,Title,Duration,Options,Image])
;
; thanks to Rhys and engunneer [Toaster Popups]
; test with [Ctrl-Shift-F12] if Notify.ahk is run
;
;=== To Fix:
;===  fill gaps from removed notifications if fit (might not be worth the wingetpos processing...?, and may not be desireable)
;===  or shift left a "column" width for more than monitor height allows
;===  or collapse open not's on new not or on close not (with delay)
;===  one last global to remove for label name... don't know if its possible
;===  flashing could be improved with options
;===  position could be controlable, could be moveable once open (stickies, reminders, etc)
;===  GN/maxcount need to be made parametric (for now it starts at 11: and allows 40)
;===  flash only works with odd number of flashing not's (easy to fix but may change functionality instead)
;===  have an Options parameter, for color/size/font stuff, position/size stuff, time action, click action, instead of so many parameters, parse internally...
;===
;====================================================================================
;====================================================================================

Notify_Demo1: 			;=== in case Notify.ahk is run instead of #include-d
OptionsList := "GF=11`nGL=30`nGC=FFFFAA`n
GR=9`nGT=0`n
TS=8`nTW=625`nTC=Black`nTF=Arial`nMS=8`n
MW=550`nMC=Black`nMF=Arial`nBC=Black`n
BW=2`nBR=9`nBT=105`nBF=150`nSC=300`nSI=250`n
ST=100`nAC=`nAT="
Options := "TC=Red MC=Blue GC=Silver"
 Notify("","Fake Tooltip 1",5,"GR=0 BR=0 BT=255 BW=1")
 Notify("Fake Tooltip 2")
Options := "TC=Red MC=Blue GC=Silver"
 Notify("Options:",OptionsList,7,Options)
Options := "GC=FFFFAA GR=9 GT=Off
 TS=8 TW=625 TC=Black TF=Arial MS=8
 MW=550 MC=Black MF=Arial BC=Black
 BW=2 BR=9 BT=105 BF=150"
 Notify("Options:","Default",10,Options)
 Notify("Notification:","This one won't go away unless clicked!",0)
 Notify("Notification:","This one won't go away unless clicked!",0,"","Off.ico")
 Hotkey, ^+F12, Notify_Demo2
Return
Notify_Demo2:
 Notify("Title","Message",2,"GC=CCCC44")
 Notify("Title","Message",3,"GR=20")
 Notify("Title","Message",5,"BT=10")
 Notify("Title","Message",7,"GC=FFFFAA GR=9
 GT=Off BT=205 TC=Black MC=Black")
 Notify()
 Notify("Title","Message",8,"GR=24 BR=25")
 Notify("Title","Message",9,"BW=4")
 Notify("Title","Message",10,"BR=0")
 Notify("Title","Message",11,"GR=0 MW=550")
 Notify("Title","Message",12,"BW=1")
 Notify("Title","Message",13,"MW=550")
 Notify("Title","Message",15,"SI=1000 SO=1000 SC=500") 		;=== slow
 Hotkey, ^+F12, Notify_Demo3
Return
Notify_Demo3:
 Notify()
 Notify()
 Notify()
 Notify()
 Notify("Notify()","Exiting in 10`nor if clicked...",-10,"GC=Lime TC=Black MC=White MW=625")
 Hotkey, ^+F12, Notify_Demo1
Return

;====================================================================================
;====================================================================================

Notify(Title="Notification!!!",Message="",Duration=15,Options="",Image="")
{
 Static                                                 ;=== assume-static mode for arrays of options
 Critical                                               ;=== don't allow interruption
 static GF := 11        ;GF is Gui First Number         ;=== defaults if no options
 static GL := 30        ;GM is Gui Last Number          ;=== options are saved between calls (ie only set once and changed if in Options)
 static GC := "FFFFAA"  ;GC is Gui Color
 static GR := 9         ;GR is Gui Radius
 static GT := "Off"     ;GT is Gui Transparency
 static TS := 8         ;TS is Title Font Size
 static TW := 625       ;TW is Title Font Weight
 static TC := "Black"   ;TC is Title Font Color
 static TF := "Arial"   ;TF is Title Font
 static MS := 8         ;MS is Message Font Size
 static MW := 550       ;MW is Message Font Weight
 static MC := "Black"   ;MC is Message Font Color
 static MF := "Arial"   ;MF is Message Font
 static BC := "Black"   ;BC is Border Colors
 static BW := 2         ;BW is Border Width/Thickness			;=== hugov, note option (BW BT) change
 static BR := 9         ;BR is Border Radius
 static BT := 105       ;BT is Border Transpacency
 static BF := 150       ;BF is Border Flash Speed
 static SC := 300       ;SC is Speed Clicked (AnimateWindow time)
 static SI := 250       ;SI is Speed In (AnimateWindow time)
 static ST := 100       ;SO is Speed TimeOut (AnimateWindow time)
 static IW := 32        ;IW is Image Width
 static IH := 32        ;IH is Image Height
 Global AC := 0         ;AC is Action Clicked (gosub label when clicked) ;=== Global Notify_Action removed for now
 Global AT := 0         ;AT is Action Timeout (gosub label when timeout)
 local ImageShift = ""
 If (Options)						;=== parse Options parameter
  Loop,Parse,Options,%A_Space%
   If (Option:= SubStr(A_LoopField,1,2))
    %Option%:= SubStr(A_LoopField,4) 			;=== two letter option and = (ie GF=) takes 3 chars, so value starts at 4 (needs to strip quotes if used)

 GN := GF 						;=== GuiNumber[GN] starts at GF[FirstGuiNumber]
 Loop							;=== max notifications, Notify() uses twice the max (for background) so 5 notifications use 10 gui numbers
  IfNotInString, NotifyList, % "|" GN			;=== check if this notification exists
   Break						;=== if not, make it
  Else							;=== if so
  If (++GN > GL)					;=== increment GN, check if under maxcount
    Return 0	;GN := GF				;=== If so, recheck, if not, return 0 ERROR (process by your script, if succedes returns guiID) (should save somehow and show when possible)

 NotifyList .= "|" GN					;=== add GN to list of open guis, | delimeted
 GN2 := GN + GL - GF + 1				;=== gui number for background gui

 Prev_DetectHiddenWindows := A_DetectHiddenWindows	;=== save current DetectHiddenWindows settings
 Prev_TitleMatchMode := A_TitleMatchMode		;=== save current TitleMatchMode settings
 DetectHiddenWindows On					;=== needed for winexist()
 SetTitleMatchMode 1					;=== needed for winexist()
 If (WinExist("NotifyGui")) 				;=== find all Notify() gui's from any scripts for placement
  WinGetPos, OtherX, OtherY				;=== change this to a loop for all windows, not just first found by winexist()
 DetectHiddenWindows %Prev_DetectHiddenWindows%		;=== restore script settings
 SetTitleMatchMode %Prev_TitleMatchMode% 		;=== restore script settings

 Gui, %GN2%:Destroy					; -  remove these once unnecessary
 Gui, %GN%:Destroy					; -  remove these once unnecessary

 Gui, %GN%:-Caption +ToolWindow +AlwaysOnTop -Border 	;=== notification gui creation
 Gui, %GN%:Color, %GC%
 Gui, %GN%:Font, w%TW% s%TS% c%TC%
 If ((Image) && FileExist(Image))
 {
  Gui, %GN%:Add, Picture, w%IW% h%IH%, % Image
  ImageShift = x+10
 }
 If (Title)
  Gui, %GN%:Add, Text, % ImageShift, % Title
 Gui, %GN%:Font, w%MW% s%MS% c%MC%
 If ((Title) && (Message))
  Gui, %GN%:Margin, , -5
 If (Message)
  Gui, %GN%:Add, Text,, % Message
 If ((Title) && (Message))
  Gui, %GN%:Margin, , 8
 Gui, %GN%:Show, Hide, NotifyGui
 Gui  %GN%:+LastFound
 WinGetPos, GX, GY, GW, GH 				;=== get notification size/position
 Gui, %GN%:Add, Text, x0 y0 w%GW% h%GH% gNotify_Action BackgroundTrans ;=== for clicking anywhere on the notification instead of just the text
 If (GR)
  WinSet, Region, % "0-0 w" GW " h" GH " R" GR "-" GR	;=== round corners of notification, notification gui creation END
 WinSet, Transparent, % GT

 SysGet, Workspace, MonitorWorkArea	;=== initial placement
 NewX := WorkSpaceRight-GW-5
 If (OtherY)
  NewY := OtherY-GH-5
 Else
  NewY := WorkspaceBottom-GH-5
 If NewY < % WorkspaceTop
  NewY := WorkspaceBottom-GH-5		;=== initial placement END

 Gui, %GN2%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20 	;=== background gui
 Gui, %GN2%:Color, %BC%
 Gui  %GN2%:+LastFound
 If (BR)
  WinSet, Region, % "0-0 w" GW+(BW*2) " h" GH+(BW*2) " R" BR "-" BR
 WinSet, Transparent, % BT

 Gui, %GN2%:Show, % "Hide x" NewX-BW " y" NewY-BW " w" GW+(BW*2) " h" GH+(BW*2)
 Gui, %GN%:Show,  % "Hide x" NewX " y" NewY, NotifyGui
 Gui  %GN%:+LastFound
 NotifyGuiID := WinExist()
 DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",250,"UInt","0x00040008") 	;=== slide up new notifications
 Gui, %GN2%:Show, NA 							;=== show background gui
 WinSet, AlwaysOnTop, On

 If Duration < 0
  Exit := GN
 If (Duration) 								;=== set timeout for notification
   SetTimer, NotifyKill%GN%, % - Abs(Duration) * 1000
 Else
  SetTimer, NotifyFlash%GN%, 150	;=== flash border/icon for permanent notification (add option for flash/noflash)

Return NotifyGuiID 							;=== change to return gui number

;====================================================================================
;====================================================================================

;=== when a notification is clicked:
Notify_Action:
 SetTimer, NotifyKill%A_Gui%, Off
 Gui, % A_Gui + 20 ":Destroy"
 Gui  %A_Gui%:+LastFound
 NotifyGuiID := WinExist()
 DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",100,"UInt", "0x00050001") 	;=== slide right FAST clicked notifications
 Gui, %A_Gui%:Destroy
 If IsLabel(Notify_Action)
  Gosub, %Notify_Action%
 StringReplace, NotifyList, NotifyList, % "|" GN, , All
 SetTimer, % "NotifyFlash" A_Gui, Off
 If (Exit = A_Gui)
  ExitApp
Return

;=== when a notification times out:
NotifyKill:
NotifyKill11:
NotifyKill12:
NotifyKill13:
NotifyKill14:
NotifyKill15:
NotifyKill16:
NotifyKill17:
NotifyKill18:
NotifyKill19: 	;=== there's gotta be a better way to do this, bueller?, bueller?
NotifyKill20:
NotifyKill21:
NotifyKill22:
NotifyKill23:
NotifyKill24:
NotifyKill25:
NotifyKill26:
NotifyKill27:
NotifyKill28:
NotifyKill29:
NotifyKill30:
 StringReplace, GK, A_ThisLabel, NotifyKill
 SetTimer, NotifyFlash%GK%, Off
 Gui, % GK + 20 ":Destroy"
 Gui  %GK%:+LastFound
 NotifyGuiID := WinExist()
 DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",300,"UInt", "0x00050001") 	;=== slide right SLOW timed-out notifications
 Gui, %GK%:Destroy
 StringReplace, NotifyList, NotifyList, % "|" GK
 If (Exit = GK)
  ExitApp
Return

;=== flashes a permanent notification [buggy]
NotifyFlash11:
NotifyFlash12:
NotifyFlash13:
NotifyFlash14:
NotifyFlash15:
NotifyFlash16:
NotifyFlash17:
NotifyFlash18:
NotifyFlash19:
NotifyFlash20: ;=== maybe instead use one timer and a FlashList like notifylist
NotifyFlash21: ;=== maybe they should just all flash
NotifyFlash22:
NotifyFlash23:
NotifyFlash24:
NotifyFlash25:
NotifyFlash26:
NotifyFlash27:
NotifyFlash28:
NotifyFlash29:
NotifyFlash30:
NotifyFlash:
 StringReplace, FlashGN, A_ThisLabel, NotifyFlash
 FlashGN2 := FlashGN + 20
 If Flashed := !Flashed
  Gui, %FlashGN2%:Color, Silver
 Else
  Gui, %FlashGN2%:Color, Black
Return
} 		;=== end of Notify() ===



;=== use in OnExit (or elsewhere) to wait for notifications to close before doing something [buggy]
;=== fix: Reference GN instead of GuiID, use negative forcetime to kill all open notifications (not yet implemented)
Notify_Wait(ForceTime="", GN=11, MaxNotifications=20)
{
 Loop % MaxNotifications
 {
  Gui %GN%:+LastFound
  If NotifyGuiID := WinExist()
  {
   WinWaitClose, , , % ForceTime
   If ErrorLevel
   {
    Gui, % GN + 20 ":Destroy"
    DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",200,"UInt", "0x00050001") 	;=== slide right FAST clicked notifications
    Gui, %GN%:Destroy
   }
   Break
  }
  GN++
 }
 Return 1
}


SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
Very nice! :D

I use BW=2, looks very good. I like it a lot.

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
sweet, i'm glad you like it, thanks for the feedback, help, and links...

i'm liking the images, but forgot to add the default image option (using a windows icon i guess) so i'll throw that in sometime...

and i want it to fill gaps left from removed notifications instead of "climbing", at least make it an option... so playing with wingetpos processing is next on my agenda, and optional side/slide-direction options, so if you want them on the left side instead, sliding from the top edge..., etc

- gwarble

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
Addictive isn't it making a function / lib public, once you get started you get all sorts of ideas... anyway thanks for posting.

re: images, what if you pass on a digit only you could use the icons present in shell32.dll, so if I pass on 4 it would be the folder icon, shell32 is default windows so should be OK to use?

<!-- m -->http://www.glennslay...ell32_icons.htm<!-- m -->

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
thanks

yeah it sure is fun, and your feedback has been invaluable (i like writing my scripts/apps to be as universal as possible (ie not too personalized to my system/me), and i'm applying that to my functions now which is helping my coding and hopefully proving useful for you and others...

i'd love to see an example you're using it in...

good idea for the icon number... how about this:
New Option: IN = 0
Image parameter is still to file but defaults to shell32.dll if not specified
if IN is > 0, uses that icon number from that file

so specifying an image would act like it does now, specifying IN=1 uses icon1 from shell32, and specifying IN=anything and Image="file.png" uses the image, and specifying IN=2 and image=file.exe uses icon2 from file.exe

- gwarble

EDIT:
here you go, now call like

Notify("T","M",5,"",5) ;=Notify("T","M",5,"IN=5","shell32.dll")
both should use Icon5 from shell32.dll

Notify("T","M",5,"IN=2","F.exe")
uses Icon2 from F.exe

IN=anything won't affect pictures, do you think IN should be static??
also, do you think image/number as the last parameter is good? otherwise i'm thinking maybe it should go image,options instead of the way it is now... not sure which would be used more (or an "IF=file.ext" option would work, but then its extra work to parse the options

lemme know what you think

;==========================================================================
;= Notify() Version 0.3 - made by gwarble - sept 09                       =
;= for displaying multiple customizable tray area notifications           =
;= thanks to Rhys, engunneer, and HugoV                                   =
;=  Notify("Example","Notitication...",10,"GC=Blue MC=White","ImageFile") =
;= now global-free and working pretty well, bugs on clicked actions       =
;= returns gui number used, or 0 if max is exceeded
;= multiple active actions are broken
;= use negative duration to exitapp on click or timeout
;==========================================================================

Notify(Title="Notification!!!",Message="",Duration=15,Options="",Image="")
{
 Static
 Critical            ;=== These options (used: TS=12...) are static (ie; remembered between calls if changed)
 static GF := 11              ;GF is Gui First Number
 static GL := 30              ;GM is Gui Last Number
 static GC := "FFFFAA"        ;GC is Gui Color
 static GR := 9               ;GR is Gui Radius
 static GT := "Off"           ;GT is Gui Transparency
 static TS := 8               ;TS is Title Font Size
 static TW := 625             ;TW is Title Font Weight
 static TC := "Black"         ;TC is Title Font Color
 static TF := "Arial"         ;TF is Title Font
 static MS := 8               ;MS is Message Font Size
 static MW := 550             ;MW is Message Font Weight
 static MC := "Black"         ;MC is Message Font Color
 static MF := "Arial"         ;MF is Message Font
 static BC := "Black"         ;BC is Border Colors
 static BW := 2               ;BW is Border Width/Thickness
 static BR := 9               ;BR is Border Radius
 static BT := 105             ;BT is Border Transpacency
 static BF := 150             ;BF is Border Flash Speed
 static SC := 300             ;SC is Speed Clicked (AnimateWindow)
 static SI := 250             ;SI is Speed In (AnimateWindow)
 static ST := 100             ;SO is Speed TimeOut (AnimateWindow)
 static IW := 32              ;IW is Image Width
 static IH := 32              ;IH is Image Height
 static IN := 0               ;IN is Icon Number
 local AC                     ;AC is Action Clicked
 local AT                     ;AT is Action Timeout
 local Notify_Action

 If (Options)
  Loop,Parse,Options,%A_Space%
   If (Option:= SubStr(A_LoopField,1,2))
    %Option%:= SubStr(A_LoopField,4) ;value starts after "AB=" so 4th char

 Local ImageOptions, GY, OtherY

 GN := GF
 Loop
  IfNotInString, NotifyList, % "|" GN  ;checks for existing gui number
   Break
  Else
  If (++GN > GL)
    Return 0             ;returns 0 if too many notifications exist, to be processed by caller
 NotifyList .= "|" GN    ;add GN to list of open guis, | delimeted
 GN2 := GN + GL - GF + 1
 If (AC)
  ActionList .= "|" GN "=" AC  ;add "|GN=Action" to ActionList

 Prev_DetectHiddenWindows := A_DetectHiddenWindows
 Prev_TitleMatchMode := A_TitleMatchMode
 DetectHiddenWindows On
 SetTitleMatchMode 1
 If (WinExist("NotifyGui"))	;find all Notify() gui's from this or other scripts for placement
  WinGetPos, OtherX, OtherY	;change this to a loop for all open notifications
 DetectHiddenWindows %Prev_DetectHiddenWindows%
 SetTitleMatchMode %Prev_TitleMatchMode%

 Gui, %GN%:-Caption +ToolWindow +AlwaysOnTop -Border 	;=== notification gui creation
 Gui, %GN%:Color, %GC%
 Gui, %GN%:Font, w%TW% s%TS% c%TC%
 If (Image)
 {
  If FileExist(Image)
   Gui, %GN%:Add, Picture, w%IW% h%IH% Icon%IN%, % Image
  Else
   Gui, %GN%:Add, Picture, w%IW% h%IH% Icon%Image%, c:\windows\system32\shell32.dll
  ImageOptions = x+10
 }
 If (Title)
  Gui, %GN%:Add, Text, % ImageOptions, % GN ": " Title
 Gui, %GN%:Font, w%MW% s%MS% c%MC%
 If ((Title) && (Message))
  Gui, %GN%:Margin, , -5
 If (Message)
  Gui, %GN%:Add, Text,, % Message
 If ((Title) && (Message))
  Gui, %GN%:Margin, , 8
 Gui, %GN%:Show, Hide, NotifyGui
 Gui  %GN%:+LastFound
 WinGetPos, GX, GY, GW, GH
 Gui, %GN%:Add, Text, x0 y0 w%GW% h%GH% gNotify_Action BackgroundTrans
 If (GR)
  WinSet, Region, % "0-0 w" GW " h" GH " R" GR "-" GR
 If (GT)
  WinSet, Transparent, % GT

 SysGet, Workspace, MonitorWorkArea
 NewX := WorkSpaceRight-GW-5
 If (OtherY)
  NewY := OtherY-GH-5
 Else
  NewY := WorkspaceBottom-GH-5
 If NewY < % WorkspaceTop
  NewY := WorkspaceBottom-GH-5

 Gui, %GN2%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20 ;=== background gui creation
 Gui, %GN2%:Color, %BC%
 Gui  %GN2%:+LastFound
 If (BR)
  WinSet, Region, % "0-0 w" GW+(BW*2) " h" GH+(BW*2) " R" BR "-" BR
 If (BT)
  WinSet, Transparent, % BT

 Gui, %GN2%:Show, % "Hide x" NewX-BW " y" NewY-BW " w" GW+(BW*2) " h" GH+(BW*2)
 Gui, %GN%:Show,  % "Hide x" NewX " y" NewY, NotifyGui
 Gui  %GN%:+LastFound
 NotifyGuiID := WinExist()
 ;=== slide up new notifications
 DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",SI,"UInt","0x00040008")
 Gui, %GN2%:Show, NA
 WinSet, AlwaysOnTop, On

 If Duration < 0
  Exit := GN
 ;MsgBox, % GN-GF+1
 If (Duration)
   SetTimer, % "NotifyKill" GN - GF + 1, % - Abs(Duration) * 1000
 Else
  SetTimer, % "NotifyFlash" GN - GF + 1, % BF

Return % GN

;==========================================================================
;==========================================================================

;=== when a notification is clicked:
Notify_Action:
 Critical
 SetTimer, NotifyKill%A_Gui%, Off
 Gui, % A_Gui + GL - GF + 1 ":Destroy"
 Gui  %A_Gui%:+LastFound
 NotifyGuiID := WinExist()
 ;=== slide right FASTer clicked notifications
 DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",SC,"UInt", "0x00050001")
 Gui, %A_Gui%:Destroy
 If (ActionList)
  Loop,Parse,ActionList,|
   If ((Action:= SubStr(A_LoopField,1,2)) = A_Gui)
   {
    TempNotify_Action:= SubStr(A_LoopField,4)
    StringReplace, ActionList, ActionList, % "|" A_Gui "=" TempNotify_Action, , All
    If IsLabel(Notify_Action := TempNotify_Action)
     Gosub, %Notify_Action%
    Notify_Action =
    Break
   }
 StringReplace, NotifyList, NotifyList, % "|" GN, , All
 SetTimer, % "NotifyFlash" A_Gui, Off
 If (Exit = A_Gui)
  ExitApp
Return

;==========================================================================
;=========================================== when a notification times out:
NotifyKill:
NotifyKill1:
NotifyKill2:
NotifyKill3:
NotifyKill4:
NotifyKill5:
NotifyKill6:
NotifyKill7:
NotifyKill8:
NotifyKill9:
NotifyKill10:
NotifyKill11:
NotifyKill12:
NotifyKill13:
NotifyKill14:
NotifyKill15:
NotifyKill16:
NotifyKill17:
NotifyKill18:
NotifyKill19:
NotifyKill20:
 StringReplace, GK, A_ThisLabel, NotifyKill
 SetTimer, NotifyFlash%GK%, Off
 GK += GF - 1
 Gui, % GK + GL - GF + 1 ":Destroy"
 Gui  %GK%:+LastFound
 NotifyGuiID := WinExist()
 ;=== slide right SLOWer timed-out notifications
 DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",ST,"UInt", "0x00050001")
 Gui, %GK%:Destroy
 StringReplace, NotifyList, NotifyList, % "|" GK
 If (Exit = GK)
  ExitApp
Return

;==========================================================================
;======================================== flashes a permanent notification:
NotifyFlash1:
NotifyFlash2:
NotifyFlash3:
NotifyFlash4:
NotifyFlash5:
NotifyFlash6:
NotifyFlash7:
NotifyFlash8:
NotifyFlash9:
NotifyFlash10:
NotifyFlash11:
NotifyFlash12:
NotifyFlash13:
NotifyFlash14:
NotifyFlash15:
NotifyFlash16:
NotifyFlash17:
NotifyFlash18:
NotifyFlash19:
NotifyFlash20:
NotifyFlash:
 StringReplace, FlashGN, A_ThisLabel, NotifyFlash
 FlashGN += GF - 1
 FlashGN2 := FlashGN + GL - GF + 1
 If Flashed%FlashGN2% := !Flashed%FlashGN2%
  Gui, %FlashGN2%:Color, Silver
 Else
  Gui, %FlashGN2%:Color, Black
Return
} 		;=== end of Notify() ===

;==========================================================================
;==========================================================================

;=== NOT YET UPDATED/FIXED
;=== use in OnExit (or elsewhere) to wait for notifications to close before doing something [buggy]
;=== fix: Reference GN instead of GuiID, use negative forcetime to kill all open notifications (not yet implemented)
Notify_Wait(ForceTime="", GN=11, MaxNotifications=20)
{
 Loop % MaxNotifications
 {
  Gui %GN%:+LastFound
  If NotifyGuiID := WinExist()
  {
   WinWaitClose, , , % ForceTime
   If ErrorLevel
   {
    Gui, % GN + 20 ":Destroy"
    DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",200,"UInt", "0x00050001") 	;=== slide right FAST clicked notifications
    Gui, %GN%:Destroy
   }
   Break
  }
  GN++
 }
 Return 1
}


SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
Nice, one suggestion:

You have
Gui, %GN%:Add, Picture, w%IW% h%IH% Icon%Image%, [color=red]c:\windows\system32\[/color]shell32.dll
I think you should replace that with
Gui, %GN%:Add, Picture, w%IW% h%IH% Icon%Image%, shell32.dll
W2K users may have c:\WINNT\.... for example and the system32\shell32.dll should be in the system path anyway so it works on all systems.

Image options, vs options image may be a good idea but I'm happy either way
:wink:

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
thanks again HugoV

i started with it as shell32.dll, but on a vista machine i use when i have to, it didnt find the file (even though it was still in system32, i didnt check the path envir variables...)

is there a better way to point to this file?

i changed it for now but it failed on my vista installation, working fine on xp

- gwarble

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
Perhaps this helps <!-- m -->http://www.autohotke...topic10325.html<!-- m -->

CSIDL_SYSTEM (0x0025)
Version 5.0. The Windows System folder. A typical path is C:\Windows\System32.

Don't know if the function works with Vista but it may be worth a shot. I'm surprised there is no A_OSDir internal var or I have overlooked it. Edit: :oops: A_WinDir

aaffe
  • Members
  • 1045 posts
  • Last active: Jan 16 2014 01:32 PM
  • Joined: 17 May 2007
hy,
one questions: If i make a notifier without duration, so you have to click it to go away....how to remove it from the script without clicking?

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
A_WinDir The Windows directory. For example: C:\Windows

do you know if, once inside the windows directory that may change names, is system32 always named system32??

- gwarble

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
@gwarble: :oops: (never had to use it) I think you can safely assume it is system32, all the dllcalls use it and they seem to work on vista & win7 as far as I know / have seen.

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
aaffee:

i broke that functionality in Notify_Wait() (at the bottom) and am implementing it like so, but its not in there yet:

Notify_ID := Notify()
Notify("","",5,"Wait",Notify_ID) ;waits 5 seconds and returns if closed it or not
Notify("","",30,"Wait",Notify_ID) ;waits 30 seconds and returns if it closed or not
Notify("","",0,"Wait",Notify_ID) ;waits indefinitely until it closes
Notify("","",-5,"Wait",Notify_ID) ;waits 5 seconds and force-close notification if still open
Notify("","",-0,"Wait",Notify_ID) ;force it closed now (or kill instead of wait)
;and if Notify_ID is not used, it will search for all Notify_Guis and wait as above, so:
Notify("","",0,"Wait") ;waits indefinitely until all notifications are gone
Notify("","",-1,"Wait") ;kill all notifications in 1 second
etc...

does that sound like an ok way to give this functionality, and remove the need for a second function?? have any better syntax ideas before i get into it?

thanks for looking!
- gwarble

bug fixes / improvements en route:
-actions are not notification-specific, fix actionlist
-notify_wait functionality moved into notify()
-find all notifications, not first-found, for initilial placement
-fill gaps with new notifications if screen height is maxes... instead of starting at the bottom again
-make transparent after animatewindow (glitches during slide if transparent)
-make animatewindow and placement options setable: direction, effect, position, stacking, collapsing, etc
save notifications if max is exceeded, display combined or delayed

aaffe
  • Members
  • 1045 posts
  • Last active: Jan 16 2014 01:32 PM
  • Joined: 17 May 2007
Thanx a lot!

aaffe
  • Members
  • 1045 posts
  • Last active: Jan 16 2014 01:32 PM
  • Joined: 17 May 2007
Hy,
why doesnt this remove the Notifier?:
 Notify("Notifier","This is a test.",0,"AC=DEMO","Icon_4.ico")
 Sleep 5000
Notify("","",-1,"Wait") 
Sleep 5000


gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
Notify_Wait functionality implemented as described above, kind of:

NotifyID := 
Notify("","",5,"Wait",NotifyID) ;= waits 5 seconds or until notification is gone
Notify("","",-5,"Wait",NotifyID) ;= waits 5 seconds or until notification is gone, and force closes it
Notify("","",0,"Wait",NotifyID) ;= force close now!!!
Notify("","","","Wait",NotifyID) ;= wait indefinitely until closes [freezes script though,hmm...]

title and message could be used as wintext search strings for notifications from other apps or groups of notifications...

v0.41:
;;;;;
;;;    Notify() 0.4 - made by gwarble - sept 09
;;
;    for displaying multiple customizable tray area notifications
;
;  thanks to Rhys, engunneer, and HugoV
;
;
; Notify([Title,Message,Duration,Options,Image])
;
;   Parameters:   - Default                     - Notes
;
;     Title        - "Notification!!!"           - "" to omit title line
;                                                     
;     Message      - ""                          - "" to omit message line
;                                                     
;     Duration     - 15                          - 0 to flash until clicked
;                                                  <0 to ExitApp on click/timeout
;                                                  -0 not yet implemented
;     Options      - GF=50 GL=74                 - string of options
;                                                  uses ((GL-GF)*2) Gui Numbers
;                                                  ie: 50 thru 99 by defaults
;                    [see function for all]        most options static/remembered
;                                                  "NO=Reset" to reset options
;                                                  see function for details
;     Image        - shell32.dll (1<Image<255)   - Image file, or
;                                                  number of icon in shell32.dll
; 
;  Returns       - Gui Number used, 0 if Gui quantity exceeded
;
;
Notify(Title="Notification!!!",Message="",Duration=15,Options="",Image="")
{
 Static                    ;Options string, eg: "TS=12 GC=Blue"
 Critical
 static GF := 50              ;GF is Gui First Number
 static GL := 74              ;GM is Gui Last Number
 static GC := "FFFFAA"        ;GC is Gui Color
 static GR := 9               ;GR is Gui Radius
 static GT := "Off"           ;GT is Gui Transparency
 static TS := 8               ;TS is Title Font Size
 static TW := 625             ;TW is Title Font Weight
 static TC := "Black"         ;TC is Title Font Color
 static TF := "Arial"         ;TF is Title Font
 static MS := 8               ;MS is Message Font Size
 static MW := 550             ;MW is Message Font Weight
 static MC := "Black"         ;MC is Message Font Color
 static MF := "Arial"         ;MF is Message Font
 static BC := "Black"         ;BC is Border Colors
 static BW := 2               ;BW is Border Width/Thickness
 static BR := 9               ;BR is Border Radius
 static BT := 105             ;BT is Border Transpacency
 static BF := 150             ;BF is Border Flash Speed
 static SC := 100             ;SC is Speed Clicked (AnimateWindow)
 static SI := 350             ;SI is Speed In (AnimateWindow)
 static ST := 450             ;SO is Speed TimeOut (AnimateWindow)
 static IW := 32              ;IW is Image Width
 static IH := 32              ;IH is Image Height
 static IN := 0               ;IN is Icon Number
 static Defaults := "GF=50 GL=74 GC=FFFFAA GR=9 GT=Off TS=8 TW=625 TC=Black TF=Arial MS=8 MW=550 MC=Black MF=Arial BC=Black BW=2 BR=9 BT=105 BF=150 SC=300 SI=250 ST=100 IW=32 IH=32 IN=0"
 local AC                     ;AC is Action Clicked
 local AT                     ;AT is Action Timeout
 local Notify_Action, ImageOptions, GY, OtherY

;==========================================================================
Notify: ;========================================= when Notify() is called:

 local NO := 0                ;NO is Notify Option [NO=Reset]
 If (Options)
 {
  IfInString, Options, =
  {
   Loop,Parse,Options,%A_Space%
    If (Option:= SubStr(A_LoopField,1,2))
     %Option%:= SubStr(A_LoopField,4)
   If NO = Reset
   {
    Options := Defaults
    Goto, Notify
   }
  }
  Else If Options = Wait
   Goto, Notify_Wait
 }


 GN := GF
 Loop
  IfNotInString, NotifyList, % "|" GN
   Break
  Else
  If (++GN > GL)
    Return 0 ;=== too many notifications open!
 NotifyList .= "|" GN
 GN2 := GN + GL - GF + 1
 If (AC)
  ActionList .= "|" GN "=" AC

 Prev_DetectHiddenWindows := A_DetectHiddenWindows
 Prev_TitleMatchMode := A_TitleMatchMode
 DetectHiddenWindows On
 SetTitleMatchMode 1
 If (WinExist("NotifyGui"))  ;=== find all Notifications from ALL scripts, for placement
  WinGetPos, OtherX, OtherY  ;=== change this to a loop for all open notifications?
 DetectHiddenWindows %Prev_DetectHiddenWindows%
 SetTitleMatchMode %Prev_TitleMatchMode%

 Gui, %GN%:-Caption +ToolWindow +AlwaysOnTop -Border
 Gui, %GN%:Color, %GC%
 Gui, %GN%:Font, w%TW% s%TS% c%TC%, %TF%
 If (Image)
 {
  If FileExist(Image)
   Gui, %GN%:Add, Picture, w%IW% h%IH% Icon%IN%, % Image
  Else
   Gui, %GN%:Add, Picture, w%IW% h%IH% Icon%Image%, c:\windows\system32\shell32.dll
  ImageOptions = x+10
 }
 If (Title)
  Gui, %GN%:Add, Text, % ImageOptions, % Title
 Gui, %GN%:Font, w%MW% s%MS% c%MC%, %MF%
 If ((Title) && (Message))
  Gui, %GN%:Margin, , -5
 If (Message)
  Gui, %GN%:Add, Text,, % Message
 If ((Title) && (Message))
  Gui, %GN%:Margin, , 8
 Gui, %GN%:Show, Hide, NotifyGui
 Gui  %GN%:+LastFound
 WinGetPos, GX, GY, GW, GH
 Gui, %GN%:Add, Text, x0 y0 w%GW% h%GH% gNotify_Action BackgroundTrans
 If (GR)
  WinSet, Region, % "0-0 w" GW " h" GH " R" GR "-" GR
 If (GT)
  WinSet, Transparent, % GT

 SysGet, Workspace, MonitorWorkArea
 NewX := WorkSpaceRight-GW-5
 If (OtherY)
  NewY := OtherY-GH-5
 Else
  NewY := WorkspaceBottom-GH-5
 If NewY < % WorkspaceTop
  NewY := WorkspaceBottom-GH-5

 Gui, %GN2%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20
 Gui, %GN2%:Color, %BC%
 Gui  %GN2%:+LastFound
 If (BR)
  WinSet, Region, % "0-0 w" GW+(BW*2) " h" GH+(BW*2) " R" BR "-" BR
 If (BT)
  WinSet, Transparent, % BT

 Gui, %GN2%:Show, % "Hide x" NewX-BW " y" NewY-BW " w" GW+(BW*2) " h" GH+(BW*2)
 Gui, %GN%:Show,  % "Hide x" NewX " y" NewY, NotifyGui
 Gui  %GN%:+LastFound
 If SI
  DllCall("AnimateWindow","UInt",WinExist(),"Int",SI,"UInt","0x00040008")
 Else
  Gui, %GN%:Show,, NotifyGui
 Gui, %GN2%:Show, NA
 WinSet, AlwaysOnTop, On

 If Duration < 0
  Exit := GN
 If (Duration)
   SetTimer, % "NotifyKill" GN - GF + 1, % - Abs(Duration) * 1000
 Else
  SetTimer, % "NotifyFlash" GN - GF + 1, % BF

Return % GN

;==========================================================================
;========================================== when a notification is clicked:
Notify_Action:
 Critical
 SetTimer, % "NotifyKill" A_Gui - GF + 1, Off
 Gui, % A_Gui + GL - GF + 1 ":Destroy"
 Gui  %A_Gui%:+LastFound
 If SC
  DllCall("AnimateWindow","UInt",WinExist(),"Int",SC,"UInt", "0x00050001")
 Gui, %A_Gui%:Destroy
 If (ActionList)
  Loop,Parse,ActionList,|
   If ((Action:= SubStr(A_LoopField,1,2)) = A_Gui)
   {
    TempNotify_Action:= SubStr(A_LoopField,4)
    StringReplace, ActionList, ActionList, % "|" A_Gui "=" TempNotify_Action, , All
    If IsLabel(Notify_Action := TempNotify_Action)
     Gosub, %Notify_Action%
    Notify_Action =
    Break
   }
 StringReplace, NotifyList, NotifyList, % "|" GN, , All
 SetTimer, % "NotifyFlash" A_Gui - GF + 1, Off
 If (Exit = A_Gui)
  ExitApp
Return

;==========================================================================
;=========================================== when a notification times out:
NotifyKill1:
NotifyKill2:
NotifyKill3:
NotifyKill4:
NotifyKill5:
NotifyKill6:
NotifyKill7:
NotifyKill8:
NotifyKill9:
NotifyKill10:
NotifyKill11:
NotifyKill12:
NotifyKill13:
NotifyKill14:
NotifyKill15:
NotifyKill16:
NotifyKill17:
NotifyKill18:
NotifyKill19:
NotifyKill20:
NotifyKill21:
NotifyKill22:
NotifyKill23:
NotifyKill24:
NotifyKill25:
 Critical
 StringReplace, GK, A_ThisLabel, NotifyKill
 SetTimer, NotifyFlash%GK%, Off
 GK += GF - 1
 Gui, % GK + GL - GF + 1 ":Destroy"
 Gui  %GK%:+LastFound
 If ST
  DllCall("AnimateWindow","UInt",WinExist(),"Int",ST,"UInt", "0x00050001")
 Gui, %GK%:Destroy
 StringReplace, NotifyList, NotifyList, % "|" GK
 If (Exit = GK)
  ExitApp
Return

;==========================================================================
;======================================== flashes a permanent notification:
NotifyFlash1:
NotifyFlash2:
NotifyFlash3:
NotifyFlash4:
NotifyFlash5:
NotifyFlash6:
NotifyFlash7:
NotifyFlash8:
NotifyFlash9:
NotifyFlash10:
NotifyFlash11:
NotifyFlash12:
NotifyFlash13:
NotifyFlash14:
NotifyFlash15:
NotifyFlash16:
NotifyFlash17:
NotifyFlash18:
NotifyFlash19:
NotifyFlash20:
NotifyFlash21:
NotifyFlash22:
NotifyFlash23:
NotifyFlash24:
NotifyFlash25:
 StringReplace, FlashGN, A_ThisLabel, NotifyFlash
 FlashGN += GF - 1
 FlashGN2 := FlashGN + GL - GF + 1
 If Flashed%FlashGN2% := !Flashed%FlashGN2%
  Gui, %FlashGN2%:Color, Silver
 Else
  Gui, %FlashGN2%:Color, Black
Return

Notify_Wait:
 If (Image)
 {
  Gui %Image%:+LastFound
  If NotifyGuiID := WinExist()
  {
   WinWaitClose, , , % Abs(Duration)
   If (ErrorLevel && Duration < 1)
   {
    Gui, % Image + GL - GF + 1 ":Destroy"
    DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",100,"UInt", "0x00050001")
    Gui, %Image%:Destroy
   }
  }
 }
 Else
  Notify("No Notification specified to wait for!","waiting for all notifications is not yet implemented")
Return
}

Example:
#SingleInstance Force

 Loop 10
  Notify("Notify " A_Index, "Duration=" Abs(20-A_Index-Mod(A_Index,3)*A_Index) " Corners=" Round((A_Index*A_Index-1)/3) " Icon=" A_Index+35,Abs(20-A_Index-Mod(A_Index,3)*A_Index),"GR=" (A_Index*A_Index-1)/3 " BR=" (A_Index*A_Index-1)/3,A_Index+35)
 Notify("Defaults","Ctrl-Shift-F12 for more...",5,"NO=Reset")
 Loop 3
  Notify("Notifier","Flashing!",0,"BF=" A_Index*A_Index*50)
 Temp := Notify("Defaults","Ctrl-Shift-F12 for more...",15,"NO=Reset")
 Notify("start waiting")
 Notify("Wait","Wait",5,"Wait",Temp)
 Notify("success`nfinished waiting")
 Notify("Wait","Wait",5,"Wait")
Return

#Include Notify.ahk

let me know what you guys think about functionality and syntax...
aaffee: hope that solves your issue
- gwarble

Edit:
i'm redoing AC and AT in a different way (internally) so those are probably broken right now, at least for multiple notifications
also, i'd love to know how you're applying notify() so i can improve it (and maybe find out about a cool script :)