Massive v1 Code Trouble

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
imkira3
Posts: 84
Joined: 10 Jan 2023, 13:57
Contact:

Massive v1 Code Trouble

27 Feb 2023, 00:45

Ever get the sense that a code is just too big to edit? I feel like I could edit a v2 code of any size, but this v1 code is giving me a headache, v2 is way easier to read. I have here a MASSIVE code I have been editing built on one of the original v1 releases. Not even 1.1, it's so old I had to use the original AHK2EXE when I compiled it. It does have some ;tips, and those were helpful. I was able to successfully change the built-in hotkeys, and made Left Win+NumpadEnter toggle a hidden Desktop. Problem is the "Send Current Window to Desktop 1" and "Send Current Window to Desktop 2" buttons. I changed them to use Left Win+NumPad1 and Left Win+NumPad2 since that will work well with my imkira3Keys project, which runs entirely on the numpad. But, I couldn't set them to Left Win+NumPadEnd and Left Win+NumPadDown so it might not work depending on the state of the numpad. I have a few ideas, including ignoring the numpad state somehow, and adding new buttons to the script directly, but so far I'm not having any luck. Here is the edited version I'm working on, and please don't rush, this code is MASSIVE:

mDesktop.ahk

Code: Select all

; Author: Jason Stallings
; Contributors: IamTheFij, imkira3
; Source available http://github.com/octalmage/mDesktop

#NoTrayIcon
#NoEnv
#SingleInstance force

SetTitleMatchMode, 2

SetTitleMatchMode, slow
SetWorkingDir, %A_ScriptDir%\


SetBatchLines , -1
SetWinDelay , -1
WinClose, ahk_class SysShadow

#include mDesktopConfig.ahk

onexit , cleanup

;Set this varible here to 0 to turn the gestures off.
gest=0


;These two have to do with the graphic desktop picker.

;Setting this varible to 0 will turn the switcher off.
;Having this on adds about 100% more mem usage.  (around 600k to 6000k)
switcher=0
;This is the amount of pixels between each window in the switcher.
spacing=25

;Settings file location. 
settings_location=C:\ProgramData\imkira3Keys\
settings_name=Settings.ini
settings=%settings_location%%settings_name%


;this is for the new api I'm working on.
api=1

/*

This is for having all windows show up in the taskbar/alt+tab.
This almost works, but is still having some major issues, I believe with the shellhook, and possible my "finddesktop_byid" function.
I need to find a quicker way to detect which desktop a window is on, maybe a new array? So instead of searching I can just do:

desktop:=win_desktop%win_id%

This might work.

*/
taskbar=0


; actual desktop switcher
;DO NOT ENABLE. Not working yet.
desktopswitcher=0



ABM_SETSTATE    := 10

ABS_NORMAL      := 0x0
ABS_AUTOHIDE    := 0x1
ABS_ALWAYSONTOP := 0x2

VarSetCapacity( APPBARDATA , 36, 0 ) 
Off :=  NumPut(  36, APPBARDATA    ) 
Off :=  NumPut( WinExist("ahk_class Shell_TrayWnd"), Off+0 )

 

;0x00000004 ABM_GETSTATE 




rc4key=[insertrc4key]

If switcher
{
	If !pToken := Gdip_Startup()
	{
		MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
		ExitApp
	}
}


If api
{
	hScript := WinExist() + 0
	IPC_SetHandler("OnData")
	gui 99: default
	gui, -caption +toolwindow
	gui, show, x0 y0 hide w0 h0,mDesktop_api
	gui 1: default
}

numDesktops := 4

gesttime:=800


;TODO: Add code to import settings from swipe.ini. 

;Create directory for settings if it doesn't exist. 
if !fileexist(settings_location)
{
	FileCreateDir, %settings_location% 
}

If !fileexist(settings)
{
	IniWrite , !^m, %settings%, Settings, unhide
	IniWrite , ^#RIGHT, %settings%, Settings, switchnext
	IniWrite , ^#LEFT, %settings%, Settings, switchprev
	IniWrite , 4, %settings%, Settings, numdesks
	IniWrite , !, %settings%, Settings, switchMod
	IniWrite , ^!, %settings%, Settings, sendmod
	IniWrite , %a_space%, %settings%, Settings, windowsOnAll
	IniWrite , 1, %settings%, Settings, desktopcircle
}

IniRead , unhidehotkey, %settings%, Settings, unhide, !^s
IniRead , nexthotkey, %settings%, Settings, switchnext, ^#RIGHT
IniRead , prevhotkey, %settings%, Settings, switchprev, ^#LEFT
IniRead , numDesktops, %settings%, Settings, numdesks, 4
IniRead , switchModifier, %settings%, Settings, switchmod, !
IniRead , sendModifier, %settings%, Settings, sendmod, ^!
IniRead , windowsOnAll, %settings%, Settings, windowsOnAll
IniRead , desktopcircle, %settings%, Settings, desktopcircle


IniRead , theswitchmod, %settings%, Settings, theswitchmod,1
IniRead , thesendmod, %settings%, Settings, thesendmod,1
IniRead , thenextmod, %settings%, Settings, thenextmod,1
IniRead , thepremod, %settings%, Settings, thepremod,1
IniRead , rightaltkey, %settings%, Settings, rightaltkey,1


SysGet, VirtualScreenWidth, 78
SysGet, VirtualScreenHeight, 79
SysGet, MonitorCount, MonitorCount


IniRead , runatstartup, %settings%, Settings, runatstartup, 0
Loop %numDesktops%
{
	IniRead , desktop%A_Index%, %settings%, Settings, desktop%A_Index%, Desktop %A_Index%
}

Hotkey , %unhidehotkey% , unhide
Hotkey , %unhidehotkey% , off

VarSetCapacity(wallpaper, 260)
DllCall("SystemParametersInfo", "Uint", 115, "Uint", 260, "str", wallpaper, "Uint", 0)

icons=0
curDesktop := 1

;TODO: Allow custom hotkeys.
If switcher
{
	Hotkey, f10, switcher
}


gosub buildmenu

PostMessage , 0x111, 28931,,, ahk_class Progman


;Gui 89: -Caption +ToolWindow +LastFound +AlwaysOnTop
;Gui 89: Add, Picture, x0 y0, banner.png
;Gui 89: Add, Text, x15 y5 w70 +BackgroundTrans vString

gosub sethotkeys

;!0::exitapp


PID := DllCall("GetCurrentProcessId")
EmptyMem(pid)


settimer, cleanmem, 450


;settimer, wait, -1

if taskbar
	SetTimer, checkactive, 250


GetCurrentWindows(1)


return



ShellMessage( wParam,lParam ) {
critical
		If (wParam=5) ;  HSHELL_WINDOWCREATED := 1
		{
		wID := NumGet( lParam+0 )         ; firstmember  ( DWord ) of SHELLHOOKINFO structure is hWnd
			WinGet, mState, MinMax, ahk_id %wID%
	
			
			
		SetFormat, Integer, Hex
; +0 ensures that temp will hold a hex integer value
lParam += 0
wID+=0
		
			switch:= win_desktop%wID%
					SetFormat, Integer, D
					StringTrimLeft, switch, switch, 2
				
					if not switch
						return
			SwitchToDesktop(switch)
			winactivate, ahk_id %wID%
			
		

		}
		return
	}
	
	
	
dec2hex(n) {
   oIF := A_FormatInteger
   SetFormat,Integer, hex
   n := StrLen(n+0) ? n+0 : n
   SetFormat,Integer, % oIF
   return n
}


OnData(Hwnd, Data, Port, Size) {
		IfInString, Data, SwitchToDesktop
		{
			StringRight, apiDesktop, Data, 1
			If apiDesktop is number
				SwitchToDesktop(apiDesktop)
		}
	}




