Jump to content

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

Toaster Popups


  • Please log in to reply
20 replies to this topic
Rhys
  • Members
  • 761 posts
  • Last active: Aug 09 2013 04:53 PM
  • Joined: 17 Apr 2007
Note - Please use Engunneer's version until I clean mine up!

Bartimus was looking for a Toaster-Style popup window, so I made this with help from aCkRiTe, BoBo, and Engunneer:
#SingleInstance Force
#NoTrayIcon
#NoEnv
DetectHiddenWindows, On

SysGet, Workspace, MonitorWorkArea
Gui, -Caption +ToolWindow +LastFound +AlwaysOnTop +Border
Gui, Color, White
Gui, Font, s14 cRed
Gui, Add, Text, gFade, Here is your toaster popup!`nClick me to make me go away!
Gui, Show, Hide
GUI_ID := WinExist()
WinGetPos, GUIX, GUIY, GUIWidth, GUIHeight, ahk_id %GUI_ID%
NewX := WorkSpaceRight-GUIWidth-5
NewY := WorkspaceBottom-GUIHeight-5
Gui, Show, Hide x%NewX% y%NewY%

DllCall("AnimateWindow","UInt",GUI_ID,"Int",500,"UInt","0x00040008") ; TOAST!
Return

Fade:
DllCall("AnimateWindow","UInt",GUI_ID,"Int",1000,"UInt","0x90000") ; Fade out when clicked
ExitApp

Since Bartimus wanted a built in function, I decided it was a good time to learn how to do that. Here's the code in function form (do I need to use that arbitrary Gui # to avoid interference with any other GUIs??) -
;Syntax: ToasterPopup(["Message"],["Font Color"],["Font Size"],["Background Color"],[Lifetime in MS (0 to persist until clicked)]
;Example:
ToasterPopup("This is a Toaster Popup...", "Blue", "14", "White", 0)
Return

ToasterPopup(TP_Message, TP_FontColor, TP_FontSize, TP_BGColor, TP_Lifespan)
{
	DetectHiddenWindows, On
	SysGet, Workspace, MonitorWorkArea
	Gui, 89:-Caption +ToolWindow +LastFound +AlwaysOnTop +Border
	Gui, 89:Color, %TP_BGColor%
	Gui, 89:Font, s%TP_FontSize% c%TP_FontColor%
	Gui, 89:Add, Text, gTP_Fade, %TP_Message%
	Gui, 89:Show, Hide
	Global GUI_ID ;Is this the proper way to use Global? I need it for TP_Fade...
	GUI_ID := WinExist()
	WinGetPos, GUIX, GUIY, GUIWidth, GUIHeight, ahk_id %GUI_ID%
	NewX := WorkSpaceRight-GUIWidth-5
	NewY := WorkspaceBottom-GUIHeight-5
	Gui, 89:Show, Hide x%NewX% y%NewY%

	DllCall("AnimateWindow","UInt",GUI_ID,"Int",500,"UInt","0x00040008") ; TOAST!
	If (TP_Lifespan=0)
	Return
	Else
	{
		Sleep, %TP_Lifespan%
		GoSub, Fade
		Return
	}

TP_Fade:
DllCall("AnimateWindow","UInt",GUI_ID,"Int",1000,"UInt","0x90000") ; Fade out when clicked
Return
}


engunneer
  • Moderators
  • 9162 posts
  • Last active: Sep 12 2014 10:36 PM
  • Joined: 30 Aug 2005
You appear to have an error, Also, I have made some changes so that the script can do other things when a LifeSpan is given, and also now supports optional parameters (since you specified [ and ] in the example comment
;Syntax: ToasterPopup([Message, FontColor, FontSize, BackgroundColor, Lifetime]); Lifetime in MS (0 to persist until clicked)
;Example:
TP_Show("This is a Toaster Popup...`nClick to make it go away")
TP_Wait()

TP_Show("This one diappears automatically", "Blue", "12", "White", 1000)

Return


