Have a Break! Warnings to rest periodically to protect eyes, back, neck, joints…
It was originally discussed
here. I made the have-a-break script stand alone, and added a few features for convenience.
The script gives you a warning after a preset time, to have a break. With a hotkey you manually dim the screen (which is also good as a screen saver), and because it is too dark for work, this dark screen indicates rest. It requires some actions, but you should get up and move, so pressing a hotkey is not too much hassle. The script uses the Windows key, with double tapping. (A little time between taps makes them normal keys. Any other key or a mouse event un-dims the screen.)
After half an hour the screen gets a little dimmer with an acoustic warning. If you don't dim the screen manually, after a further minute the screen gets a little darker, with a lauder beep, which repeats in every minute. Only double tapping the Windows key stops this, with almost complete darkness on screen. It returns to normal at a key press or mouse move.
There can be an emergency situation, e.g. when you have to answer an email, no matter what. You can always exit the script (through the tray menu), but then you have to remember to start it again (or finish the email on the dimmed screen). The following looks better: first dim the screen manually with the double-tap on the Windows key, than un-dim with any key or mouse event. If you did not have enough rest, this gives you 5 minutes extra time to finish what you were doing, then the dimming/warning process resumes. If you rested enough, you get another half an hour to work.
You may also want to know when you return to the PC if you rested enough. A progress bar can be shown, but switching off the screen completely is simpler and better as a screen saver (battery saver in laptops). It is also easy to notice if the screen is off.
The script stores the time limits in a file, having the same filename as the script, but with a .ini extension. In a GUI the user can set these time values for the current session. If he wants, the current time limits can be saved to the ini file, making them the default from now on. There is an additional time limit: the next work period. If you know there is something very important, which needs more time, call up the GUI (Ctrl-Win-B) and set the Next work span value. If you want, it can be made the default first work period, by saving the settings.
Code:
#InstallMouseHook ; For mouse events included in A_TimeIdlePhysical
IniFile := RegExReplace(A_ScriptFullPath,"(\.exe$)|(\.ahk$)",".ini")
Vars = Next,Work,Rest,Xtra,Busy
Loop Parse, Vars, `, ; Get defaults form ini file
{
IniRead %A_LoopField%, %IniFile%, Times, %A_LoopField%
%A_LoopField% *= 60000
}
Gui 2:Color, 0,0 ; Black
Gui 2:-Caption +ToolWindow +E0x20 ; No title bar, No taskbar button, Transparent for clicks
Gui 2:Show, X0 Y0 W%A_ScreenWidth% H%A_ScreenHeight% ; Show semi-transparent cover window
WinGet ID, ID, A ; ...with HWND/handle ID
Winset AlwaysOnTop,ON,ahk_id %ID% ; Keep it always on the top
WinSet Transparent,0,ahk_id %ID% ; Start as transparent
SetTimer TimeCheck, 100
WorkStart := A_TickCount + Next - Work ; First work-period is Next long
TimeCheck:
If (RestStart) { ; RestStart > 0 => resting
If (A_TimeIdlePhysical+200 < A_TickCount-RestStart) {
WinSet Transparent,0,ahk_id %ID% ; User activity = end of rest
WorkStart := A_TickCount + (A_TickCount-RestStart < Rest ? Xtra-Work : 0)
dimmed := RestStart := 0
}
Else If (A_TickCount-RestStart>Rest) ; Enough rest: switch off monitor
SendMessage 0x112, 0xF170, 1,,Program Manager ; WM_SYSCOMMAND, SC_MONITORPOWER
Return ; Continue at next time check
}
If (A_TickCount > WorkStart + Work) { ; Overworked
If (not dimmed) { ; Not yet dimmed
WinSet Transparent, 50, ahk_id %ID%
SoundPlay *48
dimmed:=1, BusyStart:=A_TickCount ; Busy start time
}
If (A_TickCount > BusyStart+Busy) { ; Already dimmed, still working
WinSet Transparent, 99, ahk_id %ID%
SoundPlay *64
BusyStart := A_TickCount ; Reset for Next warning
}
}
Return
~LWin:: ; Double hit = dim, rest in dark
If (A_PriorHotKey <> A_ThisHotKey or A_TimeSincePriorHotkey > 400)
Return
WinSet Transparent, 175, ahk_id %ID%
RestStart := A_TickCount
Return
^#b:: ; Ctrl-Win-B to control the times with GUI
field("Next","Work Next [minutes]")
field("Work","Work span until break")
field("Rest","Minimum rest time")
field("Xtra","Work after short rest")
field("Busy","Time between warnings")
Gui Add, Button, x10 y+20 w99 Default, &OK
Gui Add, Button, x+10 w99, &Save
Gui Add, Button, x+10 w99, &Cancel
Gui Show
Return
field(var,text) { ; Edit + UpDown + Text
Global
Gui Font, s8, MS Sans Serif
Gui Add, Edit, w50 x30 y+10
Gui Add, UpDown, Range1-500 v%var%, % %var%//60000
Gui Font, s11, MS Sans Serif
Gui Add, Text, x+20, %text%
}
ButtonSave: ; Save time settings in ini file
Gui Submit
Loop Parse, Vars, `,
IniWrite % %A_LoopField%, %IniFile%, Times, %A_LoopField%
ButtonOK: ; Use time values set in GUI
Gui Submit
Loop Parse, Vars, `,
%A_LoopField% *= 60000
WorkStart := A_TickCount + Next - Work
Return
GuiClose:
GuiEscape: ; Close GUI
ButtonCancel:
Gui Destroy
Return