AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Notify() v0.44 - multiple tray area notifications
Goto page 1, 2, 3, 4, 5, 6, 7, 8, 9  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
gwarble



Joined: 23 May 2009
Posts: 126
Location: north bay, california

PostPosted: Thu Sep 10, 2009 5:33 am    Post subject: Notify() v0.44 - multiple tray area notifications Reply with quote

i wrote this function to create and position multiple simultaneous tray area notifications, from any number of different scripts... Notify() can display fully-customizable, timed (or not) notification windows that can display any type of information quickly and easily (i like using it for debugging; Notify("var",var) works well), each of which can perform actions when clicked or time out, etc... try it out and let me know what you think!

stdlib compliant, just drop in your Lib folder and call Notify() to see it in action
no globals, no dependencies, _Notify_***: labels only

Notify() v0.44 - Download Notify.ahk or read the incomplete Documentation
Code:
;;;;;;;
;;;;;  Notify() 0.44                made by gwarble - sept 09
;;;      multiple tray area notifications
;          thanks to Rhys/engunneer/HugoV/Forum Posters
;
;   Notify([Title,Message,Duration,Options,Image])
;
;     Title      [!!!]          "" to omit title line
;     Message      []           "" to omit message line
;     Duration    [15]          seconds to show notification
;                                0 to flash until clicked
;                               <0 to ExitApp on click/timeout
;                               -0 not yet implemented (perm/exit)
;     Options                   string of options... see function
;          [SI=999 GC=Blue...]  most options are remembered (static)
;                               "Reset" to restore default options
;                                 if you want to show as well, use NO=Reset
;                               "Wait" to wait for a notification  ***
;       Image []                 Image file name/library or
;                                number of icon in shell32.dll
;                                Gui Number to "Wait" for          ***
;
;     Return                     Gui Number used                   ***
;                                0 if failed (too many)
;
Notify(Title="!!!",Message="",Duration=30,Options="",Image="")
{
 Static                ;Options string: "TS=12 GC=Blue..."
 static GF := 50       ;    Gui First Number  ;= override Gui: # used
 static GL := 74       ;    Gui Last Number   ;= between GF and GL
 static GC := "FFFFAA" ;    Gui Color         ;   ie: don't use GF<=Gui#<=GL
 static GR := 9        ;    Gui Radius        ;       elsewhere in your script
 static GT := "Off"    ;    Gui Transparency
 static TS := 8        ;  Title Font Size
 static TW := 625      ;  Title Font Weight
 static TC := "Black"  ;  Title Font Color
 static TF := "Arial"  ;  Title Font Face
 static MS := 8        ;Message Font Size
 static MW := 550      ;Message Font Weight
 static MC := "Black"  ;Message Font Color
 static MF := "Arial"  ;Message Font Face
 static BC := "Black"  ; Border Colors
 static BW := 2        ; Border Width/Thickness
 static BR := 13       ; Border Radius
 static BT := 105      ; Border Transpacency
 static BF := 150      ; Border Flash Speed
 static SI := 350      ;  Speed In (AnimateWindow)
 static SC := 100      ;  Speed Clicked (AnimateWindow)
 static ST := 450      ;  Speed TimeOut (AnimateWindow)
 static IW := 32       ;  Image Width
 static IH := 32       ;  Image Height
 static IN := 0        ;  Image Icon Number (from Image)
 local AC, AT          ;Actions Clicked/Timeout
 local _Notify_Action, ImageOptions, GY, OtherY


_Notify_:

 local NO := 0                ;NO is Notify Option [NO=Reset] ;local
 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 := "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"
    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% g_Notify_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, NA, NotifyGui
 Gui, %GN2%:Show, NA
 WinSet, AlwaysOnTop, On

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

Return % GN

;==========================================================================
;========================================== when a notification is clicked:
_Notify_Action:
 ;Critical
 SetTimer, % "_Notify_Kill_" 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)
   {
    Temp_Notify_Action:= SubStr(A_LoopField,4)
    StringReplace, ActionList, ActionList, % "|" A_Gui "=" Temp_Notify_Action, , All
    If IsLabel(_Notify_Action := Temp_Notify_Action)
     Gosub, %_Notify_Action%
    _Notify_Action =
    Break
   }
 StringReplace, NotifyList, NotifyList, % "|" GN, , All
 SetTimer, % "_Notify_Flash_" A_Gui - GF + 1, Off
 If (Exit = A_Gui)
  ExitApp