TP_Show(TP_Message="Hello, World", TP_FontColor="Blue", TP_FontSize="12", TP_BGColor="White", TP_Lifespan=0)
{
   Global TP_GUI_ID 
   DetectHiddenWindows, On
   SysGet, Workspace, MonitorWorkArea
   Gui, 89:-Caption +ToolWindow +LastFound +AlwaysOnTop +Border
   Gui, 89:Color, %TP_BGColor%
   Gui, 89:Font, s%TP_FontSize% c%TP_FontColor%
   Gui, 89:Add, Text, gTP_Fade, %TP_Message%
   Gui, 89:Show, Hide
   TP_GUI_ID := WinExist()
   WinGetPos, GUIX, GUIY, GUIWidth, GUIHeight, ahk_id %TP_GUI_ID%
   NewX := WorkSpaceRight-GUIWidth-5
   NewY := WorkspaceBottom-GUIHeight-5
   Gui, 89:Show, Hide x%NewX% y%NewY%

   DllCall("AnimateWindow","UInt",TP_GUI_ID,"Int",500,"UInt","0x00040008") ; TOAST!
   If (TP_Lifespan)
     SetTimer, TP_Fade, % "-" TP_Lifespan
   Return
}

TP_Wait() {
  Global TP_GUI_ID
  WinWaitClose, ahk_id %TP_GUI_ID%
}

TP_Fade:
   DllCall("AnimateWindow","UInt",TP_GUI_ID,"Int",1000,"UInt","0x90000") ; Fade out when clicked
   Gui, 89:Destroy
Return


tested! - StdLib compatible.

May also be good to add a target gosub to be run if clicked

Thanks, I may have a use for this

Feature request - Allow more than one at once.

Rhys
  • Members
  • 761 posts
  • Last active: Aug 09 2013 04:53 PM
  • Joined: 17 Apr 2007
I still have a lot to learn about functions, thanks very much for your revisions. I was happy just to get it working, but you've made it much more viable.

engunneer
  • Moderators
  • 9162 posts
  • Last active: Sep 12 2014 10:36 PM
  • Joined: 30 Aug 2005
This version allows you to call a label if the popup is clicked, but does not call it if you fade normally

;Syntax: ToasterPopup([Message, FontColor, FontSize, BackgroundColor, Lifetime, TP_CallBack]); Lifetime in MS (0 to persist until clicked)
;Example:
TP_ID := TP_Show("This is a Toaster Popup...`nClick to make it go away")
TP_Wait(TP_ID)

TP_Show("This one diappears automatically", 1000, "Blue", "12", "White")
TP_Wait()

TP_Show("This one calls another subroutine when clicked", 5000, "Blue", "12", "White","Wow")
Return


Wow:
Msgbox It called me!
Return

TP_Show(TP_Message="Hello, World", TP_Lifespan=0, TP_FontColor="Blue", TP_FontSize="12", TP_BGColor="White",  TP_CallBack="")
{
   Global TP_CallBackTarget, clicked
   TP_CallBackTarget := TP_CallBack
   DetectHiddenWindows, On
   SysGet, Workspace, MonitorWorkArea
   Gui, 89:-Caption +ToolWindow +LastFound +AlwaysOnTop +Border
   Gui, 89:Color, %TP_BGColor%
   Gui, 89:Font, s%TP_FontSize% c%TP_FontColor%
   Gui, 89:Add, Text, gTP_Fade vClicked, %TP_Message%
   Gui, 89:Show, Hide, TP_Gui
   TP_GUI_ID := WinExist("TP_Gui")
   WinGetPos, GUIX, GUIY, GUIWidth, GUIHeight, ahk_id %TP_GUI_ID%
   NewX := WorkSpaceRight-GUIWidth-5
   NewY := WorkspaceBottom-GUIHeight-5
   Gui, 89:Show, Hide x%NewX% y%NewY%

   DllCall("AnimateWindow","UInt",TP_GUI_ID,"Int",500,"UInt","0x00040008") ; TOAST!

   If (TP_Lifespan)
     SetTimer, TP_Fade, % "-" TP_Lifespan
   Return TP_GUI_ID

  TP_Fade:
     If (A_GuiControl="Clicked") and TP_CallBackTarget
    {
      If IsLabel(TP_CallBackTarget)
        Gosub, %TP_CallBackTarget%
      else
      {
        If InStr(TP_CallBackTarget, "(")
          Msgbox Cannot yet callback a function
        else
          Msgbox, not a valid CallBack
      }
        
    }
     TP_GUI_ID := WinExist("TP_Gui")
     DllCall("AnimateWindow","UInt",TP_GUI_ID,"Int",1000,"UInt","0x90000") ; Fade out when clicked
     Gui, 89:Destroy
  Return
}

