File "Toast.inc"
Path: /Translater/inc/Toast.inc
File size: 17.09 KB
MIME-type: text/plain
Charset: utf-8
%LOGME = 0
'--------------------------------------------------------------------------------
' ** Constants **
'--------------------------------------------------------------------------------
%TICK = 15 ' smaller amount of time(ms) used in transitions
%TIMER_SHOW = 2001
%TIMER_PAUSE = 2002
%TIMER_HIDE = 2003
%ITALIC = 2
%UNDERLINE = 4
%STRIKETHROUGH = 8
%BOLD = 16
%GWL_STYLE = -16
%GWL_EXSTYLE = -20
%HWND_TOPMOST = &HFFFFFFFF???
%SWP_NOSIZE = &H0001
%SWP_NOMOVE = &H0002
%LWA_COLORKEY = &H00000001
%LWA_ALPHA = &H00000002
%SEE_MASK_NOCLOSEPROCESS = &H00000040
%SEE_MASK_FLAG_NO_UI = &H00000400
%SEE_MASK_UNICODE = &H00004000
%WM_SETICON = &H80
'--------------------------------------------------------------------------------
%INVALID_HANDLE_VALUE = &HFFFFFFFF???
'%TRUE = -1
'%FALSE = 0
%INFINITE = &HFFFFFFFF??? ' Infinite timeout
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
' ** Globals **
'--------------------------------------------------------------------------------
GLOBAL toast_hFnt AS DWORD ' fonts
GLOBAL toast_width AS LONG
GLOBAL toast_height AS LONG
GLOBAL toast_alpha AS LONG
GLOBAL toast_colf AS LONG
GLOBAL toast_colb AS LONG
GLOBAL toast_text AS STRING
GLOBAL toast_pause AS LONG
GLOBAL toast_dialog() AS DWORD
GLOBAL toast_thread() AS DWORD
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
' ** Constructors **
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_SetFont (family AS STRING, siz AS LONG, weight AS LONG)
LOGME " Toast_SetFont: " + family + ", " + FORMAT$(siz) + ", " + FORMAT$(weight)
' weight: 0 normal, 2 italic, 4 bold
IF toast_hFnt <> 0 THEN FONT END toast_hFnt ' new font -> release previous one
FONT NEW family, siz, weight TO toast_hFnt
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_SetWidth (w AS LONG) ' w in pixels
LOGME " Toast_SetWidth: " + FORMAT$(w)
toast_width = w
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_SetHeight (h AS LONG) ' h in pixels
LOGME " Toast_SetHeight: " + FORMAT$(h)
toast_height = h
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_SetAlpha (a AS LONG) ' 0 <= a <= 255
LOGME " Toast_SetAlpha: " + FORMAT$(a)
toast_alpha = a
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_SetText (t AS STRING)
LOGME " Toast_SetText: " + $DQ + t + $DQ
toast_text = t
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_SetDuration (p AS LONG)
LOGME " Toast_SetDuration: " + FORMAT$(p) + " ms"
toast_pause = p
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION RGB2BGR(rgb_c AS STRING) AS STRING ' convert a RGB color to a BGR color
LOCAL bgr_c AS STRING
bgr_c = RIGHT$(rgb_c,2) + MID$(rgb_c,3,2) + LEFT$(rgb_c,2)
FUNCTION = bgr_c
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_SetTextColor (c AS STRING) ' c = hexadecimal color "RRGGBB"
LOGME " Toast_SetTextColor: &H" + c
toast_colf = VAL("&H00" + RGB2BGR(c))
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_SetBackgroundColor (c AS STRING) ' c = hexadecimal color "RRGGBB"
LOGME " Toast_SetBackgroundColor: &H" + c
toast_colb = VAL("&H00" + RGB2BGR(c))
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
' ** Functions and Subs **
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
MACRO TOAST_MAKEDLG ' (internal) common to Toast_Show_Sync() & Toast_Show_Async()
LOCAL hDlg AS DWORD
DIALOG NEW PIXELS, 0, EXE.NAME$, 0, 0, toast_width, toast_height TO hDlg
DIALOG SET COLOR hDlg, -1, %RGB_MAGENTA
CONTROL ADD GRAPHIC, hDlg, 1000, "", 0, 0, toast_width, toast_height
END MACRO
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_Show_Sync () ' Synchronous (blocking) call
LOCAL i AS LONG
TOAST_MAKEDLG
i = Toast_Create(hDlg)
LOGME "Toast NO_" + FORMAT$(i) + " (" + FORMAT$(hDlg) _
+ ") has been created as a new Synchronous (blocking) toast"
DIALOG SHOW MODAL hDlg CALL Toast_CB
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_Show_Async () ' Asynchronous (non-blocking) call
LOCAL hThread AS DWORD
LOCAL i AS LONG
THREAD CREATE Toast_NewThread(0) TO hThread
ARRAY SCAN toast_thread(), =0, TO i
toast_thread(i) = hThread
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
THREAD FUNCTION Toast_NewThread (BYVAL h AS DWORD) AS LONG ' thread used by Async
LOCAL i AS LONG
TOAST_MAKEDLG
i = Toast_Create(hDlg)
LOGME "Toast NO_" + FORMAT$(i) + " (" + FORMAT$(hDlg) _
+ ") has ben created as a new Asynchronous (NON-blocking) toast"
DIALOG SHOW MODAL hDlg CALL Toast_CB
FUNCTION = -1
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION Toast_Create (BYVAL hDlg AS DWORD) AS LONG
IF UBOUND(toast_dialog) < 0 THEN
REDIM toast_dialog(1 TO 99)
REDIM toast_thread(1 TO 99)
END IF
LOCAL i AS LONG
ARRAY SCAN toast_dialog(), =0, TO i
toast_dialog(i) = hDlg
FUNCTION = i
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION Toast_Find (BYVAL hDlg AS DWORD) AS LONG
LOCAL i AS LONG
ARRAY SCAN toast_dialog(), =hDlg, TO i
FUNCTION = i
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_Release (BYVAL hDlg AS DWORD)
LOCAL i, lRes AS LONG
ARRAY SCAN toast_dialog(), =hDlg, TO i
toast_dialog(i) = 0
IF toast_thread(i) <> 0 THEN
THREAD CLOSE toast_thread(i) TO lRes
toast_thread(i) = 0
END IF
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_Enumerate ()
LOCAL i AS LONG
LOGME "Enumerating toasts..."
FOR i = 1 TO 99
IF toast_dialog(i) = 0 THEN EXIT FOR
LOGME " - Toast NO_" + FORMAT$(i) + " (" + FORMAT$(toast_dialog(i)) + ")"
NEXT
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
'DECLARE FUNCTION SetTimer LIB "User32.dll" ALIAS "SetTimer" _
' (BYVAL hWnd AS DWORD, BYVAL nIDEvent AS DWORD, BYVAL uElapse AS DWORD, _
' OPTIONAL BYVAL lpTimerFunc AS DWORD) AS DWORD
'--------------------------------------------------------------------------------
DECLARE FUNCTION KillTimer LIB "User32.dll" ALIAS "KillTimer" _
(BYVAL hWnd AS DWORD, BYVAL nIDEvent AS DWORD) AS LONG
'--------------------------------------------------------------------------------
DECLARE FUNCTION WaitForSingleObject LIB "Kernel32.dll" _
ALIAS "WaitForSingleObject" (BYVAL hHandle AS DWORD, _
BYVAL dwMilliseconds AS DWORD) AS DWORD
'--------------------------------------------------------------------------------
DECLARE FUNCTION CloseHandle LIB "Kernel32.dll" ALIAS "CloseHandle" _
(BYVAL hObject AS DWORD) AS LONG
'--------------------------------------------------------------------------------
DECLARE FUNCTION SetWindowLong LIB "User32.dll" ALIAS "SetWindowLongW" _
(BYVAL hWnd AS DWORD, BYVAL nIndex AS LONG, BYVAL lNewLong AS LONG) AS LONG
'--------------------------------------------------------------------------------
DECLARE FUNCTION GetWindowLong LIB "User32.dll" ALIAS "GetWindowLongW" _
(BYVAL hWnd AS DWORD, BYVAL nIndex AS LONG) AS LONG
'--------------------------------------------------------------------------------
DECLARE FUNCTION SetWindowPos LIB "User32.dll" ALIAS "SetWindowPos" _
(BYVAL hWnd AS DWORD, BYVAL hWndInsertAfter AS DWORD, BYVAL x AS LONG, _
BYVAL y AS LONG, BYVAL cx AS LONG, BYVAL cy AS LONG, _
BYVAL wFlags AS DWORD) AS LONG
'--------------------------------------------------------------------------------
DECLARE FUNCTION SetLayeredWindowAttributes LIB "User32.dll" _
ALIAS "SetLayeredWindowAttributes" (BYVAL hwnd AS DWORD, _
BYVAL crKey AS DWORD, BYVAL bAlpha AS BYTE, BYVAL dwFlags AS DWORD) AS LONG
'--------------------------------------------------------------------------------
DECLARE FUNCTION SendMessage LIB "User32.dll" ALIAS "SendMessageW" _
(BYVAL hWnd AS DWORD, BYVAL dwMsg AS DWORD, BYVAL wParam AS DWORD, _
BYVAL lParam AS LONG) AS LONG
'--------------------------------------------------------------------------------
'DECLARE FUNCTION SetWindowsHookEx LIB "User32.dll" ALIAS "SetWindowsHookExW" _
' (BYVAL idHook AS LONG, BYVAL lpfn AS DWORD, BYVAL hMod AS DWORD, _
' BYVAL dwThreadId AS DWORD) AS DWORD
'--------------------------------------------------------------------------------
DECLARE FUNCTION GetCurrentThreadId LIB "Kernel32.dll" _
ALIAS "GetCurrentThreadId" () AS DWORD
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
MACRO CreateTimer (evt, tid)
evt = SetTimer(CB.HNDL, tid, %TICK, BYVAL 0)
DIALOG POST CB.HNDL, %WM_TIMER, tid, 0
END MACRO
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
CALLBACK FUNCTION Toast_CB ' Common Toast CallBack
STATIC x, y, t, evtShow, evtPause, evtHide AS LONG
STATIC t0 AS DOUBLE
LOCAL e AS STRING
LOCAL i AS LONG
SELECT CASE CB.MSG
CASE %WM_INITDIALOG
t0 = TIMER
Toast_Fill CB.HNDL ' Set toast properties & initialize its content
i = Toast_Find(CB.HNDL)
x = (i - 1) * (toast_width + 1)
y = -toast_height
CreateTimer (evtShow, %TIMER_SHOW) ' Start timer event for dialog show
CASE %WM_DESTROY
e = "Toast NO_" + FORMAT$(Toast_Find(CB.HNDL)) + " (" + FORMAT$(CB.HNDL) + ")"
LOGME e + " destroyed after displaying for " + FORMAT$(INT((TIMER-t0)*1000)) + " ms"
Toast_Release CB.HNDL
CASE %WM_TIMER
' Timer to show the toast
IF CB.WPARAM = %TIMER_SHOW THEN
IF y < 0 THEN
y += 5
DIALOG SET LOC CB.HNDL, x, y
ELSE
KillTimer CB.HNDL, evtShow
t = 1
CreateTimer (evtPause, %TIMER_PAUSE) ' Start timer event to pause the toast
END IF
' Timer to pause the toast
ELSEIF CB.WPARAM = %TIMER_PAUSE THEN
IF t = 0 THEN EXIT FUNCTION ' Cannot pause until toast is fully shown
IF t < toast_pause THEN
t += %TICK
ELSE
KillTimer CB.HNDL, evtPause
CreateTimer (evtHide, %TIMER_HIDE) ' Start timer event to hide the toast
END IF
' Timer to hide the toast
ELSEIF CB.WPARAM = %TIMER_HIDE THEN
IF y > -toast_height THEN
y -= 5
DIALOG SET LOC CB.HNDL, x, y
ELSE
KillTimer CB.HNDL, evtHide
DIALOG END CB.HNDL
END IF
END IF
END SELECT
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Toast_Fill (BYVAL hDlg AS DWORD)
LOCAL w, h AS LONG
' Initialize Styles and Extended Styles of dialog
SetWindowLong hDlg, %GWL_style, %WS_POPUP OR %WS_BORDER OR %DS_NOFAILCREATE _
OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_3DLOOK _
OR %DS_MODALFRAME OR %WS_DLGFRAME OR %DS_SETFONT OR %WS_CAPTION
SetWindowLong hDlg, %GWL_EXstyle, %WS_EX_WINDOWEDGE OR %WS_EX_CONTROLPARENT _
OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR _
OR %WS_EX_TOOLWINDOW
' Set Always On Top
SetWindowPos hDlg, %HWND_TOPMOST, 0, 0, 0, 0, %SWP_NOMOVE OR %SWP_NOSIZE
' Remove Caption
SetWindowLong hDlg, %GWL_style, GetWindowLong(hDlg, %GWL_style) XOR %WS_CAPTION
' Set Dialog alpha / Transparent Font / Transparent Background
SetWindowLong hDlg, %GWL_EXSTYLE, GetWindowLong(hDlg, %GWL_EXstyle) OR %WS_EX_LAYERED
SetLayeredWindowAttributes hDlg, %RGB_MAGENTA, toast_alpha, %LWA_Colorkey OR %LWA_ALPHA
' Initialize Dialog Content
GRAPHIC ATTACH hDlg, 1000, REDRAW
GRAPHIC COLOR toast_colf, toast_colb
GRAPHIC SET FONT toast_hFnt
GRAPHIC CLEAR
CONTROL GET SIZE hDlg, 1000 TO w, h
WRAP toast_text, w
GRAPHIC REDRAW
END SUB
'--------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------------
SUB WRAP (FullString AS STRING, w AS LONG)
LOCAL Part1, Part2 AS STRING
gbSplitWord FullString, w, Part1, Part2
WHILE LEN(Part2)
GRAPHIC PRINT Part1
gbSplitWord Part2, w, Part1, Part2
WEND
GRAPHIC PRINT Part1
END SUB
'-----------------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------------
SUB gbSplitWord(BYVAL FullString AS STRING, BYVAL w AS LONG, Part1 AS STRING, Part2 AS STRING)
LOCAL i, ww, hh AS LONG
LOCAL PreviousWords, CurrentWord AS STRING
'if only one word is in the string (no delimiter), use the entire string as Part1
i = INSTR(FullString, $SPC)
IF i = 0 THEN Part1 = FullString : Part2 = "" : EXIT SUB
'if first word is wider than available width, use that word as Part1
Part1 = LEFT$(FullString, i-1)
GRAPHIC TEXT SIZE Part1 TO ww, hh
IF ww > w THEN Part2 = MID$(FullString, i+1) : EXIT SUB
'go through all words
FOR i = 1 TO PARSECOUNT(FullString, $SPC) 'cycle through all words
CurrentWord = PARSE$(FullString, $SPC, i)
GRAPHIC TEXT SIZE PreviousWords + IIF$(i=1,"",$SPC) + CurrentWord TO ww, hh
IF ww > w THEN
'adding CurrentWord WILL exceed available width
Part1 = PreviousWords
Part2 = MID$(FullString, LEN(Part1)+2)
EXIT SUB
ELSE
'adding CurrentWord WILL NOT exceed available width
PreviousWords += IIF$(i=1,"",$SPC) + CurrentWord
Part1 = PreviousWords
Part2 = ""
END IF
NEXT
END SUB
'-----------------------------------------------------------------------------------------------
'-----------------------------------------------------------------------------------------------
SUB LOGME (e AS STRING)
IF ISFALSE %LOGME THEN EXIT SUB
LOCAL ff AS LONG
LOCAL d, t AS STRING
' Create TimeStamp
d = DATE$
d = RIGHT$(d,4) + LEFT$(d,2) + MID$(d, 4, 2)
t = TIME$
REPLACE ":" WITH "" IN t
t = d + "-" + t + ","
t = t + FORMAT$((TIMER*1000) MOD 1000, "000")
' Write To Log File
ff = FREEFILE
OPEN EXE.PATH$ + EXE.NAME$ + ".log" FOR APPEND AS #ff
PRINT #ff, "[" + t + "] " + e
CLOSE #ff
END SUB
'-----------------------------------------------------------------------------------------------