Return

;==========================================================================
;=========================================== when a notification times out:
_Notify_Kill_1:
_Notify_Kill_2:
_Notify_Kill_3:
_Notify_Kill_4:
_Notify_Kill_5:
_Notify_Kill_6:
_Notify_Kill_7:
_Notify_Kill_8:
_Notify_Kill_9:
_Notify_Kill_10:
_Notify_Kill_11:
_Notify_Kill_12:
_Notify_Kill_13:
_Notify_Kill_14:
_Notify_Kill_15:
_Notify_Kill_16:
_Notify_Kill_17:
_Notify_Kill_18:
_Notify_Kill_19:
_Notify_Kill_20:
_Notify_Kill_21:
_Notify_Kill_22:
_Notify_Kill_23:
_Notify_Kill_24:
_Notify_Kill_25:
 ;Critical
 StringReplace, GK, A_ThisLabel, _Notify_Kill_
 SetTimer, _Notify_Flash_%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:
_Notify_Flash_1:
_Notify_Flash_2:
_Notify_Flash_3:
_Notify_Flash_4:
_Notify_Flash_5:
_Notify_Flash_6:
_Notify_Flash_7:
_Notify_Flash_8:
_Notify_Flash_9:
_Notify_Flash_10:
_Notify_Flash_11:
_Notify_Flash_12:
_Notify_Flash_13:
_Notify_Flash_14:
_Notify_Flash_15:
_Notify_Flash_16:
_Notify_Flash_17:
_Notify_Flash_18:
_Notify_Flash_19:
_Notify_Flash_20:
_Notify_Flash_21:
_Notify_Flash_22:
_Notify_Flash_23:
_Notify_Flash_24:
_Notify_Flash_25:
 StringReplace, FlashGN, A_ThisLabel, _Notify_Flash_
 FlashGN += GF - 1
 FlashGN2 := FlashGN + GL - GF + 1
 If Flashed%FlashGN2% := !Flashed%FlashGN2%
  Gui, %FlashGN2%:Color, Silver
 Else
  Gui, %FlashGN2%:Color, Black
Return

;==========================================================================
;============================= wait (or force) for a notification to close:
_Notify_Wait_:
 ;Critical
 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",ST,"UInt", "0x00050001")
    Gui, %Image%:Destroy
   }
  }
 }
 Else
  Notify("No Notification specified to wait for!","waiting for all notifications is not yet implemented",10,"IN=8",A_WinDir "\explorer.exe")
Return
}

Screenshots:

Examples:
Code:
Title= Hello
Message= World
Duration=0
Options:="GC=bbffbb TC=White MC=White"
Image=14
Notify(Title,Message,Duration,Options,Image)
Code:
Notify("Title","Message",10)  ;=== typical call
Notify()  ;=== creates a default notification

Loop 10  ;=== creates 10 notifications with varying options
 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)
Action/Wait Demo:
Code:
Notify("Welcome to Notify()","Click this notification to open a new one using AC=...",0,"AC=ActionDemo IN=8 IW=48 IH=48", A_WinDir "\explorer.exe")
Return
ActionDemo:
 HotKey, ^F12, WaitDemo
 NotifyID := Notify("","this one is permanent, press ctrl-F12 to force kill after 3 seconds",0)
Return
WaitDemo:
 Notify("","",-3,"Wait",NotifyID)
 Notify("Waiting done!","It was killed after 3 seconds, even though it had 0 duration!`n`nthis notification will exitapp if clicked or waits 15 seconds",-15)