TP_Wait(TP_GUI_ID="") {
  If not (TP_GUI_ID)
   TP_GUI_ID := WinExist("TP_Gui")
  WinWaitClose, ahk_id %TP_GUI_ID%
}



Murp-e
  • Members
  • 531 posts
  • Last active: Sep 27 2011 11:44 AM
  • Joined: 12 Jan 2007
I've included the toaster script into my code through the #include command and it works and looks great. Easy to implement. I have an issue with it that I'm not sure how to handle though, I have a button which runs only a few lines of code and executes very fast. I want to notify the user with a toaster popup every time the button is pressed, but when the button is pressed before the last popup has dissappeared the code fails. I've deliberately removed the "TP_Wait" command since I want the code to be run right after the button is pushed as opposed to waiting until the popup has dissappeared. The latter would solve my problem but it would just be far too slow.

To clarify: I want one popup for every click of the button, I want them to appear immidiately after the button is pushed and I don't want to have to wait until one popup has dissappeared to be able to display another.

Can this be easily accomplished with the code as it is or will it require a lot of extra work??

Rhys
  • Members
  • 761 posts
  • Last active: Aug 09 2013 04:53 PM
  • Joined: 17 Apr 2007
Try placing Gui, 89:Destroy at the top of the function - If this doesn't work let me know. I remember some 'oddness' that happened when another popup came through when the other was 'auto-fading'.

I recently used toaster popups to display notification whenever a tab on a 'bulletin board' app was updated - These I set to last until clicked to clear. The new toaster popup replaced the existing one w/o issue (oops - see edit below).

Edit: It looks like I had already put the destroy line in my local copy of the function and forgot to update it here... :shock:

Murp-e
  • Members
  • 531 posts
  • Last active: Sep 27 2011 11:44 AM
  • Joined: 12 Jan 2007
Rhys,

Thanks a lot you for your quick reply! That's an easy solution indeed and I should have thought of it. It still has one snag though, code execution freezes for the duration of the dll "toast" animation. So I can only click on the button after the animation is complete. That said, since the animation only lasts a very short time, this isn't so much of an issue for me anymore. If there's an equally simple solution to this I'm listening, if not, this works just fine. Thanks again.

ezuk
  • Members
  • 149 posts
  • Last active: Jan 02 2013 08:54 AM
  • Joined: 04 Jun 2005
This version adds a type face argument following the font size.

;Syntax: ToasterPopup([Message, FontColor, FontSize, FontFace, BackgroundColor, Lifetime, TP_CallBack]); Lifetime in MS (0 to persist until clicked)
;Example:
TP_ID := TP_Show("This is a Toaster Popup...`nClick to make it go away")
TP_Wait(TP_ID)

TP_Show("This one diappears automatically", 1000, "Blue", "12", "Arial Black", "White")
TP_Wait()

TP_Show("This one calls another subroutine when clicked", 5000, "Blue", "12", "Times New Roman", "White","Wow")
Return


Wow:
Msgbox It called me!
Return

