Weather gadget (Gdip). Accuweather

Post your working scripts, libraries and tools for AHK v1.1 and older
drozdman
Posts: 78
Joined: 05 Dec 2015, 01:07

Weather gadget (Gdip). Accuweather

14 Aug 2018, 12:54

I replaced some Windows Vista sidebar gadgets ("Network monitor", "CPU monitor","Traditional clock with alarm"), but I didn't post the weather gadget. I thought it was personalized too much and the Accuweather website layout may change in the future. Adding to that, the website sends data with different units for USA and the world (Celsius, Fahrenheit). It may be useful to post it, even though it may not work in the future (I may not be updating it).
The gadget can be easily changed and customized. I cleaned the script and removed unnecessary features.
I hope it works in different locations
I chose a few locations like: "https://www.accuweather.com/en/it/rome/213490/current-weather/213490"
The chosen url for another location must be exactly like this one (with "/en/","/current-weather/").
I think it will work in many countries, but I didn't check this by proxy.

Weather gadget
● top left circle - toggle always on top
● double click on the title to go to the saved position
● F4 - show GUI , or click on tray icon
● more options in the right click context menu: background color; save position for next launch,
● To start not on top of other windows: enable this line #227 ;Gosub, onTop
● Accuweather forecast in popup window
● Depending on a country, data is received in Fahrenheit or Celsius degrees.
So choose units below: unit:="C" or unit:="F".
Convert Fahrenheit to Celsius with option: F_to_Celsius:=1

Save the file in Unicode or UTF-8 with signature (not in UTF-8 as it is chosen with the download feature here - it messes up unicode characters).

Spoiler
[attachment=0]Drozd_Weather_gadget.png[/attachment]
Attachments
Drozd_Weather_gadget.png
Drozd_Weather_gadget.png (3.84 KiB) Viewed 5820 times
Last edited by drozdman on 08 Sep 2019, 15:15, edited 3 times in total.
chucknp

Re: Weather gadget (Gdip). Accuweather

17 Aug 2018, 13:31

Great drozdman, thanks!

Have been using this script + your CPU Monitor + Network monitor.
sevenwenty
Posts: 7
Joined: 30 Apr 2016, 10:29

Re: Weather gadget (Gdip). Accuweather

26 Aug 2018, 21:52

Excellent work! This has a lot of potential.
How do I set the refresh rate to 15 minutes instead of the default 30 minutes? Just change the part that says "30*60*1000" to "15*60*1000"?
Some feature requests:
  • Allow any saved position. Currently, it ignores the saved position if part of the window is outside of the screen (i.e. x = 1600 on a 1680 screen).
  • Simple mode that only shows temperature. No backgrounds, no titlebar, no text; just the temperature.
  • Custom text sizes.
  • Custom window size.
  • Custom window/text colors.
  • High/low temperatures.
I've already added some of these features by commenting out lines and making minor edits. If I have time I'll try to make them into proper patches.
User avatar
mshall
Posts: 35
Joined: 13 Jul 2018, 16:42
Contact:

Re: Weather gadget (Gdip). Accuweather

27 Aug 2018, 11:44

sevenwenty wrote:How do I set the refresh rate to 15 minutes instead of the default 30 minutes?
I haven't look at the code too long, but the Accuweather API only allows you to refresh every 30 minutes (unless that has changed).
drozdman
Posts: 78
Joined: 05 Dec 2015, 01:07

Re: Weather gadget (Gdip). Accuweather

27 Aug 2018, 12:15

@sevenwenty
● about timer - yes
● Many of those things would require a complete GUI redesign. But some changes can be made easily
● You probably wanted to cut part of the window by putting it off screen.
It's easier to simply cut the GUI with
WinSet, Region, 2-18 56-18 56-50 2-50 , ahk_id %GuiHwnd% ;Drozd_weather
It will leave just the temperature control in the view.
● "saved position" - you can go to this part and remove the line with "if"

Code: Select all

	GoToSavedPos: 
	IniRead, pos_x_saved, %settings_ini%, window position, x	
	IniRead, pos_y_saved, %settings_ini%, window position, y	
	if(pos_x_saved<A_ScreenWidth-120 && pos_y_saved<A_ScreenHeight-140)
		WinMove,  Drozd_weather, ,pos_x_saved,pos_y_saved
return
If there is some more problem change A_ScreenWidth to MonitorWorkAreaRight. But that's not the issue, I think

Code: Select all

	SysGet, MonitorWorkArea, MonitorWorkArea, 1
	pos_x:=MonitorWorkAreaRight - 138 ;A_ScreenWidth - 138
	pos_y:= MonitorWorkAreaBottom -688
● You can feel free to make changes and post it. Some things would require changing a lot of code, though.


@mshall
I didn't use API, I would hahe to sign up. It's simply taken from the website.
sevenwenty
Posts: 7
Joined: 30 Apr 2016, 10:29

Re: Weather gadget (Gdip). Accuweather

26 Aug 2019, 15:55

The parser needs an update, since the data page is now JSON instead of HTML. Starts near this line:
var today =.
drozdman
Posts: 78
Joined: 05 Dec 2015, 01:07

Re: Weather gadget (Gdip). Accuweather

30 Aug 2019, 14:28

Sorry. I didn't think people used it anymore and I moved to something local.
I updated this script for Accuweather. This should work. I did it quickly, so if something doesn't work I will fix it later.

Edit: I added also normal and record temperatures in tooltip, since it's easily retrievable from JSON.
Edit: Now it should be working.

Code: Select all


/*
=== Weather gadget  
● top left circle - toggle always on top
● double click on the title to go to the saved position  
● F4 - show GUI , or click on tray icon
● more options in the right click context menu: background color; save position for next launch,
● Accuweather forecast in popup window
● Depending on a country, data is received in Fahrenheit or Celsius degrees. 
So choose units below: unit:="C" or unit:="F". 
Convert Fahrenheit to Celsius with option: F_to_Celsius:=1

● To start not on top of other windows: enable this line #227 ;Gosub, onTop
*/

;==========	
	;weather_url:="https://www.accuweather.com/en/it/rome/213490/current-weather/213490"
	;weather_url:="https://www.accuweather.com/en/pl/krakow/274455/current-weather/274455"
	weather_url:="https://www.accuweather.com/en/us/new-york-ny/10007/current-weather/349727#"
	
;==========

	;unit:="C" ; if data received in Celsius degrees (in a particular country)
	unit:="F" ; if data received in Fahrenheit (in a particular country)
	F_to_Celsius:=1 ; convert fahrenheit to Celsius	if data received in Fahrenheit
	
;==========
	write_ini:=1 ; stores data for 1 month
			
			
#SingleInstance force
#NoEnv
;#NoTrayIcon

Menu, Tray, Add , Weather , weather
Menu, Tray, Add ,
;Menu, Tray, Icon, shell32.dll,14 ; 47 ; ; 95 ;22 
Menu, Tray, Icon, netshell.dll, 86
Menu, Tray, Add , Edit Scite, Edit_Scite
Menu, Tray, Add , Edit Notepad, Edit_Notepad
Menu, Tray, Add, Exit , Exit ; double click tray icon to exit
Menu, Tray, Default, Exit 

Menu, ContextMenu, Add, On Top, OnTop
;Menu, ContextMenu, Icon, On Top, Shell32.dll, 147
Menu, ContextMenu, Icon, On Top, Shell32.dll, 248 ;wmploc.dll, 17
Menu, ContextMenu, Add, Save current position , save_position
Menu, ContextMenu, Icon, Save current position , Shell32.dll,124 ; 268 ;101 124
Menu, ContextMenu, Add,
Menu, Submenu1, Add, Black , set_bgrd_black
Menu, Submenu1, Add, Steel , set_bgrd_steel
Menu, Submenu1, Add, Blue , set_bgrd_blue  
Menu, Submenu1, Add, Green , set_bgrd_green
;Menu, Submenu1, Add, 
;Menu, Submenu1, Add, Funny style: dots, set_bgrd_style_dots
;Menu, Submenu1, Add, Funny style: dots 2, set_bgrd_style_dots2
;Menu, Submenu1, Add, Funny style: bricks, set_bgrd_style_bricks 
;Menu, Submenu1, Add, 
;Menu, Submenu1, Add, Reset background, reset_bgrd
Menu, ContextMenu, Add, Background color, :Submenu1 

Menu, ContextMenu, Add,
Menu, ContextMenu, Add , Open settings file , Open_ini
Menu, ContextMenu, Icon , Open settings file , Shell32.dll, 70
;Menu, ContextMenu, Add , Open log , Open_log
Menu, ContextMenu, Add,
Menu, ContextMenu, Add , Go to website , Go_to_web
;Menu, ContextMenu, Icon , Go to website , C:\Program Files\Internet Explorer\iexplore.exe
Menu, ContextMenu, Icon , Go to website , shell32.dll, 221
Menu, ContextMenu, Add,

Menu, ContextMenu, Add , Forecast  , Show_in_popup
;Menu, ContextMenu, Icon , Forecast , C:\Program Files\Internet Explorer\iexplore.exe
Menu, ContextMenu, Icon , Forecast , shell32.dll, 143 ;243
Menu, ContextMenu, Add,
Menu, ContextMenu, Add , Weather , weather
Menu, ContextMenu, Add ,
Menu, ContextMenu, Add, Restart, Reload
Menu, ContextMenu, Add, Exit, Exit


FileEncoding, UTF-8
SetWorkingDir %A_ScriptDir%


global settings_ini := "Drozd Weather.ini"

/* global log_file := "Temp\Temperatures_log_AHK.txt"
global reg_log_temp := "Temp\reg_Temp_log_AHK.txt"
IfNotExist Temp 
	FileCreateDir, Temp
FileAppend, Temperature log`n  , %reg_log_temp%
 */
 
	bgrd_grad_black:="0xff222222|0xff0F0F0F|33"
	bgrd_grad_steel:="0xff1A2333|0xff2C3B54|33" 
	bgrd_grad_blue:="0xff06213D|0xff133557|33" 
	bgrd_grad_green:="0xff00230A|0xff044016|33"  
	
	bgrd_grad:=bgrd_grad_green ;bgrd_grad_black

	bgrd_ramki_black:="0xff353535|0xff1C1C1C"
	bgrd_ramki_steel:="0xff2D3F5D|0xff1A2333"
	bgrd_ramki_blue:="0xff16416B|0xff0D263E" 
	bgrd_ramki_green:="0xff044016|0xff00230A" 
	
	bgrd_ramki:=bgrd_ramki_green ;bgrd_ramki_black
	

If !pToken := Gdip_Startup(){
	MsgBox, 48, No Gdiplus 
	ExitApp
}

	OnExit, Exit

	SysGet, MonitorWorkArea, MonitorWorkArea, 1
	pos_x:=MonitorWorkAreaRight - 138 ;A_ScreenWidth - 138
	pos_y:= MonitorWorkAreaBottom -688
	

	IniRead, read_, %settings_ini%, Weather, weather url	

	if(read_="ERROR" || read_=""){			
			IniWrite, %weather_url%	, %settings_ini%, Weather, weather url
			
	}else{
		weather_url:=read_
	}
	

	IniRead, pos_x_saved, %settings_ini%, window position, x	
	IniRead, pos_y_saved, %settings_ini%, window position, y	
	if(!pos_x_saved || !pos_y_saved || pos_x_saved=="ERROR" || pos_y_saved=="ERROR"){
			IniWrite, %pos_x%	, %settings_ini%, window position, x
			IniWrite, %pos_y%	, %settings_ini%, window position, y
	}else{
		if(pos_x_saved<A_ScreenWidth-120 && pos_y_saved<A_ScreenHeight-130){
			pos_x:=pos_x_saved
			pos_y:=pos_y_saved
		}
	}	


	IniRead, GUI_bgrd, %settings_ini%, Window, GUI_background	
	IniRead, GUI_ramka, %settings_ini%, Window, GUI_ramka	
	
	if(GUI_bgrd!="ERROR" && GUI_bgrd!=""  && GUI_ramka!="ERROR" && GUI_ramka!=""){
				bgrd_grad:=GUI_bgrd
				bgrd_ramki:=GUI_ramka
				
	}else{
		IniWrite, %bgrd_grad%	, %settings_ini%, Window, GUI_background
		IniWrite, %bgrd_ramki%	, %settings_ini%, Window, GUI_ramka
	}


	
Gui,1: +ToolWindow -caption +AlwaysOnTop	+HwndGuiHwnd  ;caption
Gui,1:Color, 120F00
Gui,1: -DPIScale
WonTop:=1
; bgrd:
Gui, 1: Add, Picture, x0 y0 w135 h66 vbgrd BackgroundTrans 0xE, 
Gdip_Set_bgrd(bgrd,bgrd_grad)


Gui, 1: Add, Picture, x0 y0 w134 h13 vramkaT 0xE,
Gdip_Set_bgrd(ramkaT,bgrd_ramki_black "|6")

Gui, Add, Picture, x3 y19 w53 h31 vramka 0xE,
Gui, Add, Picture, x60 y19 w72 h15 vramka1 0xE, 
Gui, Add, Picture, x60 y35 w72 h15 vramka2 0xE,
GoSub, ramka
; ramka:

Gui,1: Font, S7 w700 cD0D0D0 , Segoe UI ;
Gui,1: Add, Text , x122 y0 w10 h10 cD0D0D0 gexit BackgroundTrans Center ,  X 

Gui,1: Font, S6 w700 c9C9C9C , Segoe UI
Gui,1: Add, Text , x4 y0  c676767 vonTop_off gonTop BackgroundTrans,  % Chr(9675) ;  ○
Gui,1: Font, S9
Gui,1: Add, Text , x4 y+-13  c676767 vonTop_on gonTop BackgroundTrans, % Chr(9679) ;  ● 
GuiControl, Hide, onTop_off

Gui,1: Font, S7 w700 cE1E1E1 , Segoe UI ; Tahoma 
Gui,1: Add, Text , x18 y0 w100 vtitle gDoubleClick  BackgroundTrans  Center, Accuweather ;Drozd weather ; gGoToSavedPos



Gui,1: Font, S15 w700 cE1E1E1 , Segoe UI
Gui,1: Add, Text , x3 y19  w50  vTem gweather BackgroundTrans Center, -- 
Gui,1: Font, S8 w700 cE1E1E1 ,

Gui,1: Font, S7  w400
Gui,1: Add, Text , x0 y51 w76  vCon  gDoubleClick +HwndConID BackgroundTrans Center, 

Gui,1: Font, S7 w700 cD2D2D2, Arial
Gui,1: Add, Text, x78 y52 w56 vlast_check gDoubleClick +Hwndlast_checkID BackgroundTrans Center,
;GuiControl, Hide, last_check	


Gui,1: Font, S7  w700
Gui,1: Add, Text , x60 y21 w27 cE9C45D vHum Center BackgroundTrans , -- 
Gui,1: Add, Text , x60 y37 w27  cE9C45D vDew Center BackgroundTrans , -- 

Gui,1: Font, S7  w400
Gui,1: Add, Text , x88 y21  cD8C591 w42  BackgroundTrans, Humidity
Gui,1: Add, Text , x88 y37  cD8C591 w42  BackgroundTrans, Dew point   



;Gui,1: Add, Picture, x115 y51 w16 h16   BackgroundTrans Icon249 AltSubmit, shell32.dll ;
;Gui,1: Add, Picture, x112 y128 w16 h16    Icon249 AltSubmit, shell32.dll ;



OnMessage(0x201, "WM_LBUTTONDOWN")   
OnMessage(0x404, "AHK_NOTIFYICON") 
OnMessage(0x200, "WM_MOUSEMOVE")

Gui, 1: Show, Hide x%pos_x% y%pos_y% w134 h66  , Drozd_weather
;DllCall( "AnimateWindow", "Int", GuiHwnd, "Int", 300, "Int", 0x00000010 )
DllCall( "AnimateWindow", "Int", GuiHwnd, "Int", 300, "Int", 0x00000004 )
;Winset, Transparent,200, Drozd_weather  
WinSet, Style, -0xC00000, Drozd_weather ; COMPLETELY remove window border

	;Gosub, onTop

	GoSub, start_weather

	SetTimer,clear_memory, % 6*60*60*1000
return


AHK_NOTIFYICON(wParam, lParam){ ;click tray icon to show
    if (lParam = 0x202) {       ; WM_LBUTTONUP
				Gui,1:Show  				
    }else if (lParam = 0x203){   ; WM_LBUTTONDBLCLK
		}
}


WM_LBUTTONDOWN(){
	if(A_Gui=1){
		PostMessage, 0xA1, 2    ; movable borderless window
		
		ToolTip_("", 0.5)
	}	
}

;===================