MailslotRead(SlotHandle) ;reads one message at a time
	{
		global ReadBuffer  ;could/should be passed as ByRef parameter

		BytesToRead := 500

		DLLCall("ReadFile"
		        ,UInt, slotHandle   ;the handle from CreateMailSlot
		        ,str , readBuffer   ;see AHK DLLCall Help for why str used here
		        ,UInt, BytesToRead
		        ,UIntP, BytesActuallyRead
		        ,UInt, 0)   ;pointer to Overlapped structure, not used, so null

		If errorlevel
			Msgbox Error in ReadFile operation`nErrorLevel: %errorlevel%
		Else
			return BytesActuallyRead
	}



buildmenu:

	Ifexist , mDesktop.ico
	{
		If numDesktops <=3
		{
			Menu, tray ,icon,mDesktop.ico
		}
		Else{
			Menu, tray ,icon,mDesktop.ico
		}

	}
	menu ,tray, DeleteAll
	menu ,tray, NoStandard
	menu ,tray, NoStandard
	menu ,tray,add,Hide Icon,hideicon
	menu ,tray,add,
	menu ,tray,add,About,about
	menu ,tray,add,Settings,settings
	menu ,tray,add,
	Loop %numDesktops%
	{
		index = %A_Index%
		tempDesktop := desktop%A_Index%
		If StrLen(tempDesktop) < 1
		{
			tempDesktop = Desktop %A_Index%
			desktop%A_Index% := tempDesktop
		}
		menu , tray , add , %tempDesktop% , switchMenu
		If A_Index = %curDesktop%
		{
			menu ,tray,Check, %tempDesktop%
		}
	}
	menu ,tray,add,
	menu ,tray,add,Exit,CleanUp


return

checkactive:
hwnd := WinExist("A")

WinGetTitle, title , ahk_id %hwnd%

if (hwnd=active)
	return

	Loop, Parse, windowsOnAll, |,%A_Space%
			{
				If instr(title,a_loopfield)
				{
					return
					
				}
			}
	
active:=hwnd

switch:= win_desktop%active%
				;msgbox  %switch%
				
					if not switch
						return
						checkactive:=hwnd
			SwitchToDesktop(switch)
				winactivate, ahk_id %checkactive%
				checkactive:=

return


;This was added in to allow the user to click off of the picker, making it goaway.
;Need to find a better way to do this.
/*
~lbutton::
	sleep 200
	If switchergui
	{
		return
	}
	If switcheropen
	{
		gui 2: destroy
		gui 3: destroy
		gui 4: destroy
		gui 5: destroy
	}

return
*/

cleanmem:

	EmptyMem(pid)
return


usercanhazaccess(desk)
	{
		global rc4key
		If islocked(desk)
		{
			InputBox, password, This desktop is locked, Please enter your password:, HIDE, , , , , , 5
			iniread, dpassword, %settings%, Settings, passhex
			If not Password{
				return 0
			}

			dpassword:= RC4hex2txt(dpassword,rc4key)

			If (password=dpassword)
			{
				return 1
			}
			Else
			{
				msgbox Incorrect password!
				return 0
			}
		}
		Else
		{
			return 1
		}
	}



islocked(desk)
	{
		IniRead, locked, %settings%, Settings, locked%desk%, 0

		return 	locked
	}


sethotkeys:
#MaxThreadsPerHotkey 6
	Loop 10
	{
		If A_Index = 10
			index = 0
		Else
			index = %A_Index%

		Hotkey , %switchModifier%%index% , switch
		


		If A_Index <= %numDesktops%
			Hotkey , %switchModifier%%index% , on
		Else
			Hotkey , %switchModifier%%index% , off
	}
	Hotkey , %nexthotkey% , snext
	Hotkey , %prevhotkey% , sprev
#MaxThreadsPerHotkey 1
	Loop %numDesktops%
	{
		If A_Index = 10
			index = 0
		Else
			index = %A_Index%

		Hotkey , ~%sendModifier%%index% , sendTo

		If A_Index <= %numDesktops%
			Hotkey , ~%sendModifier%%index% , on
		Else
			Hotkey , ~%sendModifier%%index% , off
	}
return

hideicon:
	menu ,tray,NoIcon
	Hotkey , %unhidehotkey% , on
	StringReplace , DisplayKey, unhidehotkey, ^ , Control%a_space% , All
	StringReplace , DisplayKey, DisplayKey, ! , Alt%a_space% , All
	StringReplace , DisplayKey, DisplayKey, + ,Shift%a_space% , All
	msgbox The icon will now be hidden, press %DisplayKey% to unhide.
return

unhide:
	menu ,tray,Icon
	Hotkey , %unhidehotkey% , off
return

switch:


if (rightaltkey)
{
If getkeystate("ralt")
	{
		return
	}

}
		length := StrLen(A_ThisHotkey) - 1
		theDesk := SubStr(A_ThisHotkey, %length%)
		If theDesk = 0
			theDesk = 10
		SwitchToDesktop(theDesk)
	
return

sendTo:
	If getkeystate("ralt")
	{
		
		return
	}
		length := StrLen(A_ThisHotkey) - 1
		theDesk := SubStr(A_ThisHotkey, %length%)
		If theDesk = 0
			theDesk = 10
		SendActiveToDesktop(theDesk, curDesktop)

return

switchMenu:
	theDesk := A_ThisMenuItemPos - 5
	SwitchToDesktop(theDesk)
return

snext:
	SwitchToNextDesktop()
return

sprev:
	SwitchToPrevDesktop()
return

settings:
	Hotkey , %nexthotkey% , on
	Hotkey , %prevhotkey% , on
	ctrlKey = ^
	altKey = !
	winKey = #
	shiftKey = +

	Gui 7: Add, Tab2,h400, General|Desktop Names|Windows
	Gui 7: Tab, 1

	; Number of Desktops
	gui 7: add,text,,Number of Desktops (Max 10):
	gui 7: add,edit,w25 number vnewnumdesktops, %numDesktops%
	;gui 7: add,updown, Range1-10 vnewnumdesktops, %numDesktops%

	; Hide Tray icon
	gui 7: add,text,,Select a hotkey to unhide mDesktop's tray icon.
	gui 7: add,hotkey,vnewunhidehotkey, %unhidehotkey%
	Gui 7: Tab, 1
	; Modifiers for switch desktop
	gui 7: add,text,,To switch directly to a desktop:

	gui, 7: Tab, 1
	gui, 7: add, DropDownList ,w150 Choose%theswitchmod% vtheswitchmod altsubmit, Alt+Desktop Number|Ctrl+Desktop Number|Shift+Desktop Number|
	gui, 7: add, CheckBox,vrightaltkey checked%rightaltkey%, Ignore right alt key?

	gui, 7: add,text, yp+25 xm+12 ,To send an active window to a desktop:
	
	
	gui, 7: add, DropDownList,Choose%thesendmod% vthesendmod w150 altsubmit , Alt+Ctrl+Desktop Number|Shift+Alt+Desktop Number|Ctrl+Shift+Desktop Number|


	; Switch Next Hotkeys
	nexthaswin=UnChecked
	If InStr(nexthotkey, winKey)
	{
		nexthaswin=Checked
		StringReplace , cleannexthotkey, nexthotkey, # , , All
	}
	Else
	{
		cleannexthotkey := nexthotkey
	}
	gui 7: add,text,xm+12 yp+25 ,To switch to the next desktop:
	Gui 7: Add, DropDownList,altsubmit vthenextmod Choose%thenextmod% w150, Ctrl+Right Arrow|Shift+Right Arrow|Alt+Right Arrow|

	; Switch Prev Hotkeys
	prevhaswin=UnChecked
	If InStr(prevhotkey, winKey)
	{
		prevhaswin=Checked
		StringReplace , cleanprevhotkey, prevhotkey, # , , All
	}
	Else
	{
		cleanprevhotkey := prevhotkey
	}
	gui 7: add,text,xm+12 yp+25 ,To switch to the previous desktop:
	Gui 7: Add, DropDownList, vthepremod w150 altsubmit Choose%thepremod%, Ctrl+Left Arrow|Shift+Left Arrow|Alt+Left Arrow|
	If runatstartup
	{
		gui 7: add,checkbox,vrunatstartup checked, Run at Startup?
	}
	Else
	{
		gui 7: add,checkbox,vrunatstartup, Run at Startup?
	}
	If desktopcircle
	{
		gui 7: add,checkbox,vdesktopcircle checked, Desktop Cycling
	}
	Else
	{
		gui 7: add,checkbox,vdesktopcircle, Desktop Cycling
	}


	Gui 7: Tab, 2
	; Desktop Names

	gui 7: add,text,ym+26 xm+12,Name your desktops.


	namex=25
	namey=52
	locky:=52+4
	lockx=128
	Loop %numDesktops%
	{
		tempDesktop := desktop%A_Index%
		gui 7: add,edit,w100 x%namex% y%namey% vnewdesktop%A_Index% , %tempDesktop%
		namey+=25
	}
/*
	Loop %numDesktops%
	{
		If % locked%A_Index%
		{
			gui 7: add,Checkbox,y%locky% checked x%lockx% vlocked%A_Index%, Locked
		}
		Else
		{
			gui 7: add,Checkbox,y%locky%  x%lockx% vlocked%A_Index%, Locked
		}
		locky+=25

	}
	namey:=namey+10
	;Password Section
	gui 7: add,text,x%namex% y%namey%,Desktop Passowrd:
	namey+=20
	gui 7: add,edit,x%namex% w100 password y%namey% center vdpassword,  mdesktopwins
*/



	Gui 7: Tab, 3
	;Windows on all desktops
	Gui 7: Add, Text,,Windows on all desktops
	Gui 7: Add, ListView, -multi vwindowlist, Title

	Gui 7: Add, Button,gadd_window, Add
	Gui 7: Add, Button,yp xp+35 gselect, Select
	Gui 7: Add, Button,yp xp+46 gwindow_delete, Delete



	Gui 7: Tab, 1


	Gui 7: Tab,
	ControlGetPos , xx, yy, , hh, SysTabControl321,Settings
	buttony:=yy+hh+400
	gui 7: add,button, y418  x10 gsavesettings,Save
	gui +lastfound
	gui 7: show,, Settings
	settingid:=WinExist()
	gui 7: default
	Loop, Parse, windowsOnAll, |,%A_Space%
	{
		LV_Add("", a_loopfield)
	}
	gui 1: default






return

7guiclose:
	Hotkey, %nexthotkey% , off
	Hotkey, %prevhotkey% , off
	gui 7: destroy
return


select:
	sleep 100
	gui 97: default
	gui, -caption +toolwindow +alwaysontop
	gui,color,red
	gui, Add,text,,Please click a window to add to the list.
	gui,show,x25 y25

	KeyWait, lbutton,d

	wingetactivetitle, activetitle
	If not activetitle
		return
	gui 7: default
	LV_Add("", activetitle)
	gui 1: default
	gui 97: destroy
	WinActivate , ahk_id %settingid%
	activetitle=
return

window_delete:
	row:=LV_GetNext()
	LV_Delete(row)

return

savesettings:

	gui 7: submit

	; Save window on all desktops section.
	windowsOnAll=
	count:=LV_GetCount()
	Loop %count%
	{
		LV_GetText(RetrievedTitle, A_Index)
		windowsOnAll=%RetrievedTitle%|%windowsOnAll%
	}

	StringTrimRight, windowsonall, windowsonall, 1


	IniWrite , %windowsonall%, %settings%, Settings, windowsOnAll




	gui 7: destroy


IniWrite , %theswitchmod%, %settings%, settings, theswitchmod
IniWrite , %thesendmod%, %settings%, settings, thesendmod
IniWrite , %thenextmod%, %settings%, settings, thenextmod
IniWrite , %thepremod%, %settings%, settings, thepremod
IniWrite , %rightaltkey%, %settings%, settings, rightaltkey


if (thenextmod=1)
{
	newnexthotkey=^Right
}
else if (thenextmod=2)
{
	newnexthotkey=+Right
}
else if (thenextmod=3)
{
	newnexthotkey=!Right
}
else if (thenextmod=4)
{
	newnexthotkey=#NumpadEnter
}


if (thepremod=1)
{
	newprevhotkey=^Left
}
else if (thepremod=2)
{
	newprevhotkey=+Left
}
else if (thepremod=3)
{
	newprevhotkey=!Left
}
else if (thepremod=4)
{
	newprevhotkey=#NumpadEnter
}



; Set Switch Desktop Modifiers
if (theswitchmod=1)
{
	newSwitchModifier=!
}
else if (theswitchmod=2)
{
	newSwitchModifier=^
}
else if (theswitchmod=3)
{
	newSwitchModifier=+
}
else if (theswitchmod=4)
{
	newSwitchModifier=#
}


If newSwitchModifier != %switchModifier%
{
	
	Loop 10
	{
		If A_Index = 10
			index = 0
		Else
			index = %A_Index%

	

			Hotkey , %switchModifier%%index% , off
	}
	

	switchModifier := newSwitchModifier
	IniWrite , %switchModifier%, %settings%, Settings, switchmod
}



; Set Send to Desktop Modifiers
if (thesendmod=1)
{
	newSendModifier=!^
}
else if (thesendmod=2)
{
	newSendModifier=+!
}
else if (thesendmod=3)
{
	newSendModifier=^+
}
else if (thesendmod=4)
{
	newSendModifier=#
}

	If newSendModifier != %SendModifier%
	{
		sendModifier := newSendModifier
		IniWrite , %sendModifier%, %settings%, Settings, sendmod
	}

	; Save unhide hotkey
	If newunhidehotkey!= %unhidehotkey%
	{
		Hotkey , %newunhidehotkey% , unhide
		Hotkey , %newunhidehotkey% , off
		unhidehotkey= %newunhidehotkey%
		IniWrite , %unhidehotkey%, %settings%, settings, unhide
	}

	; Rename desktops
	Loop %numDesktops%
	{
		newDesktop := newdesktop%A_Index%
		oldDesktop := desktop%A_Index%
		If newDesktop != %oldDesktop%
		{
			menu , tray, rename,  %oldDesktop%, %newDesktop%
			desktop%A_Index% := newDesktop
			IniWrite , %newDesktop%, %settings%, Settings, desktop%A_Index%
		}
	}

	; Set number of desktops
	If newnumdesktops > 10
		newnumdesktops := 10
	If newnumdesktops < 1
		newnumdesktops := 1
	If newnumdesktops != %numDesktops%
	{
		If newnumdesktops < %numDesktops%
		{
			If curDesktop > %newnumdesktops%
				SwitchToDesktop(newnumdesktops)

			index := (numDesktops - newnumdesktops)
			Loop , %index%
			{
				theDesk := numDesktops - A_Index + 1
				MoveAllWindows(theDesk, curDesktop)
			}
		}
		numDesktops = %newnumdesktops%
		IniWrite , %numDesktops%, %settings%, Settings , numdesks
		
	
		
		menu , tray , deleteall
		gosub buildmenu
	}


	
	If newnexthotkey!= %nexthotkey%
	{
		
		nexthotkey = %newnexthotkey%
		Hotkey , %nexthotkey% , snext
		IniWrite , %nexthotkey%, %settings%, settings, switchnext
	}

	If newprevhotkey!=%prevhotkey%
	{
		prevhotkey = %newprevhotkey%
		Hotkey , %prevhotkey% , sprev
		IniWrite , %prevhotkey%, %settings%, settings, switchprev
	}


	; Save run at startup
	If runatstartup=1
	{
		RegWrite, REG_SZ,HKCU,Software\Microsoft\Windows\CurrentVersion\Run,mDesktop, "%A_ScriptFullPath%"
	}
	Else
	{
		RegDelete, HKCU,Software\Microsoft\Windows\CurrentVersion\Run,mDesktop
	}
	iniwrite, %runatstartup%, %settings%, Settings, runatstartup
	iniwrite, %desktopcircle%, %settings%, Settings, desktopcircle



	
	Hotkey, %nexthotkey% , on
	Hotkey, %prevhotkey% , on


	gosub sethotkeys


return

add_window:
	InputBox, window , Add a window, Please type in part of the window title you would like to remain on all desktops.
	If not window
		return
	LV_Add("", window)


	window=
return

SwitchToNextDesktop()
	{
		global

		If (curDesktop < numDesktops)
		{
			SwitchToDesktop(curDesktop + 1)
		}
		Else
		{
			If desktopcircle
				SwitchToDesktop(1)
		}
		return
	}

SwitchToPrevDesktop()
	{
		global

		If (curDesktop > 1)
		{
			SwitchToDesktop(curDesktop - 1)
		}
		Else
		{
			If desktopcircle
				SwitchToDesktop(numDesktops)
		}
		return
	}

CheckDesktop(newDesktop)
	{
		global

		Loop %numDesktops%
		{
			tempDesktop := desktop%A_Index%
			If newDesktop = %A_Index%
				menu ,tray,Check, %tempDesktop%
			Else
				menu ,tray,Uncheck, %tempDesktop%
		}
		return
	}

SwitchToDesktop(newDesktop)
	{
		global
		activate_window :=
		If not usercanhazaccess(newDesktop)
		{
			return
		}

		Loop %numDesktops%
		{
			If A_Index = 10
				index = 0
			Else
				index = %A_Index%

			Hotkey , %switchModifier%%index% , off
		}

		If (curDesktop <> newDesktop)
		{
			;pBitmap%curDesktop% := Gdip_BitmapFromScreen(0)

			;sc_CaptureScreen(0, false, curDesktop . ".jpg", "20")

			CheckDesktop(newDesktop)
			GetCurrentWindows(curDesktop)
			
		
			WinGet, aid, ID, A
			if not (checkactive)
			{
				if not aid
					active_id%curDesktop%:=winexist("Program Manager")
				else
					active_id%curDesktop%:=aid
			}
			
			ShowHideWindows(curDesktop, false)
			ShowHideWindows(newDesktop, true)
			
			
			If desktopswitcher
			{
			showdesktop:=deskshow%newDesktop%
			showdesktopOLD:=deskshow%curDesktop%
			taskshow:=taskshow%newDesktop%
			recshow:=recshow%newDesktop%
			autohidetask:=autohidetask%newDesktop%
			if taskshow
				WinShow ahk_class Shell_TrayWnd
			else
				WinHide ahk_class Shell_TrayWnd
			
			autohidetask%curDesktop%:=DllCall("Shell32.dll\SHAppBarMessage", UInt,0x00000004 , UInt,&APPBARDATA ) 
			
			showdesktopname=showdesktop%curDesktop%
			
			
			ControlGet, showing, Visible , , SysListView321, ahk_class Progman
		showdesktop%curDesktop%:=showing
		showdesktopOLD:=deskshow%curDesktop%

			if recshow
					hiderecycle(0)
			else
				hiderecycle(1)
		
			
			if autohidetask=3
			{
				NumPut( ABS_AUTOHIDE|ABS_ALWAYSONTOP, Off+24 )
				DllCall("Shell32.dll\SHAppBarMessage", UInt,ABM_SETSTATE, UInt,&APPBARDATA )
			}
			else if autohidetask=2
			{
				NumPut( ABS_ALWAYSONTOP, Off+24 )
				DllCall("Shell32.dll\SHAppBarMessage", UInt,ABM_SETSTATE, UInt,&APPBARDATA ) 
			}
			
		
	
			if  not showdesktop
			{
				
				Control, Hide,, SysListView321, ahk_class Progman
			}
			else
			{
				Control, Show,, SysListView321, ahk_class Progman
			}
			
			
			
			
		
				
				If newdesktop=1
				{
					newpath := "`%USERPROFILE`%\Desktop"
				}
				Else
				{
					newpath := "`%USERPROFILE`%\Desktop"newdesktop
					tpath=C:\Documents and Settings\%A_Username%\Desktop%newdesktop%
		
					if not fileexist(tpath)
						filecreatedir, %tpath%
				}
				
				deskicon%curDesktop%:=DeskIcons()
				ChangeDesktop(newpath)
				newiconset:=deskicon%newdesktop%
			
				DeskIcons(newiconset)
			}
			
			
			

			activate_window := active_id%newDesktop%
			if not checkactive
			{
				if activate_window
					winactivate, ahk_id %activate_window%
				else
					winactivate, Program Manager
			}

			curDesktop := newDesktop

			;WinClose , ahk_class SysShadow
			; ShowBanner("Desktop: " newDesktop)
		}
		Loop %numDesktops%
		{
			If A_Index = 10
				index = 0
			Else
				index = %A_Index%

			Hotkey , %switchModifier%%index% , on
		}
		gosub buildmenu
		gosub, trashshadows
		sleep 100
	
		return
	}



ChangeDesktop(newPath)
	{
		Critical
		global tpath
		tpath := newPath




		hModule := DllCall("GetModuleHandle", "Str", "Shell32.dll")

		fAddress := DllCall("GetProcAddress", "uint", hModule, "uint", 231)

		r := DllCall(fAddress, "uint", 0x0010, "uint", 0, "uInt", 0, "ptr", &newPath)



		;DllCall("Shell32\SHChangeNotify",uint,0x8000000,uint,0x1000,uint,0,uint,0)

		DllCall("shell32\SHGetSpecialFolderLocation","uint",0,"uint", 0x0000, "uintP",ppidl)
		VarSetCapacity(name , 228)
		name=
		DllCall("shell32\SHGetPathFromIDList","uint",ppidl,"str",name)
		;DllCall("Shell32\SHChangeNotify",uint,0x00001000,uint,0,uint,ppidl,uint,0)


			DllCall("Shell32\SHChangeNotify",uint,0x8000000,uint,0x1000,uint,0,uint,0)
			;SendMessage, 0x1A, 42,,, ahk_id 0xFFFF
			
	}
	
	hiderecycle(status=1)
{
	rbStatNew = %status%
    rbStatClas = %status%
    RegWrite, REG_DWORD, HKCU, Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu, {645FF040-5081-101B-9F08-00AA002F954E}, %rbStatClas%
    RegWrite, REG_DWORD, HKCU, Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel, {645FF040-5081-101B-9F08-00AA002F954E}, %rbStatNew%
    PostMessage, 0x111, 28931,,, ahk_class Progman
	}


DeskIcons(coords="")
	{
		Critical
		static MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x04, MEM_RELEASE := 0x8000
		static LVM_GETITEMPOSITION := 0x00001010, LVM_SETITEMPOSITION := 0x0000100F, WM_SETREDRAW := 0x000B

		ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
		If !hwWindow ; #D mode
			ControlGet, hwWindow, HWND,, SysListView321, A
		IfWinExist ahk_id %hwWindow% ; last-found window set
			WinGet, iProcessID, PID
		hProcess := DllCall("OpenProcess"   , "UInt",   0x438         ; PROCESS-OPERATION|READ|WRITE|QUERY_INFORMATION
		        , "Int",   FALSE         ; inherit = false
		        , "UInt",   iProcessID)
		If hwWindow and hProcess
		{
			ControlGet, list, list,Col1
			If !coords
			{
				VarSetCapacity(iCoord, 8)
				pItemCoord := DllCall("VirtualAllocEx", "UInt", hProcess, "UInt", 0, "UInt", 8, "UInt", MEM_COMMIT, "UInt", PAGE_READWRITE)
				Loop, Parse, list, `n
				{
					SendMessage, %LVM_GETITEMPOSITION%, % A_Index-1, %pItemCoord%
					DllCall("ReadProcessMemory", "UInt", hProcess, "UInt", pItemCoord, "UInt", &iCoord, "UInt", 8, "UIntP", cbReadWritten)
					ret .= A_LoopField ":" (NumGet(iCoord) & 0xFFFF) | ((Numget(iCoord, 4) & 0xFFFF) << 16) "`n"
				}
				DllCall("VirtualFreeEx", "UInt", hProcess, "UInt", pItemCoord, "UInt", 0, "UInt", MEM_RELEASE)
			}
			Else
			{
				SendMessage, %WM_SETREDRAW%,0,0
				Loop, Parse, list, `n
					If RegExMatch(coords,"\Q" A_LoopField "\E:\K.*",iCoord_new)
						SendMessage, %LVM_SETITEMPOSITION%, % A_Index-1, %iCoord_new%
				SendMessage, %WM_SETREDRAW%,1,0
				ret := true
			}
		}
		DllCall("CloseHandle", "UInt", hProcess)
		return ret
	}


SendToDesktop(windowID, oldDesktop, newDesktop)
	{
		global

		WinGetClass , windowClass, ahk_id %windowID%

		If windowClass != "Shell_TrayWnd"
		{
			Loop %numDesktops%
			{
				If A_Index = 10
					index = 0
				Else
					index = %A_Index%

				Hotkey , %sendModifier%%index% , off
			}

			if(newDesktop!=oldDesktop)
			{
				RemoveWindowID(oldDesktop, windowID)

				windows%newDesktop% += 1
				i := windows%newDesktop%
				win_desktop%windowID%:=newDesktop
				windows%newDesktop%%i% := windowID
				If taskbar
				{
					 WinGetPos , tx, ty, tw, th, ahk_id %windowID%
					%windowID%x:=tx
					%windowID%y:=ty
					%windowID%w:=tw
					%windowID%h:=th
					 WinSet, Disable,, ahk_id %windowID%
					 WinSet, Transparent, 0, ahk_id %windowID%
					 Win_Move(windowID, 0, 0, 0, 0)
				}
				Else
				{
					WinHide , ahk_id %windowID%
				}
				;Send, {ALT DOWN}{TAB}{ALT UP}
			}
			winshow , Start

		Loop %numDesktops%
		{
			If A_Index = 10
				index = 0
			Else
				index = %A_Index%

			Hotkey , %sendModifier%%index% , on
		}


	}

}

SendActiveToDesktop(newDesktop,curDesktop)
	{
		WinGet , id, ID, A
		SendToDesktop(id, curDesktop, newDesktop)
	}

RemoveWindowID(desktopIdx, ID)
	{
		global
		Loop , % windows%desktopIdx%
		{
			If (windows%desktopIdx%%A_Index% = ID)
			{
				RemoveWindowID_byIndex(desktopIdx, A_Index)
				windows%desktopIdx%%A_Index%=
				Break
			}
		}
	}


FindDesktop_byId(ID)
	{
		global

		Loop %numdesktops%
		{
			this_index:=a_index
			Loop , % windows%this_index%
			{
				com_id:= % windows%this_index%%A_Index%

				If (id=com_id)
					return this_index

			}

		}


	}

RemoveWindowID_byIndex(desktopIdx, ID_idx)
	{
		global
		Loop , % windows%desktopIdx% - ID_idx
		{
			idx1 := % A_Index + ID_idx - 1
			idx2 := % A_Index + ID_idx
			windows%desktopIdx%%idx1% := windows%desktopIdx%%idx2%
		}
		windows%desktopIdx% -= 1
	}

GetCurrentWindows(index)
	{
		global
		

		emptyString =
		StringSplit, windows%index%, emptyString

		WinGet , windows%index%, List,,, Program Manager

		Loop, % windows%index%
		{
			id := % windows%index%%A_Index%
			
			win_desktop%id%:=index
			
		   
	
			WinGetClass, windowClass, ahk_id %id%
			WinGetTitle, windowTitle, ahk_id %id%
			WinGet, minmax , minmax, ahk_id %id%
			testx:=%id%x
			If (testx and taskbar)
			{
				
				windows%index%%A_Index%=
				win_desktop%id%:=
			}
			If (windowClass = "Shell_TrayWnd")
			{
				windows%index%%A_Index%=
				win_desktop%id%:=
			}

			if (windowClass="Shell_SecondaryTrayWnd")
			{
				windows%index%%A_Index%=
				win_desktop%id%:=				
			}
			If (windowTitle = "Start" and windowClass="Button")
			{
				windows%index%%A_Index%=
				win_desktop%id%:=
			}
			
			
			;1BAD Day 1
			;Issue 43
			;Bring window to new desktop while dragging it.
			if (GetKeyState("LButton"))
			{
				MouseGetPos, , , MoveWin
				if (id=MoveWin)
				{
					windows%index%%A_Index%=
					win_desktop%id%:=
				}
			}
			
			
			this_idx:= A_Index
			Loop, Parse, windowsOnAll, |,%A_Space%
			{
				If instr(windowTitle,a_loopfield)
				{
					windows%index%%this_idx%=
					;win_desktop%id%:=
				}
			}
		}
	}

MoveAllWindows(oldDesktop, newDesktop)
	{
		global

		numWins := windows%oldDesktop%
		Loop , %numwins%
		{
			id := % windows%oldDesktop%%A_Index%
			SendToDesktop(id, oldDesktop, newDesktop)
		}

		ShowHideWindows(curDesktop, true)

		return
	}

ShowHideWindows(index, show)
	{
		global

		Loop , % windows%index%
		{	
			
			id := % windows%index%%A_Index%
			If show
			{
				If taskbar
				{
					WinSet, Enable,, ahk_id %id%
					Win_Move(id, %id%x, %id%y, %id%w, %id%h)
					%id%x:=
					%id%y:=
					%id%w:=
					%id%h:=
					WinSet, Transparent, off, ahk_id %id%
				}
				Else
				{
					WinShow , ahk_id %id%
				}

			}
			Else
			{
				If taskbar
				{
					 WinGetPos , tx, ty, tw, th, ahk_id %id%
					%id%x:=tx
					%id%y:=ty
					%id%w:=tw
					%id%h:=th
					 WinSet, Disable,, ahk_id %id%
					 WinSet, Transparent, 0, ahk_id %id%
					 
					Win_Move(id, 0, 0, 0, 0)
					
					
				}
				Else
				{
				
					WinHide , ahk_id %id%
					
				}
			}
		}
		return
	}

ActivateTopmost()
{
   WinGet, id, List
   Loop, %id%
   {
      id := id%A_Index%
      WinGet, a, Transparent, ahk_id %id%

      if a is not Integer
         a := "255"
      if (a!=0)
         break
   }
	
   ;WinActivate, ahk_id %id%
}


wait:
	{

		CoordMode, Pixel, Screen

		CoordMode, Mouse, Screen
		screenwidth:=A_ScreenWidth-1
		Loop
		{
			sleep 100
			MouseGetPos,xx
			If (xx=0)
			{
				ss=%ss%1
				StartTime1 := A_TickCount
				;loop
				{
					MouseGetPos,xx
					If xx<>0
						break
				}
		}
		Else If (xx=>screenwidth)
		{
			ss=%ss%2
			starttime2:=A_TickCount
			Loop
			{
				MouseGetPos,xx
				If xx<>%screenwidth%
					break
			}
		}
		StringRight, check, ss, 2
		If check=12
		{
			If not gest=0
			{

				timelapse:=A_TickCount- starttime1

				If timelapse<%gesttime%
				{
					SwitchToNextDesktop()
				}

			}
			check=
			ss=

		}
		Else If check=21
		{

			If not gest=0
			{
				timelapse:=  A_TickCount-starttime2

				If timelapse<%gesttime%
				{

					SwitchToPrevDesktop()

				}
			}
			check=
			ss=

		}
	}
check=
ss=

}
return

change:
	{
		PostMessage , 0x111, 28931,,, ahk_class Progman
		SetTimer , change, Off
	}
return

CleanUp:
	;IniWrite , %hidinglevel%, %settings%, Settings, level
	Loop , %numDesktops%
	{
		if desktopswitcher
		{
			logiconset:=deskicon%a_index%
			logiconsetname=deskicon%a_index%
			logiconset:=inize(logiconset)
			IniWrite , %logiconset%, %settings%, Settings, %logiconsetname%
			logdeskshow:=deskshow%a_index%
			logdeskshowname=deskshow%a_index%
			IniWrite , %logdeskshow%, %settings%, Settings, %logdeskshowname%
			logtaskshow:=taskshow%a_index%
			logtaskshowname=taskshow%a_index%
			IniWrite , %logtaskshow%, %settings%, Settings, %logtaskshowname%
			logautohidetask:=autohidetask%a_index%
			logautohidetaskname=autohidetask%a_index%
			IniWrite , %logautohidetask%, %settings%, Settings, %logautohidetaskname%
			logrecshow:=recshow%a_index%
			logrecshowname=recshow%a_index%
			IniWrite , %logrecshow%, %settings%, Settings, %logrecshowname%
			
			
		}
		ShowHideWindows(A_Index, true)
	
	}
	ExitApp

about:
	gui 2:add,text,,mDesktop
	gui 2:add,text,,Version: 1.7.2
	gui 2:add,text,,By: Jason Stallings
	gui 2:add,text,cblue ggourl, github.com/octalmage/mDesktop
	gui 2:add,text,,Enhancements by: Ian Fijolek
	gui 2:show
return

gourl:
	run http://github.com/octalmage/mdesktop
return

ShowBanner(Text)
	{
		Gui 89: hide
		SysGet, Workspace, MonitorWorkArea
		Trans := 255
		Gui 89: -Caption +ToolWindow +LastFound +AlwaysOnTop +Border
		Gui 89: Show, Hide
		Global GUI_ID ;Is this the proper way to use Global? I need it for TP_Fade...
		GUI_ID := WinExist()
		WinGetPos, GUIX, GUIY, GUIWidth, GUIHeight, ahk_id %GUI_ID%
		NewX := WorkSpaceRight-GUIWidth-5
		NewY := WorkspaceBottom-GUIHeight-5



		GuiControl , Text, String, %Text%

		Gui 89:  Show,x%NewX% y%NewY% h24 w92 NoActivate, MyTransparentBanner
		WinSet , Transparent, %Trans%, MyTransparentBanner
		Sleep 500

		Loop
		{
			if(Trans <= 0)
			{
				Trans := 0
				WinSet , Transparent, %Trans%, MyTransparentBanner
				break
			}

			WinSet , Transparent, %Trans%, MyTransparentBanner
		Trans := Trans - 5
		Sleep , 10
	}

return
}

trashshadows:
	Loop
	{
		If not WinExist("ahk_class SysShadow")
		{
			break
		}
		winkill,ahk_class SysShadow
	}

return

EmptyMem(pid){
		pid:=(pid) ? DllCall("GetCurrentProcessId") : pid
		h:=DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", pid)
		DllCall("SetProcessWorkingSetSize", "UInt", h, "Int", -1, "Int", -1)
		DllCall("CloseHandle", "Int", h)
	}

; Uncomment for quick reload while programing

/*
#r::
	Reload
return
*/





;This is making the required guis for the Switcher, could probably combine these into one in my new fuction.
switchermake:

	Gui, 2: -Caption +E0x80000 +LastFound  +ToolWindow +AlwaysOnTop
	Gui, 2: Show, NA
	hwnd2 := WinExist()
	Gui, 3: -Caption +E0x80000 +LastFound  +ToolWindow +AlwaysOnTop
	Gui, 3: Show, NA
	hwnd3 := WinExist()

	Gui, 4: -Caption +E0x80000 +LastFound  +ToolWindow +AlwaysOnTop
	Gui, 4: Show, NA
	hwnd4 := WinExist()
	Gui, 5: -Caption +E0x80000 +LastFound  +ToolWindow +AlwaysOnTop
	Gui, 5: Show, NA
	hwnd5 := WinExist()

	SysGet, VirtualScreenHeight, 79
	SysGet, VirtualScreenWidth, 78

	Ratio := VirtualScreenWidth/VirtualScreenHeight
	Width := 600, Height := Width*(1/Ratio)

	y1:=(A_ScreenHeight/2) - height - spacing
	y1:=Round(y1)
	x1:=(A_Screenwidth/2) - width - spacing
	x1:=Round(x1)


return

switcher:
	pBitmap%curDesktop% := Gdip_BitmapFromScreen(0)
	;sc_CaptureScreen(0, false, curDesktop . ".jpg", "20")
	gosub switchermake

	pBitmap1:= drawonwallpaper(wallpaper,1)
	Gui, 2: hide
	Gui, 3: hide
	Gui, 4: hide
	Gui, 5: hide
	drawscreenshot(1, x1, y1,hwnd2,pBitmap1)

	pBitmap2:= drawonwallpaper(wallpaper,2)
	drawscreenshot(2, x1+width+spacing, y1,hwnd3,pBitmap2)

	pBitmap3:= drawonwallpaper(wallpaper,3)
	drawscreenshot(3, x1, y1+height+spacing,hwnd4,pBitmap3)

	pBitmap4:= drawonwallpaper(wallpaper,4)
	drawscreenshot(4, x1+width+spacing, y1+height+spacing,hwnd5,pBitmap4)
	Gui, 2: show
	Gui, 3: show
	Gui, 4: show
	Gui, 5: show
	OnMessage(0x201, "WM_LBUTTONDOWN")
	switcheropen=1

return



drawscreenshot(desk,shot_x, shot_y,hwnd2,pBitmap)
	{
		;file=%A_ScriptDir%\%desk%.jpg


		OriginalWidth := Gdip_GetImageWidth(pBitmap), OriginalHeight := Gdip_GetImageHeight(pBitmap)
		Ratio := OriginalWidth/OriginalHeight

		Width := 600, Height := Width*(1/Ratio)
		hbm := CreateDIBSection(600, 600)

		hdc := CreateCompatibleDC()


		obm := SelectObject(hdc, hbm)

		G := Gdip_GraphicsFromHDC(hdc), Gdip_SetInterpolationMode(G, 7)

		Gdip_DrawImage(G, pBitmap, 0, 0, Width, Height, 0, 0, OriginalWidth, OriginalHeight)
		DetectHiddenWindows, on
		UpdateLayeredWindow(hwnd2, hdc, shot_x, shot_y, Width, Height)
		DetectHiddenWindows, off
		SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)

		Gdip_DeleteGraphics(G)
		Gdip_DisposeImage(pBitmap)

		return
	}


drawonwallpaper(wallpaper,desktop)
	{
		global windows1
		global windows2
		global windows3
		global windows4
		global windowsonall
		global MonitorCount
		global VirtualScreenHeight
		global VirtualScreenWidth
		global curdesktop





		desktopshot := Gdip_CreateBitmap(VirtualScreenWidth, VirtualScreenHeight)
		G := Gdip_GraphicsFromImage(desktopshot)

		;wallfile := Gdip_CreateBitmapFromFile(wallpaper)




		If (desktop=curdesktop)
			pBrush3 := Gdip_BrushCreateSolid(0xff666666)
		Else
			pBrush3 := Gdip_BrushCreateSolid(0xff333333)

		Gdip_FillRectangle(G, pBrush3, 0, 0, a_screenwidth, a_screenheight)

		Gdip_FillRectangle(G, pBrush3, 0, 0, VirtualScreenWidth, VirtualScreenHeight)

		;wallfile := Gdip_BitmapFromHWND(hwnd)
		Width := Gdip_GetImageWidth(wallfile), Height := Gdip_GetImageHeight(wallfile)

		;loop %monitorcount%
		;{

		;wallx:=A_ScreenWidth*(a_index-1)
		;Gdip_DrawImage(G, wallfile, wallx, 0, a_screenwidth, a_screenheight, 0, 0, Width, Height)
		;	}




		Font = Arial

		If !hFamily := Gdip_FontFamilyCreate(Font)
		{
			MsgBox, 48, Font error!, The font you have specified does not exist on the system
			ExitApp
		}
		; Delete font family as we now know the font does exist
		Gdip_DeleteFontFamily(hFamily)

		pBrush := Gdip_BrushCreateSolid(0xffc0c0c0)
		pBrush2 := Gdip_BrushCreateSolid(0xff000000)

		pPen := Gdip_CreatePen(0xff000000, 5)


		thistime=0
		times:=% windows%desktop%
		Loop , %times%
		{

			id := % windows%desktop%%times%
			DetectHiddenWindows, On
			;win1 := sGdip_BitmapFromHWND(id)
			WinGetPos , wx, wy, ww, wh, ahk_id %id%

			WinGettitle, title, ahk_id %id%


			If title=""
			{
				continue
			}
			DetectHiddenWindows, off
			pw:=ww-5
			;Gdip_DrawImage(G, win1, wx, wy, ww, wh, 0, 0, ww, wh)
			Gdip_FillRectangle(G, pBrush, wx, wy, ww, wh)
			Gdip_FillRectangle(G, pBrush2, wx, wy, ww, 30)
			Gdip_DrawRectangle(G, pPen, wx, wy, pw, wh)
			tx:=wx+5
			ty:=wy+5
			Options = x%tx% y%ty%   cffffffff r1 s20
			Gdip_TextToGraphics(G, title, Options, Font, ww, wh)
			Gdip_DisposeImage(win1)
			times--
		}

		Loop, Parse, windowsOnAll, |,%A_Space%
		{

			DetectHiddenWindows, On
			WinGet, id , id, %a_loopfield%
			;win1 := sGdip_BitmapFromHWND(id)
			WinGetPos , wx, wy, ww, wh, ahk_id %id%

			WinGettitle, title, ahk_id %id%

			If ww=0
			{
				continue
			}
			DetectHiddenWindows, off
			pw:=ww-5
			;Gdip_DrawImage(G, win1, wx, wy, ww, wh, 0, 0, ww, wh)
			Gdip_FillRectangle(G, pBrush, wx, wy, ww, wh)
			Gdip_FillRectangle(G, pBrush2, wx, wy, ww, 30)
			Gdip_DrawRectangle(G, pPen, wx, wy, pw, wh)
			tx:=wx+5
			ty:=wy+5
			Options = x%tx% y%ty%   cff000000 r1 s20
			Gdip_TextToGraphics(G, title, Options, Font, ww, wh)
			Gdip_DisposeImage(win1)
			times--
		}
		;Gdip_SaveBitmapToFile(desktopshot, "FinalImage.png")
		return desktopshot
	}

inize(var, flag=0)
{
	if not flag
	{
		StringReplace, var, var, `r`n , |, All
		StringReplace, var, var, `n , |, All
	}
	else
	{
		StringReplace, var, var, |,`n , All
	}

	return %var%

}

WM_LBUTTONDOWN()
	{
		switchergui=1
		desktopp:=A_Gui-1


		gui 2: destroy
		gui 3: destroy
		gui 4: destroy
		gui 5: destroy

		SwitchToDesktop(desktopp)
		switcheropen=0
		switchergui=0
	}




; Gdip standard library v1.38 by tic (Tariq Porter) 28/08/10
;
;#####################################################################################
;#####################################################################################
; STATUS ENUMERATION
; Return values for functions specified to have status enumerated return type
;#####################################################################################
;
; Ok =						= 0
; GenericError				= 1
; InvalidParameter			= 2
; OutOfMemory				= 3
; ObjectBusy				= 4
; InsufficientBuffer		= 5
; NotImplemented			= 6
; Win32Error				= 7
; WrongState				= 8
; Aborted					= 9
; FileNotFound				= 10
; ValueOverflow				= 11
; AccessDenied				= 12
; UnknownImageFormat		= 13
; FontFamilyNotFound		= 14
; FontStyleNotFound			= 15
; NotTrueTypeFont			= 16
; UnsupportedGdiplusVersion	= 17
; GdiplusNotInitialized		= 18
; PropertyNotFound			= 19
; PropertyNotSupported		= 20
; ProfileNotFound			= 21
;
;#####################################################################################
;#####################################################################################
; FUNCTIONS
;#####################################################################################
;
; UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)
; BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")
; StretchBlt(dDC, dx, dy, dw, dh, sDC, sx, sy, sw, sh, Raster="")
; SetImage(hwnd, hBitmap)
; Gdip_BitmapFromScreen(Screen=0, Raster="")
; CreateRectF(ByRef RectF, x, y, w, h)
; CreateSizeF(ByRef SizeF, w, h)
; CreateDIBSection
;
;#####################################################################################

; Function:     			UpdateLayeredWindow
; Description:  			Updates a layered window with the handle to the DC of a gdi bitmap
;
; hwnd        				Handle of the layered window to update
; hdc           			Handle to the DC of the GDI bitmap to update the window with
; Layeredx      			x position to place the window
; Layeredy      			y position to place the window
; Layeredw      			Width of the window
; Layeredh      			Height of the window
; Alpha         			Default = 255 : The transparency (0-255) to set the window transparency
;
; return      				If the function succeeds, the return value is nonzero
;
; notes						If x or y omitted, then layered window will use its current coordinates
;							If w or h omitted then current width and height will be used

UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)
	{
		If ((x != "") && (y != ""))
			VarSetCapacity(pt, 8), NumPut(x, pt, 0), NumPut(y, pt, 4)

		If (w = "") ||(h = "")
			WinGetPos,,, w, h, ahk_id %hwnd%

		return DllCall("UpdateLayeredWindow", "uint", hwnd, "uint", 0, "uint", ((x = "") && (y = "")) ? 0 : &pt
		        , "int64*", w|h<<32, "uint", hdc, "int64*", 0, "uint", 0, "uint*", Alpha<<16|1<<24, "uint", 2)
	}

;#####################################################################################

; Function				BitBlt
; Description			The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle
;						of pixels from the specified source device context into a destination device context.
;
; dDC					handle to destination DC
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of the area to copy
; dh					height of the area to copy
; sDC					handle to source DC
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; Raster				raster operation code
;
; return				If the function succeeds, the return value is nonzero
;
; notes					If no raster operation is specified, then SRCCOPY is used, which copies the source directly to the destination rectangle
;
; BLACKNESS				= 0x00000042
; NOTSRCERASE			= 0x001100A6
; NOTSRCCOPY			= 0x00330008
; SRCERASE				= 0x00440328
; DSTINVERT				= 0x00550009
; PATINVERT				= 0x005A0049
; SRCINVERT				= 0x00660046
; SRCAND				= 0x008800C6
; MERGEPAINT			= 0x00BB0226
; MERGECOPY				= 0x00C000CA
; SRCCOPY				= 0x00CC0020
; SRCPAINT				= 0x00EE0086
; PATCOPY				= 0x00F00021
; PATPAINT				= 0x00FB0A09
; WHITENESS				= 0x00FF0062
; CAPTUREBLT			= 0x40000000
; NOMIRRORBITMAP		= 0x80000000

BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")
	{
		return DllCall("gdi32\BitBlt", "uint", dDC, "int", dx, "int", dy, "int", dw, "int", dh
		        , "uint", sDC, "int", sx, "int", sy, "uint", Raster ? Raster : 0x00CC0020)
	}

;#####################################################################################

; Function				StretchBlt
; Description			The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle,
;						stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary.
;						The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context.
;
; ddc					handle to destination DC
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of destination rectangle
; dh					height of destination rectangle
; sdc					handle to source DC
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source rectangle
; sh					height of source rectangle
; Raster				raster operation code
;
; return				If the function succeeds, the return value is nonzero
;
; notes					If no raster operation is specified, then SRCCOPY is used. It uses the same raster operations as BitBlt

StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster="")
	{
		return DllCall("gdi32\StretchBlt", "uint", ddc, "int", dx, "int", dy, "int", dw, "int", dh
		        , "uint", sdc, "int", sx, "int", sy, "int", sw, "int", sh, "uint", Raster ? Raster : 0x00CC0020)
	}

;#####################################################################################

; Function				SetStretchBltMode
; Description			The SetStretchBltMode function sets the bitmap stretching mode in the specified device context
;
; hdc					handle to the DC
; iStretchMode			The stretching mode, describing how the target will be stretched
;
; return				If the function succeeds, the return value is the previous stretching mode. If it fails it will return 0
;
; STRETCH_ANDSCANS 		= 0x01
; STRETCH_ORSCANS 		= 0x02
; STRETCH_DELETESCANS 	= 0x03
; STRETCH_HALFTONE 		= 0x04

SetStretchBltMode(hdc, iStretchMode=4)
	{
		return DllCall("gdi32\SetStretchBltMode", "uint", hdc, "int", iStretchMode)
	}

;#####################################################################################

; Function				SetImage
; Description			Associates a new image with a static control
;
; hwnd					handle of the control to update
; hBitmap				a gdi bitmap to associate the static control with
;
; return				If the function succeeds, the return value is nonzero

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

;#####################################################################################

; Function				SetSysColorToControl
; Description			Sets a solid colour to a control
;
; hwnd					handle of the control to update
; SysColor				A system colour to set to the control
;
; return				If the function succeeds, the return value is zero
;
; notes					A control must have the 0xE style set to it so it is recognised as a bitmap
;						By default SysColor=15 is used which is COLOR_3DFACE. This is the standard background for a control
;
; COLOR_3DDKSHADOW				= 21
; COLOR_3DFACE					= 15
; COLOR_3DHIGHLIGHT				= 20
; COLOR_3DHILIGHT				= 20
; COLOR_3DLIGHT					= 22
; COLOR_3DSHADOW				= 16
; COLOR_ACTIVEBORDER			= 10
; COLOR_ACTIVECAPTION			= 2
; COLOR_APPWORKSPACE			= 12
; COLOR_BACKGROUND				= 1
; COLOR_BTNFACE					= 15
; COLOR_BTNHIGHLIGHT			= 20
; COLOR_BTNHILIGHT				= 20
; COLOR_BTNSHADOW				= 16
; COLOR_BTNTEXT					= 18
; COLOR_CAPTIONTEXT				= 9
; COLOR_DESKTOP					= 1
; COLOR_GRADIENTACTIVECAPTION	= 27
; COLOR_GRADIENTINACTIVECAPTION	= 28
; COLOR_GRAYTEXT				= 17
; COLOR_HIGHLIGHT				= 13
; COLOR_HIGHLIGHTTEXT			= 14
; COLOR_HOTLIGHT				= 26
; COLOR_INACTIVEBORDER			= 11
; COLOR_INACTIVECAPTION			= 3
; COLOR_INACTIVECAPTIONTEXT		= 19
; COLOR_INFOBK					= 24
; COLOR_INFOTEXT				= 23
; COLOR_MENU					= 4
; COLOR_MENUHILIGHT				= 29
; COLOR_MENUBAR					= 30
; COLOR_MENUTEXT				= 7
; COLOR_SCROLLBAR				= 0
; COLOR_WINDOW					= 5
; COLOR_WINDOWFRAME				= 6
; COLOR_WINDOWTEXT				= 8

SetSysColorToControl(hwnd, SysColor=15)
	{
		WinGetPos,,, w, h, ahk_id %hwnd%
		bc := DllCall("GetSysColor", "Int", SysColor)
		pBrushClear := Gdip_BrushCreateSolid(0xff000000 | (bc >> 16 | bc & 0xff00 | (bc & 0xff) << 16))
		pBitmap := Gdip_CreateBitmap(w, h), G := Gdip_GraphicsFromImage(pBitmap)
		Gdip_FillRectangle(G, pBrushClear, 0, 0, w, h)
		hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
		SetImage(hwnd, hBitmap)
		Gdip_DeleteBrush(pBrushClear)
		Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
		return 0
	}

;#####################################################################################

; Function				Gdip_BitmapFromScreen
; Description			Gets a gdi+ bitmap from the screen
;
; Screen				0 = All screens
;						Any numerical value = Just that screen
;						x|y|w|h = Take specific coordinates with a width and height
; Raster				raster operation code
;
; return      			If the function succeeds, the return value is a pointer to a gdi+ bitmap
;						-1:		one or more of x,y,w,h not passed properly
;
; notes					If no raster operation is specified, then SRCCOPY is used to the returned bitmap

Gdip_BitmapFromScreen(Screen=0, Raster="")
	{
		If (Screen = 0)
		{
			Sysget, x, 76
			Sysget, y, 77
			Sysget, w, 78
			Sysget, h, 79
		}
		Else If (Screen&1 != "")
		{
			Sysget, M, Monitor, %Screen%
			x := MLeft, y := MTop, w := MRight-MLeft, h := MBottom-MTop
		}
		Else
		{
			StringSplit, S, Screen, |
			x := S1, y := S2, w := S3, h := S4
		}

		If (x = "") || (y = "") || (w = "") || (h = "")
			return -1

		chdc := CreateCompatibleDC(), hbm := CreateDIBSection(w, h, chdc), obm := SelectObject(chdc, hbm), hhdc := GetDC()
		BitBlt(chdc, 0, 0, w, h, hhdc, x, y, Raster)
		ReleaseDC(hhdc)

		pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
		SelectObject(hhdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
		return pBitmap
	}

;#####################################################################################

; Function				Gdip_BitmapFromHWND
; Description			Uses PrintWindow to get a handle to the specified window and return a bitmap from it
;
; hwnd					handle to the window to get a bitmap from
;
; return				If the function succeeds, the return value is a pointer to a gdi+ bitmap
;
; notes					Window must not be not minimised in order to get a handle to it's client area

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
	}
;#####################################################################################

; Function    			CreateRectF
; Description			Creates a RectF object, containing a the coordinates and dimensions of a rectangle
;
; RectF       			Name to call the RectF object
; x            			x-coordinate of the upper left corner of the rectangle
; y            			y-coordinate of the upper left corner of the rectangle
; w            			Width of the rectangle
; h            			Height of the rectangle
;
; return      			No return value

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")
	}
;#####################################################################################

; Function		    	CreateSizeF
; Description			Creates a SizeF object, containing an 2 values
;
; SizeF         		Name to call the SizeF object
; w            			w-value for the SizeF object
; h            			h-value for the SizeF object
;
; return      			No Return value

CreateSizeF(ByRef SizeF, w, h)
	{
		VarSetCapacity(SizeF, 8)
		NumPut(w, SizeF, 0, "float"), NumPut(h, SizeF, 4, "float")
	}
;#####################################################################################

; Function		    	CreatePointF
; Description			Creates a SizeF object, containing an 2 values
;
; SizeF         		Name to call the SizeF object
; w            			w-value for the SizeF object
; h            			h-value for the SizeF object
;
; return      			No Return value

CreatePointF(ByRef PointF, x, y)
	{
		VarSetCapacity(PointF, 8)
		NumPut(x, PointF, 0, "float"), NumPut(y, PointF, 4, "float")
	}
;#####################################################################################

; Function				CreateDIBSection
; Description			The CreateDIBSection function creates a DIB (Device Independent Bitmap) that applications can write to directly
;
; w						width of the bitmap to create
; h						height of the bitmap to create
; hdc					a handle to the device context to use the palette from
; bpp					bits per pixel (32 = ARGB)
; ppvBits				A pointer to a variable that receives a pointer to the location of the DIB bit values
;
; return				returns a DIB. A gdi bitmap
;
; notes					ppvBits will receive the location of the pixels in the DIB

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

		If !hdc
			ReleaseDC(hdc2)
		return hbm
	}

;#####################################################################################

; Function				PrintWindow
; Description			The PrintWindow function copies a visual window into the specified device context (DC), typically a printer DC
;
; hwnd					A handle to the window that will be copied
; hdc					A handle to the device context
; Flags					Drawing options
;
; return				If the function succeeds, it returns a nonzero value
;
; PW_CLIENTONLY			= 1

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

;#####################################################################################

; Function				DestroyIcon
; Description			Destroys an icon and frees any memory the icon occupied
;
; hIcon					Handle to the icon to be destroyed. The icon must not be in use
;
; return				If the function succeeds, the return value is nonzero

DestroyIcon(hIcon)
	{
		return DllCall("DestroyIcon", "uint", hIcon)
	}

;#####################################################################################

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

;#####################################################################################

CreateCompatibleBitmap(hdc, w, h)
	{
		return DllCall("gdi32\CreateCompatibleBitmap", "uint", hdc, "int", w, "int", h)
	}

;#####################################################################################

; Function				CreateCompatibleDC
; Description			This function creates a memory device context (DC) compatible with the specified device
;
; hdc					Handle to an existing device context
;
; return				returns the handle to a device context or 0 on failure
;
; notes					If this handle is 0 (by default), the function creates a memory device context compatible with the application's current screen

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

;#####################################################################################

; Function				SelectObject
; Description			The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type
;
; hdc					Handle to a DC
; hgdiobj				A handle to the object to be selected into the DC
;
; return				If the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced
;
; notes					The specified object must have been created by using one of the following functions
;						Bitmap - CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBSection (A single bitmap cannot be selected into more than one DC at the same time)
;						Brush - CreateBrushIndirect, CreateDIBPatternBrush, CreateDIBPatternBrushPt, CreateHatchBrush, CreatePatternBrush, CreateSolidBrush
;						Font - CreateFont, CreateFontIndirect
;						Pen - CreatePen, CreatePenIndirect
;						Region - CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect
;
; notes					If the selected object is a region and the function succeeds, the return value is one of the following value
;
; SIMPLEREGION			= 2 Region consists of a single rectangle
; COMPLEXREGION			= 3 Region consists of more than one rectangle
; NULLREGION			= 1 Region is empty

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

;#####################################################################################

; Function				DeleteObject
; Description			This function deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object
;						After the object is deleted, the specified handle is no longer valid
;
; hObject				Handle to a logical pen, brush, font, bitmap, region, or palette to delete
;
; return				Nonzero indicates success. Zero indicates that the specified handle is not valid or that the handle is currently selected into a device context

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

;#####################################################################################

; Function				GetDC
; Description			This function retrieves a handle to a display device context (DC) for the client area of the specified window.
;						The display device context can be used in subsequent graphics display interface (GDI) functions to draw in the client area of the window.
;
; hwnd					Handle to the window whose device context is to be retrieved. If this value is NULL, GetDC retrieves the device context for the entire screen
;
; return				The handle the device context for the specified window's client area indicates success. NULL indicates failure

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

;#####################################################################################

; Function				ReleaseDC
; Description			This function releases a device context (DC), freeing it for use by other applications. The effect of ReleaseDC depends on the type of device context
;
; hdc					Handle to the device context to be released
; hwnd					Handle to the window whose device context is to be released
;
; return				1 = released
;						0 = not released
;
; notes					The application must call the ReleaseDC function for each call to the GetWindowDC function and for each call to the GetDC function that retrieves a common device context
;						An application cannot use the ReleaseDC function to release a device context that was created by calling the CreateDC function; instead, it must use the DeleteDC function.

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

;#####################################################################################

; Function				DeleteDC
; Description			The DeleteDC function deletes the specified device context (DC)
;
; hdc					A handle to the device context
;
; return				If the function succeeds, the return value is nonzero
;
; notes					An application must not delete a DC whose handle was obtained by calling the GetDC function. Instead, it must call the ReleaseDC function to free the DC

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

; Function				Gdip_LibraryVersion
; Description			Get the current library version
;
; return				the library version
;
; notes					This is useful for non compiled programs to ensure that a person doesn't run an old version when testing your scripts

Gdip_LibraryVersion()
	{
		return 1.38
	}

;#####################################################################################

; Function:    			Gdip_BitmapFromBRA
; Description: 			Gets a pointer to a gdi+ bitmap from a BRA file
;
; BRAFromMemIn			The variable for a BRA file read to memory
; File					The name of the file, or its number that you would like (This depends on alternate parameter)
; Alternate				Changes whether the File parameter is the file name or its number
;
; return      			If the function succeeds, the return value is a pointer to a gdi+ bitmap
;						-1 = The BRA variable is empty
;						-2 = The BRA has an incorrect header
;						-3 = The BRA has information missing
;						-4 = Could not find file inside the BRA

Gdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate=0)
	{
		If !BRAFromMemIn
			return -1
		Loop, Parse, BRAFromMemIn, `n
		{
			If (A_Index = 1)
			{
				StringSplit, Header, A_LoopField, |
				If (Header0 != 4 || Header2 != "BRA!")
					return -2
			}
			Else If (A_Index = 2)
			{
				StringSplit, Info, A_LoopField, |
				If (Info0 != 3)
					return -3
			}
			Else
				break
		}
		If !Alternate
			StringReplace, File, File, \, \\, All
		RegExMatch(BRAFromMemIn, "mi`n)^" (Alternate ? File "\|.+?\|(\d+)\|(\d+)" : "\d+\|" File "\|(\d+)\|(\d+)") "$", FileInfo)
		If !FileInfo
			return -4

		hData := DllCall("GlobalAlloc", "uint", 2, "uint", FileInfo2)
		pData := DllCall("GlobalLock", "uint", hData)
		DllCall("RtlMoveMemory", "uint", pData, "uint", &BRAFromMemIn+Info2+FileInfo1, "uint", FileInfo2)
		DllCall("GlobalUnlock", "uint", hData)
		DllCall("ole32\CreateStreamOnHGlobal", "uint", hData, "int", 1, "uint*", pStream)
		DllCall("gdiplus\GdipCreateBitmapFromStream", "uint", pStream, "uint*", pBitmap)
		DllCall(NumGet(NumGet(1*pStream)+8), "uint", pStream)
		return pBitmap
	}