TP_Show(TP_Message="Hello, World", TP_Lifespan=0, TP_FontColor="Blue", TP_FontSize="14", TP_FontFace="Colibri", TP_BGColor="White",  TP_CallBack="")
{
   Global TP_CallBackTarget, clicked
   TP_CallBackTarget := TP_CallBack
   DetectHiddenWindows, On
   SysGet, Workspace, MonitorWorkArea
   Gui, 89:-Caption +ToolWindow +LastFound +AlwaysOnTop +Border
   Gui, 89:Color, %TP_BGColor%
   Gui, 89:Font, s%TP_FontSize% c%TP_FontColor%,%TP_FontFace%
   Gui, 89:Add, Text, gTP_Fade vClicked, %TP_Message%
   Gui, 89:Show, Hide, TP_Gui
   TP_GUI_ID := WinExist("TP_Gui")
   WinGetPos, GUIX, GUIY, GUIWidth, GUIHeight, ahk_id %TP_GUI_ID%
   NewX := WorkSpaceRight-GUIWidth-5
   NewY := WorkspaceBottom-GUIHeight-5
   Gui, 89:Show, Hide x%NewX% y%NewY%

   DllCall("AnimateWindow","UInt",TP_GUI_ID,"Int",500,"UInt","0x00040008") ; TOAST!

   If (TP_Lifespan)
     SetTimer, TP_Fade, % "-" TP_Lifespan
   Return TP_GUI_ID

  TP_Fade:
     If (A_GuiControl="Clicked") and TP_CallBackTarget
    {
      If IsLabel(TP_CallBackTarget)
        Gosub, %TP_CallBackTarget%
      else
      {
        If InStr(TP_CallBackTarget, "(")
          Msgbox Cannot yet callback a function
        else
          Msgbox, not a valid CallBack
      }
        
    }
     TP_GUI_ID := WinExist("TP_Gui")
     DllCall("AnimateWindow","UInt",TP_GUI_ID,"Int",1000,"UInt","0x90000") ; Fade out when clicked
     Gui, 89:Destroy
  Return
}

TP_Wait(TP_GUI_ID="") {
  If not (TP_GUI_ID)
   TP_GUI_ID := WinExist("TP_Gui")
  WinWaitClose, ahk_id %TP_GUI_ID%
}




infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
Here's a version that gives you the option to have a bold title for the popup, and adds capturing the GuiEvent (including rightclick) of the user for use with the callback label (or whatever). To reference the event, check the global variable: TP_GuiEvent which is set to the same as A_GuiEvent.
; ##### ### Example ### ##### ;
Title = This Title is Bold and optional
Message = This is normal text. You can display a bunch of information here.
Lifespan = 8000 ;ms
FontSize = 8
FontColor = 0x00437e
BGColor = 0xE3F2FE

TP_Show(Title, Message, Lifespan, FontSize, FontColor, BGColor, "Test") 
return