WM_MOUSEMOVE(){
		global GuiHwnd, tray_tip, tipOn, ConID, last_checkID
		MouseGetPos,, ,winID,control , 3 ; hwnd
		if(winID==GuiHwnd){
			GuiControl, Show, last_check	
			SetTimer, hide_time, -6000
			
			if(control==ConID && tipOn!=1){	
				tipOn:=1
				;ToolTipFont("s11 w700", "Segoe UI")
				ToolTipFont("s10", "Segoe UI Semibold")
				ToolTipColor("F2EEDC", "900000")
				ToolTip_(tray_tip, 3)
			}else if(control==last_checkID && tipOn!=2){
				tipOn:=2
				ToolTipFont("s9", "Segoe UI")
				ToolTipColor("FFFFFF","333333")
				ToolTip_("` last checked ", 1)
			}
		}
}

;======================================


start_weather:
	GoSub, weather
	SetTimer, weather, % 30*60*1000  ; 0.5h		
			del_last_month()
return

weather:
	Gosub, weather_get
	Gosub, write_
return



weather_get:
	if !InternetConnection(){
		SetTimer, check_again, -60000
		return
	}

	;GuiControlGet,t1,1:, last_check 
	GuiControl,, last_check, 
	GuiControl,, last_check, connecting
	Contents:=DownloadToString(weather_url)
	;RegExMatch(Contents,"im)dew", test )

	;MsgBox,,, % Contents
	
	
/*   RegExMatch(Contents,"im)<div id=""detail-now""[\s\S]*<div id=""feature-history"">", today )
	;MsgBox,,, % today
  RegExMatch(today,"im)<li>Dew Point: <strong>(\d+)&#176;&nbsp;F",dew )
	RegExMatch(today,"im)<th scope=""row"">Now</th>\s*<td>(\d+)&deg;</td>",temper )
  RegExMatch(today,"im)<div id=""detail-now"" class=""detail-tab-panel day""[\s\S]*<span class=""cond"">(.*?)</span>",cond )
	RegExMatch(today,"im)<li>Humidity: <strong>(\d+%)</strong>",Humid )
	RegExMatch(today,"im)<div id=""detail-now""[\s\S]*<span class=""cond"">(.*?)</span>",cond )
	RegExMatch(today,"im)<th scope=""row"">Yesterday</th>\s*<td>(\d+)&deg;</td>",yesterday )

	if !today  ; fix NYC Feb4 2019
	{
			RegExMatch(Contents,"im)<div class=""conditions-wrapper day"">[\s\S]*<div id=""trending-now""", today )		
		if !today
			RegExMatch(Contents,"im)<ul id=""detail-tab-buttons"" class=""block-tabs"">[\s\S]*<div id=""trending-now""", today )
		;MsgBox,4096,, %   "`n"  today
		RegExMatch(today,"im)<div class=""hi"">(\d+)&deg;</div>",temper )
		RegExMatch(today,"im)<div>Dew Point: (\d+)°?&nbsp;F</div>",dew )
		RegExMatch(today,"im)<div class=""phrase"">(.*?)</div>",cond )
		RegExMatch(today,"im)<div>Humidity: (\d+%)</div>",Humid )
		RegExMatch(today,"im)<th scope=""row"">Yesterday</th>\s*<td>(\d+)&deg;</td>",yesterday )
		;MsgBox,4096,, % "temp="  temper1 "`ndew="  dew1 "`n" cond1 "`n" Humid1 "`n" yesterday1
		;MsgBox,,, % today	
	}
	 */

/* 	RegExMatch(Contents,"im)<div class=""conditions-wrapper[\s\S]*?<div class=""block"">", today )
	MsgBox,4096,, %   "`n" today 
	RegExMatch(today,"im)<div class=""temp"">[\r\n\t]+<div class=""hi"">(\d+)&deg;",temper)  
	RegExMatch(today,"im)<div>Dew Point: (\d+)Â?°&nbsp;F<\/div>",dew) 
	RegExMatch(today,"im)<div class=""realfeel"">RealFeel&#174; (\d+)",temperFeel)  
	RegExMatch(today,"im)<div>Humidity: (\d+)%",Humid)	
	RegExMatch(today,"im)<div class=""phrase"">([^<]+)<\/div>", cond)  
	
	MsgBox,4096,, % "T=" temper1 "`nFeel=" temperFeel1 "`nnight="  temperNight1  "`nDew="  dew1 "`nH=" Humid1 "%" "`n" cond1
	 */
	; ======JSON========
	RegExMatch(Contents,"im)var sunMoon[\s\S]*var locales", today )
	RegExMatch(today,"im)var curCon =[\s\S]*", curCon )
	RegExMatch(curCon,"im)""temp"":""(\d+)Â?°""",temper )
	RegExMatch(curCon,"im)""dewPoint"":""(\d+)Â?°""",dew )
  RegExMatch(curCon,"im)""realFeel"":""(\d+)Â?°""",temperFeel )
	RegExMatch(curCon,"im)""humidity"":""(\d+)",Humid )
	RegExMatch(curCon,"im)""phrase"":""(.*?)""",cond )  
/* 
	RegExMatch(today,"im)""day"":{""dTemp"":""(\d+)",temper )	
	RegExMatch(today,"im)""night"":{""dTemp"":""(\d+)",temperNight )	
	RegExMatch(today,"im)""realFeel"":""(\d+)",temperFeel )		
	RegExMatch(today,"im)""dewPoint"":""(\d+)",dew )	
	RegExMatch(today,"im)""humidity"":""(\d+)",Humid )
	RegExMatch(today,"im)""phrase"":""(.*?)""",cond )
	  */
		
		
		
		
	RegExMatch(today,"im)""normals"":{""high"":{""value"":""(\d+)Â?°""},""low"":{""value"":""(\d+)Â?°""}",normals )
	RegExMatch(today,"im)""records"":{""high"":{""value"":""(\d+)Â?°"",""year"":(\d+)},""low"":{""value"":""(\d+)Â?°"",""year"":(\d+)}}}",records )
	; ======JSON========	
	;MsgBox,4096,, % "T=" temper1 "`nFeel=" temperFeel1 "`nnight="  temperNight1  "`nDew="  dew1 "`nH=" Humid1 "%" "`n" cond1

	;MsgBox,4096,, % today  "`n"   "`n"
	
	tem:=temper1
	if tem is not integer 
	{
		;MsgBox,,Drozd Weather, % "Temperature read error.`nWill check again in 1 min." , 1
		Gosub, popupGUI
		SetTimer, check_again,  % 1*60*1000
		return
	}
	dew:=dew1
	;yester:=yesterday1
	temFeel:=temperFeel1
	temNight:=temperNight1
	
	if(F_to_Celsius){
		tem:=f_C(tem) Chr(176) "C" ;"°C" 
		dew:=f_C(dew) Chr(176) "C" ;"°C" 
		temNight:=f_C(temNight) Chr(176) "C"
		temFeel:=f_C(temFeel) Chr(176) "C"
		;yester:=f_C(yester) Chr(176) "C" ;"°C" 
		
	}else{
		tem:=tem Chr(176) unit  ;"°"
		dew:=dew Chr(176) unit   ;"°"
		temNight:=temNight Chr(176) unit
		temFeel:=temFeel Chr(176) unit
		;yester:=yester Chr(176) unit  ;"°"
	}
	
	hum:=Humid1 "%"
	last_temp:=tem


	normT:= "  Normal high: "  normals1 "F" " | low: "  normals2 "F"
	recT:= "  Record high: "  records1 "F" " in " records2 " | low: " records3 "F" " in " records4 
	
	strT:="  Temperature:   " tem "  "
	strD:="  Dew point:       " dew "  "
	strH:="  Humidity:         " hum "  "
	strY_:="  Feels Like:        " temperFeel1 "F"
	;strY_2:="  Night Temp.:    " temperNight1 "F"
	;strY:="  Yesterday:        " yester

	tray_tip:="  " cond1 "`n" strT "`n" strY_ "`n"  strD "`n" strH "`n" strY_2 "`n  ------`n" normT "`n" recT
	
	
 	normT:= "  Normal high: " f_C(normals1) "°C (" normals1 "F)" " | low: "  f_C(normals2) "°C (" normals2 "F)"
	recT:= "  Record high: " f_C(records1) "°C (" records1 "F)" " in " records2 " | low: "  f_C(records3) "°C (" records3 "F)" " in " records4 

	strT_:="  Temperature:   " tem " (" temper1 "F)" "  "
	strD_:="  Dew point:       " dew " (" dew1 "F)" "  "
	strH_:="  Humidity:         " hum "  "
	strY_:="  Feels Like:        " temFeel " ("	temperFeel1 "F)"
	;strY_2:="  Night Temp:    " temNight " ("	temperNight1 "F)"
	;strY_:="  Yesterday:        " yester " ("	yesterday1 "F)"
	tray_tipC_F:="  " cond1 "`n" strT_ "`n" strY_ "`n"  strD_ "`n" strH_  "`n  ------`n" normT "`n" recT
	
	tray_tip:=(F_to_Celsius==1) ? tray_tipC_F : tray_tip
	
	GuiControl,, Tem, %tem%  
	GuiControl,, Hum, %hum%
	GuiControl,, Dew, %dew%  
	GuiControl,, Con, %cond1%

	FormatTime, date, %A_Now%, HH:mm ;MMMd 
	GuiControl,, last_check, %date%
	SetTimer, hide_time, -3000
return


write_:
	if(write_ini!=1)
		return
	IniRead, today_1, %settings_ini%, %  A_MM " " A_YYYY , % A_MMM A_DD
	IniRead, reg_log_, %settings_ini%, %  A_MM " " A_YYYY , % A_MMM A_DD


	reg_log_:=(reg_log_=="ERROR") ? "" : reg_log_ " | " 
	reg_log:= A_Hour "h " tem
	reg_log:=reg_log_ reg_log
	
	
	if !InStr(reg_log_,A_Hour "h")
	IniWrite, %reg_log%	, %settings_ini%, %  A_MM " " A_YYYY, % A_MMM A_DD
return


hide_time:
	SetTimer, hide_time, Off
	GuiControl, Hide, last_check	
return


check_again:
	Gosub, weather	
return


popupGUI:
;Gui,4: Destroy
Gui,4:+ToolWindow -Caption +HwndGuiHwnd_2
Gui,4:Color, 700000

Gui,4:+Owner1  +AlwaysOnTop
;Gui,4: +Parent%GuiHwnd%
;DllCall("SetParent", "uint", GuiHwnd_2, "uint", GuiHwnd)


Gui,4: Font, S7 w700 cE1E1E1 Q5, Verdana ;Arial ;Segoe UI Semibold
;Gui,4: Add, Text, x3 y8 w128 ,% "Temperature read error. `nWill check again in 1 min."
;Gui,4:+Parent%GuiHwnd%
;MsgBox,4096,, %  pos_x "`n"  pos_y

Gui,4: Add, Text, x3 y6 w128 ,% "Temperature read error. `nWill check again in 1 min."
pos_x4:= pos_x, pos_y4:=pos_y+13
WinGetPos ,pos_x1,pos_y1,,, ahk_id %GuiHwnd%
pos_x4:= pos_x1, pos_y4:=pos_y1+13
Gui, 4:Show, x%pos_x4% y%pos_y4% w134 h38 NA, Drozd_popupGUI
SetTimer, Dest_popupGUI, -3000
return

Dest_popupGUI:
Gui,4: Destroy
return

f_C(t,d:=0){ ;(°F  -  32)  x  5/9 = °C ;fahrenheit_to_celsius
	t:= (t-32)*(5/9)
	t:=Round(t,d)
	return t
}




;======================