;#####################################################################################

; Function				Gdip_DrawRectangle
; Description			This function uses a pen to draw the outline of a rectangle into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rectangle
; y						y-coordinate of the top left of the rectangle
; w						width of the rectanlge
; h						height of the rectangle
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

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

;#####################################################################################

; Function				Gdip_DrawRoundedRectangle
; Description			This function uses a pen to draw the outline of a rounded rectangle into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rounded rectangle
; y						y-coordinate of the top left of the rounded rectangle
; w						width of the rectanlge
; h						height of the rectangle
; r						radius of the rounded corners
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

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
	}

;#####################################################################################

; Function				Gdip_DrawEllipse
; Description			This function uses a pen to draw the outline of an ellipse into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rectangle the ellipse will be drawn into
; y						y-coordinate of the top left of the rectangle the ellipse will be drawn into
; w						width of the ellipse
; h						height of the ellipse
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

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

;#####################################################################################

; Function				Gdip_DrawBezier
; Description			This function uses a pen to draw the outline of a bezier (a weighted curve) into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x1					x-coordinate of the start of the bezier
; y1					y-coordinate of the start of the bezier
; x2					x-coordinate of the first arc of the bezier
; y2					y-coordinate of the first arc of the bezier
; x3					x-coordinate of the second arc of the bezier
; y3					y-coordinate of the second arc of the bezier
; x4					x-coordinate of the end of the bezier
; y4					y-coordinate of the end of the bezier
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawBezier(pGraphics, pPen, x1, y1, x2, y2, x3, y3, x4, y4)
	{
		return DllCall("gdiplus\GdipDrawBezier", "uint", pgraphics, "uint", pPen
		        , "float", x1, "float", y1, "float", x2, "float", y2
		        , "float", x3, "float", y3, "float", x4, "float", y4)
	}