Test:
	MsgBox, , TP Callback Test, Event received:  %TP_GuiEvent%		`
return



;Use: TP_Show([ Title, Message, Lifespan, FontSize, FontColor, BGColor, CallbackLabel ])   
TP_Show(TP_Title="", TP_Message="Hello, World", TP_Lifespan=0, TP_FontSize="12", TP_FontColor="Blue", TP_BGColor="White",  TP_CallBack="")
{
	Global TP_GuiEvent
	Static TP_CallBackTarget, TP_GUI_ID
	TP_CallBackTarget := TP_CallBack
	
	DetectHiddenWindows, On
	SysGet, Workspace, MonitorWorkArea
	
	Gui, 89:-Caption +ToolWindow +LastFound +AlwaysOnTop +Border
	Gui, 89:Color, %TP_BGColor%
	If (TP_Title) {
		TP_TitleSize := TP_FontSize + 1
		Gui, 89:Font, s%TP_TitleSize% c%TP_FontColor% w700
		Gui, 89:Add, Text, r1 center gTP_Fade x5 y5, %TP_Title%
		Gui, 89:Margin, 0, 0
	}
	Gui, 89:Font, s%TP_FontSize% c%TP_FontColor% w400
	Gui, 89:Add, Text, gTP_Fade x5, %TP_Message%
	IfNotEqual, TP_Title,, Gui, 89:Margin, 5, 5
	Gui, 89:Show, Hide, TP_Gui
	TP_GUI_ID := WinExist("TP_Gui")
	WinGetPos, , , GUIWidth, GUIHeight, ahk_id %TP_GUI_ID%
	NewX := WorkSpaceRight-GUIWidth-5
	NewY := WorkspaceBottom-GUIHeight-5
	Gui, 89:Show, Hide x%NewX% y%NewY%
	DllCall("AnimateWindow","UInt", TP_GUI_ID,"Int", GuiHeight*10,"UInt", 0x40008)
	If (TP_Lifespan)
		SetTimer, TP_Fade, -%TP_Lifespan%
Return TP_GUI_ID

89GuiContextMenu:
TP_Fade:
	If (A_GuiEvent and TP_CallBackTarget)
	{
		TP_GuiEvent := A_GuiEvent
		If IsLabel(TP_CallBackTarget)
			Gosub, %TP_CallBackTarget%
		else
		{
			If InStr(TP_CallBackTarget, "(")
			Msgbox Cannot yet callback a function
			else
			Msgbox, not a valid CallBack
		}
	}
	DllCall("AnimateWindow","UInt", TP_GUI_ID,"Int", 600,"UInt", 0x90000)
	Gui, 89:Destroy
Return
}

TP_Wait(TP_GUI_ID="") {
  If not (TP_GUI_ID)
   TP_GUI_ID := WinExist("TP_Gui")
  WinWaitClose, ahk_id %TP_GUI_ID%
}
If you use a title, there could be problems where clicking it doesn't activate the gLabel because both text areas (title and message) could be not the same size and you could not click on a control, just empty space between them. I tried helping this by using no margin between them, maybe an OnMessage() would work better & for the whole gui. But as long as you click on text, it should work. :)

Bartimus
  • Members
  • 237 posts
  • Last active: Nov 10 2016 05:01 PM
  • Joined: 10 Nov 2005
W:oW !

I didn't know there was a whole other project on this. The work looks great. Glad I sorta had a hand in it all.... sorta :)

Ice_Tea
  • Members
  • 131 posts
  • Last active: Aug 25 2010 11:11 AM
  • Joined: 12 Jan 2008
Nice1!!!

I merged ezuk's & infogulch's modifications, and reordered the parameters in a way that I think lazy people like, as ahk wont let me have empty parameters I've put parameters like fontsize/color/face/bgcolor @ as the last ones of the parameters (it uses infogulch's setup as default, I liked his/her setup...), I just find this usefull as I don't like filling in many parameters...

As infogulch said; the text labels aren't covering the whole box, therefor it will not trigger on click/rclick unless you hit the text labels...
EDIT: I partly fixed the problem infogulch adressed, the title and text labels are now covering the width of the window, meaning that you can now click @ the far right of the title, earlier it required you to hit the title, the 5 first x&y pixels are not clickable...

EDIT 2: Added: Speed of the toaster, how fast it should appear, 10 is the default speed, 2 is faster than 10, 100 is really slow, meaning higher numbers are slower! NOTE!!: My version doesn't use same labels as I've added this to my Lib I've renamed the functions to names that I feel comfortable with... It also destroys the previous toaster instead of just adding additional text controls...

Title = This Title is Bold and optional
Message = This is normal text. You can display a bunch of information here.
;Lifespan = 8000 ;ms
FontSize = 8
FontColor = 0x00437e
BGColor = 0xE3F2FE
FontFace=Arial

;TP_Show(Title, Message, Lifespan, "Test", FontSize, FontColor, BGColor, FontFace) 
;tempvar := TP_Show(Title, Message, Lifespan, "Test")
tempvar := TP_Show(Title, Message, Lifespan)
;TP_Wait(tempvar)
TP_Wait()
MsgBox
return

Test:
   MsgBox, , TP Callback Test, Event received:  %TP_GuiEvent%      `
return