del_last_month(){
  global reg_log_temp
	prev_m:= (A_MM!=01) ? dig(A_MM - 1) " " A_YYYY : 12 " " A_YYYY-1 
	IniRead, prev_month , %settings_ini%, % prev_m
  if(prev_month!=""){
		if FileExist(reg_log_temp){
			FileAppend, `n%prev_m%`n  , %reg_log_temp%
			FileAppend, %prev_month%`n  , %reg_log_temp%
		}
    IniDelete,  %settings_ini%, %prev_m% 
  }
	; leftovers 
	Loop % A_MM-1 {
		prev_m:=dig(A_MM-A_Index) " " A_YYYY
		IniRead, prev_month , %settings_ini%, % prev_m
		if(prev_month!=""){
			IniDelete,  %settings_ini%, %prev_m%
		}
	}
	
}


dig(num){ ;to_two_digits
   num:= num<=9 ? "0" . num : num
   return num
}


;============================================


Show_in_popup:
	HTML_page:=DownloadToString(weather_url)
	 
	if(F_to_Celsius){
		Gosub, change_FtoC

		if(RegExMatch(HTML_page,"i)<li>Ceiling: <strong>(\d+) ft<",match)){
			match:=RegExReplace(match,match1 " ft",feet_to_m(match1))
			HTML_page:=RegExReplace(HTML_page,"im)<li>Ceiling: <strong>(\d+) ft<", match)		
		}

		if(RegExMatch(HTML_page,"i)<li>Visibility: <strong>(\d+) mi", match)){
			match:=RegExReplace(match,match1 " mi", mile_to_km(match1))
			HTML_page:=RegExReplace(HTML_page,"im)<li>Visibility: <strong>(\d+) mi", match)
		} 
		
		if(RegExMatch(HTML_page,"i)<li class=""wind""><strong>(\d+) mph<",match)){		 
			match:=RegExReplace(match,match1 " mph",mile_to_km(match1) "/h")
			HTML_page:=RegExReplace(HTML_page,"im)<li class=""wind""><strong>(\d+) mph<", match)
		} 
	}

	
	RegExMatch(HTML_page,"im)<link rel=""stylesheet"" href=""(.+)?"" type=""text/css""",css)
	urlCSS:=css1

;RegExMatch(HTML_page,"im)<!-- /.feed-controls -->\s+(<div id=""feed-tabs"" class=""panel-list"">[\s\S]*Next 5 Days[\s\S]*)<div class=""rise-modules"">",Next_5_Days)

RegExMatch(HTML_page,"ims)<!-- /.feed-controls -->\s+(<div id=""feed-tabs"" class=""panel-list"">.*Next 5 Days.*?)(?=<div class=""panel-body-content"">)",Next_5_Days) 	

HTML_page1 = 
( comments
  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  <html>
  <head><meta http-equiv="X-UA-Compatible" content="IE=Edge"></head>
  <style></style>
  <title>Forecast</title>
  </head>
  <body><center> ;<h1> TEST </h1>
)

HTML_page:= HTML_page1 Next_5_Days1  "<a href='" weather_url "'>" weather_url "</a><br>" "</center></body></html>"

;urlCSS:="https://vortex.accuweather.com/adc2010/stylesheets/slate.min-20180522-1001.css"
addCSS:= "<link rel=""stylesheet"" type=""text/css"" href=""" urlCSS """ />"
HTML_page:=RegExReplace(HTML_page,"im)<\/head>", addCSS "</head>")
 
w:=700 , h:=710
;w:=560 , h:=700
Gui,5: Add, ActiveX, vWB w%w% h%h% +Resize +VScroll +HScroll, about:<!DOCTYPE html><meta http-equiv="X-UA-Compatible" content="IE=edge">
  WB.silent := true 
  document := WB.Document
  document.open()
  document.write(HTML_page)
  document.close()
	;WB.Document.Body.Style.Zoom := "80%"
Gui,5: +HWNDWin_id 
;Gui,5: +Owner1  +AlwaysOnTop
Gui,5: Show,% "w" w+20 " h" h+10, IE ActiveX  
match:= document:= HTML_page:=""
return

5GuiClose:
	Gui,5: Destroy
return


change_FtoC:
	HTML_page:=RegExReplace(HTML_page,"im)<\/head>", addCSS "</head>")	 
	HTML_page2:=HTML_page
	RegExMatch(HTML_page2,"im)(\d\d)&deg;(?C1:Replacer)")
	HTML_page:=RegExReplace(HTML_page,"im)&deg;(?:F(?!\)))?","")
	HTML_page2:=""
	
	if(RegExMatch(HTML_page,"i)<li>Dew Point: <strong>(\d+)&#176;&nbsp;F<",match)){
		match:=RegExReplace(match,match1 ,f_C(match1))
		match:=RegExReplace(match,"F<","C<")
		HTML_page:=RegExReplace(HTML_page,"im)<li>Dew Point: <strong>(\d+)&#176;&nbsp;F<", match)
	}
	HTML_page:=RegExReplace(HTML_page,"im)<li>Dew Point: <strong>(\d+)&#176;&nbsp;F<", match)
return


Replacer(match,1,pos){
	global HTML_page
	repl:=f_C(match1) "°" 
	HTML_page:=RegExReplace(HTML_page,"im)" match1,repl,,1,pos)
	return 1
}


mile_to_km(mi){
	return Round(mi*1.60934) " km"
}

feet_to_m(leg){
	return Round(leg* 0.3048) " m"
}

;============================================

;======================
InternetConnection(flag:=0x40) { 
	return DllCall("Wininet.dll\InternetGetConnectedState", "Str", flag,"Int",0) 
}

;======================


DownloadToString(url, encoding="utf-8"){ ;https://autohotkey.com/board/topic/89198-simple-download-bin-tostring-und-tofile/ Bentschi
  static a := "AutoHotkey/" A_AhkVersion
  if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
    return 0
  c := s := 0, o := ""
  if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
  {
    while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
    {
      VarSetCapacity(b, s, 0)
      DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
      o .= StrGet(&b, r>>(encoding="utf-16"||encoding="cp1200"), encoding)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", f)
  }
  DllCall("wininet\InternetCloseHandle", "ptr", h)
  return o
}

DownloadToFile(url, filename){
  static a := "AutoHotkey/" A_AhkVersion
  if (!(o := FileOpen(filename, "w")) || !DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
    return 0
  c := s := 0
  if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
  {
    while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
    {
      VarSetCapacity(b, s, 0)
      DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
      c += r
      o.rawWrite(b, r)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", f)
  }
  DllCall("wininet\InternetCloseHandle", "ptr", h)
  o.close()
  return c
}

;=============================
ramka: ;bgrd:
	Gdip_Set_bgrd(ramka,bgrd_ramki "|15",,0)	
	Gdip_Set_bgrd(ramka2,bgrd_ramki "|7",,0)
	Gdip_Set_bgrd(ramka1,bgrd_ramki "|7",,0)
	
return

Gdip_Set_bgrd(ByRef Variable, Background=0x00000000,Hatch=0,border=0){
	GuiControlGet, Pos, Pos, Variable
	GuiControlGet, hwnd, hwnd, Variable  
	
	pBitmap := Gdip_CreateBitmap(Posw, Posh), G := Gdip_GraphicsFromImage(pBitmap), Gdip_SetSmoothingMode(G, 4)	
	
	Background_:=StrSplit(Background,"|")
	if(Background_.Length() >1){
		;=== with gradient =====
		;pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 10, grad_color1, grad_color2 ,1) 
		grad_color_rim:=Background_[1]
		grad_color_mid:=Background_[2]
		size:=Background_[3]

		if(Hatch=0){
			pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, size, grad_color_rim, grad_color_mid ,1) 
		}else{
			pBrushFront :=Gdip_BrushCreateHatch(grad_color_rim, grad_color_mid, Hatch) ; kropki
		}
		Gdip_FillRectangle(G, pBrushFront,-1, -1,  PosW+1, Posh+1)
	;========
	}else{
		pBrushBack := Gdip_BrushCreateSolid(Background)
		Gdip_FillRectangle(G, pBrushBack, 0, 0, PosW, Posh)
	}

	if(border==1){
		pPen:=Gdip_CreatePen(0xff111111, 1) 
		Gdip_DrawRectangle(G, pPen,0, 0, PosW-1, Posh-1)
		;Gdip_DrawRoundedRectangle(G, pPen,0, 0, PosW-1, Posh-1,4)
	}
	
	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	SetImage(hwnd, hBitmap)
	
	Gdip_DeleteBrush(pBrushFront), Gdip_DeleteBrush(pBrushBack)
	Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
	Return, 0
}



;=========================================


set_bgrd_black:
	IniWrite, %bgrd_grad_black%	, %settings_ini%, Window, GUI_background
	IniWrite, %bgrd_ramki_black%	, %settings_ini%, Window, GUI_ramka
return

set_bgrd_steel:
	IniWrite, %bgrd_grad_steel%	, %settings_ini%, Window, GUI_background
	IniWrite, %bgrd_ramki_steel%	, %settings_ini%, Window, GUI_ramka
return

set_bgrd_blue:
	IniWrite, %bgrd_grad_blue%	, %settings_ini%, Window, GUI_background
	IniWrite, %bgrd_ramki_blue%	, %settings_ini%, Window, GUI_ramka
return

set_bgrd_green:
	IniWrite, %bgrd_grad_green%	, %settings_ini%, Window, GUI_background
	IniWrite, %bgrd_ramki_green%	, %settings_ini%, Window, GUI_ramka
return





;=========================================

save_position:
	WinGetPos, x1,y1,,, ahk_id %GuiHwnd%
	IniWrite, %x1%	, %settings_ini%, window position, x
	IniWrite, %y1%	, %settings_ini%, window position, y
return


Open_ini:
Run, %settings_ini%
return

Open_log:
;Run, %log_file%
return

Go_to_web: 
Run, %weather_url%
return

Open_log2:
	if(A_GuiEvent == "DoubleClick")
	Run, %log_file%
return


Open_ini2:
	if(A_GuiEvent == "DoubleClick")
	Run, %settings_ini%
return

;=========================================

onTop:
		WonTop:=!WonTop             
		if WonTop {
			WinSet, AlwaysOnTop, on, Drozd_weather
			GuiControl, Show, onTop_on
			GuiControl, Hide, onTop_off
		}else{
			WinSet, AlwaysOnTop, off, Drozd_weather
			GuiControl, Show, onTop_off
			GuiControl, Hide, onTop_on
		}	
return

GoToSavedPos: ; DoubleClick
	IniRead, pos_x_saved, %settings_ini%, window position, x	
	IniRead, pos_y_saved, %settings_ini%, window position, y	
	if(pos_x_saved<A_ScreenWidth-120 && pos_y_saved<A_ScreenHeight-140)
		WinMove,  Drozd_weather, ,pos_x_saved,pos_y_saved
return


DoubleClick:

return

DisableWindowsFeature(){ ; prevent copy to  clipboard when double clicked ;autohotkey.com/boards/viewtopic.php?t=3569
   Static Dummy1 := OnMessage(0x00A3, "DisableWindowsFeature") ; WM_NCLBUTTONDBLCLK
   Static Dummy2 := OnMessage(0x0203, "DisableWindowsFeature") ; WM_LBUTTONDBLCLK
   If (A_GuiControl) {
      GuiControlGet, HCTRL, Hwnd, %A_GuiControl%
      WinGetClass, Class, ahk_id %HCTRL%
      If (Class = "Static")
				if (A_GuiControl= "Con"){					
					Gosub, Open_ini
				}else if (A_GuiControl= "last_check"){					
					Gosub, Open_log
				}else if (A_GuiControl= "title"){					
					Gosub, GoToSavedPos
				}			 
         Return 0
   }
}



;============================================



ToolTip_(tekst,t:=2,screen:=0){
	if(screen){
		CoordMode, ToolTip,Screen		
		if(screen==1){
			ToolTip, %tekst% ,600, 350
		}else{
			ToolTip, %tekst% ;,600, 350
		}	
	}else{
		CoordMode , ToolTip, Relative

		GuiControlGet, Pos, Pos, edit_1
		tipX:= PosX+ 4, tipY:=PosY +2
		ToolTip, %tekst% ,%tipX%, %tipY%
	}
	t:=t*1000
	Settimer, ToolTip_close , -%t%
}

ToolTip_close:
	Settimer, ToolTip_close , Off
	tipOn:=0
	ToolTip
return


;=========================================

clear_memory:
	EmptyMem(PID)
return


EmptyMem(PID:=0){ ;by heresy https://autohotkey.com/board/topic/30042-run-ahk-scripts-with-less-half-or-even-less-memory-usage/
    PID:=(PID) ? PID : DllCall("GetCurrentProcessId") 
    h:=DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", pid)
    DllCall("SetProcessWorkingSetSize", "UInt", h, "Int", -1, "Int", -1)
    DllCall("CloseHandle", "Int", h)
}

;======================================


;~^g:: Gosub, test 



test:
return


GuiContextMenu:
Menu, ContextMenu, Show, %A_GuiX%, %A_GuiY%
Return


~$F4::
	Gui 1: Show
return

WindowSpy:
Run, "C:\Program Files\AutoHotkey\AU3_Spy.exe" ;"C:\Program Files\AutoHotkey\WindowSpy.ahk"
WinWait, ahk_exe AU3_Spy.exe , , 3
WinMove, Active Window Info, , 1100
return

Reload:
Reload
return

Edit_Notepad:
Run, "C:\Program Files\Misc\Notepad2\Notepad2.exe" "%A_ScriptFullPath%"
return

Edit_Scite:
Run, "C:\Program Files\AutoHotkey\SciTE\SciTE.exe"  "%A_ScriptFullPath%"
return


Close:
;Esc:: 
GuiClose:
Exit:
Gdip_Shutdown(pToken)
DllCall( "AnimateWindow", "Int", GuiHwnd, "Int", 300, "Int", 0x00050008 )
ExitApp

;#Include C:\Program Files\Misc\AutoHotkey Scripts\functions_Gdip.ahk

Gdip_Startup()
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"	
	if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("LoadLibrary", "str", "gdiplus")
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
	return pToken
}

Gdip_Shutdown(pToken)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"	
	DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
	if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("FreeLibrary", Ptr, hModule)
	return 0
}



SetImage(hwnd, hBitmap)
{
	SendMessage, 0x172, 0x0, hBitmap,, ahk_id %hwnd%
	E := ErrorLevel
	DeleteObject(E)
	return E
}

Gdip_BitmapFromHWND(hwnd)
{
	WinGetPos,,, Width, Height, ahk_id %hwnd%
	hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
	PrintWindow(hwnd, hdc)
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
	return pBitmap
}

Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)
{
	DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "uint", pBitmap, "uint*", hbm, "int", Background)
	return hbm
}

CreateCompatibleDC(hdc=0)
{
   return DllCall("CreateCompatibleDC", "uint", hdc)
}

SelectObject(hdc, hgdiobj)
{
   return DllCall("SelectObject", "uint", hdc, "uint", hgdiobj)
}

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	
	NumPut(w, bi, 4, "uint")
	, NumPut(h, bi, 8, "uint")
	, NumPut(40, bi, 0, "uint")
	, NumPut(1, bi, 12, "ushort")
	, NumPut(0, bi, 16, "uInt")
	, NumPut(bpp, bi, 14, "ushort")
	
	hbm := DllCall("CreateDIBSection"
					, Ptr, hdc2
					, Ptr, &bi
					, "uint", 0
					, A_PtrSize ? "UPtr*" : "uint*", ppvBits
					, Ptr, 0
					, "uint", 0, Ptr)

	if !hdc
		ReleaseDC(hdc2)
	return hbm
}

Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
{
   return DllCall("gdiplus\GdipSetSmoothingMode", "uint", pGraphics, "int", SmoothingMode)
}





Gdip_CreatePen(ARGB, w)
{
   DllCall("gdiplus\GdipCreatePen1", "int", ARGB, "float", w, "int", 2, "uint*", pPen)
   return pPen
}

Gdip_CloneBrush(pBrush)
{
	DllCall("gdiplus\GdipCloneBrush", "uint", pBrush, "uint*", pBrushClone)
	return pBrushClone
}



Gdip_BrushCreateSolid(ARGB=0xff000000)
{
	DllCall("gdiplus\GdipCreateSolidFill", "int", ARGB, "uint*", pBrush)
	return pBrush
}


Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode=1, WrapMode=1)
{
	CreateRectF(RectF, x, y, w, h)
	DllCall("gdiplus\GdipCreateLineBrushFromRect", "uint", &RectF, "int", ARGB1, "int", ARGB2, "int", LinearGradientMode, "int", WrapMode, "uint*", LGpBrush)
	return LGpBrush
}




Gdip_DeletePath(Path)
{
	return DllCall("gdiplus\GdipDeletePath", "uint", Path)
}


PrintWindow(hwnd, hdc, Flags=0)
{
	return DllCall("PrintWindow", "uint", hwnd, "uint", hdc, "uint", Flags)
}


Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
	return pBitmap
}

Gdip_GetDC(pGraphics)
{
	DllCall("gdiplus\GdipGetDC", "uint", pGraphics, "uint*", hdc)
	return hdc
}

GetDC(hwnd=0)
{
	return DllCall("GetDC", "uint", hwnd)
}

DeleteObject(hObject)
{
   return DllCall("DeleteObject", "uint", hObject)
}

DeleteDC(hdc)
{
   return DllCall("DeleteDC", "uint", hdc)
}

ReleaseDC(hdc, hwnd=0)
{
   return DllCall("ReleaseDC", "uint", hwnd, "uint", hdc)
}



CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}


Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
{
   return DllCall("gdiplus\GdipDrawRectangle", "uint", pGraphics, "uint", pPen, "float", x, "float", y, "float", w, "float", h)
}



Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
{
   return DllCall("gdiplus\GdipFillRectangle", "uint", pGraphics, "int", pBrush
   , "float", x, "float", y, "float", w, "float", h)
}

Gdip_GraphicsFromImage(pBitmap)
{
    DllCall("gdiplus\GdipGetImageGraphicsContext", "uint", pBitmap, "uint*", pGraphics)
    return pGraphics
}

Gdip_CreateBitmap(Width, Height, Format=0x26200A)
{
    DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", 0, "int", Format, "uint", 0, "uint*", pBitmap)
    Return pBitmap
}



Gdip_DeletePen(pPen)
{
   return DllCall("gdiplus\GdipDeletePen", "uint", pPen)
}


Gdip_DeleteBrush(pBrush)
{
   return DllCall("gdiplus\GdipDeleteBrush", "uint", pBrush)
}


Gdip_DisposeImage(pBitmap)
{
   return DllCall("gdiplus\GdipDisposeImage", "uint", pBitmap)
}

Gdip_DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", "uint", pGraphics)
}


Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	SplitPath, sOutput,,, Extension
	if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
		return -1
	Extension := "." Extension

	DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
	VarSetCapacity(ci, nSize)
	DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
	if !(nCount && nSize)
		return -2
	
	If (A_IsUnicode){
		StrGet_Name := "StrGet"
		Loop, %nCount%
		{
			sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+idx
			break
		}
	} else {
		Loop, %nCount%
		{
			Location := NumGet(ci, 76*(A_Index-1)+44)
			nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
			VarSetCapacity(sString, nSize)
			DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+76*(A_Index-1)
			break
		}
	}
	
	if !pCodec
		return -3

	if (Quality != 75)
	{
		Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
		if Extension in .JPG,.JPEG,.JPE,.JFIF
		{
			DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
			VarSetCapacity(EncoderParameters, nSize, 0)
			DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
			Loop, % NumGet(EncoderParameters, "UInt")      ;%
			{
				elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
				if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
				{
					p := elem+&EncoderParameters-pad-4
					NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
					break
				}
			}      
		}
	}

	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
		VarSetCapacity(wOutput, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
		VarSetCapacity(wOutput, -1)
		if !VarSetCapacity(wOutput)
			return -4
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", p ? p : 0)
	}
	else
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", p ? p : 0)
	return E ? -5 : 0
}


Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0)
{
	DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
} 



;================================
 
ToolTipFont(Options := "", Name := "", hwnd := ""){ ;lexikos https://autohotkey.com/boards/viewtopic.php?t=4777
    static hfont := 0
    if (hwnd = "")
        hfont := Options="Default" ? 0 : _TTG("Font", Options, Name), _TTHook()
    else
        DllCall("SendMessage", "ptr", hwnd, "uint", 0x30, "ptr", hfont, "ptr", 0)
}
 
ToolTipColor(Background := "", Text := "", hwnd := ""){
    static bc := "", tc := ""
    if (hwnd = "") {
        if (Background != "")
            bc := Background="Default" ? "" : _TTG("Color", Background)
        if (Text != "")
            tc := Text="Default" ? "" : _TTG("Color", Text)
        _TTHook()
    }
    else {
        VarSetCapacity(empty, 2, 0)
        DllCall("UxTheme.dll\SetWindowTheme", "ptr", hwnd, "ptr", 0
            , "ptr", (bc != "" && tc != "") ? &empty : 0)
        if (bc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1043, "ptr", bc, "ptr", 0)
        if (tc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1044, "ptr", tc, "ptr", 0)
    }
}
 
_TTHook(){
    static hook := 0
    if !hook
        hook := DllCall("SetWindowsHookExW", "int", 4
            , "ptr", RegisterCallback("_TTWndProc"), "ptr", 0
            , "uint", DllCall("GetCurrentThreadId"), "ptr")
}
 
_TTWndProc(nCode, _wp, _lp) {
    Critical 999
   ;lParam  := NumGet(_lp+0*A_PtrSize)
   ;wParam  := NumGet(_lp+1*A_PtrSize)
    uMsg    := NumGet(_lp+2*A_PtrSize, "uint")
    hwnd    := NumGet(_lp+3*A_PtrSize)
    if (nCode >= 0 && (uMsg = 1081 || uMsg = 1036)) {
        _hack_ = ahk_id %hwnd%
        WinGetClass wclass, %_hack_%
        if (wclass = "tooltips_class32") {
            ToolTipColor(,, hwnd)
            ToolTipFont(,, hwnd)
        }
    }
    return DllCall("CallNextHookEx", "ptr", 0, "int", nCode, "ptr", _wp, "ptr", _lp, "ptr")
}
 
_TTG(Cmd, Arg1, Arg2 := "") {
    static htext := 0, hgui := 0
    if !htext {
        Gui _TTG: Add, Text, +hwndhtext
        Gui _TTG: +hwndhgui +0x40000000
    }
    Gui _TTG: %Cmd%, %Arg1%, %Arg2%
    if (Cmd = "Font") {
        GuiControl _TTG: Font, %htext%
        SendMessage 0x31, 0, 0,, ahk_id %htext%
        return ErrorLevel
    }
    if (Cmd = "Color") {
        hdc := DllCall("GetDC", "ptr", htext, "ptr")
        SendMessage 0x138, hdc, htext,, ahk_id %hgui%
        clr := DllCall("GetBkColor", "ptr", hdc, "uint")
        DllCall("ReleaseDC", "ptr", htext, "ptr", hdc)
        return clr
    }
}

;==================================


sevenwenty
Posts: 7
Joined: 30 Apr 2016, 10:29

Re: Weather gadget (Gdip). Accuweather

05 Oct 2019, 22:19

The data page no longer contains weather info, as of a few days ago. Maybe it requires some sort of browser emulation?

I suspect this script is more popular than you'd expect. Nothing else I've found so far is as good (AHK or not). It's fast, accurate, and customizable.
drozdman
Posts: 78
Joined: 05 Dec 2015, 01:07

Re: Weather gadget (Gdip). Accuweather

06 Oct 2019, 14:55

@sevenwenty
I tried to change user agent to Firefox, but still it doesn't get anything. They are blocking it, for sure.

Code: Select all

weather_url:="https://www.accuweather.com/en/us/new-york-ny/10007/current-weather/349727"
Contents:=DownloadToString2(weather_url)
MsgBox,4096,, %   "Contents`n"  Contents
	
DownloadToString2(url, encoding="utf-8"){
 ; static a := "AutoHotkey/" A_AhkVersion
	static a :="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0"
  if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
    return 0
  c := s := 0, o := ""
  if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
  {
    while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
    {
      VarSetCapacity(b, s, 0)
      DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
      o .= StrGet(&b, r>>(encoding="utf-16"||encoding="cp1200"), encoding)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", f)
  }
  DllCall("wininet\InternetCloseHandle", "ptr", h)
  return o
}
drozdman
Posts: 78
Joined: 05 Dec 2015, 01:07

Re: Weather gadget (Gdip). Accuweather

19 Oct 2019, 15:17

I tried again with MSN website. It may not block the traffic, if too many people use it.
● One has to choose web address for data in Fahrenheit or Celsius degrees and choose units: unit:="C" or unit:="F".
It's mainly done for Celsius (barometer in metric).
● I added icons.
with_icon:=1 or 2 or 3 (position), with_icon:=0 - no icon (gotten from "Hourly Forecast" - 1 hour ahead)
Image for hourly changes - 1h ahead. It's not perfect. The site sends different content to different browsers, so AHK gets sometimes different images for hourly changes.
● I added also a forecast in a popup. I made it look like my Opera 12 extension.

For how long it will work, I don't know.
I haven't checked this for long, so some bug may come up.

Edit: fix on Nov1 2019

Code: Select all



/*
=== Weather gadget  
● top left circle - toggle always on top
● double click on the title to go to the saved position  
● F4 - show GUI , or click on tray icon
● more options in the right click context menu: background color; save position for next launch,
● weather forecast in popup window, in menu or double click on "last time checked" - bottom right
● choose web address "weather_url" - data is received in Fahrenheit or Celsius degrees. 
So choose units below: unit:="C" or unit:="F". 

● To start not on top of other windows: enable this line #227 ;Gosub, onTop
● Weather icon added. with_icon:=1 or 2 or 3 (position), with_icon:=0 - no icon (gotten from "Hourly Forecast" - 1 hour ahead)
*/

;==========	
	weather_url:="https://www.msn.com/en-us/weather/today/New-York,NY,United-States/we-city?iso=US&savedegree=true&weadegreetype=C"
;==========

	unit:="C" ; if data received in Celsius degrees
;	unit:="F" ; if data received in Fahrenheit 
;	F_to_Celsius:=1 ; convert fahrenheit to Celsius	if data received in Fahrenheit
	
;==========
	write_ini:=1 ; stores data for 1 month
			
			
#SingleInstance force
#NoEnv
;#NoTrayIcon

OnExit, On_Exit

Menu, Tray, Add , Weather , weather
Menu, Tray, Add ,
;Menu, Tray, Icon, shell32.dll,14 ; 47 ; ; 95 ;22 
Menu, Tray, Icon, netshell.dll, 86
Menu, Tray, Add , Edit Scite, Edit_Scite
Menu, Tray, Add , Edit Notepad, Edit_Notepad
Menu, Tray, Add, Exit , Exit ; double click tray icon to exit
Menu, Tray, Default, Exit 

Menu, ContextMenu, Add, On Top, OnTop
;Menu, ContextMenu, Icon, On Top, Shell32.dll, 147
Menu, ContextMenu, Icon, On Top, Shell32.dll, 248 ;wmploc.dll, 17
Menu, ContextMenu, Add, Save current position , save_position
Menu, ContextMenu, Icon, Save current position , Shell32.dll,124 ; 268 ;101 124
Menu, ContextMenu, Add,
Menu, Submenu1, Add, Black , set_bgrd_black
Menu, Submenu1, Add, Steel , set_bgrd_steel
Menu, Submenu1, Add, Blue , set_bgrd_blue  
Menu, Submenu1, Add, Green , set_bgrd_green
;Menu, Submenu1, Add, 
;Menu, Submenu1, Add, Funny style: dots, set_bgrd_style_dots
;Menu, Submenu1, Add, Funny style: dots 2, set_bgrd_style_dots2
;Menu, Submenu1, Add, Funny style: bricks, set_bgrd_style_bricks 
;Menu, Submenu1, Add, 
;Menu, Submenu1, Add, Reset background, reset_bgrd
Menu, ContextMenu, Add, Background color, :Submenu1 

Menu, ContextMenu, Add,
Menu, ContextMenu, Add , Open settings file , Open_ini
Menu, ContextMenu, Icon , Open settings file , Shell32.dll, 70
;Menu, ContextMenu, Add , Open log , Open_log
Menu, ContextMenu, Add,
Menu, ContextMenu, Add , Go to website , Go_to_web
;Menu, ContextMenu, Add , Go to forecast , Go_to_web_for
;Menu, ContextMenu, Icon , Go to website , C:\Program Files\Internet Explorer\iexplore.exe
Menu, ContextMenu, Icon , Go to website , shell32.dll, 221
;Menu, ContextMenu, Add , Go to forecast , Go_to_web_for
;Menu, ContextMenu, Icon , Go to forecast , shell32.dll, 221
Menu, ContextMenu, Add,

Menu, ContextMenu, Add , Forecast  , Show_in_popup
;Menu, ContextMenu, Icon , Forecast , C:\Program Files\Internet Explorer\iexplore.exe
Menu, ContextMenu, Icon , Forecast , shell32.dll, 143 ;243
Menu, ContextMenu, Add,
Menu, ContextMenu, Add , Weather , weather
Menu, ContextMenu, Add ,
Menu, ContextMenu, Add, Restart, Reload
Menu, ContextMenu, Add, Exit, Exit


FileEncoding, UTF-8
SetWorkingDir %A_ScriptDir%

	global img_folder:=A_Temp "\Drozd_Weather"
	IfNotExist %img_folder% 
	FileCreateDir, %img_folder%
	
	global with_icon:=1
	
global settings_ini := "Drozd Weather MSN.ini"

/* global log_file := "Temp\Temperatures_log_AHK.txt"
global reg_log_temp := "Temp\reg_Temp_log_AHK.txt"
IfNotExist Temp 
	FileCreateDir, Temp
FileAppend, Temperature log`n  , %reg_log_temp%
 */
 
	bgrd_grad_black:="0xff222222|0xff0F0F0F|33"
	bgrd_grad_steel:="0xff1A2333|0xff2C3B54|33" 
	bgrd_grad_blue:="0xff06213D|0xff133557|33" 
	bgrd_grad_green:="0xff00230A|0xff044016|33"  
	
	bgrd_grad:=bgrd_grad_green ;bgrd_grad_black

	bgrd_ramki_black:="0xff353535|0xff1C1C1C"
	bgrd_ramki_steel:="0xff2D3F5D|0xff1A2333"
	bgrd_ramki_blue:="0xff16416B|0xff0D263E" 
	bgrd_ramki_green:="0xff044016|0xff00230A" 
	
	bgrd_ramki:=bgrd_ramki_green ;bgrd_ramki_black
	

If !pToken := Gdip_Startup(){
	MsgBox, 48, No Gdiplus 
	ExitApp
}

	OnExit, Exit

	SysGet, MonitorWorkArea, MonitorWorkArea, 1
	pos_x:=MonitorWorkAreaRight - 138 ;A_ScreenWidth - 138
	pos_y:= MonitorWorkAreaBottom -688
	

	IniRead, read_, %settings_ini%, Weather, weather url	

	if(read_="ERROR" || read_=""){			
			IniWrite, %weather_url%	, %settings_ini%, Weather, weather url
			
	}else{
		weather_url:=read_
	}
	

	IniRead, pos_x_saved, %settings_ini%, window position, x	
	IniRead, pos_y_saved, %settings_ini%, window position, y	
	if(!pos_x_saved || !pos_y_saved || pos_x_saved=="ERROR" || pos_y_saved=="ERROR"){
			IniWrite, %pos_x%	, %settings_ini%, window position, x
			IniWrite, %pos_y%	, %settings_ini%, window position, y
	}else{
		if(pos_x_saved<A_ScreenWidth-120 && pos_y_saved<A_ScreenHeight-130){
			pos_x:=pos_x_saved
			pos_y:=pos_y_saved
		}
	}	


	IniRead, GUI_bgrd, %settings_ini%, Window, GUI_background	
	IniRead, GUI_ramka, %settings_ini%, Window, GUI_ramka	
	
	if(GUI_bgrd!="ERROR" && GUI_bgrd!=""  && GUI_ramka!="ERROR" && GUI_ramka!=""){
				bgrd_grad:=GUI_bgrd
				bgrd_ramki:=GUI_ramka
				
	}else{
		IniWrite, %bgrd_grad%	, %settings_ini%, Window, GUI_background
		IniWrite, %bgrd_ramki%	, %settings_ini%, Window, GUI_ramka
	}

;gosub , Show_in_popup
;	return

Gui,1: +ToolWindow -caption +AlwaysOnTop	+HwndGuiHwnd  ;caption
Gui,1:Color, 120F00
Gui,1: -DPIScale
WonTop:=1
; bgrd:
Gui, 1: Add, Picture, x0 y0 w135 h66 vbgrd BackgroundTrans 0xE, 
Gdip_Set_bgrd(bgrd,bgrd_grad)


Gui, 1: Add, Picture, x0 y0 w134 h13 vramkaT 0xE,
Gdip_Set_bgrd(ramkaT,bgrd_ramki_black "|6")

;with_icon:=1

if(with_icon=1){
	Gui, Add, Picture, x35 y19 w54 h31 vramka 0xE,
	Gui, Add, Picture, x3 y19 w31 h31 vramka3 0xE,
	Gdip_Set_bgrd(ramka3, bgrd_ramki "|16")	
	Gui,1: Add, Picture, x3 y19 w30 h30 vIMG_0 BackgroundTrans, 
	Gui, Add, Picture, x90 y19 w42 h15 vramka1 0xE, 
	Gui, Add, Picture, x90 y35 w42 h15 vramka2 0xE,	
	Gui,1: Font, S7  w700 cD2D2D2, Segoe UI ;Arial
	Gui,1: Add, Text , x90 y21 w30 cE9C45D vHum  BackgroundTrans Center, --
	Gui,1: Add, Text , x90 y37 w30 cE9C45D vDew  BackgroundTrans Center, --
	Gui,1: Font, S7  w700 cD2D2D2, Segoe UI
	Gui,1: Add, Text , x118 y21  cD8C591 BackgroundTrans, H
	Gui,1: Add, Text , x118 y37  cD8C591 BackgroundTrans, DP
	
	Gui,1: Font, S15 w700 cE1E1E1 , Segoe UI
	Gui,1: Add, Text , x35 y19  w54  vTem gweather BackgroundTrans Center, -- 
	
}else if(with_icon=2){
	Gui, Add, Picture, x3 y19 w54 h31 vramka 0xE,
	Gui, Add, Picture, x58 y19 w31 h31 vramka3 0xE,
	Gdip_Set_bgrd(ramka3, bgrd_ramki "|16")	
	Gui,1: Add, Picture, x59 y19 w30 h30 vIMG_0 BackgroundTrans, 
	Gui, Add, Picture, x90 y19 w42 h15 vramka1 0xE, 
	Gui, Add, Picture, x90 y35 w42 h15 vramka2 0xE,	
	Gui,1: Font, S7  w700 cD2D2D2,  Segoe UI ;Arial
	Gui,1: Add, Text , x90 y21 w30 cE9C45D vHum  BackgroundTrans Center, --
	Gui,1: Add, Text , x90 y37 w30  cE9C45D vDew  BackgroundTrans Center, --
	Gui,1: Font, S7  w700 ,  Segoe UI
	Gui,1: Add, Text , x118 y21  cD8C591   BackgroundTrans, H
	Gui,1: Add, Text , x118 y37  cD8C591   BackgroundTrans, DP 	
	
	Gui,1: Font, S15 w700 cE1E1E1 , Segoe UI
	Gui,1: Add, Text , x3 y19  w54  vTem gweather BackgroundTrans Center, -- 
	
}else if(with_icon=3){	
	Gui, Add, Picture, x3 y19 w53 h32 vramka 0xE,
	Gui, Add, Picture, x59 y19 w42 h15 vramka1 0xE, 
	Gui, Add, Picture, x59 y36 w42 h15 vramka2 0xE,
	Gui,1: Font, S7  w700 cD2D2D2, Segoe UI ;Arial
	Gui,1: Add, Text , x58 y21 w30 cE9C45D vHum  BackgroundTrans Center, -- 
	Gui,1: Add, Text , x58 y37 w30  cE9C45D vDew  BackgroundTrans Center , -- 

	Gui,1: Font, S7  w700 cD2D2D2, Segoe UI ;Arial
	Gui,1: Add, Text , x87 y21  cD8C591   BackgroundTrans, H
	Gui,1: Add, Text , x87 y37 cD8C591   BackgroundTrans, DP  	
	Gui,1: Add, Picture, x104 y19 w30 h30 vIMG_0 BackgroundTrans,	

	Gui,1: Font, S15 w700 cE1E1E1 , Segoe UI
	Gui,1: Add, Text , x3 y19  w54  vTem gweather BackgroundTrans Center, -- 

	
}else{
	Gui, Add, Picture, x3 y19 w53 h31 vramka 0xE,
	Gui, Add, Picture, x60 y19 w72 h15 vramka1 0xE, 
	Gui, Add, Picture, x60 y35 w72 h15 vramka2 0xE,
	;GoSub, ramka ; ramka:
	Gui,1: Font, S8 w700 cE1E1E1 ,
	Gui,1: Font, S7  w700 cD2D2D2, Arial
	Gui,1: Add, Text , x60 y21 w27 cE9C45D vHum Center BackgroundTrans , -- 
	Gui,1: Add, Text , x60 y37 w27  cE9C45D vDew Center BackgroundTrans , -- 

	Gui,1: Font, S7  w400 cD2D2D2, Arial
	Gui,1: Add, Text , x88 y21  cD8C591 w42  BackgroundTrans, Humidity
	Gui,1: Add, Text , x88 y37  cD8C591 w42  BackgroundTrans, Dew point 

	Gui,1: Font, S15 w700 cE1E1E1 , Segoe UI
	Gui,1: Add, Text , x3 y19  w50  vTem gweather BackgroundTrans Center, -- 
}	

	Gdip_Set_bgrd(ramka,bgrd_ramki "|15",,0)	
	Gdip_Set_bgrd(ramka2,bgrd_ramki "|7",,0)
	Gdip_Set_bgrd(ramka1,bgrd_ramki "|7",,0)

Gui,1: Font, S7 w700 cD0D0D0 , Segoe UI ;
Gui,1: Add, Text , x122 y0 w10 h10 cD0D0D0 gexit BackgroundTrans Center ,  X 
Gui,1: Font, S6 w700 c9C9C9C , Segoe UI
Gui,1: Add, Text , x4 y0  c676767 vonTop_off gonTop BackgroundTrans,  % Chr(9675) ;  ○
Gui,1: Font, S9
Gui,1: Add, Text , x4 y+-13  c676767 vonTop_on gonTop BackgroundTrans, % Chr(9679) ;  ● 
GuiControl, Hide, onTop_off

Gui,1: Font, S7 w700 cE1E1E1 , Segoe UI ; Tahoma 
Gui,1: Add, Text , x18 y0 w100 vtitle gDoubleClick  BackgroundTrans  Center, Weather ;Drozd weather ; gGoToSavedPos

	
Gui,1: Font, S7  w400
Gui,1: Add, Text , x0 y51 w76  vCon  gDoubleClick +HwndConID BackgroundTrans Center, 

Gui,1: Font, S7 w700 cD2D2D2, Arial
Gui,1: Add, Text, x78 y52 w56 vlast_check gDoubleClick +Hwndlast_checkID BackgroundTrans Center,
;GuiControl, Hide, last_check	

;Gui,1: Add, Picture, x115 y51 w16 h16   BackgroundTrans Icon249 AltSubmit, shell32.dll ;
;Gui,1: Add, Picture, x112 y128 w16 h16    Icon249 AltSubmit, shell32.dll ;


OnMessage(0x201, "WM_LBUTTONDOWN")   
OnMessage(0x404, "AHK_NOTIFYICON") 
OnMessage(0x200, "WM_MOUSEMOVE")

Gui, 1: Show, Hide x%pos_x% y%pos_y% w134 h66  , Drozd_weather
;DllCall( "AnimateWindow", "Int", GuiHwnd, "Int", 300, "Int", 0x00000010 )
DllCall( "AnimateWindow", "Int", GuiHwnd, "Int", 300, "Int", 0x00000004 )
;Winset, Transparent,200, Drozd_weather  
WinSet, Style, -0xC00000, Drozd_weather ; COMPLETELY remove window border

	;Gosub, onTop

	GoSub, start_weather
	SetTimer,clear_memory, % 6*60*60*1000
	;GuiControl,1:, IMG_0 , *w30 *h30 C:\a\cloud.png
return


AHK_NOTIFYICON(wParam, lParam){ ;click tray icon to show
    if (lParam = 0x202) {       ; WM_LBUTTONUP
				Gui,1:Show  				
    }else if (lParam = 0x203){   ; WM_LBUTTONDBLCLK
		}
}


WM_LBUTTONDOWN(){
	if(A_Gui=1 || A_Gui=2){
		PostMessage, 0xA1, 2    ; movable borderless window
		
		ToolTip_("", 0.5)
	}	
}

;===================

WM_MOUSEMOVE(){
		global GuiHwnd, tray_tip, tipOn, ConID, last_checkID
		MouseGetPos,, ,winID,control , 3 ; hwnd
		if(winID==GuiHwnd){
			GuiControl, Show, last_check	
			SetTimer, hide_time, -6000
			
			if(control==ConID && tipOn!=1){	
				tipOn:=1
				;ToolTipFont("s11 w700", "Segoe UI")
				ToolTipFont("s10", "Segoe UI Semibold")
				ToolTipColor("F2EEDC", "900000")
				ToolTip_(tray_tip, 3)
			}else if(control==last_checkID && tipOn!=2){
				tipOn:=2
				ToolTipFont("s9", "Segoe UI")
				ToolTipColor("FFFFFF","333333")
				ToolTip_("` last checked ", 1)
			}
		}
}

;======================================


start_weather:
	GoSub, weather
	SetTimer, weather, % 30*60*1000  ; 0.5h		
			del_last_month()
return

weather:
	Gosub, weather_get
	Gosub, write_
return



weather_get:
	if !InternetConnection(){
		SetTimer, check_again, -60000
		return
	}

;now___

 	;from_file:="C:\a\x\Weather\MSN Weather.html"
	;FileRead, HTML_page, %from_file%	
	
	;GuiControlGet,t1,1:, last_check 
	GuiControl,, last_check, 
	GuiControl,, last_check, connecting
	HTML_page:=DownloadToString(weather_url)
	;FileDelete, C:\a\test Weather MSN Weather.html
	;FileAppend, %HTML_page%, C:\a\test Weather MSN Weather.html
	RegExMatch(HTML_page,"im)<div class=""current-info""([\s\S]*?)Hourly Forecast", today) ;
	;MsgBox,4096,, %  today "`n"  
	
	RegExMatch(today,"im)<span class=""current"" aria-label=""[^""]*"">(-?\d+)<",temper)
	RegExMatch(today,"im)<span>Dew Point</span> (-?\d+)",dew)
	RegExMatch(today,"im)<span>Humidity</span> (\d+)",hum)
	RegExMatch(today,"im)<span>Feels Like</span> (-?\d+)",temperFeel)
	RegExMatch(today,"im)<div class=""weather-info"">\s*<span>(.+?)<\/span>",cond)
	RegExMatch(today,"im)<li><span>Barometer</span> (\d+\.\d+ mb)</li>",bar)
	;MsgBox,4096,, % "temp=" temper1 "`ndew=" dew1 "`nhum=" hum1 "`n" temperFeel1  "`n" cond1 "`n" bar1
	
	FormatTime, t,, t 
	;StringLower, t, t
	FormatTime, h,, h
	if(h t="11P"){
		hour:="12A"
	}else if(h t="12P"){
		hour:="1P"
	}else if(h t="11A"){
		hour:="12P"	
	}else if(h t="12A"){
		hour:="1A"
	}else{	
		hour:=(h+1) t 
	}

	RegExMatch(HTML_page,"im)<p class=""time"">" hour "</p>.+?<p class=""time"">",pic)
	;MsgBox,4096,, % hour "`n"  "`n" pic 
	RegExMatch(pic,"im)src=""(.*?)""",pic)
	src_0:="https:" pic1

	;MsgBox,4096,, % src_0  "`n" hour "`n" pic
	;Run, %src_0%
	img_name:= img_folder "\img_0.png"  
	UrlDownloadToFile, %src_0% , %img_name%
	GuiControl,1:, IMG_0 , *w30 *h30 %img_name%
	
	tem:=temper1
	dew:=dew1
	temFeel:=temperFeel1	
	hum:=hum1 "%"
	con:=cond1
	bar:=bar1
	;MsgBox,4096,, % "temp=" tem "`ndew=" dew "`nhum=" hum "`n" temFeel  "`n" con "`n" bar1
	if tem is not integer 
	{
		;MsgBox,,Drozd Weather, % "Temperature read error.`nWill check again in 1 min." , 1
		Gosub, popupGUI
		SetTimer, check_again,  % 1*60*1000
		return
	}
	

		tem:=tem Chr(176) unit  ;"°"
		dew:=dew Chr(176) unit   ;"°"		
		temFeel:=temFeel Chr(176) unit		

	last_temp:=tem

	strT:="  Temperature:   " tem "  "
	strD:="  Dew point:       " dew "  "
	strH:="  Humidity:         " hum "  "
	strY_:="  Feels Like:        " temFeel
	strP_:="  Pressure:          " bar

	tray_tip:="  " con "`n" strT "`n" strY_ "`n"  strD "`n" strH "`n" strP_ ;"`n  " hour ;strY_2 ;"`n  ------`n" normT "`n" recT

	Menu,Tray,Tip, %  "  " con "`n" strT "`n"  strD "`n" strP_ "`n  hour: " hour

	global obj_today:= Object()
	obj_today.name:="today"
	obj_today.high:=tem
	;obj_today.low:=
	obj_today.dew:=dew
	obj_today.temFeel:=temFeel
	obj_today.hum:=hum
	obj_today.bar:=bar
	obj_today.con:=con

	
	GuiControl,, Tem, %tem%  
	GuiControl,, Hum, %hum%
	GuiControl,, Dew, %dew%  
	GuiControl,, Con, %con%

	

	FormatTime, date, %A_Now%, HH:mm ;MMMd 
	GuiControl,, last_check, %date%
	SetTimer, hide_time, -3000
return


write_:
	if(write_ini!=1)
		return
	IniRead, today_1, %settings_ini%, %  A_MM " " A_YYYY , % A_MMM A_DD
	IniRead, reg_log_, %settings_ini%, %  A_MM " " A_YYYY , % A_MMM A_DD


	reg_log_:=(reg_log_=="ERROR") ? "" : reg_log_ " | " 
	reg_log:= A_Hour "h " tem
	reg_log:=reg_log_ reg_log
	
	
	if !InStr(reg_log_,A_Hour "h")
	IniWrite, %reg_log%	, %settings_ini%, %  A_MM " " A_YYYY, % A_MMM A_DD
return


hide_time:
	SetTimer, hide_time, Off
	GuiControl, Hide, last_check	
return


check_again:
	Gosub, weather	
return


popupGUI:
;Gui,4: Destroy
Gui,4:+ToolWindow -Caption +HwndGuiHwnd_2
Gui,4:Color, 700000

Gui,4:+Owner1  +AlwaysOnTop
;Gui,4: +Parent%GuiHwnd%
;DllCall("SetParent", "uint", GuiHwnd_2, "uint", GuiHwnd)


Gui,4: Font, S7 w700 cE1E1E1 Q5, Verdana ;Arial ;Segoe UI Semibold
;Gui,4: Add, Text, x3 y8 w128 ,% "Temperature read error. `nWill check again in 1 min."
;Gui,4:+Parent%GuiHwnd%
;MsgBox,4096,, %  pos_x "`n"  pos_y

Gui,4: Add, Text, x3 y6 w128 ,% "Temperature read error. `nWill check again in 1 min."
pos_x4:= pos_x, pos_y4:=pos_y+13
WinGetPos ,pos_x1,pos_y1,,, ahk_id %GuiHwnd%
pos_x4:= pos_x1, pos_y4:=pos_y1+13
Gui, 4:Show, x%pos_x4% y%pos_y4% w134 h38 NA, Drozd_popupGUI
SetTimer, Dest_popupGUI, -3000
return

Dest_popupGUI:
Gui,4: Destroy
return

f_C(t,d:=0){ ;(°F  -  32)  x  5/9 = °C ;fahrenheit_to_celsius
	t:= (t-32)*(5/9)
	t:=Round(t,d)
	return t
}




;======================

del_last_month(){
  global reg_log_temp
	prev_m:= (A_MM!=01) ? dig(A_MM - 1) " " A_YYYY : 12 " " A_YYYY-1 
	IniRead, prev_month , %settings_ini%, % prev_m
  if(prev_month!=""){
		if FileExist(reg_log_temp){
			FileAppend, `n%prev_m%`n  , %reg_log_temp%
			FileAppend, %prev_month%`n  , %reg_log_temp%
		}
    IniDelete,  %settings_ini%, %prev_m% 
  }
	; leftovers 
	Loop % A_MM-1 {
		prev_m:=dig(A_MM-A_Index) " " A_YYYY
		IniRead, prev_month , %settings_ini%, % prev_m
		if(prev_month!=""){
			IniDelete,  %settings_ini%, %prev_m%
		}
	}
	
}


dig(num){ ;to_two_digits
   num:= num<=9 ? "0" . num : num
   return num
}


;============================================

weather_forecast:


	;from_file:="C:\a\x\Weather\MSN Weather.html"
	;FileRead, HTML_page, %from_file%	
	weather_forecast_url:= weather_url
	HTML_page:=DownloadToString(weather_forecast_url)
	
	RegExMatch(HTML_page,"im)<h2>Daily Forecast</h2>([\s\S]*)""weathernews-headingtext""", forecast) ;

;MsgBox,4096,, % forecast
 	daysObj:=Object()
	pos_ := 1, ind:=1
	While pos_ {
		;if(pos_<=0) 
		;	break
		pos_:=RegExMatch(forecast,"im)<div class=""dt"">([\s\S]*?)(?:<div class=""dt"">|class='normalsection')",day, pos_)
 
		RegExMatch(day,"im)<div class=""dt"">\s*<span>(\w+)<\/span>\s*<span>\s*(\d+)<\/span>",date)
		RegExMatch(day,"im)<p class=""daytemphigh"">(-?\d+)&#176;</p>\s*<p>(-?\d+)&#176",daytemp)
		RegExMatch(day,"im)src=""([^""]*)"" alt=""([^""]*)""",cond)
		if(!daytemp)
			break
		ind:=A_Index
		daysObj[ind]:=Object()
		daysObj[ind].day:=date1, daysObj[ind].date:=date2
		daysObj[ind].temHigh:=daytemp1 Chr(176) , daysObj[ind].temLow:=daytemp2 Chr(176) ;"°"
		daysObj[ind].src:="https:" cond1 , daysObj[ind].con:=cond2
		img_name:= img_folder "\" "img" A_Index ".png"
		UrlDownloadToFile, % daysObj[ind].src , %img_name%
		daysObj[ind].img:=img_name
		
		src:="https:" cond1
		con:=cond2
		pos_:=pos_ +StrLen(day) -30
		if(pos_<0) 
			pos_:=0
		ind:=ind+1

	}
return

;now___

Show_in_popup: 
	;Gosub, weather_get
	Gosub, weather_forecast
	bgrd_grad_2:="0xff293A56|0xff243146|75" ;bgrd_grad_steel	
	width_:=430
	height_:=520
	width_r:=564

;Gui,2:+ToolWindow +AlwaysOnTop
Gui,2: -border	+HwndGuiHwnd_2 
Gui,2:Color, 120F00
Gui,2: -DPIScale
; bgrd:
Gui, 2: Add, Picture, x0 y0 w%width_% h%height_% vbgrd_2 +Hwndbckgr_2Hwnd  BackgroundTrans 0xE, 
Gdip_Set_bgrd_2(bgrd_2,bgrd_grad_2,null,null,1) 
Gui, 2: Add, Picture, x0 y0 w%width_% h20 vramkaT 0xE,
Gdip_Set_bgrd_2(ramkaT,"0xff383D46|0xff1E2126|13",null,null,1)

Gui,2: Font, S10 w700 cD0D0D0 , Segoe UI ;
x_close:=width_-18
Gui,2: Add, Text , x%x_close% y0 w18 h18 cD0D0D0 gClosePop BackgroundTrans Center ,  X 

Gui,2: Font, S10 w700 cE1E1E1 , Segoe UI 
Gui,2: Add, Text , x0 y0 w%width_% vtitle  BackgroundTrans  Center, Weather Forecast 


	Gui,2: Add, Picture, x20 y+10 w%width_r% h30 vramka_21 0xE,
	Gdip_Set_bgrd_2(ramka_21,"0xff601A13|0xff44120E|16",obj_today,1,0,1)
	Gui,2: Add, Picture, x20 y+4 w%width_r% h30 vramka_22 0xE,
	Gdip_Set_bgrd_2(ramka_22,"0xff601A13|0xff44120E|16",obj_today,1,0,2)		
	 

Loop, % daysObj.Length() {
	str:=daysObj[A_Index].date " , " daysObj[A_Index].day "`n"  daysObj[A_Index].temp " , " daysObj[A_Index].temLow "`n"  daysObj[A_Index].cond
	ind=ramka_1%A_Index%
	str:=parsed[A_Index].date " , " parsed[A_Index].lDOW " , " parsed[A_Index].day.dTemp " / " parsed[A_Index].night.dTemp " , " parsed[A_Index].day.phrase "`n" 
		if(A_Index=1){
			Gui,2: Add, Picture, x20 y+16 w%width_r% h34 vramka_10 0xE,
			Gdip_Set_bgrd_2(ramka_10,"0xff11344E|0xff0C2936|30",daysObj[1],1,0,3)
			Gui,2: Add, Picture, x210  y+-34 w30 h30 vIMG%A_Index% BackgroundTrans, % daysObj[A_Index].img 
		}else if(A_Index>1 && A_Index<7){
			Gui,2: Add, Picture, x20 y+10 w%width_r% h34 vramka_1%A_Index% 0xE,
			Gdip_Set_bgrd_2(%ind%,"0xff601A13|0xff44120E|30",daysObj[A_Index],1)
			Gui,2: Add, Picture, x210 y+-34 w30 h30 vIMG%A_Index% BackgroundTrans, % daysObj[A_Index].img
		}else if(A_Index=12){
			Gui,2: Add, Picture, x20 y+10 w%width_r% h23 vramka_1%A_Index% 0xE,
			Gdip_Set_bgrd_2(%ind%,"0xff601A13|0xff44120E|30",daysObj[A_Index],1)	
			Gui,2: Add, Picture, x210 y+-30 w30 h30 vIMG%A_Index% BackgroundTrans, % daysObj[A_Index].img	
		}else if(A_Index>=12){
			Gui,2: Add, Picture, x20 y+5 w%width_r% h23 vramka_1%A_Index% 0xE,
			Gdip_Set_bgrd_2(%ind%,"0xff601A13|0xff44120E|30",daysObj[A_Index],1)
			Gui,2: Add, Picture, x210 y+-30 w30 h30 vIMG%A_Index% BackgroundTrans, % daysObj[A_Index].img 	
		}else{
			Gui,2: Add, Picture, x20 y+6 w%width_r% h30 vramka_1%A_Index% 0xE,
			Gdip_Set_bgrd_2(%ind%,"0xff11344E|0xff0C2936|16",daysObj[A_Index],1)
			Gui,2: Add, Picture, x210 y+-31 w30 h30 vIMG%A_Index% BackgroundTrans, % daysObj[A_Index].img
		}
}
	
Gui, 2: Show,  w%width_% h%height_%  , Drozd_weather_forecast

return

ClosePop:
Gui, 2: Destroy 
return

;===========================================================


Gdip_Set_bgrd_2(ByRef Variable, Background,ByRef obj,ramka=0,bckgr=0,first=0){
	GuiControlGet, Pos,2:Pos, Variable
	GuiControlGet, hwnd,2:hwnd, Variable 
	pBitmap := Gdip_CreateBitmap(PosW, PosH), G := Gdip_GraphicsFromImage(pBitmap), Gdip_SetSmoothingMode(G, 4)	
	
	Background_:=StrSplit(Background,"|")
	if(Background_.Length() >1){
		;=== with gradient =====
		grad_color_rim:=Background_[1]
		grad_color_mid:=Background_[2]
		size:=Background_[3]
		pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, size, grad_color_rim, grad_color_mid ,1) 
		if(bckgr){
			Gdip_FillRectangle(G, pBrushFront,-1, -1,  PosW+1, Posh+1)
		}else{
			pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, size, 0xff293A56, 0xff243146 ,1)
			
			Gdip_FillRectangle(G, pBrushFront,-1, -1,  PosW+1, Posh+1)
		} 		
		;Gdip_FillRectangle(G, pBrushFront,-1, -1,  PosW+1, Posh+1)
		;Gdip_FillRoundedRectangle(G, pBrushFront,-1, -1,  PosW+1, Posh+1, 10)
	;========
	}else{
		pBrushBack := Gdip_BrushCreateSolid(Background)
		Gdip_FillRectangle(G, pBrushBack, 0, 0, PosW, Posh)
	}
	
	if(ramka=1){
			col:=grad_color_mid ;
			colorS1:=0xff667480 ;0xff7F869F
			col:=0xff888888 ;0xff000000
			col:=colorS1
			;pPen:=Gdip_CreatePen(col, 1)	
			pPen:=Gdip_CreatePen(0xff000000, 1)
			pPen2:=Gdip_CreatePen(col, 1)	
			color3:=0xffDFBC59
			pPen3:=Gdip_CreatePen(color3, 1)			
			;pPen2:=Gdip_CreatePen(0xffDDDDDD, 1)
			color1:=0xffDDDDDD ,  color2:=0xffBBBBBB ;  0xff7F869F
			color1a:=0xffCCCCCC
			color3:=0xffDFBC59
			colorS:=0xff667480 ;0xff7F869F
			colorG:=0xffDFBC59 , colorG2:=0xffCB985A, colorG3:=0xffB98A51, colorG4:=0xffCBAB51   ;colorG:=0xffE9C45D, colorG2:=0xffE6B375
			date:=obj.date " " obj.day
			date1:=obj.date , day:= obj.day
			temp:=obj.temHigh "/"  obj.temLow
			temp1:=obj.temHigh , temp2:= "/"  obj.temLow
			cond:=obj.con
			img:=obj.src

		if(obj.name="today"){
			;obj.high, obj.low, obj.temFeel, obj.dew, obj.hum,obj.bar,obj.con
			if(first=1){
				pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 15, 0xff19283F, 0xff203B66 ,1)  ;blue	 
				;pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 15, 0xff153F14, 0xff0F2C0E ,1)  ;green			

				Gdip_FillRoundedRectangle(G, pBrushFront, 1,0,70, 29, 8) ;
				Gdip_DrawRoundedRectangle(G, pPen,0, 0, 70, 29,8)	
				Gdip_TextToG(G,"Today", 0xff000000,13,4,15, 70, 25,"Tahoma",1)
				Gdip_TextToG(G,"Today", color1a,11,5,15, 70, 25,"Tahoma",1)
			
				Gdip_FillRoundedRectangle(G, pBrushFront, 76,0,310, 29, 8) ;
				Gdip_DrawRoundedRectangle(G, pPen,75, 0, 310, 29,7)				
				Gdip_TextToG(G,"Temperature:", colorG3,83,8,11, 90, 25,"Tahoma",1)
				Gdip_TextToG(G,obj.high, 0xff000000,176,4,15, 50, 25,"Tahoma",1)
				Gdip_TextToG(G,obj.high, colorG,174,5,15, 50, 25,"Tahoma",1)
		
				Gdip_TextToG(G,"Feels like:", colorG3,249,8,11, 90, 25,"Tahoma",1)
				Gdip_TextToG(G,obj.temFeel, 0xff000000,325,5,13, 50, 25,"Tahoma",1)
				Gdip_TextToG(G,obj.temFeel, colorG4,323,6,13, 50, 25,"Tahoma",1)

				}else if(first=2){
				pBrushFront:= Gdip_CreateLineBrushFromRect(0, 0, 1, 15, 0xff19283F, 0xff203B66 ,1)  ;blue	
				Gdip_FillRoundedRectangle(G, pBrushFront, 1,4,108, 22, 8) ;
				Gdip_DrawRoundedRectangle(G, pPen,0, 4, 110, 22,7)	
				Gdip_TextToG(G,"Humidity:", colorG3,10,8.5,11, 90, 25,"Tahoma",1)
				Gdip_TextToG(G,obj.hum,0xff000000,71,7,12, 50, 25,"Tahoma",1)
				Gdip_TextToG(G,obj.hum, colorG4,69,8,12, 50, 25,"Tahoma",1)


				Gdip_FillRoundedRectangle(G, pBrushFront, 116,4,118, 22, 8) ;
				Gdip_DrawRoundedRectangle(G, pPen,115, 4, 120, 22,7)		
				Gdip_TextToG(G,"Dew point:", colorG3,125,8.5,11, 90, 25,"Tahoma",1)
				Gdip_TextToG(G,obj.dew,0xff000000,195,6.5,12, 50, 25,"Tahoma",1)
				Gdip_TextToG(G,obj.dew, colorG,193,7.5,12, 50, 25,"Tahoma",1)
				
				Gdip_FillRoundedRectangle(G, pBrushFront, 242,4,142, 22, 8) ;
				Gdip_DrawRoundedRectangle(G, pPen,241, 4, 144, 22,7)				
				
				Gdip_TextToG(G,"Barometer:", colorG3,250,8,11, 90, 25,"Tahoma",1)
				;Gdip_TextToG(G,RegExReplace(obj.bar,"\.\d\d",""), colorG2,390,8,12, 90, 25,"Tahoma",1)
				bar:=RegExReplace(obj.bar,"\.\d\d","")
				Gdip_TextToG(G,bar, 0xff000000,326,7,11, 80, 25,"Tahoma",1)
				Gdip_TextToG(G,bar, colorG4,324,8,11, 80, 25,"Tahoma",1)
			}	
	
			}else if(PosH>30){
			
			if(first=3){
				;pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 15, 0xff153F14, 0xff0F2C0E ,1)  ;green
				pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 15, 0xff19283F, 0xff203B66 ,1)  ;blue
				;pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 15, 0xff203B66, 0xff19283F ,1)  ;blue		
				Gdip_FillRoundedRectangle(G, pBrushFront, 1,1,74, 32, 8) ; date
				Gdip_FillRoundedRectangle(G, pBrushFront, 84,1,82, 32, 8) ;temp
			}else{			
				pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 15, 0xff601A13, 0xff44120E ,1) 
				Gdip_FillRoundedRectangle(G, pBrushFront, 1,1,74, 32, 8) ; date
				Gdip_FillRoundedRectangle(G, pBrushFront, 84,1,82, 32, 8) ;temp			
			}
			
			x0:=(StrLen(date1)>4) ?  4 : (StrLen(date1)=3) ? 11 :8 

			if(obj.day="Sun"){
				Gdip_TextToG(G,day, 0xff000000,  12,8,13, 40, 25,"Tahoma",1)
				Gdip_TextToG(G,day, color3,   10,9,13, 40, 25,"Tahoma",1)
			}else{
				Gdip_TextToG(G,day, 0xff000000,  12,8,13, 40, 25,"Tahoma",1)
				Gdip_TextToG(G,day, color1,   10,9,13, 40, 25,"Tahoma",1)
			}
			
			Gdip_TextToG(G,date1, color1,50,11,11, 44, 25,"Tahoma",1)

			x1:=(StrLen(temp1)>3) ? 90 : 94, x2:=(StrLen(temp1)>3) ? 128 : 126
			Gdip_TextToG(G,temp1, 0xff000000, x1+2,6,16, 50, 25,"Tahoma",1)		
			Gdip_TextToG(G,temp1, colorG, x1,7,16, 50, 25,"Tahoma",1)
			Gdip_TextToG(G,temp2, colorG2,x2,9,13, 40, 25,"Tahoma",1)

			Gdip_TextToG(G,cond,  color2, 240,10,11,340, 25,"Tahoma",1)

			Gdip_DrawRoundedRectangle(G, pPen,0, 1, 76, 32,7)
			Gdip_DrawRoundedRectangle(G, pPen,84, 1, 82, 32,7)

		}else if(PosH<25){
			pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 10, 0xff203B66, 0xff19283F ,1)  ;blue			
			Gdip_FillRoundedRectangle(G, pBrushFront, 1,0,74, 22, 8) ; date
			Gdip_FillRoundedRectangle(G, pBrushFront, 84,0,82, 22, 8) ;temp
			
			x0:=(StrLen(date1)>4) ?  4:8
			
			if(obj.day="Sun"){
				Gdip_TextToG(G,day, 0xff000000,12,4,10, 40, 25,"Tahoma",1)
				Gdip_TextToG(G,day, color3,    10,5,10, 40, 25,"Tahoma",1)
			}else{
				Gdip_TextToG(G,day, 0xff000000,12,4,10, 40, 25,"Tahoma",1)
				Gdip_TextToG(G,day, color1a,   10,5,10, 40, 25,"Tahoma",1)
			}
			Gdip_TextToG(G,date1, color1a,50,6,10, 44, 25,"Tahoma",1)
			x1:=(StrLen(temp1)>3) ? 90 : 94, x2:=(StrLen(temp1)>3) ? 126 : 123
			Gdip_TextToG(G,temp1, colorG, x1,4,12, 50, 25,"Tahoma",1)
			Gdip_TextToG(G,temp2, colorG2,x2,6,9, 40, 25,"Tahoma",1)
			
			Gdip_TextToG(G,cond, colorS, 240,6,9, 340, 25,"Tahoma",1)
			Gdip_DrawRoundedRectangle(G, pPen2,0, 0, 76, 22,7)
			Gdip_DrawRoundedRectangle(G, pPen2,84, 0, 82, 22,7)

		}else{	
			pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 15, 0xff203B66, 0xff19283F ,1)  ;blue			
			Gdip_FillRoundedRectangle(G, pBrushFront, 1,1,74, 32, 8) ; date
			Gdip_FillRoundedRectangle(G, pBrushFront, 84,1,82, 32, 8) ;temp
			
			x0:=(StrLen(date1)>4) ?  4:8

			if(obj.day="Sun"){
				Gdip_TextToG(G,day, 0xff000000,12,7,12, 40, 25,"Tahoma",1)
				Gdip_TextToG(G,day, color3,    10,8,12, 40, 25,"Tahoma",1)
			}else{
				Gdip_TextToG(G,day, 0xff000000,12,7,12, 40, 25,"Tahoma",1)
				Gdip_TextToG(G,day, color1a,   10,8,12, 40, 25,"Tahoma",1)
			}
			Gdip_TextToG(G,date1, color1a,50,9,10, 44, 25,"Tahoma",1)
			x1:=(StrLen(temp1)>3) ? 90 : 94, x2:=(StrLen(temp1)>3) ? 126 : 123
			Gdip_TextToG(G,temp1, 0xff000000, x1+2,5,14, 50, 25,"Tahoma",1)
			Gdip_TextToG(G,temp1, colorG, x1,6,14, 50, 25,"Tahoma",1)
			Gdip_TextToG(G,temp2, colorG2,x2,8,11, 40, 25,"Tahoma",1)

			Gdip_TextToG(G,cond, colorS, 240,8,10, 340, 25,"Tahoma",1)

			Gdip_DrawRoundedRectangle(G, pPen2,0, 1, 76, 28,7)
			Gdip_DrawRoundedRectangle(G, pPen2,84, 1, 82, 28,7)
			
		}
	}

	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	SetImage(hwnd, hBitmap)
	
	Gdip_DeleteBrush(pBrushFront), Gdip_DeleteBrush(pBrushBack),Gdip_DeletePen(pPen),Gdip_DeletePen(pPen2),Gdip_DeletePen(pPen3)
	Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
	Return, 0
}