;#####################################################################################

; Function				Gdip_DrawArc
; Description			This function uses a pen to draw the outline of an arc into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the start of the arc
; y						y-coordinate of the start of the arc
; w						width of the arc
; h						height of the arc
; StartAngle			specifies the angle between the x-axis and the starting point of the arc
; SweepAngle			specifies the angle between the starting and ending points of the arc
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawArc(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)
	{
		return DllCall("gdiplus\GdipDrawArc", "uint", pGraphics, "uint", pPen, "float", x
		        , "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
	}

;#####################################################################################

; Function				Gdip_DrawPie
; Description			This function uses a pen to draw the outline of a pie into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the start of the pie
; y						y-coordinate of the start of the pie
; w						width of the pie
; h						height of the pie
; StartAngle			specifies the angle between the x-axis and the starting point of the pie
; SweepAngle			specifies the angle between the starting and ending points of the pie
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawPie(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)
	{
		return DllCall("gdiplus\GdipDrawPie", "uint", pGraphics, "uint", pPen, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
	}

;#####################################################################################

; Function				Gdip_DrawLine
; Description			This function uses a pen to draw a line into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x1					x-coordinate of the start of the line
; y1					y-coordinate of the start of the line
; x2					x-coordinate of the end of the line
; y2					y-coordinate of the end of the line
;
; return				status enumeration. 0 = success

Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2)
	{
		return DllCall("gdiplus\GdipDrawLine", "uint", pGraphics, "uint", pPen
		        , "float", x1, "float", y1, "float", x2, "float", y2)
	}

;#####################################################################################

; Function				Gdip_DrawLines
; Description			This function uses a pen to draw a series of joined lines into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; Points				the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return				status enumeration. 0 = success

Gdip_DrawLines(pGraphics, pPen, Points)
	{
		StringSplit, Points, Points, |
		VarSetCapacity(PointF, 8*Points0)
		Loop, %Points0%
		{
			StringSplit, Coord, Points%A_Index%, `,
			NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
		}
		return DllCall("gdiplus\GdipDrawLines", "uint", pGraphics, "uint", pPen, "uint", &PointF, "int", Points0)
	}

;#####################################################################################

; Function				Gdip_FillRectangle
; Description			This function uses a brush to fill a rectangle in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the rectangle
; y						y-coordinate of the top left of the rectangle
; w						width of the rectanlge
; h						height of the rectangle
;
; return				status enumeration. 0 = success

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

;#####################################################################################

; Function				Gdip_FillRoundedRectangle
; Description			This function uses a brush to fill a rounded rectangle in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the rounded rectangle
; y						y-coordinate of the top left of the rounded rectangle
; w						width of the rectanlge
; h						height of the rectangle
; r						radius of the rounded corners
;
; return				status enumeration. 0 = success

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
	}

;#####################################################################################

; Function				Gdip_FillPolygon
; Description			This function uses a brush to fill a polygon in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Points				the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return				status enumeration. 0 = success
;
; notes					Alternate will fill the polygon as a whole, wheras winding will fill each new "segment"
; Alternate 			= 0
; Winding 				= 1

Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode=0)
	{
		StringSplit, Points, Points, |
		VarSetCapacity(PointF, 8*Points0)
		Loop, %Points0%
		{
			StringSplit, Coord, Points%A_Index%, `,
			NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
		}
		return DllCall("gdiplus\GdipFillPolygon", "uint", pGraphics, "uint", pBrush, "uint", &PointF, "int", Points0, "int", FillMode)
	}

;#####################################################################################

; Function				Gdip_FillPie
; Description			This function uses a brush to fill a pie in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the pie
; y						y-coordinate of the top left of the pie
; w						width of the pie
; h						height of the pie
; StartAngle			specifies the angle between the x-axis and the starting point of the pie
; SweepAngle			specifies the angle between the starting and ending points of the pie
;
; return				status enumeration. 0 = success

Gdip_FillPie(pGraphics, pBrush, x, y, w, h, StartAngle, SweepAngle)
	{
		return DllCall("gdiplus\GdipFillPie", "uint", pGraphics, "uint", pBrush
		        , "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
	}

;#####################################################################################

; Function				Gdip_FillEllipse
; Description			This function uses a brush to fill an ellipse in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the ellipse
; y						y-coordinate of the top left of the ellipse
; w						width of the ellipse
; h						height of the ellipse
;
; return				status enumeration. 0 = success

Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h)
	{
		return DllCall("gdiplus\GdipFillEllipse", "uint", pGraphics, "uint", pBrush, "float", x, "float", y, "float", w, "float", h)
	}

;#####################################################################################

; Function				Gdip_FillRegion
; Description			This function uses a brush to fill a region in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Region				Pointer to a Region
;
; return				status enumeration. 0 = success
;
; notes					You can create a region Gdip_CreateRegion() and then add to this

Gdip_FillRegion(pGraphics, pBrush, Region)
	{
		return DllCall("gdiplus\GdipFillRegion", "uint", pGraphics, "uint", pBrush, "uint", Region)
	}

;#####################################################################################

; Function				Gdip_FillPath
; Description			This function uses a brush to fill a path in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Region				Pointer to a Path
;
; return				status enumeration. 0 = success

Gdip_FillPath(pGraphics, pBrush, Path)
	{
		return DllCall("gdiplus\GdipFillPath", "uint", pGraphics, "uint", pBrush, "uint", Path)
	}

;#####################################################################################

; Function				Gdip_DrawImagePointsRect
; Description			This function draws a bitmap into the Graphics of another bitmap and skews it
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBitmap				Pointer to a bitmap to be drawn
; Points				Points passed as x1,y1|x2,y2|x3,y3 (3 points: top left, top right, bottom left) describing the drawing of the bitmap
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source rectangle
; sh					height of source rectangle
; Matrix				a matrix used to alter image attributes when drawing
;
; return				status enumeration. 0 = success
;
; notes					if sx,sy,sw,sh are missed then the entire source bitmap will be used
;						Matrix can be omitted to just draw with no alteration to ARGB
;						Matrix may be passed as a digit from 0 - 1 to change just transparency
;						Matrix can be passed as a matrix with any delimiter

Gdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx="", sy="", sw="", sh="", Matrix=1)
	{
		StringSplit, Points, Points, |
		VarSetCapacity(PointF, 8*Points0)
		Loop, %Points0%
		{
			StringSplit, Coord, Points%A_Index%, `,
			NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
		}

		If (Matrix&1 = "")
			ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
		Else If (Matrix != 1)
			ImageAttr := Gdip_SetImageAttributesColorMatrix("1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|" Matrix "|0|0|0|0|0|1")

		If (sx = "" && sy = "" && sw = "" && sh = "")
		{
			sx := 0, sy := 0
			sw := Gdip_GetImageWidth(pBitmap)
			sh := Gdip_GetImageHeight(pBitmap)
		}

		E := DllCall("gdiplus\GdipDrawImagePointsRect", "uint", pGraphics, "uint", pBitmap
		        , "uint", &PointF, "int", Points0, "float", sx, "float", sy, "float", sw, "float", sh
		        , "int", 2, "uint", ImageAttr, "uint", 0, "uint", 0)
		If ImageAttr
			Gdip_DisposeImageAttributes(ImageAttr)
		return E
	}

;#####################################################################################

; Function				Gdip_DrawImage
; Description			This function draws a bitmap into the Graphics of another bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBitmap				Pointer to a bitmap to be drawn
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of destination image
; dh					height of destination image
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source image
; sh					height of source image
; Matrix				a matrix used to alter image attributes when drawing
;
; return				status enumeration. 0 = success
;
; notes					if sx,sy,sw,sh are missed then the entire source bitmap will be used
;						Gdip_DrawImage performs faster
;						Matrix can be omitted to just draw with no alteration to ARGB
;						Matrix may be passed as a digit from 0 - 1 to change just transparency
;						Matrix can be passed as a matrix with any delimiter. For example:
;						MatrixBright=
;						(
;						1.5		|0		|0		|0		|0
;						0		|1.5	|0		|0		|0
;						0		|0		|1.5	|0		|0
;						0		|0		|0		|1		|0
;						0.05	|0.05	|0.05	|0		|1
;						)
;
; notes					MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
;						MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
;						MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|0|0|0|0|1

Gdip_DrawImage(pGraphics, pBitmap, dx="", dy="", dw="", dh="", sx="", sy="", sw="", sh="", Matrix=1)
	{
		If (Matrix&1 = "")
			ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
		Else If (Matrix != 1)
			ImageAttr := Gdip_SetImageAttributesColorMatrix("1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|" Matrix "|0|0|0|0|0|1")

		If (sx = "" && sy = "" && sw = "" && sh = "")
		{
			If (dx = "" && dy = "" && dw = "" && dh = "")
			{
				sx := dx := 0, sy := dy := 0
				sw := dw := Gdip_GetImageWidth(pBitmap)
				sh := dh := Gdip_GetImageHeight(pBitmap)
			}
			Else
			{
				sx := sy := 0
				sw := Gdip_GetImageWidth(pBitmap)
				sh := Gdip_GetImageHeight(pBitmap)
			}
		}

		E := DllCall("gdiplus\GdipDrawImageRectRect", "uint", pGraphics, "uint", pBitmap
		        , "float", dx, "float", dy, "float", dw, "float", dh
		        , "float", sx, "float", sy, "float", sw, "float", sh
		        , "int", 2, "uint", ImageAttr, "uint", 0, "uint", 0)
		If ImageAttr
			Gdip_DisposeImageAttributes(ImageAttr)
		return E
	}

;#####################################################################################

; Function				Gdip_SetImageAttributesColorMatrix
; Description			This function creates an image matrix ready for drawing
;
; Matrix				a matrix used to alter image attributes when drawing
;						passed with any delimeter
;
; return				returns an image matrix on sucess or 0 if it fails
;
; notes					MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
;						MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
;						MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|0|0|0|0|1

Gdip_SetImageAttributesColorMatrix(Matrix)
	{
		VarSetCapacity(ColourMatrix, 100, 0)
		Matrix := RegExReplace(RegExReplace(Matrix, "^[^\d-\.]+([\d\.])", "$1", "", 1), "[^\d-\.]+", "|")
		StringSplit, Matrix, Matrix, |
		Loop, 25
		{
			Matrix := (Matrix%A_Index% != "") ? Matrix%A_Index% : Mod(A_Index-1, 6) ? 0 : 1
			NumPut(Matrix, ColourMatrix, (A_Index-1)*4, "float")
		}
		DllCall("gdiplus\GdipCreateImageAttributes", "uint*", ImageAttr)
		DllCall("gdiplus\GdipSetImageAttributesColorMatrix", "uint", ImageAttr, "int", 1, "int", 1, "uint", &ColourMatrix, "int", 0, "int", 0)
		return ImageAttr
	}

;#####################################################################################

; Function				Gdip_GraphicsFromImage
; Description			This function gets the graphics for a bitmap used for drawing functions
;
; pBitmap				Pointer to a bitmap to get the pointer to its graphics
;
; return				returns a pointer to the graphics of a bitmap
;
; notes					a bitmap can be drawn into the graphics of another bitmap

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

;#####################################################################################

; Function				Gdip_GraphicsFromHDC
; Description			This function gets the graphics from the handle to a device context
;
; hdc					This is the handle to the device context
;
; return				returns a pointer to the graphics of a bitmap
;
; notes					You can draw a bitmap into the graphics of another bitmap

Gdip_GraphicsFromHDC(hdc)
	{
		DllCall("gdiplus\GdipCreateFromHDC", "uint", hdc, "uint*", pGraphics)
		return pGraphics
	}

;#####################################################################################

; Function				Gdip_GetDC
; Description			This function gets the device context of the passed Graphics
;
; hdc					This is the handle to the device context
;
; return				returns the device context for the graphics of a bitmap

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

;#####################################################################################

; Function				Gdip_ReleaseDC
; Description			This function releases a device context from use for further use
;
; pGraphics				Pointer to the graphics of a bitmap
; hdc					This is the handle to the device context
;
; return				status enumeration. 0 = success

Gdip_ReleaseDC(pGraphics, hdc)
	{
		return DllCall("gdiplus\GdipReleaseDC", "uint", pGraphics, "uint", hdc)
	}

;#####################################################################################

; Function				Gdip_GraphicsClear
; Description			Clears the graphics of a bitmap ready for further drawing
;
; pGraphics				Pointer to the graphics of a bitmap
; ARGB					The colour to clear the graphics to
;
; return				status enumeration. 0 = success
;
; notes					By default this will make the background invisible
;						Using clipping regions you can clear a particular area on the graphics rather than clearing the entire graphics

Gdip_GraphicsClear(pGraphics, ARGB=0x00ffffff)
	{
		return DllCall("gdiplus\GdipGraphicsClear", "uint", pGraphics, "int", ARGB)
	}

;#####################################################################################

; Function				Gdip_BlurBitmap
; Description			Gives a pointer to a blurred bitmap from a pointer to a bitmap
;
; pBitmap				Pointer to a bitmap to be blurred
; Blur					The Amount to blur a bitmap by from 1 (least blur) to 100 (most blur)
;
; return				If the function succeeds, the return value is a pointer to the new blurred bitmap
;						-1 = The blur parameter is outside the range 1-100
;
; notes					This function will not dispose of the original bitmap

Gdip_BlurBitmap(pBitmap, Blur)
	{
		If (Blur > 100) || (Blur < 1)
			return -1

		sWidth := Gdip_GetImageWidth(pBitmap), sHeight := Gdip_GetImageHeight(pBitmap)
		dWidth := sWidth//Blur, dHeight := sHeight//Blur

		pBitmap1 := Gdip_CreateBitmap(dWidth, dHeight)
		G1 := Gdip_GraphicsFromImage(pBitmap1)
		Gdip_SetInterpolationMode(G1, 7)
		Gdip_DrawImage(G1, pBitmap, 0, 0, dWidth, dHeight, 0, 0, sWidth, sHeight)

		Gdip_DeleteGraphics(G1)

		pBitmap2 := Gdip_CreateBitmap(sWidth, sHeight)
		G2 := Gdip_GraphicsFromImage(pBitmap2)
		Gdip_SetInterpolationMode(G2, 7)
		Gdip_DrawImage(G2, pBitmap1, 0, 0, sWidth, sHeight, 0, 0, dWidth, dHeight)

		Gdip_DeleteGraphics(G2)
		Gdip_DisposeImage(pBitmap1)
		return pBitmap2
	}

;#####################################################################################

; Function:     		Gdip_SaveBitmapToFile
; Description:  		Saves a bitmap to a file in any supported format onto disk
;
; pBitmap				Pointer to a bitmap
; sOutput      			The name of the file that the bitmap will be saved to. Supported extensions are: .BMP,.DIB,.RLE,.JPG,.JPEG,.JPE,.JFIF,.GIF,.TIF,.TIFF,.PNG
; Quality      			If saving as jpg (.JPG,.JPEG,.JPE,.JFIF) then quality can be 1-100 with default at maximum quality
;
; return      			If the function succeeds, the return value is zero, otherwise:
;						-1 = Extension supplied is not a supported file format
;						-2 = Could not get a list of encoders on system
;						-3 = Could not find matching encoder for specified file format
;						-4 = Could not get WideChar name of output file
;						-5 = Could not save file to disk
;
; notes					This function will use the extension supplied from the sOutput parameter to determine the output format

Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75)
	{
		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, "uint", &ci)
		If !(nCount && nSize)
			return -2

		Loop, %nCount%
		{
			Location := NumGet(ci, 76*(A_Index-1)+44)
			If !A_IsUnicode
			{
				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
			}
			Else
			{
				nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
				sString := ""
				Loop, %nSize%
					sString .= Chr(NumGet(Location+0, 2*(A_Index-1), "char"))
				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", "uint", pBitmap, "uint", pCodec, "uint*", nSize)
				VarSetCapacity(EncoderParameters, nSize, 0)
				DllCall("gdiplus\GdipGetEncoderParameterList", "uint", pBitmap, "uint", pCodec, "uint", nSize, "uint", &EncoderParameters)
				Loop, % NumGet(EncoderParameters)      ;%
				{
					If (NumGet(EncoderParameters, (28*(A_Index-1))+20) = 1) && (NumGet(EncoderParameters, (28*(A_Index-1))+24) = 6)
					{
						p := (28*(A_Index-1))+&EncoderParameters
						NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20)))
						break
					}
				}
			}
		}

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

;#####################################################################################

; Function				Gdip_GetPixel
; Description			Gets the ARGB of a pixel in a bitmap
;
; pBitmap				Pointer to a bitmap
; x						x-coordinate of the pixel
; y						y-coordinate of the pixel
;
; return				Returns the ARGB value of the pixel

Gdip_GetPixel(pBitmap, x, y)
	{
		DllCall("gdiplus\GdipBitmapGetPixel", "uint", pBitmap, "int", x, "int", y, "uint*", ARGB)
		return ARGB
	}

;#####################################################################################

; Function				Gdip_SetPixel
; Description			Sets the ARGB of a pixel in a bitmap
;
; pBitmap				Pointer to a bitmap
; x						x-coordinate of the pixel
; y						y-coordinate of the pixel
;
; return				status enumeration. 0 = success

Gdip_SetPixel(pBitmap, x, y, ARGB)
	{
		return DllCall("gdiplus\GdipBitmapSetPixel", "uint", pBitmap, "int", x, "int", y, "int", ARGB)
	}

;#####################################################################################

; Function				Gdip_GetImageWidth
; Description			Gives the width of a bitmap
;
; pBitmap				Pointer to a bitmap
;
; return				Returns the width in pixels of the supplied bitmap

Gdip_GetImageWidth(pBitmap)
	{
		DllCall("gdiplus\GdipGetImageWidth", "uint", pBitmap, "uint*", Width)
		return Width
	}

;#####################################################################################

; Function				Gdip_GetImageHeight
; Description			Gives the height of a bitmap
;
; pBitmap				Pointer to a bitmap
;
; return				Returns the height in pixels of the supplied bitmap

Gdip_GetImageHeight(pBitmap)
	{
		DllCall("gdiplus\GdipGetImageHeight", "uint", pBitmap, "uint*", Height)
		return Height
	}

;#####################################################################################

; Function				Gdip_GetDimensions
; Description			Gives the width and height of a bitmap
;
; pBitmap				Pointer to a bitmap
; Width					ByRef variable. This variable will be set to the width of the bitmap
; Height				ByRef variable. This variable will be set to the height of the bitmap
;
; return				No return value
;						Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the height

Gdip_GetDimensions(pBitmap, ByRef Width, ByRef Height)
	{
		Width := Gdip_GetImageWidth(pBitmap)
		Height := Gdip_GetImageHeight(pBitmap)
	}

;#####################################################################################

Gdip_GetImagePixelFormat(pBitmap)
	{
		DllCall("gdiplus\GdipGetImagePixelFormat", "uint", pBitmap, "uint*", Format)
		return Format
	}

;#####################################################################################

; Function				Gdip_GetDpiX
; Description			Gives the horizontal dots per inch of the graphics of a bitmap
;
; pBitmap				Pointer to a bitmap
; Width					ByRef variable. This variable will be set to the width of the bitmap
; Height				ByRef variable. This variable will be set to the height of the bitmap
;
; return				No return value
;						Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the height

Gdip_GetDpiX(pGraphics)
	{
		DllCall("gdiplus\GdipGetDpiX", "uint", pGraphics, "float*", dpix)
		return Round(dpix)
	}

Gdip_GetDpiY(pGraphics)
	{
		DllCall("gdiplus\GdipGetDpiY", "uint", pGraphics, "float*", dpiy)
		return Round(dpiy)
	}

Gdip_GetImageHorizontalResolution(pBitmap)
	{
		DllCall("gdiplus\GdipGetImageHorizontalResolution", "uint", pBitmap, "float*", dpix)
		return Round(dpix)
	}

Gdip_GetImageVerticalResolution(pBitmap)
	{
		DllCall("gdiplus\GdipGetImageVerticalResolution", "uint", pBitmap, "float*", dpiy)
		return Round(dpiy)
	}

Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize="")
	{
		SplitPath, sFile,,, ext
		If ext in exe,dll
		{
			Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16
			VarSetCapacity(buf, 40)
			Loop, Parse, Sizes, |
			{
				DllCall("PrivateExtractIcons", "str", sFile, "int", IconNumber-1, "int", A_LoopField, "int", A_LoopField, "uint*", hIcon, "uint*", 0, "uint", 1, "uint", 0)
				If !hIcon
					continue

				If !DllCall("GetIconInfo", "uint", hIcon, "uint", &buf)
				{
					DestroyIcon(hIcon)
					continue
				}
				hbmColor := NumGet(buf, 16)
				hbmMask  := NumGet(buf, 12)

				If !(hbmColor && DllCall("GetObject", "uint", hbmColor, "int", 24, "uint", &buf))
				{
					DestroyIcon(hIcon)
					continue
				}
				break
			}
			If !hIcon
				return -1

			Width := NumGet(buf, 4, "int"),  Height := NumGet(buf, 8, "int")
			hbm := CreateDIBSection(Width, -Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)

			If !DllCall("DrawIconEx", "uint", hdc, "int", 0, "int", 0, "uint", hIcon, "uint", Width, "uint", Height, "uint", 0, "uint", 0, "uint", 3)
			{
				DestroyIcon(hIcon)
				return -2
			}

			VarSetCapacity(dib, 84)
			DllCall("GetObject", "uint", hbm, "int", 84, "uint", &dib)
			Stride := NumGet(dib, 12), Bits := NumGet(dib, 20)

			DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", Stride, "int", 0x26200A, "uint", Bits, "uint*", pBitmapOld)
			pBitmap := Gdip_CreateBitmap(Width, Height), G := Gdip_GraphicsFromImage(pBitmap)
			Gdip_DrawImage(G, pBitmapOld, 0, 0, Width, Height, 0, 0, Width, Height)
			SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
			Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmapOld)
			DestroyIcon(hIcon)
		}
		Else
		{
			If !A_IsUnicode
			{
				VarSetCapacity(wFile, 1023)
				DllCall("kernel32\MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &sFile, "int", -1, "uint", &wFile, "int", 512)
				DllCall("gdiplus\GdipCreateBitmapFromFile", "uint", &wFile, "uint*", pBitmap)
			}
			Else
				DllCall("gdiplus\GdipCreateBitmapFromFile", "uint", &sFile, "uint*", pBitmap)
		}
		return pBitmap
	}

Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)
	{
		DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "uint", hBitmap, "uint", Palette, "uint*", pBitmap)
		return pBitmap
	}

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

Gdip_CreateBitmapFromHICON(hIcon)
	{
		DllCall("gdiplus\GdipCreateBitmapFromHICON", "uint", hIcon, "uint*", pBitmap)
		return pBitmap
	}

Gdip_CreateHICONFromBitmap(pBitmap)
	{
		DllCall("gdiplus\GdipCreateHICONFromBitmap", "uint", pBitmap, "uint*", hIcon)
		return hIcon
	}

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

Gdip_CreateBitmapFromClipboard()
	{
		If !DllCall("OpenClipboard", "uint", 0)
			return -1
		If !DllCall("IsClipboardFormatAvailable", "uint", 8)
			return -2
		If !hBitmap := DllCall("GetClipboardData", "uint", 2)
			return -3
		If !pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap)
			return -4
		If !DllCall("CloseClipboard")
			return -5
		DeleteObject(hBitmap)
		return pBitmap
	}

Gdip_SetBitmapToClipboard(pBitmap)
	{
		hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
		DllCall("GetObject", "uint", hBitmap, "int", VarSetCapacity(oi, 84, 0), "uint", &oi)
		hdib := DllCall("GlobalAlloc", "uint", 2, "uint", 40+NumGet(oi, 44))
		pdib := DllCall("GlobalLock", "uint", hdib)
		DllCall("RtlMoveMemory", "uint", pdib, "uint", &oi+24, "uint", 40)
		DllCall("RtlMoveMemory", "Uint", pdib+40, "Uint", NumGet(oi, 20), "uint", NumGet(oi, 44))
		DllCall("GlobalUnlock", "uint", hdib)
		DllCall("DeleteObject", "uint", hBitmap)
		DllCall("OpenClipboard", "uint", 0)
		DllCall("EmptyClipboard")
		DllCall("SetClipboardData", "uint", 8, "uint", hdib)
		DllCall("CloseClipboard")
	}

Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format=0x26200A)
	{
		DllCall("gdiplus\GdipCloneBitmapArea", "float", x, "float", y, "float", w, "float", h
		        , "int", Format, "uint", pBitmap, "uint*", pBitmapDest)
		return pBitmapDest
	}

;#####################################################################################
; Create resources
;#####################################################################################

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

Gdip_CreatePenFromBrush(pBrush, w)
	{
		DllCall("gdiplus\GdipCreatePen2", "uint", pBrush, "float", w, "int", 2, "uint*", pPen)
		return pPen
	}

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

; HatchStyleHorizontal = 0
; HatchStyleVertical = 1
; HatchStyleForwardDiagonal = 2
; HatchStyleBackwardDiagonal = 3
; HatchStyleCross = 4
; HatchStyleDiagonalCross = 5
; HatchStyle05Percent = 6
; HatchStyle10Percent = 7
; HatchStyle20Percent = 8
; HatchStyle25Percent = 9
; HatchStyle30Percent = 10
; HatchStyle40Percent = 11
; HatchStyle50Percent = 12
; HatchStyle60Percent = 13
; HatchStyle70Percent = 14
; HatchStyle75Percent = 15
; HatchStyle80Percent = 16
; HatchStyle90Percent = 17
; HatchStyleLightDownwardDiagonal = 18
; HatchStyleLightUpwardDiagonal = 19
; HatchStyleDarkDownwardDiagonal = 20
; HatchStyleDarkUpwardDiagonal = 21
; HatchStyleWideDownwardDiagonal = 22
; HatchStyleWideUpwardDiagonal = 23
; HatchStyleLightVertical = 24
; HatchStyleLightHorizontal = 25
; HatchStyleNarrowVertical = 26
; HatchStyleNarrowHorizontal = 27
; HatchStyleDarkVertical = 28
; HatchStyleDarkHorizontal = 29
; HatchStyleDashedDownwardDiagonal = 30
; HatchStyleDashedUpwardDiagonal = 31
; HatchStyleDashedHorizontal = 32
; HatchStyleDashedVertical = 33
; HatchStyleSmallConfetti = 34
; HatchStyleLargeConfetti = 35
; HatchStyleZigZag = 36
; HatchStyleWave = 37
; HatchStyleDiagonalBrick = 38
; HatchStyleHorizontalBrick = 39
; HatchStyleWeave = 40
; HatchStylePlaid = 41
; HatchStyleDivot = 42
; HatchStyleDottedGrid = 43
; HatchStyleDottedDiamond = 44
; HatchStyleShingle = 45
; HatchStyleTrellis = 46
; HatchStyleSphere = 47
; HatchStyleSmallGrid = 48
; HatchStyleSmallCheckerBoard = 49
; HatchStyleLargeCheckerBoard = 50
; HatchStyleOutlinedDiamond = 51
; HatchStyleSolidDiamond = 52
; HatchStyleTotal = 53
Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0)
	{
		DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "int", ARGBfront, "int", ARGBback, "uint*", pBrush)
		return pBrush
	}

;GpStatus WINGDIPAPI GdipCreateTexture2I(GpImage *image, GpWrapMode wrapmode, INT x, INT y, INT width, INT height, GpTexture **texture)
;GpStatus WINGDIPAPI GdipCreateTexture2(GpImage *image, GpWrapMode wrapmode, REAL x, REAL y, REAL width, REAL height, GpTexture **texture)
;GpStatus WINGDIPAPI GdipCreateTexture(GpImage *image, GpWrapMode wrapmode, GpTexture **texture)

Gdip_CreateTextureBrush(pBitmap, WrapMode=1, x=0, y=0, w="", h="")
	{
		If !(w && h)
			DllCall("gdiplus\GdipCreateTexture", "uint", pBitmap, "int", WrapMode, "uint*", pBrush)
		Else
			DllCall("gdiplus\GdipCreateTexture2", "uint", pBitmap, "int", WrapMode, "float", x, "float", y, "float", w, "float", h, "uint*", pBrush)
		return pBrush
	}

; WrapModeTile = 0
; WrapModeTileFlipX = 1
; WrapModeTileFlipY = 2
; WrapModeTileFlipXY = 3
; WrapModeClamp = 4
Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode=1)
	{
		CreatePointF(PointF1, x1, y1), CreatePointF(PointF2, x2, y2)
		DllCall("gdiplus\GdipCreateLineBrush", "uint", &PointF1, "uint", &PointF2, "int", ARGB1, "int", ARGB2, "int", WrapMode, "uint*", LGpBrush)
		return LGpBrush
	}

; LinearGradientModeHorizontal = 0
; LinearGradientModeVertical = 1
; LinearGradientModeForwardDiagonal = 2
; LinearGradientModeBackwardDiagonal = 3
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_CloneBrush(pBrush)
	{
		static pNewBrush
		VarSetCapacity(pNewBrush, 288, 0)
		DllCall("RtlMoveMemory", "uint", &pNewBrush, "uint", pBrush, "uint", 288)
		VarSetCapacity(pNewBrush, -1)
		return &pNewBrush
	}

;#####################################################################################
; Delete resources
;#####################################################################################

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_DisposeImageAttributes(ImageAttr)
	{
		return DllCall("gdiplus\GdipDisposeImageAttributes", "uint", ImageAttr)
	}

Gdip_DeleteFont(hFont)
	{
		return DllCall("gdiplus\GdipDeleteFont", "uint", hFont)
	}

Gdip_DeleteStringFormat(hFormat)
	{
		return DllCall("gdiplus\GdipDeleteStringFormat", "uint", hFormat)
	}

Gdip_DeleteFontFamily(hFamily)
	{
		return DllCall("gdiplus\GdipDeleteFontFamily", "uint", hFamily)
	}

Gdip_DeleteMatrix(Matrix)
	{
		return DllCall("gdiplus\GdipDeleteMatrix", "uint", Matrix)
	}

;#####################################################################################
; Text functions
;#####################################################################################

Gdip_TextToGraphics(pGraphics, Text, Options, Font="Arial", Width="", Height="", Measure=0)
	{
		IWidth := Width, IHeight:= Height

		RegExMatch(Options, "i)X([\-\d\.]+)(p*)", xpos)
		RegExMatch(Options, "i)Y([\-\d\.]+)(p*)", ypos)
		RegExMatch(Options, "i)W([\-\d\.]+)(p*)", Width)
		RegExMatch(Options, "i)H([\-\d\.]+)(p*)", Height)
		RegExMatch(Options, "i)C(?!(entre|enter))([a-f\d]+)", Colour)
		RegExMatch(Options, "i)Top|Up|Bottom|Down|vCentre|vCenter", vPos)
		RegExMatch(Options, "i)R(\d)", Rendering)
		RegExMatch(Options, "i)S(\d+)(p*)", Size)

		If !Gdip_DeleteBrush(Gdip_CloneBrush(Colour2))
			PassBrush := 1, pBrush := Colour2

		If !(IWidth && IHeight) && (xpos2 || ypos2 || Width2 || Height2 || Size2)
			return -1

		Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
		Loop, Parse, Styles, |
		{
			If RegExMatch(Options, "\b" A_loopField)
				Style |= (A_LoopField != "StrikeOut") ? (A_Index-1) : 8
		}

		Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
		Loop, Parse, Alignments, |
		{
			If RegExMatch(Options, "\b" A_loopField)
				Align |= A_Index//2.1      ; 0|0|1|1|2|2
		}

		xpos := (xpos1 != "") ? xpos2 ? IWidth*(xpos1/100) : xpos1 : 0
		ypos := (ypos1 != "") ? ypos2 ? IHeight*(ypos1/100) : ypos1 : 0
		Width := Width1 ? Width2 ? IWidth*(Width1/100) : Width1 : IWidth
		Height := Height1 ? Height2 ? IHeight*(Height1/100) : Height1 : IHeight
		If !PassBrush
			Colour := "0x" (Colour2 ? Colour2 : "ff000000")
		Rendering := ((Rendering1 >= 0) && (Rendering1 <= 5)) ? Rendering1 : 4
		Size := (Size1 > 0) ? Size2 ? IHeight*(Size1/100) : Size1 : 12

		hFamily := Gdip_FontFamilyCreate(Font)
		hFont := Gdip_FontCreate(hFamily, Size, Style)
		hFormat := Gdip_StringFormatCreate(0x4000)
		pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)
		If !(hFamily && hFont && hFormat && pBrush && pGraphics)
			return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0

		CreateRectF(RC, xpos, ypos, Width, Height)
		Gdip_SetStringFormatAlign(hFormat, Align)
		Gdip_SetTextRenderingHint(pGraphics, Rendering)
		ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)

		If vPos
		{
			StringSplit, ReturnRC, ReturnRC, |

			If (vPos = "vCentre") || (vPos = "vCenter")
				ypos += (Height-ReturnRC4)//2
			Else If (vPos = "Top") || (vPos = "Up")
				ypos := 0
			Else If (vPos = "Bottom") || (vPos = "Down")
				ypos := Height-ReturnRC4

			CreateRectF(RC, xpos, ypos, Width, ReturnRC4)
			ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)
		}

		If !Measure
			E := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

		If !PassBrush
			Gdip_DeleteBrush(pBrush)
		Gdip_DeleteStringFormat(hFormat)
		Gdip_DeleteFont(hFont)
		Gdip_DeleteFontFamily(hFamily)
		return E ? E : ReturnRC
	}

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

Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
	{
		VarSetCapacity(RC, 16)
		If !A_IsUnicode
		{
			nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &sString, "int", -1, "uint", 0, "int", 0)
			VarSetCapacity(wString, nSize*2)
			DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &sString, "int", -1, "uint", &wString, "int", nSize)
			DllCall("gdiplus\GdipMeasureString", "uint", pGraphics
			        , "uint", &wString, "int", -1, "uint", hFont, "uint", &RectF, "uint", hFormat, "uint", &RC, "uint*", Chars, "uint*", Lines)
		}
		Else
		{
			DllCall("gdiplus\GdipMeasureString", "uint", pGraphics
			        , "uint", &sString, "int", -1, "uint", hFont, "uint", &RectF, "uint", hFormat, "uint", &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
	}

; Near = 0
; Center = 1
; Far = 2
Gdip_SetStringFormatAlign(hFormat, Align)
	{
		return DllCall("gdiplus\GdipSetStringFormatAlign", "uint", hFormat, "int", Align)
	}

Gdip_StringFormatCreate(Format=0, Lang=0)
	{
		DllCall("gdiplus\GdipCreateStringFormat", "int", Format, "int", Lang, "uint*", hFormat)
		return hFormat
	}

; Regular = 0
; Bold = 1
; Italic = 2
; BoldItalic = 3
; Underline = 4
; Strikeout = 8
Gdip_FontCreate(hFamily, Size, Style=0)
	{
		DllCall("gdiplus\GdipCreateFont", "uint", hFamily, "float", Size, "int", Style, "int", 0, "uint*", hFont)
		return hFont
	}

Gdip_FontFamilyCreate(Font)
	{
		If !A_IsUnicode
		{
			nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &Font, "int", -1, "uint", 0, "int", 0)
			VarSetCapacity(wFont, nSize*2)
			DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &Font, "int", -1, "uint", &wFont, "int", nSize)
			DllCall("gdiplus\GdipCreateFontFamilyFromName", "uint", &wFont, "uint", 0, "uint*", hFamily)
		}
		Else
			DllCall("gdiplus\GdipCreateFontFamilyFromName", "uint", &Font, "uint", 0, "uint*", hFamily)
		return hFamily
	}

;#####################################################################################
; Matrix functions
;#####################################################################################

Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y)
	{
		DllCall("gdiplus\GdipCreateMatrix2", "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y, "uint*", Matrix)
		return Matrix
	}

Gdip_CreateMatrix()
	{
		DllCall("gdiplus\GdipCreateMatrix", "uint*", Matrix)
		return Matrix
	}

;#####################################################################################
; GraphicsPath functions
;#####################################################################################

; Alternate = 0
; Winding = 1
Gdip_CreatePath(BrushMode=0)
	{
		DllCall("gdiplus\GdipCreatePath", "int", BrushMode, "uint*", Path)
		return Path
	}

Gdip_AddPathEllipse(Path, x, y, w, h)
	{
		return DllCall("gdiplus\GdipAddPathEllipse", "uint", Path, "float", x, "float", y, "float", w, "float", h)
	}

Gdip_AddPathPolygon(Path, Points)
	{
		StringSplit, Points, Points, |
		VarSetCapacity(PointF, 8*Points0)
		Loop, %Points0%
		{
			StringSplit, Coord, Points%A_Index%, `,
			NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
		}

		return DllCall("gdiplus\GdipAddPathPolygon", "uint", Path, "uint", &PointF, "int", Points0)
	}

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