;Use: TP_Show([ Title, Message, Lifespan, FontSize, FontColor, BGColor, CallbackLabel ])   
Toast(TP_Title="", TP_Message="", TP_Lifespan=0, TP_CallBack="", TP_Speed="10", TP_TitleSize="9", TP_FontSize="8", TP_FontColor="0x00437e", TP_BGColor="0xE3F2FE",  TP_FontFace="")
{
   Global TP_GuiEvent
   Static TP_CallBackTarget, TP_GUI_ID
   TP_CallBackTarget := TP_CallBack
   
   DetectHiddenWindows, On
   SysGet, Workspace, MonitorWorkArea
   Gui, 89:Destroy
   Gui, 89:-Caption +ToolWindow +LastFound +AlwaysOnTop +Border
   Gui, 89:Color, %TP_BGColor%
   If (TP_Title) {
      TP_TitleSize := TP_FontSize + 1
      Gui, 89:Font, s%TP_TitleSize% c%TP_FontColor% w700, %TP_FontFace%
      Gui, 89:Add, Text, r1 gToast_Fade x5 y5, %TP_Title%
      Gui, 89:Margin, 0, 0
   }
   Gui, 89:Font, s%TP_FontSize% c%TP_FontColor% w400, %TP_FontFace%
   Gui, 89:Add, Text, gToast_Fade x5, %TP_Message%
   IfNotEqual, TP_Title,, Gui, 89:Margin, 5, 5
   Gui, 89:Show, Hide, TP_Gui
   TP_GUI_ID := WinExist("TP_Gui")
   WinGetPos, , , GUIWidth, GUIHeight, ahk_id %TP_GUI_ID%
   NewX := WorkSpaceRight-GUIWidth-5
   NewY := WorkspaceBottom-GUIHeight-5
   Gui, 89:Show, Hide x%NewX% y%NewY%
   WinGetPos,,,Width
   GuiControl, 89:Move, Static1, % "w" . GuiWidth-7
   GuiControl, 89:Move, Static2, % "w" . GuiWidth-7
   DllCall("AnimateWindow","UInt", TP_GUI_ID,"Int", GuiHeight*TP_Speed,"UInt", 0x40008)
   If (TP_Lifespan)
      SetTimer, Toast_Fade, -%TP_Lifespan%
Return TP_GUI_ID

89GuiContextMenu:
Toast_Fade:
   If (A_GuiEvent and TP_CallBackTarget)
   {
      TP_GuiEvent := A_GuiEvent
      If IsLabel(TP_CallBackTarget)
         Gosub, %TP_CallBackTarget%
      else
      {
         If InStr(TP_CallBackTarget, "(")
         Msgbox Cannot yet callback a function
         else
         Msgbox, not a valid CallBack
      }
   }
   DllCall("AnimateWindow","UInt", TP_GUI_ID,"Int", 600,"UInt", 0x90000)
   Gui, 89:Destroy
Return
}

Toast_Wait(TP_GUI_ID="") {
  If not (TP_GUI_ID)
   TP_GUI_ID := WinExist("TP_Gui")
  WinWaitClose, ahk_id %TP_GUI_ID%
}

Sry if I forgot anything...

ABCza
  • Members
  • 132 posts
  • Last active: Jan 04 2015 01:02 AM
  • Joined: 03 Jun 2008
OMFG this ROCKS!!! Thank you :)
All my scripts/snippets are released under the WTFPL: http://sam.zoy.org/wtfpl/COPYING

icefreez
  • Members
  • 180 posts
  • Last active: Jan 08 2019 10:26 PM
  • Joined: 15 May 2007
I was just looking for a nice popup GUI. This is great.

Makes a few of my scripts a little nicer for displaying notifications :D I used to just plop text centered none selectable as a tooltip :p This is much better.

Reynoldz
  • Members
  • 41 posts
  • Last active: Jul 23 2009 11:32 PM
  • Joined: 29 Jan 2009
Autohotkey needs to make a function that allows you to do this, i reckon...

Rhys
  • Members
  • 761 posts
  • Last active: Aug 09 2013 04:53 PM
  • Joined: 17 Apr 2007
Funny that I've always meant to come back and make this function a little nicer, with better options. That's the great thing about open source: Bartiumus had an idea that I hacked together a quick solution for, and several other people came in to improve it and add their own features :)

The nice thing about AHK is that you can make your own flavor of this and include it in your standard library so that you can use it easily (I'm not sure if something like this would be proper for inclusion in AHK out of the box).

I still have this tagged to come back to one day, especially for "It still has one snag though, code execution freezes for the duration of the dll "toast" animation." and "Feature request - Allow more than one at once."