;==================================

Gdip_TextToG(ByRef G, Text, color,x, y,size,Width, Height,Font:="Arial",Style=1,Align=0){
	;Style := 1 ;, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
	pBrushT := Gdip_BrushCreateSolid(color)	
	CreateRectF(RC, x, y, Width,Height )	
	hFamily := Gdip_FontFamilyCreate(Font)
	hFont := Gdip_FontCreate(hFamily, size, Style)
	FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
	Rendering:=5
	
	hFormat := Gdip_StringFormatCreate(FormatStyle)		
	Gdip_SetStringFormatAlign(hFormat, Align)
	
	Gdip_SetTextRenderingHint(G, Rendering)
	ReturnRC := Gdip_MeasureString(G, Text, hFont, hFormat, RC) 

	E :=Gdip_DrawString(G, Text, hFont, hFormat, pBrushT, RC)
	
	Gdip_DeleteBrush(pBrushT)	
	Gdip_DeleteStringFormat(hFormat), Gdip_DeleteFont(hFont),	Gdip_DeleteFontFamily(hFamily)
	return E ? E : ReturnRC
}




;===========================================================


/* Show_in_popup:  ;Forecast
	HTML_page:=DownloadToString(weather_url)
	 
	if(F_to_Celsius){
		Gosub, change_FtoC

		if(RegExMatch(HTML_page,"i)<li>Ceiling: <strong>(\d+) ft<",match)){
			match:=RegExReplace(match,match1 " ft",feet_to_m(match1))
			HTML_page:=RegExReplace(HTML_page,"im)<li>Ceiling: <strong>(\d+) ft<", match)		
		}

		if(RegExMatch(HTML_page,"i)<li>Visibility: <strong>(\d+) mi", match)){
			match:=RegExReplace(match,match1 " mi", mile_to_km(match1))
			HTML_page:=RegExReplace(HTML_page,"im)<li>Visibility: <strong>(\d+) mi", match)
		} 
		
		if(RegExMatch(HTML_page,"i)<li class=""wind""><strong>(\d+) mph<",match)){		 
			match:=RegExReplace(match,match1 " mph",mile_to_km(match1) "/h")
			HTML_page:=RegExReplace(HTML_page,"im)<li class=""wind""><strong>(\d+) mph<", match)
		} 
	}

	
	RegExMatch(HTML_page,"im)<link rel=""stylesheet"" href=""(.+)?"" type=""text/css""",css)
	urlCSS:=css1

;RegExMatch(HTML_page,"im)<!-- /.feed-controls -->\s+(<div id=""feed-tabs"" class=""panel-list"">[\s\S]*Next 5 Days[\s\S]*)<div class=""rise-modules"">",Next_5_Days)

RegExMatch(HTML_page,"ims)<!-- /.feed-controls -->\s+(<div id=""feed-tabs"" class=""panel-list"">.*Next 5 Days.*?)(?=<div class=""panel-body-content"">)",Next_5_Days) 	

HTML_page1 = 
( comments
  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  <html>
  <head><meta http-equiv="X-UA-Compatible" content="IE=Edge"></head>
  <style></style>
  <title>Forecast</title>
  </head>
  <body><center> ;<h1> TEST </h1>
)

HTML_page:= HTML_page1 Next_5_Days1  "<a href='" weather_url "'>" weather_url "</a><br>" "</center></body></html>"

;urlCSS:="https://vortex.accuweather.com/adc2010/stylesheets/slate.min-20180522-1001.css"
addCSS:= "<link rel=""stylesheet"" type=""text/css"" href=""" urlCSS """ />"
HTML_page:=RegExReplace(HTML_page,"im)<\/head>", addCSS "</head>")
 
w:=700 , h:=710
;w:=560 , h:=700
Gui,5: Add, ActiveX, vWB w%w% h%h% +Resize +VScroll +HScroll, about:<!DOCTYPE html><meta http-equiv="X-UA-Compatible" content="IE=edge">
  WB.silent := true 
  document := WB.Document
  document.open()
  document.write(HTML_page)
  document.close()
	;WB.Document.Body.Style.Zoom := "80%"
Gui,5: +HWNDWin_id 
;Gui,5: +Owner1  +AlwaysOnTop
Gui,5: Show,% "w" w+20 " h" h+10, IE ActiveX  
match:= document:= HTML_page:=""
return
 */
 