;#####################################################################################
; Quality functions
;#####################################################################################

; SystemDefault = 0
; SingleBitPerPixelGridFit = 1
; SingleBitPerPixel = 2
; AntiAliasGridFit = 3
; AntiAlias = 4
Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
	{
		return DllCall("gdiplus\GdipSetTextRenderingHint", "uint", pGraphics, "int", RenderingHint)
	}

; Default = 0
; LowQuality = 1
; HighQuality = 2
; Bilinear = 3
; Bicubic = 4
; NearestNeighbor = 5
; HighQualityBilinear = 6
; HighQualityBicubic = 7
Gdip_SetInterpolationMode(pGraphics, InterpolationMode)
	{
		return DllCall("gdiplus\GdipSetInterpolationMode", "uint", pGraphics, "int", InterpolationMode)
	}

; Default = 0
; HighSpeed = 1
; HighQuality = 2
; None = 3
; AntiAlias = 4
Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
	{
		return DllCall("gdiplus\GdipSetSmoothingMode", "uint", pGraphics, "int", SmoothingMode)
	}

; CompositingModeSourceOver = 0 (blended)
; CompositingModeSourceCopy = 1 (overwrite)
Gdip_SetCompositingMode(pGraphics, CompositingMode=0)
	{
		return DllCall("gdiplus\GdipSetCompositingMode", "uint", pGraphics, "int", CompositingMode)
	}

