;TheWeatherGuy Weather 1.8 December 21, 2008 ;Things to Do: ;Add pictures with tooltip forecast (FileInstall) ;Change Icon ;------------------------------------------------------------------------------------------------------------------------ #SingleInstance force #NoTrayIcon #Include, Gdip.ahk ;------------------------------------------------------------------------------------------------------------------------ Set_ScriptVariables() IfNotExist, Settings.ini { Set_DefaultVariables() Display_Welcome() Load_WeatherContextMenu() Gosub, Display_Options }else { Load_WeatherContextMenu() Gosub, Update_Weather } RETURN ;------------------------------------------------------------------------------------------------------------------------ 2ButtonOK: Gui, 2: Submit Menu, WeatherMenu, Enable, Options... IfNotExist, Settings.ini UseLocation:=Location1 else { IfEqual, LocationA, %UseLocation% UseLocation:=Location1 else UseLocation:=Location2 } Save_UserSettings() return 2GuiClose: IfNotExist, Settings.ini ExitApp Menu, WeatherMenu, Enable, Options... Gui, 2: Destroy return 3GuiClose: Gui, 3: Destroy return 3GuiSize: WinGetPos,,, AlertW, AlertH, Alert Information Loop, %Length% GuiControl, 3: Move, AlertBox%a_index%, % "w" (AlertW-60) "h" (AlertH-90) return 4GuiClose: Gui, 4: Destroy return Alert_Alert: URLDownloadToFile, %AlertBaseURL%%Alert1%, Rough_Alert.txt FileRead, RoughAlert, Rough_Alert.txt grep(RoughAlert, "
(.+)<\/pre>", RoughSevereDescr) StringReplace, RoughSevereDescrA, RoughSevereDescr,, ``, All StringSplit, RoughSevereDescrB, RoughSevereDescrA, `` Loop, %Length% { S:=RoughSevereDescrB%a_index% RegExMatch(S, "s)
(.+)\$\$", RoughSevereDescrC)
SevereDescr%a_index% := RoughSevereDescrC1
}
Gui, 3: Add, Tab2, vTabbedAlerts w%AlertTabWidth% h%AlertTabHeight% +Buttons TCS_FLATBUTTONS, %Severe%
brush := DllCall("CreateSolidBrush", "UInt", RGB(255,255,255))
OnMessage(0x138, "Change_BackgroundColor")
Loop, %Length%
{
Gui, 3: Tab, %a_index%
AlertDescr:=SevereDescr%a_index%
Gui, 3: Add, Edit, ReadOnly vAlertBox%a_index% +VScroll HwndAlertID%a_index%, %AlertDescr%
}
Gui, 3: +Resize +MinSize
Gui, 3: Show, w%AlertTabWidth% h%AlertTabHeight%, Alert Information
SelectText(AlertID1, -1, -1)
return
Change_BackgroundColor(wParam, lParam, msg, hwnd)
{
global
If(A_Gui = 3 or A_Gui = 4)
{
DllCall("SetTextColor", "UInt", wParam, "UInt", RGB(0, 0, 0))
DllCall("SetBkMode", "UInt", wParam, "UInt", 1)
Return brush
}
}
CurrentOne:
GuiControl, Text, Location1, %CurrentLocation%
return
CurrentTwo:
GuiControl, Text, Location2, %CurrentLocation%
return
Display_Help:
IfWinNotExist, %ProgramName% Help
{
HelpTopic1=Right click on the Weather GUI and select "Options...".
HelpTopic2=Right click on the Weather GuI and select "Lock" to lock the Weather GUI. To unlock the Weather GUI, repeat the action.
HelpTopic3=Right click on the Weather GUI and select "Update".
HelpTopic4=Hold down the left mouse button on the Weather GUI and move the mouse.
HelpTopic5=Right click on the Weather GUI and select "Exit".
HelpTopic6=Right click on the Weather GUI and select "Reload".
HelpTopic7=Middle click on the Weather GUI (only works if Location Detection is unchecked in Options).
HelpTopic8=Scroll the mouse wheel on the Weather GUI (the Weather GUI must be the active window for this to work, so click on the Weather GUI if the scrolling does not work).
HelpTopic9=Ensure that "Display Severe Weather Alerts" in Options is checked. When there is an severe weather alert, a red rounded rectangle will appear on the Weather GUI. Double click that red rounded rectangle with the left mouse button to view the details of the severe weather alert(s).
HelpTopic10=Ensure that "Use Location Detection" in Options is checked.
Gui, 4: Add, Text,, I want to...
HelpList=Edit the Options||Lock/Unlock the Weather GUI|Manually Update the Forecast|Move the Weather GUI|Quit %ProgramName%|Restart %ProgramName%|Toggle Forecasted Location|View More of the Forecast|View Severe Weather Alerts|View the Forecast of My Current Location
Gui, 4: Add, ListBox, Section w%HelpWidth% h%HelpHeight% vHelpTopics gDisplay_HelpInformation AltSubmit, %HelpList%
brush := DllCall("CreateSolidBrush", "UInt", RGB(255,255,255))
OnMessage(0x138, "Change_BackgroundColor")
Gui, 4: Add, Edit, % "w" . HelpWidth-30 . " h" . HelpHeight-4 . " ys ReadOnly vHelpInfo +VScroll +Wrap HwndInfoID"
Gui, 4: Show, AutoSize, %ProgramName% Help
GuiControl, 4: +Redraw, HelpInfo
Gosub, Display_HelpInformation
}
return
Display_HelpInformation:
Gui, 4: Submit, NoHide
ShowTheInfo:= HelpTopic%HelpTopics%
GuiControl, 4: Text, HelpInfo, %ShowTheInfo%
return
Display_Options:
Menu, WeatherMenu, Disable, Options...
Get_Location()
Gui, 2: Add, Text, Section w240 h22 Center vTitleA, Current Location Detected As:
Gui, 2: Add, Text, ys+17 xs w240 h22 Center vTitleB, %CurrentLocation%
Gui, 2: Add, Text, Section, Enter Location One:
Gui, 2: Add, Edit, w120 h22 -Multi vLocation1, %LocationA%
Gui, 2: Add, Button, vUseItA gCurrentOne, Use Current Location
Gui, 2: Add, Text, ys vTextLoc2, Enter Location Two:
Gui, 2: Add, Edit, w120 h22 -Multi vLocation2, %LocationB%
Gui, 2: Add, Button, vUseItB gCurrentTwo, Use Current Location
Gui, 2: Add, Text, xs y+30, Select Update Frequency (minutes):
Gui, 2: Add, Edit, xs
Gui, 2: Add, UpDown, vUpdateFrequency Range1-180, %UpdateFrequency%
Gui, 2: Add, Checkbox, Checked%LocationDetectionState% vLocationDetection gToggle_LocationControls, Use Location Detection
Gui, 2: Add, Checkbox, Checked%ShowAlertState% vShowAlerts, Display Severe Weather Alerts
Gui, 2: Add, Button, y+10 default, OK
Gui, 2: Show, AutoSize Center, %ProgramName% Options
WinGetPos,,, WeatherWidthConfig,, %ProgramName% Options
MoveXA := WeatherWidthConfig/2, MoveXB := MoveXA/2
GuiControl, 2: MoveDraw, OK, x%MoveXB% W%MoveXA%
Gosub, Toggle_LocationControls
return
Display_Weather:
SetBatchLines, -1
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}OnExit, Exit
Gui, 1: -Caption +E0x80000 +LastFound +ToolWindow +OwnDialogs
Gui, 1: Show, NoActivate, Weather GUI
IfEqual, TimerUsed, 1
{
WinSet, Bottom,, Weather GUI
TimerUsed:=0
}
hwnd1 := WinExist()
hbm := CreateDIBSection(WeatherWidth, WeatherHeight)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetSmoothingMode(G, 4)
pBrush := Gdip_BrushCreateSolid(0xaa000000)
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, WeatherWidth, WeatherHeight, 20)
Gdip_DeleteBrush(pBrush)
If !Gdip_FontFamilyCreate(Font)
{
MsgBox, 48, Font error!, The font you have specified does not exist on the system
ExitApp
}
IfEqual, Warning, 1
{
pBrush := Gdip_BrushCreateSolid(0xcf800000)
Gdip_FillRoundedRectangle(G, pBrush, WarningX, WarningY, 90, 30, 5)
Gdip_DeleteBrush(pBrush)
Options1 = x5p y88p w90p Bold Centre cbbffffff r4 s16
Gdip_TextToGraphics(G, "ALERT", Options1, Font, WeatherWidth, WeatherHeight)
}
Options2 = x5p y1p w90p Underline Bold Centre cbbffffff r4 s14
Options3 = x5p y10p w90p Underline Bold Centre cbbffffff r4 s12
Options4 = x5p y15p w90p Centre cbbffffff r4 s12
Options5 = x5p y45p w90p Underline Bold Centre cbbffffff r4 s12
Options6 = x5p y50p w90p Centre cbbffffff r4 s12
Options7 = x5p y96p w90p Centre cbbffffff r4 s10
Options8 = x3p y93p w90p Right cbbffffff r4 s10
IfEqual, LocationDetectionState, 1
Gdip_TextToGraphics(G, CurrentLocation, Options2, Font, WeatherWidth, WeatherHeight)
else
Gdip_TextToGraphics(G, UseLocation, Options2, Font, WeatherWidth, WeatherHeight)
Set_Forecast()
Gdip_TextToGraphics(G, ForecastTitle1, Options3, Font, WeatherWidth, WeatherHeight)
Gdip_TextToGraphics(G, ForecastDescr1, Options4, Font, WeatherWidth, WeatherHeight)
Gdip_TextToGraphics(G, ForecastTitle2, Options5, Font, WeatherWidth, WeatherHeight)
Gdip_TextToGraphics(G, ForecastDescr2, Options6, Font, WeatherWidth, WeatherHeight)
Gdip_TextToGraphics(G, LastUpdate, Options7, Font, WeatherWidth, WeatherHeight)
Page:=Round(ForecastD/4) " of 6"
Gdip_TextToGraphics(G, Page, Options8, Font, WeatherWidth, WeatherHeight)
UpdateLayeredWindow(hwnd1, hdc, WeatherX, WeatherY, WeatherWidth, WeatherHeight)
OnMessage(0x20A, "WM_MOUSEWHEEL")
OnMessage(0x207, "WM_MBUTTONDOWN")
OnMessage(0x218, "WM_POWERBROADCAST")
OnMessage(0x204, "WM_RBUTTONDOWN")
OnMessage(0x203, "WM_LBUTTONDBLCLK")
OnMessage(0x201, "WM_LBUTTONDOWN")
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
RETURN
return
Display_Welcome()
{
global
MsgBox, 33, Welcome to %ProgramName%, Welcome to %ProgramName%!`n`nWould you like to begin Setup?
IfMsgBox Cancel
ExitApp
}
Exit:
Gdip_Shutdown(pToken)
ExitApp
return
Get_Location()
{
global
UrlDownloadToFile, %LocationURL%, Rough_CurrentLocation.txt
FileRead, RoughLocation, Rough_CurrentLocation.txt
RegExMatch(RoughLocation, ">City:<.+?\barial_bold"">([^>]*?)", city)
RegExMatch(RoughLocation, "target=""_blank"">([^>]*?)", state)
CurrentLocation:=city1 ", " state1
}
Get_Weather:
Load_UserSettings()
IfEqual, LocationDetectionState, 1
{
Get_Location()
URLDownloadToFile, %WeatherBaseURL%%CurrentLocation%, Rough_Weather.txt
}else
URLDownloadToFile, %WeatherBaseURL%%UseLocation%, Rough_Weather.txt
FileRead, RoughWeather, Rough_Weather.txt
RegExMatch(RoughWeather, "name=""contents"">\s*([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
", descr)
IfEqual, descr1,
{
RegExMatch(RoughWeather, "name=""contents"">\s*Hazardous weather condition\(s\):
\s*([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
([^<]*?)([^<]*?)
", descr)
RegExMatch(descr1, """([^<]*?)"">", Alert)
IfEqual, ShowAlertState, 1
{
Warning:=1
ClickIt:=1
}
loop, 26
{
next:=a_index+1
descr%a_index%:=descr%next%
}
}else
{
ClickIt:=0
Warning:=0
}
FormatTime, LastUpdateBase,, h:mm tt MMM dd, yyyy
LastUpdate:="Last Update: "LastUpdateBase
UpdateMilliTime := UpdateFrequency*60000
SetTimer, Update_WeatherTimer, %UpdateMilliTime%
return
grep(h, n, ByRef v, b = 0, s = 1, d = ",", z = true)
{
Loop
If s := RegExMatch(h, n, c, s)
p .= s . d, s += z ? StrLen(c) : 1, y .= (b ? c%b% : c) . d
Else Return, SubStr(p, 1, -1), v := SubStr(y, 1, -1)
}
Load_WeatherContextMenu()
{
global
Menu, WeatherMenu, Add, Options..., Display_Options
Menu, WeatherMenu, Add, Help..., Display_Help
Menu, WeatherMenu, Add, Update, Update_Weather
Menu, WeatherMenu, Add, Lock, LockIt
Menu, WeatherMenu, Add, Reload, Restart
Menu, WeatherMenu, Add, Exit, Exit
}
Load_UserSettings()
{
global
IniRead, LocationA, Settings.ini, Locations, Location One
IniRead, LocationB, Settings.ini, Locations, Location Two
IniRead, UseLocation, Settings.ini, Locations, Use Location
IniRead, ForecastA, Settings.ini, Forecast, ForecastTitle1
IniRead, ForecastB, Settings.ini, Forecast, ForecastDescr1
IniRead, ForecastC, Settings.ini, Forecast, ForecastTitle2
IniRead, ForecastD, Settings.ini, Forecast, ForecastDescr2
IniRead, UpdateFrequency, Settings.ini, Update, Frequency
IniRead, LocationDetectionState, Settings.ini, Detection, Locatation Detection
IniRead, Ref1, Settings.ini, Detection, Reference Location One
IniRead, Ref2, Settings.ini, Detection, Reference Location Two
IniRead, ShowAlertState, Settings.ini, Alert, Show Alerts
IniRead, WeatherX, Settings.ini, GUI Location, WindowX
IniRead, WeatherY, Settings.ini, GUI Location, WindowY
IniRead, Lock, Settings.ini, GUI Location, Lock
IfEqual, Lock, 1
Menu, WeatherMenu, Check, Lock
IfEqual, ShowAlertState, 0
Warning:=0
}
LockIt:
IfEqual, Lock, 1
Lock := 0
else
Lock := 1
IniWrite, %Lock%, Settings.ini, GUI Location, Lock
Menu, WeatherMenu, ToggleCheck, Lock
Gosub, Display_Weather
return
RGB(r, g, b)
{
Return (b << 16) + (g << 8) + r
}
Restart:
Reload
return
Save_ForecastDays()
{
global
IniWrite, %ForecastA%, Settings.ini, Forecast, ForecastTitle1
IniWrite, %ForecastB%, Settings.ini, Forecast, ForecastDescr1
IniWrite, %ForecastC%, Settings.ini, Forecast, ForecastTitle2
IniWrite, %ForecastD%, Settings.ini, Forecast, ForecastDescr2
}
Save_Position()
{
global
WinGetPos, x, y,,, ahk_id %hwnd1%
WeatherX := x
WeatherY := y
IniWrite, %WeatherX%, Settings.ini, GUI Location, WindowX
IniWrite, %WeatherY%, Settings.ini, GUI Location, WindowY
}
Save_UserSettings()
{
global
IniWrite, %Location1%, Settings.ini, Locations, Location One
IniWrite, %Location2%, Settings.ini, Locations, Location Two
IniWrite, %UseLocation%, Settings.ini, Locations, Use Location
IniWrite, %ForecastA%, Settings.ini, Forecast, ForecastTitle1
IniWrite, %ForecastB%, Settings.ini, Forecast, ForecastDescr1
IniWrite, %ForecastC%, Settings.ini, Forecast, ForecastTitle2
IniWrite, %ForecastD%, Settings.ini, Forecast, ForecastDescr2
IniWrite, %UpdateFrequency%, Settings.ini, Update, Frequency
IniWrite, %LocationDetection%, Settings.ini, Detection, Locatation Detection
IniWrite, %ShowAlerts%, Settings.ini, Alert, Show Alerts
IniWrite, %WeatherX%, Settings.ini, GUI Location, WindowX
IniWrite, %WeatherY%, Settings.ini, GUI Location, WindowY
IniWrite, %Lock%, Settings.ini, GUI Location, Lock
Gui, 2: Destroy
Gosub, Update_Weather
}
Save_UseLocation()
{
global
IniWrite, %UseLocation%, Settings.ini, Locations, Use Location
Gosub, Update_Weather
}
SelectText( ControlID, start=0, end=-1 )
{
SendMessage, 0xB1, start, end,, ahk_id %ControlID%
return (ErrorLevel != "FAIL")
}
Set_DefaultVariables()
{
global
WeatherX := (A_ScreenWidth-WeatherWidth)/2, WeatherY := (A_ScreenHeight-WeatherHeight)/2
Lock := 0
UpdateFrequency = 60
LocationDetectionState = 0
ShowAlertState = 0
ForecastA := 1, ForecastB := 2, ForecastC := 3, ForecastD := 4
}
Set_Forecast()
{
global
ForecastTitle1:=descr%ForecastA%
ForecastDescr1:=descr%ForecastB%
ForecastTitle2:=descr%ForecastC%
ForecastDescr2:=descr%ForecastD%
}
Set_ScriptVariables()
{
global
ProgramName := "Weather"
WeatherBaseURL = http://forecast.weather.gov/zipcity.php?inputstring=
AlertBaseURL = http://forecast.weather.gov/
LocationURL = http://www.geoiptool.com
WeatherWidth := 195, WeatherHeight := 410
WarningX:=(WeatherWidth-90)/2, WarningY:=WeatherHeight-55
WarningXB:=WarningX+90, WarningYB:=WarningY+30
Font = Arial
AlertTabWidth:=A_ScreenWidth/2, AlertTabHeight:=A_ScreenHeight/3
HelpWidth:=A_ScreenWidth/7, HelpHeight:=A_ScreenHeight/6
}
Toggle_LocationControls:
GuiControlGet, OnOff, 2:, LocationDetection
IfEqual, OnOff, 1
{
GuiControl, 2: +ReadOnly, Location1
GuiControl, 2: +ReadOnly, Location2
GuiControl, 2: Disable, UseItA
GuiControl, 2: Disable, UseItB
}else
{
GuiControl, 2: -ReadOnly, Location1
GuiControl, 2: -ReadOnly, Location2
GuiControl, 2: Enable, UseItA
GuiControl, 2: Enable, UseItB
}
return
Update_Weather:
Gosub, Get_Weather
Gosub, Display_Weather
return
Update_WeatherTimer:
TimerUsed:=1
Gosub, Update_Weather
return
WM_LBUTTONDBLCLK()
{
global
IfWinNotExist, Alert Information
{
IfEqual, A_Gui, 1
{
IfEqual, ClickIt, 1
{
IfEqual, ShowAlertState, 1
{
CoordMode, Mouse, Relative
MouseGetPos, XClicked, YClicked
if XClicked between %WarningX% and %WarningXB%
{
if YClicked between %WarningY% and %WarningYB%
Gosub, Alert_Alert
RETURN
}
}
}
}
}
}
WM_LBUTTONDOWN()
{
global
If(A_Gui = 1 and Lock = 0)
{
PostMessage, 0xA1, 2
loop
{
GetKeyState, MouseUp, LButton, P
IfEqual, MouseUp, U
{
Save_Position()
BREAK
}
}
}
}
WM_MBUTTONDOWN()
{
global
IfEqual, A_Gui, 1
{
IfEqual, LocationDetectionState, 1
RETURN
else
{
loop
{
GetKeyState, MiddleUp, MButton, P
IfEqual, MiddleUp, U
{
IfEqual, UseLocation, %LocationA%
UseLocation:=LocationB
else
UseLocation:=LocationA
BREAK
}
}
Save_UseLocation()
}
}
}
WM_MOUSEWHEEL(wParam, lParam)
{
global
IfEqual, A_Gui, 1
{
If (wParam = 7864320)
{
IfEqual, ForecastD, 24
{
ForecastA:=1
ForecastB:=2
ForecastC:=3
ForecastD:=4
}else
{
ForecastA:=ForecastA+4
ForecastB:=ForecastB+4
ForecastC:=ForecastC+4
ForecastD:=ForecastD+4
}
Save_ForecastDays()
Gosub, Update_Weather
}
If (wParam = 4287102976)
{
IfEqual, ForecastA, 1
{
ForecastA:=21
ForecastB:=22
ForecastC:=23
ForecastD:=24
}else
{
ForecastA:=ForecastA-4
ForecastB:=ForecastB-4
ForecastC:=ForecastC-4
ForecastD:=ForecastD-4
}
Save_ForecastDays()
Gosub, Update_Weather
}
}
}
WM_POWERBROADCAST(wParam, lParam)
{
If (wParam = 7 OR wParam = 8)
SetTimer, Update_WeatherTimer, 30000
}
WM_RBUTTONDOWN()
{
IfEqual, A_Gui, 1
Menu, WeatherMenu, Show
}