5GuiClose:
	Gui,5: Destroy
return


change_FtoC:
	HTML_page:=RegExReplace(HTML_page,"im)<\/head>", addCSS "</head>")	 
	HTML_page2:=HTML_page
	RegExMatch(HTML_page2,"im)(\d\d)&deg;(?C1:Replacer)")
	HTML_page:=RegExReplace(HTML_page,"im)&deg;(?:F(?!\)))?","")
	HTML_page2:=""
	
	if(RegExMatch(HTML_page,"i)<li>Dew Point: <strong>(\d+)&#176;&nbsp;F<",match)){
		match:=RegExReplace(match,match1 ,f_C(match1))
		match:=RegExReplace(match,"F<","C<")
		HTML_page:=RegExReplace(HTML_page,"im)<li>Dew Point: <strong>(\d+)&#176;&nbsp;F<", match)
	}
	HTML_page:=RegExReplace(HTML_page,"im)<li>Dew Point: <strong>(\d+)&#176;&nbsp;F<", match)
return


Replacer(match,1,pos){
	global HTML_page
	repl:=f_C(match1) "°" 
	HTML_page:=RegExReplace(HTML_page,"im)" match1,repl,,1,pos)
	return 1
}


mile_to_km(mi){
	return Round(mi*1.60934) " km"
}