;#####################################################################################
; Extra functions
;#####################################################################################

Gdip_Startup()
	{
		If !DllCall("GetModuleHandle", "str", "gdiplus")
			DllCall("LoadLibrary", "str", "gdiplus")
		VarSetCapacity(si, 16, 0), si := Chr(1)
		DllCall("gdiplus\GdiplusStartup", "uint*", pToken, "uint", &si, "uint", 0)
		return pToken
	}

Gdip_Shutdown(pToken)
	{
		DllCall("gdiplus\GdiplusShutdown", "uint", pToken)
		If hModule := DllCall("GetModuleHandle", "str", "gdiplus")
			DllCall("FreeLibrary", "uint", hModule)
		return 0
	}

; Prepend = 0; The new operation is applied before the old operation.
; Append = 1; The new operation is applied after the old operation.
Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder=0)
	{
		return DllCall("gdiplus\GdipRotateWorldTransform", "uint", pGraphics, "float", Angle, "int", MatrixOrder)
	}

Gdip_ScaleWorldTransform(pGraphics, x, y, MatrixOrder=0)
	{
		return DllCall("gdiplus\GdipScaleWorldTransform", "uint", pGraphics, "float", x, "float", y, "int", MatrixOrder)
	}

Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder=0)
	{
		return DllCall("gdiplus\GdipTranslateWorldTransform", "uint", pGraphics, "float", x, "float", y, "int", MatrixOrder)
	}

Gdip_ResetWorldTransform(pGraphics)
	{
		return DllCall("gdiplus\GdipResetWorldTransform", "uint", pGraphics)
	}

Gdip_GetRotatedTranslation(Width, Height, Angle, ByRef xTranslation, ByRef yTranslation)
	{
		pi := 3.14159, TAngle := Angle*(pi/180)

		Bound := (Angle >= 0) ? Mod(Angle, 360) : 360-Mod(-Angle, -360)
		If ((Bound >= 0) && (Bound <= 90))
			xTranslation := Height*Sin(TAngle), yTranslation := 0
		Else If ((Bound > 90) && (Bound <= 180))
			xTranslation := (Height*Sin(TAngle))-(Width*Cos(TAngle)), yTranslation := -Height*Cos(TAngle)
		Else If ((Bound > 180) && (Bound <= 270))
			xTranslation := -(Width*Cos(TAngle)), yTranslation := -(Height*Cos(TAngle))-(Width*Sin(TAngle))
		Else If ((Bound > 270) && (Bound <= 360))
			xTranslation := 0, yTranslation := -Width*Sin(TAngle)
	}

