;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, "

([^<]*?)

", RoughSevereA) StringSplit, RoughSevereB, RoughSevereA, `, Length:=0 Loop, parse, RoughSevereA, `, Length+=1 Loop, %Length% { S:=RoughSevereB%a_index% RegExMatch(S, "

([^<]*?)

", RoughSevereC) IfEqual, a_index, 1 Severe := RoughSevereC1 else Severe := Severe "|" RoughSevereC1 } grep(RoughAlert, "s)
(.+)<\/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 }