feet_to_m(leg){
	return Round(leg* 0.3048) " m"
}

;============================================

;======================
InternetConnection(flag:=0x40) { 
	return DllCall("Wininet.dll\InternetGetConnectedState", "Str", flag,"Int",0) 
}

;======================


DownloadToString(url, encoding="utf-8"){ ;https://autohotkey.com/board/topic/89198-simple-download-bin-tostring-und-tofile/ Bentschi
  static a := "AutoHotkey/" A_AhkVersion
	;static a :="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0"
  if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
    return 0
  c := s := 0, o := ""
  if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
  {
    while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
    {
      VarSetCapacity(b, s, 0)
      DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
      o .= StrGet(&b, r>>(encoding="utf-16"||encoding="cp1200"), encoding)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", f)
  }
  DllCall("wininet\InternetCloseHandle", "ptr", h)
  return o
}

DownloadToFile(url, filename){
  static a := "AutoHotkey/" A_AhkVersion
  if (!(o := FileOpen(filename, "w")) || !DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
    return 0
  c := s := 0
  if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
  {
    while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
    {
      VarSetCapacity(b, s, 0)
      DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
      c += r
      o.rawWrite(b, r)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", f)
  }
  DllCall("wininet\InternetCloseHandle", "ptr", h)
  o.close()
  return c
}

;=============================
ramka: ;bgrd:
	Gdip_Set_bgrd(ramka,bgrd_ramki "|15",,0)	
	Gdip_Set_bgrd(ramka2,bgrd_ramki "|7",,0)
	Gdip_Set_bgrd(ramka1,bgrd_ramki "|7",,0)
	
return

Gdip_Set_bgrd(ByRef Variable, Background=0x00000000,Hatch=0,border=0){
	GuiControlGet, Pos, Pos, Variable
	GuiControlGet, hwnd, hwnd, Variable  
	
	pBitmap := Gdip_CreateBitmap(Posw, Posh), G := Gdip_GraphicsFromImage(pBitmap), Gdip_SetSmoothingMode(G, 4)	
	
	Background_:=StrSplit(Background,"|")
	if(Background_.Length() >1){
		;=== with gradient =====
		;pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, 10, grad_color1, grad_color2 ,1) 
		grad_color_rim:=Background_[1]
		grad_color_mid:=Background_[2]
		size:=Background_[3]

		if(Hatch=0){
			pBrushFront := Gdip_CreateLineBrushFromRect(0, 0, 1, size, grad_color_rim, grad_color_mid ,1) 
		}else{
			pBrushFront :=Gdip_BrushCreateHatch(grad_color_rim, grad_color_mid, Hatch) ; kropki
		}
		Gdip_FillRectangle(G, pBrushFront,-1, -1,  PosW+1, Posh+1)
	;========
	}else{
		pBrushBack := Gdip_BrushCreateSolid(Background)
		Gdip_FillRectangle(G, pBrushBack, 0, 0, PosW, Posh)
	}

	if(border==1){
		pPen:=Gdip_CreatePen(0xff111111, 1) 
		Gdip_DrawRectangle(G, pPen,0, 0, PosW-1, Posh-1)
		;Gdip_DrawRoundedRectangle(G, pPen,0, 0, PosW-1, Posh-1,4)
	}
	
	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	SetImage(hwnd, hBitmap)
	
	Gdip_DeleteBrush(pBrushFront), Gdip_DeleteBrush(pBrushBack)
	Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
	Return, 0
}



;=========================================


set_bgrd_black:
	IniWrite, %bgrd_grad_black%	, %settings_ini%, Window, GUI_background
	IniWrite, %bgrd_ramki_black%	, %settings_ini%, Window, GUI_ramka
return

set_bgrd_steel:
	IniWrite, %bgrd_grad_steel%	, %settings_ini%, Window, GUI_background
	IniWrite, %bgrd_ramki_steel%	, %settings_ini%, Window, GUI_ramka
return

set_bgrd_blue:
	IniWrite, %bgrd_grad_blue%	, %settings_ini%, Window, GUI_background
	IniWrite, %bgrd_ramki_blue%	, %settings_ini%, Window, GUI_ramka
return

set_bgrd_green:
	IniWrite, %bgrd_grad_green%	, %settings_ini%, Window, GUI_background
	IniWrite, %bgrd_ramki_green%	, %settings_ini%, Window, GUI_ramka
return





;=========================================

save_position:
	WinGetPos, x1,y1,,, ahk_id %GuiHwnd%
	IniWrite, %x1%	, %settings_ini%, window position, x
	IniWrite, %y1%	, %settings_ini%, window position, y
return


Open_ini:
Run, %settings_ini%
return

Open_log:
;Run, %log_file%
return

Forecast:
Gosub, Show_in_popup
return

Go_to_web: 
Run, %weather_url%
return

Go_to_web_for:
weather_forecast_url:= StrReplace(weather_url, "/current-weather/", "/daily-weather-forecast/")
Run, %weather_forecast_url%
return

Open_log2:
	if(A_GuiEvent == "DoubleClick")
	Run, %log_file%
return


Open_ini2:
	if(A_GuiEvent == "DoubleClick")
	Run, %settings_ini%
return

;=========================================

onTop:
		WonTop:=!WonTop             
		if WonTop {
			WinSet, AlwaysOnTop, on, Drozd_weather
			GuiControl, Show, onTop_on
			GuiControl, Hide, onTop_off
		}else{
			WinSet, AlwaysOnTop, off, Drozd_weather
			GuiControl, Show, onTop_off
			GuiControl, Hide, onTop_on
		}	
return

GoToSavedPos: ; DoubleClick
	IniRead, pos_x_saved, %settings_ini%, window position, x	
	IniRead, pos_y_saved, %settings_ini%, window position, y	
	if(pos_x_saved<A_ScreenWidth-120 && pos_y_saved<A_ScreenHeight-140)
		WinMove,  Drozd_weather, ,pos_x_saved,pos_y_saved
return


DoubleClick:

return

DisableWindowsFeature(){ ; prevent copy to  clipboard when double clicked ;autohotkey.com/boards/viewtopic.php?t=3569
   Static Dummy1 := OnMessage(0x00A3, "DisableWindowsFeature") ; WM_NCLBUTTONDBLCLK
   Static Dummy2 := OnMessage(0x0203, "DisableWindowsFeature") ; WM_LBUTTONDBLCLK
   If (A_GuiControl) {
      GuiControlGet, HCTRL, Hwnd, %A_GuiControl%
      WinGetClass, Class, ahk_id %HCTRL%
      If (Class = "Static")
				if (A_GuiControl= "Con"){					
					Gosub, Open_ini
				}else if (A_GuiControl= "last_check"){					
					;Gosub, Open_log
					Gosub, Forecast
				}else if (A_GuiControl= "title"){					
					Gosub, GoToSavedPos
				}			 
         Return 0
   }
}



;============================================



ToolTip_(tekst,t:=2,screen:=0){
	if(screen){
		CoordMode, ToolTip,Screen		
		if(screen==1){
			ToolTip, %tekst% ,600, 350
		}else{
			ToolTip, %tekst% ;,600, 350
		}	
	}else{
		CoordMode , ToolTip, Relative

		GuiControlGet, Pos, Pos, edit_1
		tipX:= PosX+ 4, tipY:=PosY +2
		ToolTip, %tekst% ,%tipX%, %tipY%
	}
	t:=t*1000
	Settimer, ToolTip_close , -%t%
}

ToolTip_close:
	Settimer, ToolTip_close , Off
	tipOn:=0
	ToolTip
return


;=========================================

clear_memory:
	EmptyMem(PID)
return


EmptyMem(PID:=0){ ;by heresy https://autohotkey.com/board/topic/30042-run-ahk-scripts-with-less-half-or-even-less-memory-usage/
    PID:=(PID) ? PID : DllCall("GetCurrentProcessId") 
    h:=DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", pid)
    DllCall("SetProcessWorkingSetSize", "UInt", h, "Int", -1, "Int", -1)
    DllCall("CloseHandle", "Int", h)
}

;======================================


;~^g:: Gosub, test 



test:
return


GuiContextMenu:
Menu, ContextMenu, Show, %A_GuiX%, %A_GuiY%
Return


~$F4::
	Gui 1: Show
return

WindowSpy:
Run, "C:\Program Files\AutoHotkey\AU3_Spy.exe" ;"C:\Program Files\AutoHotkey\WindowSpy.ahk"
WinWait, ahk_exe AU3_Spy.exe , , 3
WinMove, Active Window Info, , 1100
return

Reload:
Reload
return

Edit_Notepad:
Run, "C:\Program Files\Misc\Notepad2\Notepad2.exe" "%A_ScriptFullPath%"
return

Edit_Scite:
Run, "C:\Program Files\AutoHotkey\SciTE\SciTE.exe"  "%A_ScriptFullPath%"
return


On_Exit:
Close:
;Esc:: 
GuiClose:
Exit:
	Gdip_Shutdown(pToken)
	DllCall( "AnimateWindow", "Int", GuiHwnd, "Int", 300, "Int", 0x00050008 )
	FileDelete,  %img_folder%\*.png
ExitApp

;#Include C:\Program Files\Misc\AutoHotkey Scripts\functions_Gdip.ahk

Gdip_Startup()
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"	
	if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("LoadLibrary", "str", "gdiplus")
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
	return pToken
}

Gdip_Shutdown(pToken)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"	
	DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
	if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("FreeLibrary", Ptr, hModule)
	return 0
}