Gdip_GetRotatedDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight)
	{
		pi := 3.14159, TAngle := Angle*(pi/180)
		If !(Width && Height)
			return -1
		RWidth := Ceil(Abs(Width*Cos(TAngle))+Abs(Height*Sin(TAngle)))
		RHeight := Ceil(Abs(Width*Sin(TAngle))+Abs(Height*Cos(Tangle)))
	}

; Replace = 0
; Intersect = 1
; Union = 2
; Xor = 3
; Exclude = 4
; Complement = 5
Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0)
	{
		return DllCall("gdiplus\GdipSetClipRect", "uint", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
	}

Gdip_SetClipPath(pGraphics, Path, CombineMode=0)
	{
		return DllCall("gdiplus\GdipSetClipPath", "uint", pGraphics, "uint", Path, "int", CombineMode)
	}

Gdip_ResetClip(pGraphics)
	{
		return DllCall("gdiplus\GdipResetClip", "uint", pGraphics)
	}

Gdip_GetClipRegion(pGraphics)
	{
		Region := Gdip_CreateRegion()
		DllCall("gdiplus\GdipGetClip", "uint" pGraphics, "uint*", Region)
		return Region
	}

Gdip_SetClipRegion(pGraphics, Region, CombineMode=0)
	{
		return DllCall("gdiplus\GdipSetClipRegion", "uint", pGraphics, "uint", Region, "int", CombineMode)
	}

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

Gdip_DeleteRegion(Region)
	{
		return DllCall("gdiplus\GdipDeleteRegion", "uint", Region)
	}



RC4txt2hex(Data,Pass) {
		Format := A_FormatInteger
		SetFormat Integer, Hex
		b := 0, j := 0
		VarSetCapacity(Result,StrLen(Data)*2)
		Loop 256
			a := A_Index - 1
		        ,Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1))
		        ,sBox%a% := a
		Loop 256
			a := A_Index - 1
		        ,b := b + sBox%a% + Key%a%  & 255
		        ,sBox%a% := (sBox%b%+0, sBox%b% := sBox%a%) ; SWAP(a,b)
		Loop Parse, Data
			i := A_Index & 255
		        ,j := sBox%i% + j  & 255
		        ,k := sBox%i% + sBox%j%  & 255
		        ,sBox%i% := (sBox%j%+0, sBox%j% := sBox%i%) ; SWAP(i,j)
		        ,Result .= SubStr(Asc(A_LoopField)^sBox%k%, -1, 2)
		StringReplace Result, Result, x, 0, All
		SetFormat Integer, %Format%
		Return Result
	}

RC4hex2txt(Data,Pass) {
		b := 0, j := 0, x := "0x"
		VarSetCapacity(Result,StrLen(Data)//2)
		Loop 256
			a := A_Index - 1
		        ,Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1))
		        ,sBox%a% := a
		Loop 256
			a := A_Index - 1
		        ,b := b + sBox%a% + Key%a%  & 255
		        ,sBox%a% := (sBox%b%+0, sBox%b% := sBox%a%) ; SWAP(a,b)
		Loop % StrLen(Data)//2
			i := A_Index  & 255
		        ,j := sBox%i% + j  & 255
		        ,k := sBox%i% + sBox%j%  & 255
		        ,sBox%i% := (sBox%j%+0, sBox%j% := sBox%i%) ; SWAP(i,j)
		        ,Result .= Chr((x . SubStr(Data,2*A_Index-1,2)) ^ sBox%k%)
		Return Result
	}




IPC_Send(Hwnd, Data="", Port=100, DataSize="") {
		static WM_COPYDATA = 74, INT_MAX=2147483647
		If Port not between 0 AND %INT_MAX%
			return A_ThisFunc "> Port number is not in a positive integer range: " Port

		If (DataSize = "")
			DataSize := StrLen(Data)+1, pData := &Data, Port := -Port			;use negative port for textual messages
		Else pData := Data

		VarSetCapacity(COPYDATA, 12)
		        , NumPut(Port,		COPYDATA, 0)
		        , NumPut(DataSize, COPYDATA, 4)
		        , NumPut(pData,	COPYDATA, 8)

		Gui, +LastFound
		SendMessage, WM_COPYDATA, WinExist(), &COPYDATA,, ahk_id %Hwnd%
		return ErrorLevel="FAIL" ? false : true
	}

/*
Function:	 SetHandler
Set the data handler.

Parameters:
Handler - Function that will be called when data is received.

Handler:
>			 Handler(Hwnd, Data, Port, DataSize)

Hwnd	- Handle of the window passing data.
Data	- Data that is received.
Port	- Data port.
DataSize - If DataSize is not empty, Data is pointer to the actuall data. Otherwise Data is textual message.
*/
IPC_SetHandler( Handler ){
		static WM_COPYDATA = 74

		If !IsFunc( Handler )
			return A_ThisFunc "> Invalid handler: " Handler

		OnMessage(WM_COPYDATA, "IPC_onCopyData")
		IPC_onCopyData(Handler, "")
	}


IPC_onCopyData(WParam, LParam) {
		static Handler
		If Lparam =
			return  Handler := WParam

		port := NumGet(Lparam+0, 0, "Int"), data := NumGet(Lparam+8)
		If port < 0
			data := DllCall("MulDiv", "Int", data, "Int",1, "Int", 1, "str"), port := -port
		Else size := NumGet(LParam+4)

		%handler%(WParam, data, port, size)
		return 1
	}
mDesktopConfig.ahk

Code: Select all

/*
	Title:	mDesktopConfig
			*Set of window functions*
 */


/*
 Function:	Animate
 			Enables you to produce special effects when showing or hiding windows.
 
 Parameters:
 			Type		- White space separated list of animation flags. By default, these flags take effect when showing a window.
			Time		- Specifies how long it takes to play the animation, in millisecond .
 
 Animation types:
			activate	- Activates the window. Do not use this value with HIDE flag.
			blend		- Uses a fade effect. This flag can be used only if hwnd is a top-level window.
			center		- Makes the window appear to collapse inward if HIDE is used or expand outward if the HIDE is not used. The various direction flags have no effect.
			hide		- Hides the window. By default, the window is shown.
			slide		- Uses slide animation. Ignored when used with CENTER.
			:
			hneg		- Animates the window from right to left. This flag can be used with roll or slide animation. It is ignored when used with CENTER or BLEND.
			hpos		- Animates the window from left to right. This flag can be used with roll or slide animation. It is ignored when used with CENTER or BLEND.
			vneg		- Animates the window from top to bottom. This flag can be used with roll or slide animation. It is ignored when used with CENTER or BLEND.
			vpos		- Animates the window from bottom to top. This flag can be used with roll or slide animation. It is ignored when used with CENTER or BLEND.

 Remarks:
			When using slide or roll animation, you must specify the direction.
			You can combine HPOS or HNEG with VPOS or VNEG to animate a window diagonally.
			If a child window is displayed partially clipped, when it is animated it will have holes where it is clipped.
			Avoid animating a window that has a drop shadow because it produces visually distracting, jerky animations.

 Returns:
 			If the function succeeds, the return value is nonzero.
 
 Example:
		>  Win_Animate(hWnd, "hide blend", 500)
 
 */
Win_Animate(Hwnd, Type="", Time=100){
	static AW_ACTIVATE = 0x20000, AW_BLEND=0x80000, AW_CENTER=0x10, AW_HIDE=0x10000
			,AW_HNEG=0x2, AW_HPOS=0x1, AW_SLIDE=0x40000, AW_VNEG=0x8, AW_VPOS=0x4

	hFlags := 0
	loop, parse, Type, %A_Tab%%A_Space%, %A_Tab%%A_Space%
		ifEqual, A_LoopField,,continue
		else hFlags |= AW_%A_LoopField%

	ifEqual, hFlags, ,return "Err: Some of the types are invalid"
	DllCall("AnimateWindow", "uint", Hwnd, "uint", Time, "uint", hFlags)
}

/*
 Function:	FromPoint
 			Retrieves a handle to the top level window that contains the specified point.
 
 Parameters:
 			X, Y - Point. Use word "mouse" as X to use mouse coordinates.
 */
Win_FromPoint(X="mouse", Y="") { 
	if X=mouse
		VarSetCapacity(POINT, 8), DllCall("GetCursorPos", "uint", &POINT), X := NumGet(POINT), Y := NumGet(POINT, 4)

	VarSetCapacity(POINT, 8), NumPut(X, POINT, 0, "Int"), NumPut(Y, POINT, 4, "Int")
	return DllCall("WindowFromPoint", &POINT)
}

/*
 Function:	Get
 			Get window information
 
 Parameters:
 			pQ			- List of query parameters.
			o1 .. o9	- Reference to output variables. R,L,B & N query parameters can return multiple outputs.
 
 Query:
 			C,I			- Class, pId.
			R,L,B,N		- One of the window rectangles: R (window Rectangle), L (cLient rectangle screen coordinates), B (ver/hor Border), N (captioN rect).
 						  N gives size of the caption regardless of the window style. These coordinates include all title-bar elements except the window menu.
						  The function returns x, y, w & h separated by space. 
						  For all 4 query parameters you can additionaly specify x,y,w,h arguments in any order (except Border which can have only x(hor) and y(ver) arguments) to
						  extract desired number into ouput variable.
 			S,E			- Style, Extended style
 		    P,A,O		- Parents handle, Ancestors handle, Owners handle
 			M			- Module full path (owner exe), unlike WinGet,,ProcessName which returns only name without path.
 			T			- Title for top level windows or Text for child windows
 
 Returns:
 			o1
 
 Examples:
 (start code)
  	Win_Get(hwnd, "CIT", class, pid, text)					;get class, pid and text
    Win_Get(hwnd, "RxwTC", x, w, t, c)						;get x & width attributes of window rect, title and class
  	Win_Get(hwnd, "RxywhCLxyTBy",wx,wy,ww,wh,c,lx,ly,t,b)	;get all 4 attributes of window rect, class, x & y of client rect, text and horizontal border height
    right := Win_Get(hwnd, "Rx") + Win_Get(hwnd, "Rw")		;first output is returned as function result so u can use function in expressions.
    Win_Get(hwnd, "Rxw", x, w), right := x+w				;the same as above but faster
    right := Win_Get(hwnd, "Rxw", x, w ) + w				;not recommended
 (end code)
 */
Win_Get(Hwnd, pQ="", ByRef o1="", ByRef o2="", ByRef o3="", ByRef o4="", ByRef o5="", ByRef o6="", ByRef o7="", ByRef o8="", ByRef o9="") {
	if pQ contains R,B,L
		VarSetCapacity(WI, 60, 0), NumPut(60, WI),  DllCall("GetWindowInfo", "uint", Hwnd, "uint", &WI)

	k := i := 0
	loop
	{
		i++, k++
		if (_ := SubStr(pQ, k, 1)) = ""
			break

		if !IsLabel("Win_Get_" _ )
			return A_ThisFunc "> Invalid query parameter: " _
		Goto %A_ThisFunc%_%_%

		Win_Get_C:
				WinGetClass, o%i%, ahk_id %hwnd%		
		continue

		Win_Get_I:
				WinGet, o%i%, PID, ahk_id20/08/2009 %hwnd%		
		continue

		Win_Get_N:
				rect := "title"
				VarSetCapacity(TBI, 44, 0), NumPut(44, TBI, 0), DllCall("GetTitleBarInfo", "uint", hwnd, "str", TBI)
				title_x := NumGet(TBI, 4, "Int"), title_y := NumGet(TBI, 8, "Int"), title_w := NumGet(TBI, 12) - title_x, title_h := NumGet(TBI, 16) - title_y 
				goto Win_Get_Rect
		Win_Get_B:
				rect := "border"
				border_x := NumGet(WI, 48, "UInt"),  border_y := NumGet(WI, 52, "UInt")	
				goto Win_Get_Rect
		Win_Get_R:
				rect := "window"
				window_x := NumGet(WI, 4,  "Int"),  window_y := NumGet(WI, 8,  "Int"),  window_w := NumGet(WI, 12, "Int") - window_x,  window_h := NumGet(WI, 16, "Int") - window_y
				goto Win_Get_Rect
		Win_Get_L: 
				client_x := NumGet(WI, 20, "Int"),  client_y := NumGet(WI, 24, "Int"),  client_w := NumGet(WI, 28, "Int") - client_x,  client_h := NumGet(WI, 32, "Int") - client_y
				rect := "client"
		Win_Get_Rect:
				k++, arg := SubStr(pQ, k, 1)
				if arg in x,y,w,h
				{
					o%i% := %rect%_%arg%, j := i++
					goto Win_Get_Rect
				}
				else if !j
						  o%i% := %rect%_x " " %rect%_y  (_ = "B" ? "" : " " %rect%_w " " %rect%_h)
				
		rect := "", k--, i--, j := 0
		continue
		Win_Get_S:
			WinGet, o%i%, Style, ahk_id %Hwnd%
		continue
		Win_Get_E: 
			WinGet, o%i%, ExStyle, ahk_id %Hwnd%
		continue
		Win_Get_P: 
			o%i% := DllCall("GetParent", "uint", Hwnd)
		continue
		Win_Get_A: 
			o%i% := DllCall("GetAncestor", "uint", Hwnd, "uint", 2) ; GA_ROOT
		continue
		Win_Get_O: 
			o%i% := DllCall("GetWindowLong", "uint", Hwnd, "int", -8) ; GWL_HWNDPARENT
		continue
		Win_Get_T:
			if DllCall("IsChild", "uint", hwnd)
				 WinGetText, o%i%, ahk_id %hwnd%
			else WinGetTitle, o%i%, ahk_id %hwnd%
		continue
		Win_Get_M: 
			WinGet, _, PID, ahk_id %hwnd%
			hp := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", _ ) 
			if (ErrorLevel or !hp) 
				continue
			VarSetCapacity(buf, 512, 0), DllCall( "psapi.dll\GetModuleFileNameExA", "uint", hp, "uint", 0, "str", buf, "uint", 512),  DllCall( "CloseHandle", hp ) 
			o%i% := buf 
		continue
	}	
	
	return o1
}

/*
 Function:	GetRect
 			Get window rectangle.
 
 Parameters:
 			hwnd		- Window handle
			pQ			- Query parameter: ordered list of x, y, w and h characters. If you specify * as first char rectangle will be raltive to the client area of window's parent.
						  Leave pQ empty or "*" to return all attributes separated by space.
			o1 .. o4	- Reference to output variables. 

 Returns:
			o1

 Remarks:
			This function is faster alternative to <Get> with R parameter. However, if you query additional window info using <Get>, it may be faster and definitely more 
			convenient then obtaining the info using alternatives. 
			Besides that, you can't use <Get> to obtain relative coordinates of child windows.

 Examples:
	(start code)
  			Win_GetRect(hwnd, "xw", x, w)		;get x & width
  			Win_GetRect(hwnd, "yhx", y, h, x)	;get y, height, and x
  			p := Win_GetRect(hwnd, "x") + 5		;for single query parameter you don't need output variable as function returns o1
  			all := Win_GetRect(hwnd)			;return all
  			Win_Get(hwnd, "*hx", h, x)			;return relative h and x
  			all_rel := WiN_Get(hwnd, "*")		;return all relative coorinates
	(end code)
 */
Win_GetRect(hwnd, pQ="", ByRef o1="", ByRef o2="", ByRef o3="", ByRef o4="") {
	VarSetCapacity(RECT, 16), r := DllCall("GetWindowRect", "uint", hwnd, "uint", &RECT)
	ifEqual, r, 0, return

	if (pQ = "") or pQ = ("*")
		retAll := true,  pQ .= "xywh"

	xx := NumGet(RECT, 0, "Int"), yy := NumGet(RECT, 4, "Int")
	if SubStr(pQ, 1, 1) = "*"
	{
		Win_Get(DllCall("GetParent", "uint", hwnd), "Lxy", lx, ly), xx -= lx, yy -= ly
		StringTrimLeft, pQ, pQ, 1
	}
	
	loop, parse, pQ
		if A_LoopField = x
			o%A_Index% := xx
		else if A_LoopField = y
			o%A_Index% := yy
		else if A_LoopField = w
			o%A_Index% := NumGet(RECT, 8, "Int") - xx - ( lx ? lx : 0)
		else if A_LoopField = h
			o%A_Index% := NumGet(RECT, 12, "Int") - yy - ( ly ? ly : 0 )

	return retAll ? o1 " " o2 " " o3 " " o4 : o1
}


/*
 Function:	Is
 			Checks handle against specified criterium.
 
 Parameters:
			pQ			- Query parameter.

 Query:
			win			- True if handle is window.
			child		- True if handle is child window.
			enabled		- True if window is enabled.
			visible		- True if window is visible.
			max			- True if window is maximized.
			hung		- True if window is hung and doesn't respond to messages.

 Returns:
			TRUE or FALSE
 */
Win_Is(Hwnd, pQ="win") {
	static is_win = "IsWindow", is_child="IsChild", is_enabled="IsWindowEnabled", is_visible="IsWindowVisible", is_max = "IsZoomed", is_hung = "IsHungAppWindow"
	fun := "is_" pQ, fun := %fun%

	ifEqual, fun, , return A_ThisFunc "> Invalid query parameter: " pQ
	return DllCall(fun, "uint", Hwnd)
}

/*
 Function:	Move
			Change the size and position of a child, pop-up, or top-level window.
	
 Parameters:
			X..H		- Size / position. You can omit any parameter to keep its current value.
			Flags		- Can be R or A.

 Flags:
			R - Does not redraw changes. If this flag is set, no repainting of any kind occurs. 
			A - Asynchronous mode - if the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.

 Returns:
			True if successful, False otherwise.

 Remarks:
			Does not produce the same effect as ControlMove on child windows. Mentioned AHK function puts child window relative to the ancestor window rectangle 
			while Win_Move puts it relative to the parent's client rectangle which is usually the wanted behavior.
			WinMove produces the same effect as Win_Move on child controls, except its X and Y parameters are not optional which makes lot of addtional code for frequent operation: moving the control by some offset of its current position. 
			In order to do that you must get the current position of the control. That can be done with ControlGetPos which works in pair with ControlMove hence it is not relative to the client rect or WinGetPos which returns screen coordinates of child control so those can not 
			be imediatelly used in WinMove as it positions child window relative to the parents client rect. This scenario can be additionaly complicated by the fact that each window may have its own theme which influences the size of its borders, non client area, etc...

 */