Return
#Include Notify.ahk

Notify() 0.43
by gwarble
september 2009

thanks to Rhys/engunneer [Toaster Popups] and HugoV [help/recommendations]

i'm new to releasing my code and would greatly appreciate any feedback/suggestions/ideas/criticism/etc... on this function, which is similar to/can replace: TP Toaster Popup, TrayTip and Menu Tray Tip, some ToolTips, and has similar functionality to snarl and growl for tray notifications


Last edited by gwarble on Mon Dec 07, 2009 7:16 am; edited 31 times in total
Back to top
View user's profile Send private message
hugov



Joined: 27 May 2007
Posts: 2428

PostPosted: Thu Sep 10, 2009 8:45 am    Post subject: Reply with quote

Nice and easy to use. In NotifyWait there is a reference to an icon in notifier.exe you may wish to comment out for people just downloading notify.ahk
_________________
Tut 4 Newbies
TF : Text file & string lib, TF Forum
Back to top
View user's profile Send private message Visit poster's website
gwarble



Joined: 23 May 2009
Posts: 126
Location: north bay, california

PostPosted: Thu Sep 10, 2009 8:57 am    Post subject: fixed Reply with quote

thanks, fixed

also made the function file alone able to run for testing, so you can just download Notify.ahk and run it without Notifier or including:

^+F12 for test notifications, doesnt show all options but lets you see the multiple window detection (also, run 2 copies of it to see how it handles two scripts using notify() )

Edit: code updated in initial post

Download:
http://arcadefanatic.com/notifier/Downloads/Notify.ahk

thanks for trying it out

- gwarble

=====================================
anyone know a better way to have seperate timers/timer lengths (dynamically) than this cob solution:
Code:

 SetTimer, NotifyKill%GuiNumber%, % "-" Duration * 1000 ;in function call
 ...
NotifyKill11: ;function subs
NotifyKill12:
NotifyKill13:
NotifyKill14:
NotifyKill15:
NotifyKill16:
NotifyKill17:
NotifyKill18:
NotifyKill19:
NotifyKill20:
NotifyKill:
 StringReplace, GuiNumber, A_ThisLabel, NotifyKill ;crappy dynamic timer solution
 GuiNumber2 := GuiNumber + 20
 Gui, %GuiNumber2%:Destroy
 Gui  %GuiNumber%:+LastFound
 NotifyGuiID := WinExist()
 DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",600,"UInt", "0x00050001")    ;=== slide right SLOW timed-out notifications
 Gui, %GuiNumber%:Destroy
 NotifyCount--
 SetTimer, NotifyFlash, Off
 If (Exit)
  ExitApp
Return

there's gotta be a better way


Last edited by gwarble on Sun Sep 13, 2009 6:30 pm; edited 1 time in total
Back to top
View user's profile Send private message
gwarble



Joined: 23 May 2009
Posts: 126
Location: north bay, california

PostPosted: Sun Sep 13, 2009 6:09 am    Post subject: Reply with quote

worked out all the kinks for multiple guis, now need to clean up the code a bit, but now multiple can show, while each retaining its own timer

here's some screenshots of it in use in my other app:

i'd love to see it in use in your scripts
- gwarble




Last edited by gwarble on Sun Dec 06, 2009 8:43 pm; edited 2 times in total
Back to top
View user's profile Send private message
hugov



Joined: 27 May 2007
Posts: 2428

PostPosted: Sun Sep 13, 2009 6:19 am    Post subject: Reply with quote

Some ideas:

- I prefer rectangular notifications vs rounded, perhaps you could introduce a style or rounding parameter for the winset

- I also use ToasterPopups which I modified to be able to include images in the TP

- The border is drawn with transparency perhaps allow colours so you can have a red border for example

Edit: re timer question, for some ideas see http://www.autohotkey.com/forum/viewtopic.php?t=48670, lexikos post
_________________
Tut 4 Newbies
TF : Text file & string lib, TF Forum
Back to top
View user's profile Send private message Visit poster's website
gwarble