SetImage(hwnd, hBitmap)
{
	SendMessage, 0x172, 0x0, hBitmap,, ahk_id %hwnd%
	E := ErrorLevel
	DeleteObject(E)
	return E
}

Gdip_BitmapFromHWND(hwnd)
{
	WinGetPos,,, Width, Height, ahk_id %hwnd%
	hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
	PrintWindow(hwnd, hdc)
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
	return pBitmap
}

Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)
{
	DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "uint", pBitmap, "uint*", hbm, "int", Background)
	return hbm
}

CreateCompatibleDC(hdc=0)
{
   return DllCall("CreateCompatibleDC", "uint", hdc)
}

SelectObject(hdc, hgdiobj)
{
   return DllCall("SelectObject", "uint", hdc, "uint", hgdiobj)
}

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	
	NumPut(w, bi, 4, "uint")
	, NumPut(h, bi, 8, "uint")
	, NumPut(40, bi, 0, "uint")
	, NumPut(1, bi, 12, "ushort")
	, NumPut(0, bi, 16, "uInt")
	, NumPut(bpp, bi, 14, "ushort")
	
	hbm := DllCall("CreateDIBSection"
					, Ptr, hdc2
					, Ptr, &bi
					, "uint", 0
					, A_PtrSize ? "UPtr*" : "uint*", ppvBits
					, Ptr, 0
					, "uint", 0, Ptr)

	if !hdc
		ReleaseDC(hdc2)
	return hbm
}

Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
{
   return DllCall("gdiplus\GdipSetSmoothingMode", "uint", pGraphics, "int", SmoothingMode)
}





Gdip_CreatePen(ARGB, w)
{
   DllCall("gdiplus\GdipCreatePen1", "int", ARGB, "float", w, "int", 2, "uint*", pPen)
   return pPen
}

Gdip_CloneBrush(pBrush)
{
	DllCall("gdiplus\GdipCloneBrush", "uint", pBrush, "uint*", pBrushClone)
	return pBrushClone
}



Gdip_BrushCreateSolid(ARGB=0xff000000)
{
	DllCall("gdiplus\GdipCreateSolidFill", "int", ARGB, "uint*", pBrush)
	return pBrush
}


Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode=1, WrapMode=1)
{
	CreateRectF(RectF, x, y, w, h)
	DllCall("gdiplus\GdipCreateLineBrushFromRect", "uint", &RectF, "int", ARGB1, "int", ARGB2, "int", LinearGradientMode, "int", WrapMode, "uint*", LGpBrush)
	return LGpBrush
}




Gdip_DeletePath(Path)
{
	return DllCall("gdiplus\GdipDeletePath", "uint", Path)
}


PrintWindow(hwnd, hdc, Flags=0)
{
	return DllCall("PrintWindow", "uint", hwnd, "uint", hdc, "uint", Flags)
}


Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
	return pBitmap
}

Gdip_GetDC(pGraphics)
{
	DllCall("gdiplus\GdipGetDC", "uint", pGraphics, "uint*", hdc)
	return hdc
}

GetDC(hwnd=0)
{
	return DllCall("GetDC", "uint", hwnd)
}

DeleteObject(hObject)
{
   return DllCall("DeleteObject", "uint", hObject)
}

DeleteDC(hdc)
{
   return DllCall("DeleteDC", "uint", hdc)
}

ReleaseDC(hdc, hwnd=0)
{
   return DllCall("ReleaseDC", "uint", hwnd, "uint", hdc)
}



CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}


Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
{
   return DllCall("gdiplus\GdipDrawRectangle", "uint", pGraphics, "uint", pPen, "float", x, "float", y, "float", w, "float", h)
}



Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
{
   return DllCall("gdiplus\GdipFillRectangle", "uint", pGraphics, "int", pBrush
   , "float", x, "float", y, "float", w, "float", h)
}

Gdip_GraphicsFromImage(pBitmap)
{
    DllCall("gdiplus\GdipGetImageGraphicsContext", "uint", pBitmap, "uint*", pGraphics)
    return pGraphics
}

Gdip_CreateBitmap(Width, Height, Format=0x26200A)
{
    DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", 0, "int", Format, "uint", 0, "uint*", pBitmap)
    Return pBitmap
}



Gdip_DeletePen(pPen)
{
   return DllCall("gdiplus\GdipDeletePen", "uint", pPen)
}


Gdip_DeleteBrush(pBrush)
{
   return DllCall("gdiplus\GdipDeleteBrush", "uint", pBrush)
}


Gdip_DisposeImage(pBitmap)
{
   return DllCall("gdiplus\GdipDisposeImage", "uint", pBitmap)
}

Gdip_DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", "uint", pGraphics)
}


Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	SplitPath, sOutput,,, Extension
	if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
		return -1
	Extension := "." Extension

	DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
	VarSetCapacity(ci, nSize)
	DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
	if !(nCount && nSize)
		return -2
	
	If (A_IsUnicode){
		StrGet_Name := "StrGet"
		Loop, %nCount%
		{
			sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+idx
			break
		}
	} else {
		Loop, %nCount%
		{
			Location := NumGet(ci, 76*(A_Index-1)+44)
			nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
			VarSetCapacity(sString, nSize)
			DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+76*(A_Index-1)
			break
		}
	}
	
	if !pCodec
		return -3

	if (Quality != 75)
	{
		Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
		if Extension in .JPG,.JPEG,.JPE,.JFIF
		{
			DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
			VarSetCapacity(EncoderParameters, nSize, 0)
			DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
			Loop, % NumGet(EncoderParameters, "UInt")      ;%
			{
				elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
				if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
				{
					p := elem+&EncoderParameters-pad-4
					NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
					break
				}
			}      
		}
	}

	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
		VarSetCapacity(wOutput, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
		VarSetCapacity(wOutput, -1)
		if !VarSetCapacity(wOutput)
			return -4
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", p ? p : 0)
	}
	else
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", p ? p : 0)
	return E ? -5 : 0
}


Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0)
{
	DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
} 



Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r)
{
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
	Gdip_ResetClip(pGraphics)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_DrawEllipse(pGraphics, pPen, x, y, 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y, 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x, y+h-(2*r), 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_ResetClip(pGraphics)
	return E
}

Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)
{
	Region := Gdip_GetClipRegion(pGraphics)
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_FillEllipse(pGraphics, pBrush, x, y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_DeleteRegion(Region)
	return E
}

Gdip_FontCreate(hFamily, Size, Style=0)
{
   DllCall("gdiplus\GdipCreateFont", A_PtrSize ? "UPtr" : "UInt", hFamily, "float", Size, "int", Style, "int", 0, A_PtrSize ? "UPtr*" : "UInt*", hFont)
   return hFont
}

Gdip_FontFamilyCreate(Font)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, "uint", 0, "int", 0)
		VarSetCapacity(wFont, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, Ptr, &wFont, "int", nSize)
	}
	
	DllCall("gdiplus\GdipCreateFontFamilyFromName"
					, Ptr, A_IsUnicode ? &Font : &wFont
					, "uint", 0
					, A_PtrSize ? "UPtr*" : "UInt*", hFamily)
	
	return hFamily
}