Win_Move(Hwnd, X="", Y="", W="", H="", Flags="") {
;	static SWP_NOMOVE=2, SWP_NOREDRAW=8, SWP_NOSIZE=1, SWP_NOZORDER=4, SWP_NOACTIVATE = 0x10, SWP_ASYNCWINDOWPOS=0x4000, HWND_BOTTOM=1, HWND_TOPMOST=-1, HWND_NOTOPMOST = -2
	static SWP_NOMOVE=2, SWP_NOSIZE=1, SWP_NOZORDER=4, SWP_NOACTIVATE = 0x10, SWP_R=8, SWP_A=0x4000

	hFlags := SWP_NOZORDER | SWP_NOACTIVATE
	loop, parse, Flags
		hFlags |= SWP_%A_LoopField%
		
	if (x y != "") {
		p := DllCall("GetParent", "uint", hwnd), Win_Get(p, "Lxy", px, py), Win_GetRect(hwnd, "xywh", cx, cy, cw, ch)
		if x=
			x := cx - px
		if y=
			y := cy - py
	} else hFlags |= SWP_NOMOVE

	if (h w != "") {
		if !cx
			Win_GetRect(hwnd, "wh", cw, ch)
		if w=
			w := cw
		if h=
			h := ch
	} else  hFlags |= SWP_NOSIZE

	return DllCall("SetWindowPos", "uint", Hwnd, "uint", 0, "int", x, "int", y, "int", w, "int", h, "uint", hFlags)
}

/*
 Function:	MoveDelta
 			Move the window by specified amount.
 
 Parameters:
			Xd .. Hd - Delta to add to each window rect property. Skipped properties will not be changed.
			Flags	 - The same as in <Move>.

 Returns:
			True if successful, False otherwise.
 */

Win_MoveDelta( Hwnd, Xd="", Yd="", Wd="", Hd="", Flags="" ) {
	Win_GetRect(Hwnd, "*xywh", cx, cy, cw, ch)
	return Win_Move( Hwnd, cx+Xd, cy+Yd, cw+Wd, ch+Hd, flags)
}

/* 
  Function:	Recall
			Store & recall window position, size and/or state.

  Parameters:
		Options		- White space separated list of options. See bellow.		
		Hwnd		- Hwnd of the window for which to store data or Gui number if AHK window. 
					If omitted, function will use Hwnd of the default AHK Gui. You can also use Gui, N:Default 
					prior to calling the function. For 3td party windows, this parameter is mandatory. 
					Set 0 as hwnd to return position string without applying it to any window. This can be used for AHK Guis to
					calculate size of controls based on window size and position, when needed. 

		IniFileName	- Ini file to use as storage. Function will save the data under the [Recall] section.
					If omited, Windows Registry key HKEY_CURRENT_USER\AutoHotKey\Win is used. Each script is uniquely determined by its full path 
					so same scripts with different name will not share the storage.
					
  Options:
		">", "<", "-", "--" - Operation, mandatory option. Use ">" to store or "<" to recall window position.
					It can be optionally followed by the string representing the name of the storage location for that window.
					You need to use name if your script stores more then one window, otherwise it will be saved under unnamed location.
					">" and "<" are special names that can be used to store or recall all AHK Guis.
					"-"	operation is used alone as an argument to delete Registry or Ini sections belonging to the script.
					"--" operation is used alone as an argument to delete all Registry entries for all scripts.

		
		-Min	  - Don't save minimize state.
		-Max	  - Don't save maximized state.		
					
  Returns:
			Position string, space separated list of syntax "left top right bottom state cw ch" of the window. 
			Empty if no recall data is stored for the window.
			State can be 1 (normal) 2 (minimized) or 3 (maximized).
			cw & ch numbers are present only for AHK Guis and represent client width & height which can be used 
			without modifications in Gui, Show command.

  Examples:
		Single Gui Example:
		(start code)
		 Gui, +Resize +LastFound
		 WinSetTitle, MyGui
		 if !Win_Recall("<")                     ;Recall gui if its position is already saved
			Gui, Show, h300 w300, MyGui         ; otherwise use these defaults.
		return

		GuiClose:
			Win_Recall(">")                     ;Store the Gui.
			ExitApp
		return
		(end code)

		Snippets:
		(start code)
			Win_Recall(">MyGui")					;Save position for default Gui under name MyGui.
			Win_Recall("<MyGui")					;Recall position for MyGui for default Gui
			
			Win_Recall(">MyGui2", Hwnd)				;Save window position under MyGui2 name, given the window handle or Gui number.
			Win_Recall(">>")						;Save all Guis. The names will be given by their number.
			Win_Recall("<<")						;Recall all Guis.

			Win_Recall("-")							;Delete all Registry enteries for the script.
			Win_Recall("--")						;Delete all Registry enteries for all scripts.

			pos := Win_Recall("<MyWin", 0)			;Return position string only for window saved under the "MyWin" name.
		(end code)
 */
Win_Recall(Options, Hwnd="", IniFileName=""){
	static key="Software\AutoHotkey\Win", section="Recall"

	if (Options = "-"){
		ifNotEqual, IniFileName,, IniDelete, %IniFileName%, %section%
		else loop, HKEY_CURRENT_USER, %key%
			 InStr(A_LoopRegName, A_ScriptFullPath) ? 
				RegDelete, HKEY_CURRENT_USER, %key%, %A_LoopRegName%		
		return
	} else if (Options = "--") {
		RegDelete, HKEY_CURRENT_USER, %key%
		return
	}
	
	loop, parse, Options, %A_Space%%A_Tab%, %A_Space%%A_Tab%
	{
		ifEqual, A_LoopField, ,continue	
		f := SubStr(A_LoopField, 1, 1),  p := SubStr(A_LoopField, 2)

		ifEqual, f, >, SetEnv, op, % ">", name := p
		else ifEqual, f, <, SetEnv, op, % "<", name := p
		else ifEqual, A_LoopField, -Min, SetEnv, noMin, 1
		else ifEqual, A_LoopField, -Max, SetEnv, noMax, 1
	}

	if (Hwnd = "") || (Hwnd>0 && Hwnd <= 99) {
		ifEqual, Hwnd,, Gui, +LastFoundExist
		else Gui, %Hwnd%:+LastFound
		Hwnd := WinExist()
	}

	if name in <,>
	{		
		Loop, 99 {
			Gui, %A_Index%:+LastFoundExist
			if WinExist() {
				name := A_Index, Hwnd := WinExist()
				gosub %A_ThisFunc%
			}
		}
		return
	}	

 Win_Recall:
	if (op = "<") {
		if IniFileName !=
			 IniRead, pos, %IniFileName%, %section%, !%name%, %A_Space%
		else RegRead, pos, REG_SZ,  HKEY_CURRENT_USER, %key%, %A_ScriptFullPath%!%name%
		if (pos = "") or !Hwnd 
			return pos
		
		VarSetCapacity(WP, 44, 0),  NumPut(44,WP)
		StringSplit p, pos, %A_Space%
		p5 := (p5=2 && noMin) || (p5=3 && noMax) ? 1 : p5
		loop, 4
			NumPut(p%A_Index%, WP, (A_Index+6)*4, "Int")
		NumPut(p5, WP, 8, "UInt")
		DllCall("SetWindowPlacement", "uint", Hwnd, "uint", &WP)
	} 
	else if (op = ">"){			
		VarSetCapacity(WP, 44, 0),  NumPut(44,WP)
		DllCall("GetWindowPlacement", "uint", Hwnd, "uint", &WP)
		WinGetClass, cls, ahk_id %hwnd%
		if (cls="AutoHotkeyGUI")
			Win_Get(Hwnd, "Lwh",w,h),   szAHK := " " w " " h		;Store AHK client width & height so it can be used with Gui, Show.

		pos := ""
		loop, 4
			pos .= NumGet(WP, (A_Index+6)*4, "Int") " "
		s := NumGet(WP, 8, "UInt") 
		pos	.= (s != 0 ? s : 1) szAHK
		
		if IniFileName !=
			 IniWrite, %pos%, %IniFileName%, %section%, !%name%
		else RegWrite, REG_SZ,  HKEY_CURRENT_USER, %key%, %A_ScriptFullPath%!%name%, %pos%
	}	
  return pos
}

/*
 Function:	Redraw
 			Redraws the window.

 Parameters:
			Hwnd	- Handle of the window. If this parameter is omited, Redraw updates the desktop window.
			Option  - "-" to disable redrawing for the window. "+" to enable it and redraw it. By default empty.
 
 Returns:
			A nonzero value indicates success. Zero indicates failure.

 Remarks:
			This function will update the window for sure, unlike WinSet or InvalidateRect.
 */
Win_Redraw( Hwnd=0, Option="" ) {
	static WM_SETREDRAW=0xB, RDW_ALLCHILDREN:=0x80, RDW_ERASE:=0x4, RDW_ERASENOW:=0x200, RDW_FRAME:=0x400, RDW_INTERNALPAINT:=0x2, RDW_INVALIDATE:=0x1, RDW_NOCHILDREN:=0x40, RDW_NOERASE:=0x20, RDW_NOFRAME:=0x800, RDW_NOINTERNALPAINT:=0x10, RDW_UPDATENOW:=0x100, RDW_VALIDATE:=0x8

	if (Option != "") {
		old := A_DetectHiddenWindows
		DetectHiddenWindows, on
		bEnable := Option="+"
		SendMessage, 0xB, bEnable,,,ahk_id %Hwnd%
		DetectHiddenWindows, %old%
		ifEqual, bEnable, 0, return		
	}
	return DllCall("RedrawWindow", "uint", Hwnd, "uint", 0, "uint", 0, "uint" ,RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW | RDW_ALLCHILDREN)
}

/*
 Function:	SetCaption
 			Set visibility of the window caption.

 Parameters:
			Flag	- Set + to show the caption or - otherwise. If omited, caption will be toggled.
 */
Win_SetCaption(Hwnd, Flag="^"){
	oldDetect := A_DetectHiddenWindows
	DetectHiddenWindows, on
	WinSet, Style, %Flag%0xC00000
	DetectHiddenWindows, %oldDetect%
}

/*
 Function:	SetMenu
 			Set the window menu.
 
 Parameters:
			hMenu	- Handle of the menu to set for window. By default 0 means that menu will be removed.

 Returns:
			Handle of the previous menu.

 */
Win_SetMenu(Hwnd, hMenu=0){
	hPrevMenu := DllCall("GetMenu", "uint", hwnd, "Uint")
	DllCall("SetMenu", "uint", hwnd, "uint", hMenu)
	return hPrevMenu
}

/*
 Function:	SetIcon
 			Set the titlebar icon for the window.
 
 Parameters:
			Icon	- Path to the icon. If omited, icon is removed. If integer, handle to the already loaded icon.
			Flag	- 1 sets the large icon for the window, 0 sets the small icon for the window. 

 Returns:
			The return value is a handle to the previous large or small icon, depending on the Flag value.

 */
Win_SetIcon( Hwnd, Icon="", Flag=1){
	static WM_SETICON = 0x80, LR_LOADFROMFILE=0x10, IMAGE_ICON=1

	if Flag not in 0,1
		return A_ThisFunc "> Unsupported Flag: " Flag

	if Icon != 
		hIcon := Icon+0 != "" ? Icon : DllCall("LoadImage", "Uint", 0, "str", Icon, "uint",IMAGE_ICON, "int", 32, "int", 32, "uint", LR_LOADFROMFILE)  

	SendMessage, WM_SETICON, %Flag%, hIcon, , ahk_id %Hwnd%
	return ErrorLevel
}

/*
 Function:	SetParent
 			Changes the parent window of the specified window.
 
 Parameters:
			hParent	- Handle to the parent window. If this parameter is 0, the desktop window becomes the new parent window.

 Returns:
			If the function succeeds, the return value is a handle to the previous parent window.
 */
Win_SetParent(Hwnd, hParent=0){
	return DllCall("SetParent", "uint", Hwnd, "uint", hParent)
}


/*
 Function:	SetOwner
 			Changes the owner window of the specified window.
 
 Parameters:
			hOwner	- Handle to the owner window.

 Returns:
			Handle of the previous owner.

 Remarks:
			An owned window is always above its owner in the z-order. The system automatically destroys an owned window when its owner is destroyed. An owned window is hidden when its owner is minimized. 
			Only an overlapped or pop-up window can be an owner window; a child window cannot be an owner window.
 */

;Famous misleading statement. Almost as misleading as the choice of GWL_HWNDPARENT as the name. It has nothing to do with a window's parent. 
;It really changes the Owner exactly the same thing as including the Owner argument in the Show statement. 
;A more accurate version might be: "SetWindowLong with the GWL_HWNDPARENT will not change the parent of a child window. Instead, use the SetParent function."
;GWL_HWNDPARENT should have been called GWL_HWNDOWNER, but nobody noticed it until after a bazillion copies of the SDK had gone out. This is what happens 
;when the the dev team lives on M&Ms and CocaCola for to long. Too bad. Live with it.
;
Win_SetOwner(Hwnd, hOwner){
	static GWL_HWNDPARENT = -8
	return DllCall("SetWindowLong", "uint", Hwnd, "int", GWL_HWNDPARENT, "uint", hOwner)		
}

/*
 Function:	SetToolWindow
 			Set the WS_EX_TOOLWINDOW style for the window.
 
 Parameters:
			Flag	- Set + to show the caption or - otherwise. If omited, caption will be toggled.
 */
Win_SetToolWindow(Hwnd, Flag="^") {
	static WS_EX_TOOLWINDOW = 0x80	
	oldDetect := A_DetectHiddenWindows
	DetectHiddenWindows, on
	WinSet, ExStyle, %FLag%0x80, ahk_id %Hwnd%	
	DetectHiddenWindows, %oldDetect%
}

/*
 Function:	Show
 			Show / Hide window.
 
 Parameters:
			bShow	- True to show (default), False to hide window.

 Returns:
		If the window was previously visible, the return value is nonzero. 
		If the window was previously hidden, the return value is zero.
 */
Win_Show(Hwnd, bShow=true) {
	return DllCall("ShowWindow", "uint", Hwnd, "uint", bShow ? 5:0)
}

/*
 Function:	ShowSysMenu
 			Show system menu for a window (ALT + SPACE menu).
 
 Parameters:
			X, Y	- Coordinates on which to show menu. Pass word "mouse" as X (default) to use mouse coordinates.


 Returns:
			True if menu has been shown, False otherwise.
 */
Win_ShowSysMenu(Hwnd, X="mouse", Y="") {
	static WM_SYSCOMMAND = 0x112, TPM_RETURNCMD=0x100

	oldDetect := A_DetectHiddenWindows
	DetectHiddenWindows, on
	Process, Exist
	h := WinExist("ahk_pid " ErrorLevel)
	DetectHiddenWindows, %oldDetect%

	if X=mouse
		VarSetCapacity(POINT, 8), DllCall("GetCursorPos", "uint", &POINT), X := NumGet(POINT), Y := NumGet(POINT, 4)

	hSysMenu := DllCall("GetSystemMenu", "Uint", Hwnd, "int", False) 
	r := DllCall("TrackPopupMenu", "uint", hSysMenu, "uint", TPM_RETURNCMD, "int", X, "int", Y, "int", 0, "uint", h, "uint", 0)
	ifEqual, r, 0, return
	PostMessage, WM_SYSCOMMAND, r,,,ahk_id %Hwnd%
	return 1
}

/*
 Function:	Subclass 
			Subclass child window (control)
 
 Parameters: 
			hCtrl   - Handle to the child window to be subclassed
			Fun		- New window procedure. You can also pass function address here in order to subclass child window
					  with previously created window procedure.
			Opt		- Optional callback options for Fun, by default "" 
		   $WndProc - Optional reference to the ouptut variable that will receive address of the new window procedure.

 Returns:
			The addresss of to the previous window procedure or 0 on error	

 Remarks:
			Works only for controls created in the autohotkey process.

 Example:
	(start code)
  	if !Win_SubClass(hwndList, "MyWindowProc") 
  	     MsgBox, Subclassing failed. 
  	... 
  	MyWindowProc(hwnd, uMsg, wParam, lParam){ 
  
  	   if (uMsg = .....)  
            ; my message handling here 
  
  	   return DllCall("CallWindowProcA", "UInt", A_EventInfo, "UInt", hwnd, "UInt", uMsg, "UInt", wParam, "UInt", lParam) 
  	}
	(end code)
 */
Win_Subclass(hCtrl, Fun, Opt="", ByRef $WndProc="") { 
	if Fun is not integer
	{
		 oldProc := DllCall("GetWindowLong", "uint", hCtrl, "uint", -4) 
		 ifEqual, oldProc, 0, return 0 
		 $WndProc := RegisterCallback(Fun, Opt, 4, oldProc) 
		 ifEqual, $WndProc, , return 0
	}
	else $WndProc := Fun
	   
    return DllCall("SetWindowLong", "UInt", hCtrl, "Int", -4, "Int", $WndProc, "UInt") 
}

/*
Group: About
	o v1.2  by majkinetor.
	o Reference: <http://msdn.microsoft.com/en-us/library/ms632595(VS.85).aspx>
	o Licenced under GNU GPL <http://creativecommons.org/licenses/GPL/2.0/>
/*
Settings.ini

Code: Select all

[Settings]
unhide=+^!M
switchnext=<#NumpadEnter
switchprev=<#NumpadEnter
numdesks=2
switchMod=^
sendmod=<#numpad
windowsOnAll= 
desktopcircle=1
theswitchmod=2
thesendmod=4
thenextmod=4
thepremod=4
rightaltkey=1
runatstartup=0

[Mod action: Moved topic to v1 section. The main section is for v2. Please post in the correct forum.]
User avatar
RDC
Posts: 112
Joined: 29 Jan 2023, 10:22

Re: Massive v1 Code Trouble

27 Feb 2023, 09:48

5,000 lines of code?? :shock:
Good luck, but I don't think you'll get many to dig through that many lines of code for you.
If possible, try breaking down to the section(s) you think may be causing the trouble.
My hats off to you. That is a huge undertaking.
imkira3
Posts: 84
Joined: 10 Jan 2023, 13:57
Contact:

Re: Massive v1 Code Trouble

27 Feb 2023, 09:59

Lol yeah I figured. Oh well, no matter. This is a cool code though, I can't wait to figure it out. Probably the quickest and most discreet bosskey script I have ever seen, and the fact you can send windows from one desktop to the other is pretty great

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Descolada and 181 guests