Joined: 23 May 2009
Posts: 126
Location: north bay, california

PostPosted: Sun Sep 13, 2009 6:21 pm    Post subject: Reply with quote

for now its easy to comment out the lines for winset,region (rounded corners) and manually change the background guis color (or if you want it to look like a tooltip you could drop the second gui altogether)

to make it parameter based, would you prefer
Notify(title,msg,dur,......,colorthis,colorthat,thicknessthis,thicknessthat)
with tons of parameters, or:
Notify(title,msg,dur,action, "FClrRed GClrBlue BClrGreen FSize12 FWght500")
letting notify parse a single parameter for all these options

i'm thinking the latter, which could have lots easily including:
font size,color,titlesize,messagesize,font face,weight,modifiers(italic etc)
gui color,size,flashcolor, backgroundcolor, opacity, clickthru or not, clickaction and timeoutaction, background border thickness, lots more, gui numbers, etc

let me know what approach to go which is most appreciated
-gwarble

EDIT:
oh yeah, and i'm adding images at the moment, the whole reason i made this function is for that last screenshot, to replace the bottom gui with this dynamically positioning Notify() gui, so images are being implemented now, but again i'd love to know the way you would prefer to call the function
Back to top
View user's profile Send private message
hugov



Joined: 27 May 2007
Posts: 2428

PostPosted: Sun Sep 13, 2009 6:45 pm    Post subject: Reply with quote

Vote+ for the images Cool

For the parameters, some suggestions close to yours:
http://www.autohotkey.com/forum/viewtopic.php?t=19254&highlight=named+parameters
http://www.autohotkey.com/forum/viewtopic.php?p=280766#280766

Edit: alternative could be an NotifyInit() function where a used can define some prefered standards like style, font, color, border etc which would be global vars of course __NotifyStyle=Rounded, __NotifyFGC=cc0000 etc
_________________
Tut 4 Newbies
TF : Text file & string lib, TF Forum
Back to top
View user's profile Send private message Visit poster's website
gwarble



Joined: 23 May 2009
Posts: 126
Location: north bay, california

PostPosted: Sun Sep 13, 2009 9:05 pm    Post subject: Reply with quote

i like the init function idea, but i don't like having globals

how about using either:

Notify("Notify_Configure",blah,blah.....blah,blah)

which would prevent a notification called Notify_Configure or something, and set static variables this way...

or i think the best is the options parameter, which set statics if used, but statics are default if they are never used, therefore not needing to be specified each call unless you want it to change... so:

Code:

Options := "TS10 TW600 TCBlack MS8 MW400 MCBlue GN11 GCFF44FF GT200" ;...
Notify(Title,Message,Duration,Action,Options)
;TS is Title Font Size
;TW is Title Font Weight
;TF is Title Font
;TC is Title Font Color
;
;MS is Message Font Size
;MW is Message Font Weight
;MF is Message Font
;MC is Message Font Color
;
;GF is First Gui Number available
;GL is Last Gui Number available ;difference is max #
;GC is Gui Color
;GR is Gui Rounded Corners (in pixels)
;
;BC is Border (Background Gui) Color
;BT is Border (Background Gui) Border Thickness
;BF is Border (Background gui) flash speed
;
;there's more that could be added, and they could be added later without changing any parameters/break functionality


also, would you want a title, message, and an image? or IfFileExist, title then show the image and now have a title

- gwarble

edit: if the first option is used Notify("Notify_Configure") then i could also use Notify("Notify_Wait") and loose the second function
Back to top
View user's profile Send private message
hugov



Joined: 27 May 2007
Posts: 2428

PostPosted: Sun Sep 13, 2009 9:16 pm    Post subject: Reply with quote

I would prefer TS=10 over TS10 as you can see from the examples above it is easier for the user to understand and parse. I don't mind much how you do it either with init or options, currently I use Notify(A_ScriptName, "Done", -3) a lot so that is nice and short, images, colours & styles are just a bonus Wink
_________________
Tut 4 Newbies
TF : Text file & string lib, TF Forum
Back to top
View user's profile Send private message Visit poster's website
Guest