Gdip_SetStringFormatAlign(hFormat, Align)
{
   return DllCall("gdiplus\GdipSetStringFormatAlign", A_PtrSize ? "UPtr" : "UInt", hFormat, "int", Align)
}

Gdip_StringFormatCreate(Format=0, Lang=0)
{
   DllCall("gdiplus\GdipCreateStringFormat", "int", Format, "int", Lang, A_PtrSize ? "UPtr*" : "UInt*", hFormat)
   return hFormat
}

Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
{
	return DllCall("gdiplus\GdipSetTextRenderingHint", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", RenderingHint)
}


Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	VarSetCapacity(RC, 16)
	if !A_IsUnicode
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, "uint", 0, "int", 0)
		VarSetCapacity(wString, nSize*2)   
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
	}
	
	DllCall("gdiplus\GdipMeasureString"
					, Ptr, pGraphics
					, Ptr, A_IsUnicode ? &sString : &wString
					, "int", -1
					, Ptr, hFont
					, Ptr, &RectF
					, Ptr, hFormat
					, Ptr, &RC
					, "uint*", Chars
					, "uint*", Lines)
	
	return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}

Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, 0, "int", 0)
		VarSetCapacity(wString, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
	}
	
	return DllCall("gdiplus\GdipDrawString"
					, Ptr, pGraphics
					, Ptr, A_IsUnicode ? &sString : &wString
					, "int", -1
					, Ptr, hFont
					, Ptr, &RectF
					, Ptr, hFormat
					, Ptr, pBrush)
}

Gdip_DeleteFont(hFont)
{
   return DllCall("gdiplus\GdipDeleteFont", A_PtrSize ? "UPtr" : "UInt", hFont)
}


Gdip_DeleteStringFormat(hFormat)
{
   return DllCall("gdiplus\GdipDeleteStringFormat", A_PtrSize ? "UPtr" : "UInt", hFormat)
}


Gdip_DeleteFontFamily(hFamily)
{
   return DllCall("gdiplus\GdipDeleteFontFamily", A_PtrSize ? "UPtr" : "UInt", hFamily)
}

Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0)
{
   return DllCall("gdiplus\GdipSetClipRect",  A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
}

Gdip_ResetClip(pGraphics)
{
   return DllCall("gdiplus\GdipResetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}

Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipDrawEllipse", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h)
}

Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipFillEllipse", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
}

Gdip_GetClipRegion(pGraphics)
{
	Region := Gdip_CreateRegion()
	DllCall("gdiplus\GdipGetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics, "UInt*", Region)
	return Region
}

Gdip_CreateRegion()
{
	DllCall("gdiplus\GdipCreateRegion", "UInt*", Region)
	return Region
}


Gdip_DeleteRegion(Region)
{
	return DllCall("gdiplus\GdipDeleteRegion", A_PtrSize ? "UPtr" : "UInt", Region)
}

Gdip_SetClipRegion(pGraphics, Region, CombineMode=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipSetClipRegion", Ptr, pGraphics, Ptr, Region, "int", CombineMode)
}


;================================
 
ToolTipFont(Options := "", Name := "", hwnd := ""){ ;lexikos https://autohotkey.com/boards/viewtopic.php?t=4777
    static hfont := 0
    if (hwnd = "")
        hfont := Options="Default" ? 0 : _TTG("Font", Options, Name), _TTHook()
    else
        DllCall("SendMessage", "ptr", hwnd, "uint", 0x30, "ptr", hfont, "ptr", 0)
}
 
ToolTipColor(Background := "", Text := "", hwnd := ""){
    static bc := "", tc := ""
    if (hwnd = "") {
        if (Background != "")
            bc := Background="Default" ? "" : _TTG("Color", Background)
        if (Text != "")
            tc := Text="Default" ? "" : _TTG("Color", Text)
        _TTHook()
    }
    else {
        VarSetCapacity(empty, 2, 0)
        DllCall("UxTheme.dll\SetWindowTheme", "ptr", hwnd, "ptr", 0
            , "ptr", (bc != "" && tc != "") ? &empty : 0)
        if (bc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1043, "ptr", bc, "ptr", 0)
        if (tc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1044, "ptr", tc, "ptr", 0)
    }
}
 
_TTHook(){
    static hook := 0
    if !hook
        hook := DllCall("SetWindowsHookExW", "int", 4
            , "ptr", RegisterCallback("_TTWndProc"), "ptr", 0
            , "uint", DllCall("GetCurrentThreadId"), "ptr")
}
 
_TTWndProc(nCode, _wp, _lp) {
    Critical 999
   ;lParam  := NumGet(_lp+0*A_PtrSize)
   ;wParam  := NumGet(_lp+1*A_PtrSize)
    uMsg    := NumGet(_lp+2*A_PtrSize, "uint")
    hwnd    := NumGet(_lp+3*A_PtrSize)
    if (nCode >= 0 && (uMsg = 1081 || uMsg = 1036)) {
        _hack_ = ahk_id %hwnd%
        WinGetClass wclass, %_hack_%
        if (wclass = "tooltips_class32") {
            ToolTipColor(,, hwnd)
            ToolTipFont(,, hwnd)
        }
    }
    return DllCall("CallNextHookEx", "ptr", 0, "int", nCode, "ptr", _wp, "ptr", _lp, "ptr")
}
 
_TTG(Cmd, Arg1, Arg2 := "") {
    static htext := 0, hgui := 0
    if !htext {
        Gui _TTG: Add, Text, +hwndhtext
        Gui _TTG: +hwndhgui +0x40000000
    }
    Gui _TTG: %Cmd%, %Arg1%, %Arg2%
    if (Cmd = "Font") {
        GuiControl _TTG: Font, %htext%
        SendMessage 0x31, 0, 0,, ahk_id %htext%
        return ErrorLevel
    }
    if (Cmd = "Color") {
        hdc := DllCall("GetDC", "ptr", htext, "ptr")
        SendMessage 0x138, hdc, htext,, ahk_id %hgui%
        clr := DllCall("GetBkColor", "ptr", hdc, "uint")
        DllCall("ReleaseDC", "ptr", htext, "ptr", hdc)
        return clr
    }
}

;==================================
/*
 * Lib: JSON.ahk
 * License:
 *     WTFPL [http://wtfpl.net/]
 * Links:
 *     GitHub:     - https://github.com/cocobelgica/AutoHotkey-JSON
 *     Forum Topic - http://goo.gl/r0zI8t
 *     Email:      - cocobelgica <at> gmail <dot> com
 */

class JSON
{
	/**
	 * Method: Load
	 *     Parses a JSON string into an AHK value
	 * Syntax:
	 *     value := JSON.Load( text [, reviver ] )
	 * Parameter(s):
	 *     value      [retval] - parsed value
	 *     text    [in, ByRef] - JSON formatted string
	 *     reviver   [in, opt] - function object, similar to JavaScript's
	 *                           JSON.parse() 'reviver' parameter
	 */
	class Load extends JSON.Functor
	{
		Call(self, ByRef text, reviver:="")
		{
			this.rev := IsObject(reviver) ? reviver : false
		; Object keys(and array indices) are temporarily stored in arrays so that
		; we can enumerate them in the order they appear in the document/text instead
		; of alphabetically. Skip if no reviver function is specified.
			this.keys := this.rev ? {} : false

			static quot := Chr(34), bashq := "\" . quot
			     , json_value := quot . "{[01234567890-tfn"
			     , json_value_or_array_closing := quot . "{[]01234567890-tfn"
			     , object_key_or_object_closing := quot . "}"

			key := ""
			is_key := false
			root := {}
			stack := [root]
			next := json_value
			pos := 0

			while ((ch := SubStr(text, ++pos, 1)) != "") {
				if InStr(" `t`r`n", ch)
					continue
				if !InStr(next, ch, 1)
					this.ParseError(next, text, pos)

				holder := stack[1]
				is_array := holder.IsArray

				if InStr(",:", ch) {
					next := (is_key := !is_array && ch == ",") ? quot : json_value

				} else if InStr("}]", ch) {
					ObjRemoveAt(stack, 1)
					next := stack[1]==root ? "" : stack[1].IsArray ? ",]" : ",}"

				} else {
					if InStr("{[", ch) {
					; Check if Array() is overridden and if its return value has
					; the 'IsArray' property. If so, Array() will be called normally,
					; otherwise, use a custom base object for arrays
						static json_array := Func("Array").IsBuiltIn || ![].IsArray ? {IsArray: true} : 0
					
					; sacrifice readability for minor(actually negligible) performance gain
						(ch == "{")
							? ( is_key := true
							  , value := {}
							  , next := object_key_or_object_closing )
						; ch == "["
							: ( value := json_array ? new json_array : []
							  , next := json_value_or_array_closing )
						
						ObjInsertAt(stack, 1, value)

						if (this.keys)
							this.keys[value] := []
					
					} else {
						if (ch == quot) {
							i := pos
							while (i := InStr(text, quot,, i+1)) {
								value := StrReplace(SubStr(text, pos+1, i-pos-1), "\\", "\u005c")

								static tail := A_AhkVersion<"2" ? 0 : -1
								if (SubStr(value, tail) != "\")
									break
							}

							if (!i)
								this.ParseError("'", text, pos)

							  value := StrReplace(value,  "\/",  "/")
							, value := StrReplace(value, bashq, quot)
							, value := StrReplace(value,  "\b", "`b")
							, value := StrReplace(value,  "\f", "`f")
							, value := StrReplace(value,  "\n", "`n")
							, value := StrReplace(value,  "\r", "`r")
							, value := StrReplace(value,  "\t", "`t")

							pos := i ; update pos
							
							i := 0
							while (i := InStr(value, "\",, i+1)) {
								if !(SubStr(value, i+1, 1) == "u")
									this.ParseError("\", text, pos - StrLen(SubStr(value, i+1)))

								uffff := Abs("0x" . SubStr(value, i+2, 4))
								if (A_IsUnicode || uffff < 0x100)
									value := SubStr(value, 1, i-1) . Chr(uffff) . SubStr(value, i+6)
							}

							if (is_key) {
								key := value, next := ":"
								continue
							}
						
						} else {
							value := SubStr(text, pos, i := RegExMatch(text, "[\]\},\s]|$",, pos)-pos)

							static number := "number", integer :="integer"
							if value is %number%
							{
								if value is %integer%
									value += 0
							}
							else if (value == "true" || value == "false")
								value := %value% + 0
							else if (value == "null")
								value := ""
							else
							; we can do more here to pinpoint the actual culprit
							; but that's just too much extra work.
								this.ParseError(next, text, pos, i)

							pos += i-1
						}

						next := holder==root ? "" : is_array ? ",]" : ",}"
					} ; If InStr("{[", ch) { ... } else

					is_array? key := ObjPush(holder, value) : holder[key] := value

					if (this.keys && this.keys.HasKey(holder))
						this.keys[holder].Push(key)
				}
			
			} ; while ( ... )

			return this.rev ? this.Walk(root, "") : root[""]
		}

		ParseError(expect, ByRef text, pos, len:=1)
		{
			static quot := Chr(34), qurly := quot . "}"
			
			line := StrSplit(SubStr(text, 1, pos), "`n", "`r").Length()
			col := pos - InStr(text, "`n",, -(StrLen(text)-pos+1))
			msg := Format("{1}`n`nLine:`t{2}`nCol:`t{3}`nChar:`t{4}"
			,     (expect == "")     ? "Extra data"
			    : (expect == "'")    ? "Unterminated string starting at"
			    : (expect == "\")    ? "Invalid \escape"
			    : (expect == ":")    ? "Expecting ':' delimiter"
			    : (expect == quot)   ? "Expecting object key enclosed in double quotes"
			    : (expect == qurly)  ? "Expecting object key enclosed in double quotes or object closing '}'"
			    : (expect == ",}")   ? "Expecting ',' delimiter or object closing '}'"
			    : (expect == ",]")   ? "Expecting ',' delimiter or array closing ']'"
			    : InStr(expect, "]") ? "Expecting JSON value or array closing ']'"
			    :                      "Expecting JSON value(string, number, true, false, null, object or array)"
			, line, col, pos)

			static offset := A_AhkVersion<"2" ? -3 : -4
			throw Exception(msg, offset, SubStr(text, pos, len))
		}

		Walk(holder, key)
		{
			value := holder[key]
			if IsObject(value) {
				for i, k in this.keys[value] {
					; check if ObjHasKey(value, k) ??
					v := this.Walk(value, k)
					if (v != JSON.Undefined)
						value[k] := v
					else
						ObjDelete(value, k)
				}
			}
			
			return this.rev.Call(holder, key, value)
		}
	}

	/**
	 * Method: Dump
	 *     Converts an AHK value into a JSON string
	 * Syntax:
	 *     str := JSON.Dump( value [, replacer, space ] )
	 * Parameter(s):
	 *     str        [retval] - JSON representation of an AHK value
	 *     value          [in] - any value(object, string, number)
	 *     replacer  [in, opt] - function object, similar to JavaScript's
	 *                           JSON.stringify() 'replacer' parameter
	 *     space     [in, opt] - similar to JavaScript's JSON.stringify()
	 *                           'space' parameter
	 */
	class Dump extends JSON.Functor
	{
		Call(self, value, replacer:="", space:="")
		{
			this.rep := IsObject(replacer) ? replacer : ""

			this.gap := ""
			if (space) {
				static integer := "integer"
				if space is %integer%
					Loop, % ((n := Abs(space))>10 ? 10 : n)
						this.gap .= " "
				else
					this.gap := SubStr(space, 1, 10)

				this.indent := "`n"
			}

			return this.Str({"": value}, "")
		}

		Str(holder, key)
		{
			value := holder[key]

			if (this.rep)
				value := this.rep.Call(holder, key, ObjHasKey(holder, key) ? value : JSON.Undefined)

			if IsObject(value) {
				static type := A_AhkVersion<"2" ? "" : Func("Type")
				if (type ? type.Call(value) == "Object" : ObjGetCapacity(value) != "") {
					if (this.gap) {
						stepback := this.indent
						this.indent .= this.gap
					}

					is_array := value.IsArray
					if (!is_array) {
						for i in value
							is_array := i == A_Index
						until !is_array
					}

					str := ""
					if (is_array) {
						Loop, % value.Length() {
							if (this.gap)
								str .= this.indent
							
							v := this.Str(value, A_Index)
							str .= (v != "") ? v . "," : "null,"
						}
					} else {
						colon := this.gap ? ": " : ":"
						for k in value {
							v := this.Str(value, k)
							if (v != "") {
								if (this.gap)
									str .= this.indent

								str .= this.Quote(k) . colon . v . ","
							}
						}
					}

					if (str != "") {
						str := RTrim(str, ",")
						if (this.gap)
							str .= stepback
					}

					if (this.gap)
						this.indent := stepback

					return is_array ? "[" . str . "]" : "{" . str . "}"
				}
			
			} else ; is_number ? value : "value"
				return ObjGetCapacity([value], 1)=="" ? value : this.Quote(value)
		}

		Quote(string)
		{
			static quot := Chr(34), bashq := "\" . quot

			if (string != "") {
				  string := StrReplace(string,  "\",  "\\")
				; , string := StrReplace(string,  "/",  "\/") ; optional in ECMAScript
				, string := StrReplace(string, quot, bashq)
				, string := StrReplace(string, "`b",  "\b")
				, string := StrReplace(string, "`f",  "\f")
				, string := StrReplace(string, "`n",  "\n")
				, string := StrReplace(string, "`r",  "\r")
				, string := StrReplace(string, "`t",  "\t")

				static rx_escapable := A_AhkVersion<"2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]"
				while RegExMatch(string, rx_escapable, m)
					string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value)))
			}

			return quot . string . quot
		}
	}

	Undefined[]
	{
		get {
			static empty := {}, vt_empty := ComObject(0, &empty, 1)
			return vt_empty
		}
	}

	class Functor
	{
		__Call(method, ByRef arg, args*)
		{
			if IsObject(method)
				return (new this).Call(method, arg, args*)
			else if (method == "")
				return (new this).Call(arg, args*)
		}
	}
}



screenshot Drozd weather  MSN Oct19 2019.png
screenshot Drozd weather MSN Oct19 2019.png (3.71 KiB) Viewed 4154 times



screenshot Drozd weather  MSN Oct19 2019.png
screenshot Drozd weather MSN Oct19 2019.png (3.71 KiB) Viewed 4154 times
Attachments
screenshot Drozd weather forecast MSN.png
screenshot Drozd weather forecast MSN.png (41.78 KiB) Viewed 4154 times
drozdman
Posts: 78
Joined: 05 Dec 2015, 01:07

Re: Weather gadget (Gdip). Accuweather

01 Nov 2019, 15:12

Should be updated. Fix for negative temperatures.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: kashmirLZ and 71 guests