PostPosted: Sun Sep 13, 2009 9:19 pm    Post subject: Reply with quote

oh crap are you using -3 to exitapp after the three seconds? cuz i removed that functionality, thinking you could use Notify(title,msg,3,"ExitSub") as an action...

but if yo ulike it i kind of do too, and its easy to have in there
-gwarble
Back to top
gwarble



Joined: 23 May 2009
Posts: 126
Location: north bay, california

PostPosted: Sun Sep 13, 2009 9:23 pm    Post subject: Reply with quote

or if it saves all variables as static,

You could call:
Notify(A_ScriptName, "Done", -3)
once
and then call
Notify()
every other time for the same notification

also, personally i don't like the "=" in the options since it isnt consistent with other uses of =, of which there are already 2... but i'm not opposed and will start that way... if its there the option names could be long and descriptive, but i kind of like the two letter approach...
??
- gwarble

edit: do we want:
Notify(Title,Msg,Image,Dur...
or image file in with the options
different uses would make either one more convenient... although my use would call for a different image being used on each notification (having a dedicated parameter being easier), i think most people would set the image to an image for the script and use it for all notifications... especially with two scripts using notify()

- gwarble
Back to top
View user's profile Send private message
hugov



Joined: 27 May 2007
Posts: 2428

PostPosted: Sun Sep 13, 2009 9:27 pm    Post subject: Reply with quote

Edit: you types while I was typing. So this refers to -3

I like it yes, the Notify is so much nicer to have then the regular MsgBox Done to indicate when a lenghty script is, well, done Wink

Currently I use costum (per script) toasterpopups to either use with windows taskschedular to remind me of stuff or give feedback while a script is running, in all of these cases I like the script to close after the last notify (its done), so by using -3 it saves me a line in the script and it is easier to type then an another notify command/line.

Re: images mmm not sure what would be best, perhaps per notify so you can use different images for start/working/paused/ready/exit type of messages?

Perhaps also introduce some basic system icons as with MsgBox? That way you don't have to include an image with a script that uses Notify.
_________________
Tut 4 Newbies
TF : Text file & string lib, TF Forum


Last edited by hugov on Sun Sep 13, 2009 9:31 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
gwarble



Joined: 23 May 2009
Posts: 126
Location: north bay, california

PostPosted: Sun Sep 13, 2009 9:28 pm    Post subject: Reply with quote

great feedback, thanks, back in it goes
Back to top
View user's profile Send private message
hugov



Joined: 27 May 2007
Posts: 2428

PostPosted: Sun Sep 13, 2009 9:32 pm    Post subject: Reply with quote

I was typing again while you was reading/typing so just to let you know: look above Cool
_________________
Tut 4 Newbies
TF : Text file & string lib, TF Forum
Back to top
View user's profile Send private message Visit poster's website
gwarble



Joined: 23 May 2009
Posts: 126
Location: north bay, california

PostPosted: Sun Sep 13, 2009 11:39 pm    Post subject: Reply with quote

sounds good man, thanks for the feedback

i'm putting back in -duration, adding images, and converting to an options parameter now, i'll get a new version up shortly

- gwarble

edit:
HugoV:
got back to it, no images yet but try this for no corner rounding, option testing, color control, let me know what oyu think about the usage syntax for your script

Code:
;
;    Notify() Version 0.2
;  made by gwarble - sept 09
;
; for displaying multiple tray area notifications
;
;    Notify([Message,Title,Duration,Action,FontColor,FontSize,GuiColor,StartGN,MaxGuiCount])
;
; thanks to Rhys and engunneer [Toaster Popups]
; test with [Ctrl-Shift-1] [^+1] 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
; Notify("Notify()","This is a sample notification.`nIt will last for 15 seconds unless clicked.`nNotify.ahk is meant to be #Include-d.`nDownload Notifier for a working example.`n`nCtrl-Shift-F12 for more...`n`nThanks for trying!",15)
 Notify("f","f",13,"TC=Red GR=2 BT=2")
 Notify("f","f",13,"TC=Red GR=4 BT=2")
 Notify("f","f",13,"TC=Red GR=6 BT=2")
 Notify("f","f",13,"TC=Red GR=9 BT=2 BC=Red")
 Notify()
 Notify()
 Notify()
 Hotkey, ^+F12, Notify_Demo2
Return
Notify_Demo2:
 Notify()
 Notify("Notification:","This one won't go away unless clicked",0)
 Hotkey, ^+F12, Notify_Demo3
Return
Notify_Demo3:
; NotifyID := Notify("Test Notify","This notification will close in 2 seconds...", 2, "","Red", 8, "Black")
 NotifyID := Notify()
 Hotkey, ^+F12, Notify_Demo1
Return

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

Notify(Title="Notification!!!",Message="",Duration=15,Options="")
{
 Static                     ;=== assume-static mode for arrays of options
 Critical                  ;=== don't allow interruption
 ;Global Notify_Action := Action            ;=== global Action label name, i don't know a way to keep actions but not have a global

 static GF := 11    ;GF is Initial GN      ;=== defaults if no options
 static GL := 30      ;GM is Last GN         ;=== options are saved between calls (ie only set once)
 static GC := "FFFFAA"   ;GC is Gui Color
 static GR := 9      ;GR is Gui Radius
 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 Color
 static BT := 2      ;BT is Border Thickness
 static BF := 150   ;BF is Border Flash Speed
 static AC := ""   ;AC is Clicked Action (gosub label when clicked)
 static AT := ""   ;AT is Action Timeout (gosub label when timeout)
 static AI := ""   ;AI is Action In (not really useful, is it? an action upon creation)
 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)

 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 = (GF=1) means value starts at 4 (needs to strip quotes if used)

 GN := GF
 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
    GN := GF ;Return 0                  ;=== 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 (Title)
  Gui, %GN%:Add, Text, gNotify_Action, % Title
 Gui, %GN%:Font, w%MW% s%MS% c%MC%
 If ((Title) && (Message))
  Gui, %GN%:Margin, , -5
 If (Message)
  Gui, %GN%:Add, Text, gNotify_Action, % Message
 If ((Title) && (Message))
  Gui, %GN%:Margin, , 8
 Gui, %GN%:Show, Hide, NotifyGui
 Gui  %GN%:+LastFound
 WinGetPos, GUIX, GUIY, GW, GH
 Gui, %GN%:Add, Text, x0 y0 w%GW% h%GH% gNotify_Action BackgroundTrans ;=== for clicking anywhere on the notification instead of just the text
 WinSet, Region, % "0-0 w" GW " h" GH " R" GR "-" GR   ;=== round corners of notification, notification gui creation END

 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
 WinSet, Region, % "0-0 w" GW+(BT*2) " h" GH+(BT*2) " R" GR "-" GR
 WinSet, Transparent, 105                  ;=== background gui END

 Gui, %GN2%:Show, % "Hide x" NewX-BT " y" NewY-BT " w" GW+3 " h" GH+3
 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
  Notify_Exit%GN% = 1
 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
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, GN, A_ThisLabel, NotifyKill
 SetTimer, NotifyFlash%GN%, Off
 Gui, % GN + 20 ":Destroy"
 Gui  %GN%:+LastFound
 NotifyGuiID := WinExist()
 DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",300,"UInt", "0x00050001")    ;=== slide right SLOW timed-out notifications
 Gui, %GN%:Destroy
 StringReplace, NotifyList, NotifyList, % "|" GN
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
}



edit: oops, i guess yo uneed all those statics so they dont get reinitialized

edit: ok version 0.3 is updated in first post


Last edited by gwarble on Mon Sep 14, 2009 6:26 am; edited 1 time in total
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3, 4, 5, 6, 7, 8, 9  Next
Page 1 of 9

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group