1. kenutary12.03.2025 в 17:48от
  2. DAVINCI12.03.2025 в 17:29от
  3. D1zo12.03.2025 в 17:04от
Загрузка...

AHK Скрипт NoSpread,NoRecoil и так далее

Тема в разделе "Battlefield", создана пользователем Reimu, 23.02.2016.

  1. Reimu

    Reimu

    Статус:
    Оффлайн
    Регистрация:
    15.01.14
    Сообщения:
    391
    Репутация:
    256 +/-
    [​IMG]

    Сохраняем оба файла в .ahk формате - два файла а не в один, Как компелировать/использовать AHK скрипты
    Запускаем игру и ставим в настройках игры Borderless
    Запускаем наш скрипт
    Активация скрипта Numpad0
    Для того что бы убрать окно меню скрипта, щелкните на окно игры

    AHK:
    Код:
    #NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
    ; #Warn  ; Enable warnings to assist with detecting common errors.
    SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
    SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
    #SingleInstance Force
    #NoEnv
    #include GDI+.ahk
    SetBatchLines -1
    MaxROF = 2000
    MaxVel = 10000
    IniRead,NoSpread,Settings.dfd,Settings,Spread,100
    NoSpreadOld := NoSpread + 2
    IniRead,NoRecoil,Settings.dfd,Settings,Recoil,0
    IniRead,Overlay,Settings.dfd,Settings,Overlay,0
    IniRead,Breath,Settings.dfd,Settings,Breath,0
    IniRead,Spotting,Settings.dfd,Settings,Spotting,0
    IniRead,PlayerRadar,Settings.dfd,Settings,PlayerRadar,0
    IniRead,showTeam,Settings.dfd,Settings,ShowTeam,0
    IniRead,PosCX1,Settings.dfd,Settings,PosCX1,1920
    IniRead,PosCY1,Settings.dfd,Settings,PosCY1,540
    IniRead,ROFAuto,Settings.dfd,Settings,ROFAuto,0
    IniRead,Auto,Settings.dfd,Settings,Auto,%A_Space%
    IniRead,GravitySet,Settings.dfd,Settings,Gravity,0
    IniRead,MuzzleVel,Settings.dfd,Settings,MuzzleSet,0
    iniRead,MuzzleV,Settings.dfd,Settings,MuzzleVelocity
     
    Process,Priority,,R
     
    ;0BBCE9410
    ;151B1D500
     
    ;Type---------------
    PROGRAM = Battlefield 4
    Settimer,Base,10
    Settimer,pData,10
    Settimer, WindowXY,100
    Settimer, Spread,300
    Settimer, Recoil,300
    Settimer, MuzzleVelocitySetting,300
    Settimer, ROFSetting,300
    Settimer, GravitySetting,300
    ;Settimer, Debug, 10
    Settimer,Breath,300
    Settimer, SaveSettings,5000
    Settimer,Overlay,300
     
    If !pToken := Gdip_Startup()
    {
       MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
       ExitApp
    }
     
    /*
    Offset(kl="")
    {
    CLIENTGAMECONTEXT = 0x24a0c00 ;0 +  Base
    ANGLES := 0x21e3400 ;+ base
    ;---------gamecontext----------
    ClientPlayerManager := 0x60 ;GameContext 
    idToPlayerMapOffset := 0x548 ;ClientPlayerManager
    ;------------------ReadLocalPlayer --------------------
    ClientPlayer = 0x540 ;ClientPlayerManager 
    ClientSoldier = 0x14d0 ;ClientPlayer 
    ClientReplication = 0x490 ;ClientSoldier
    soldierWeaponsComponent = 0x570 ;ClientSoldier 
    breathControlHandler = 0x588 ;clientSoldier
    pHealthComponent = 0x140 ;ClientSoldier
    ActiveSlot = 0x0a98 ;SoldierWeaponCompenent 
    CurrentAnimatedWeaponHandler = 0x0890 ;soldierWeaponComponent
    ClientSoldierWeapon := * 0x8 ;currentAnimantedWeaponHandler + ActiveSlot
    CorrectedFiring := 0x49c0 ;Angles
    WeaponSway := 0x78 ;CorrectedFiring
    WeaponSwayData := 0x08 ;WeaponSway
    ;---------------------PlayerData-------------------
    InVehicle := 0x14c0 ;clientPlayer
    TeamID := 0x13cc ;Clientplayer
    Health := 0x20 ;pHealthComponent
    projectilesLoaded := 0x01a0 ;CorrectedFiring
    ProjectilesInMagazines := 0x01a4 ;CorrectedFiring
    PositionX := 0x30 ;clientReplication
    PositionY := 0x34 ;ClientReplication
    PositionZ := 0x38 ;clientReplication
    flYaw := 0x4D8 ;clientSoldier
    Return %kl%
    }
    */
     
     
    MainGui():
    if WinExist("Battlefield 4")
    {
    WinGetPos,Xpos, YPos,WidthW,HeightH,Battlefield 4
    PosX := XPos+10, PosY := YPos +20
    Gui +AlwaysOnTop -Caption +ToolWindow
    Gui, Color, FA0000
    gui, font,cFF0000 S12 Bold, Arial
    Gui, Add, Text, x10 y10 w100 h20 vNSpread ,Spread %NoSpread%
    Gui, Add, Slider,x120 y10 W50 h20 Center NoTicks Range0-100 vNoSpread gSpread ,%NoSpread%
     
    Gui, Add, text, x10 y30 w100 h30, NoRecoil
    Gui, Add, CheckBox,x120 y30 Checked%NoRecoil% vNoRecoil ; gRecoil
     
    Gui,Add,Text, x10 y50 W100 H40,Overlay
    Gui, Add, CheckBox, x120 y50 Checked%Overlay% vOverlay gOverlay
     
    gui, Add, Text, x10 y70 w120 h30, NoBreath
    Gui, Add, CheckBox, X120 y70 Checked%Breath% vBreath gBreath
     
    Gui, Add, Text,x10 y90 w120 h30,MiniMap Spotting
    Gui, Add, CheckBox,x120 y90 Checked%Spotting% vSpotting gpData
     
    Gui, Add, Text,x10 y110 w120 h30,EnemyRadar
    Gui, Add, Checkbox,x120 y110 Checked%PlayerRadar% vPlayerRadar gpData
     
    Gui, Add, Text ,x10 y130 w120 H30,ShowTeam
    Gui, Add, CheckBox,x120 y130 Checked%ShowTeam% vShowTeam gpData
     
    Gui, Add, Text,x10 y150 W120 H30,HorzPos
    Gui, Add, Slider,x120 y150 w50 h20 Center NoTicks range0-%A_ScreenWidth% vPosCX1 gpData,%PosCX1%
     
    Gui, Add, Text,x10 y170 W120 H30,VertPos
    Gui, Add, Slider,x120 y170 w50 h20 Center NoTicks range0-%A_ScreenHeight% vPosCY1 gpData,%PosCY1%
     
    Gui, Add, Text, x10 y190 w110 h20 vRPMAuto,ROF %Auto%
    Gui, Add, CheckBox,x120 y190  h15 w15 Checked%ROFAuto% vROFAuto 
    Gui, Add, Slider,x140 y190 w50 h20 Center NoTicks range0-%MaxROF% vAuto, %Auto%
     
    Gui, Add, text,x10 y210 w110 h20,NoGravity
    Gui, Add, CheckBox,x120 y210 h15 w15 Checked%GravitySet% vGravitySet ; gRecoil
     
    Gui, Add, Text,x10 y230 w110 h20 vMuzzleText,Vel %MuzzleV%
    Gui, Add, CheckBox,x120 y230  h15 w15 Checked%MuzzleVel% vMuzzleVel 
    Gui, Add, Slider,x140 y230 w50 h20 Center NoTicks range0-%MaxVel% vMuzzleV, %MuzzleV%
     
    Gui, Show, NA x%PosX% y%PosY%,Gui77
    WinSet, TransColor,FA0000, Gui77
    }
    return
     
     
    ~Numpad0::
    IfWinNotActive,Gui77
    {
    	WinGetPos,Xpos, YPos,WidthW,HeightH,Battlefield 4
        PosX := XPos, PosY := YPos
    	Gui, Show,x%PosX% y%PosY%,Gui77
    	WinMove,Gui77,,PosX,PosY
    }
    return
     
    WindowXY:
    WinGetPos,Xpos, YPos,WidthW,HeightH,Battlefield 4
    IfWinNotActive,Gui77
    	Gui,Hide
    IfWinNotExist,Battlefield 4
    {
    	FileDelete,%A_WorkingDir%\Backup.dfd
    	ExitApp
    }
    return
     
    Spread:
    Gui, Submit, Nohide
    if Done = 1
    {
    NoSpreadDec := Round(NoSpread/100,3)
    VarHex := FloatToHex(NoSpreadDec)
    StringTrimRight,NoSpreadDec,NoSpreadDec,1
    GuiControl,,NSpread,Spread %NoSpreadDec%
    	WriteMemory(VarHex,WeaponSwayData+0x0430,PROGRAM) ;VisualSpreadADS
    	WriteMemory(VarHex,WeaponSwayData+0x0434,PROGRAM) ;ProjectileSpreadADS
    	WriteMemory(VarHex,WeaponSwayData+0x0438,PROGRAM) ;VisualSpread
    	WriteMemory(VarHex,WeaponSwayData+0x043C,PROGRAM) ;ProjectileSpread
    }
    return
     
    Recoil:
    if Done = 1
    {
    Gui, Submit, Nohide
    if NoRecoil = 1
    	{
    		;if (Recoil1 = FloatToHex(100)) && (Recoil2 = FloatToHex(0))
    		;	return
    		iniRead,WeaponNameLoad,Backup.dfd,%CurrentWeaponName3%,Weapon
    		if WeaponNameLoad != %CurrentWeaponName3%
    		{
    			IniWrite,%CurrentWeaponName3%,Backup.dfd,%CurrentWeaponName3%,Weapon
    			IniWrite,%Recoil1%,Backup.dfd,%CurrentWeaponName3%,Recoil1B
    			IniWrite,%Recoil2%,Backup.dfd,%CurrentWeaponName3%,Recoil2B
    			}
    			WriteMemory(FloatToHex(100),WeaponSwayData+0x0440,PROGRAM)
    			WriteMemory(FloatToHex(0),WeaponSwayData+0x0444,PROGRAM)
    		}
    		
    if NoRecoil = 0
       {
    	iniRead,WeaponNameLoad,Backup.dfd,%CurrentWeaponName3%,Weapon
    	if WeaponNameLoad != ERROR
    	{
    	IniRead,Recoil1Ret,Backup.dfd,%CurrentWeaponName3%,Recoil1B
    	IniRead,Recoil2Ret,Backup.dfd,%CurrentWeaponName3%,Recoil2B
    ;	if (Recoil1 = Recoil1Ret) && (Recoil2 = Recoil2Ret)
    	;	return
    		WriteMemory(Recoil1Ret,WeaponSwayData+0x0440,PROGRAM)
    		WriteMemory(Recoil2Ret,WeaponSwayData+0x0444,PROGRAM)
    	    }
    	}
    }
    return
     
     
    ROFSetting:
    if Done = 1
    {
    Gui, Submit, Nohide
    if ROFAuto = 1
    	{
    		iniRead,ROF,Backup.dfd,%CurrentWeaponName3%,ROFAuto
    		if ROF = ERROR
    		{
    			IniWrite,%ClientROFAuto%,Backup.dfd,%CurrentWeaponName3%,ROFAuto
    			IniWrite,%ClientROFBurst%,Backup.dfd,%CurrentWeaponName3%,ROFBurst
    		}
    		else
    		{
    			RPM1 := Auto
    			VarHexRPM1 := FloatToHex(Auto)
    			GuiControl,,RPMAuto,ROF %Auto%
    		;	if (ClientROFAuto = HexToFloat(VarHexRPM1))
    		;		return
    			WriteMemory(VarHexRPM1,FiringFunctionData+0x1c8,PROGRAM)
    			WriteMemory(VarHexRPM1,FiringFunctionData+0x1cc,PROGRAM)
    		}
    }
    	
    if ROFAuto = 0
    	{
    		iniRead,ROF,Backup.dfd,%CurrentWeaponName3%,ROFAuto
    		if ROF != ERROR
    		{
    			IniRead,BackupROFAuto,Backup.dfd,%CurrentWeaponName3%,ROFAuto
    			IniRead,BackupROFBurst,Backup.dfd,%CurrentWeaponName3%,ROFBurst
    			VarHexRPM3 := BackupROFAuto
    			VarHexRPM4 := BackupROFBurst
    			GuiControl,,RPMAuto,ROF %BackupROFAuto%
    		;	if (ClientROFAuto = HexToFloat(VarHexRPM3))
    		;		return
    			WriteMemory(FloatToHex(VarHexRPM3),FiringFunctionData+0x1c8,PROGRAM)
    			WriteMemory(FloatToHex(VarHexRPM4),FiringFunctionData+0x1cc,PROGRAM)
    		}
    	}
    }
    return
     
    GravitySetting:
    if Done = 1
    {
    if GravitySet = 1
    	{
    		iniRead,GravityBackup,Backup.dfd,%CurrentWeaponName3%,Gravity
    		if GravityBackup = ERROR
    		{
    			IniWrite,%Gravity%,Backup.dfd,%CurrentWeaponName3%,Gravity
    		}
    		else 
    		{
    			if (Gravity = 0)
    				return
    			WriteMemory(FloatToHex(0),BulletEntityData+0x130,PROGRAM)		
    		}
    	}
    	
    if GravitySet = 0
    	{
    		iniRead,GravityBackup,Backup.dfd,%CurrentWeaponName3%,Gravity
    		if GravityBackup != ERROR
    		{
    			VarHexGr := FloatToHex(GravityBackup)
    			if (Gravity = GravityBackup)
    				return
    			WriteMemory(VarHexGr,BulletEntityData+0x130,PROGRAM)
    		}
    	}
    }
    return
     
    MuzzleVelocitySetting:
    if Done = 1
    {
    Gui, Submit, Nohide
    if MuzzleVel = 1 
    	{
    		iniRead,MuzzleBackup,Backup.dfd,%CurrentWeaponName3%,MuzzleVelocity
    		if MuzzleBackup = ERROR
    		{
    			IniWrite,%MuzzleVelo%,Backup.dfd,%CurrentWeaponName3%,MuzzleVelocity
    		}
    		else
    		{
    			GuiControl,,MuzzleText,Vel %MuzzleV%
    		;	if (MuzzleVelo = HexToFloat(FloatToHex(MuzzleV))) 
    		;		return
    			WriteMemory(FloatToHex(MuzzleV),FiringFunctionData+0x88,PROGRAM)
    		}
    }
    	
    if MuzzleVel = 0
    	{
    		iniRead,MuzzleBackup,Backup.dfd,%CurrentWeaponName3%,MuzzleVelocity
    		if MuzzleBackup != ERROR
    		{
    			GuiControl,,MuzzleText,Vel %MuzzleBackup%
    			VarHexVel := FloatToHex(MuzzleBackup)
    		;	if (MuzzleVelo = MuzzleBackup) 
    		;		return
    			WriteMemory(VarHexVel,FiringFunctionData+0x88,PROGRAM)
    		}
    	}
    }
    return
     
    Overlay:
    if Overlay = 1
    {
    Settimer, OverlayUpdate,1 
    }
    if Overlay = 0
    {
    	Settimer, OverlayUpdate, Off
    	Gui,2: Destroy
    }
    return
     
    OverlayUpdate:
    projectilesLoaded := Convert(ReadMemory(CFiring+0x01a0,PROGRAM),"D")
    projectilesInMagazines := Convert(ReadMemory(CFiring+0x01a4,PROGRAM),"D")
    SendText := Round(HexToFloat(Convert(ReadMemory(HealthComponent+0x20,PROGRAM),"H"))) " / 100 `n" projectilesLoaded " / " ProjectilesInMagazines
    Width := 120, Height := 50
    Gui, 2:  -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop
    Gui, 2: Show, NA
    hwnd1 := WinExist()
    hbm := CreateDIBSection(Width, Height)
    hdc := CreateCompatibleDC()
    obm := SelectObject(hdc, hbm)
    G := Gdip_GraphicsFromHDC(hdc)
    Gdip_SetSmoothingMode(G, 4)
    pBrush := Gdip_BrushCreateSolid(0x00000000)
    Gdip_FillRoundedRectangle(G, pBrush, 0, 0, Width, Height, 20)
    Gdip_DeleteBrush(pBrush)
    Font = Arial
    If !hFamily := Gdip_FontFamilyCreate(Font)
    {
       MsgBox, 48, Font error!, The font you have specified does not exist on the system
       ExitApp
    }
    Options = x10p y30p w80p Left cFF00ff00 r4 s15 BoldItalic
    Gdip_TextToGraphics(G, SendText, Options, Font, Width, Height) 
    UpdateLayeredWindow(hwnd1, hdc, PosX, PosY+180, Width, Height)
    Gdip_DeleteFontFamily(hFamily)
    SelectObject(hdc, obm)
    DeleteObject(hbm)
    DeleteDC(hdc)
    Gdip_DeleteGraphics(G)
    return
     
    Breath:
    if Breath = 1
    {
    if InVehicle = 1
    	return
    if Done = 1
    {
    	WriteMemory(0x00,BreathControlHandler+0x38,PROGRAM)
    	WriteMemory(0x00,BreathControlHandler+0x3C,PROGRAM)
    	WriteMemory(0x00,BreathControlHandler+0x40,PROGRAM)
    	WriteMemory(0x00,BreathControlHandler+0x44,PROGRAM)
    	WriteMemory(0x00,BreathControlHandler+0x48,PROGRAM)
    	WriteMemory(0x00,BreathControlHandler+0x4C,PROGRAM)
    	WriteMemory(0x00,BreathControlHandler+0x58,PROGRAM)
    }
    else
    	return
    }
    return
     
    Debug:
    Tooltip % "Base " Base " `n Deploy  " DeployScreen " `n Context " Convert(GameContext,"H") "`n  ClientPlayerManager  " Convert(ClientPlayerManager,"H") "`n ClientPlayer" Convert(ClientPlayer,"H") " `n InVehicle " Convert(InVehicle,"H") "`n PlayerName " PlayerName "`n CLTeamID " Convert(ClientPlayerTeamID,"H") " `n  ClientSoldier " Convert(ClientSoldier,"H") " `n HealthComponent " Convert(HealthComponent,"H") " `n ClientHealth " ClientHealth " `n  `n Angle  " Convert(Angles,"H") " `n CorrectedFiring " Convert(CFiring,"H") " `n W " Convert(CurrentWeaponName,"H") " `n W2 " Convert(CurrentWeaponName2,"H") "`n W3 " CurrentWeaponName3 " `n PrimaryFire " Convert(PrimaryFire,"H") " `n FirngFuncData " Convert(FiringFunctionData,"H") " `n BulletEntityData " Convert(BulletEntityData,"H") " `n WeaponSway " Convert(WeaponSway,"H") " `n WeaponSwayData " Convert(WeaponSwayData,"H")  " `n `n IdToPlayerMapOffset " Convert(IdToPlayerMapOffset,"H") " `n pPlayer " Convert(pPlayer,"H") "`n pSoldierName" pSoldierName "`n pPlayerTeamID " Convert(pPlayerTeamID,"H") "`n pSoldier " Convert(pSoldier,"H") "`n pHealthComponent " Convert(pHealthComponent,"H") "`n pHealth " pHealth "`n pReplication " Convert(pReplication,"H")   ,1800,0
    return
     
     
    pData:
    Gui, Submit, Nohide
    if PlayerRadar = 1
    {
    Straal := (2*150)
    PosCX := PosCX1 - Straal
    PosCY := PosCY1 - Straal 
    Width3 := WidthW, Height3 := HeightH
    Gui, 4:  -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop 
     
    Gui, 4: Show, NA 
    hwnd3 := WinExist()
    hbm3 := CreateDIBSection(Width3, Height3)
    hdc3 := CreateCompatibleDC()
    obm3 := SelectObject(hdc3, hbm3)
    G3 := Gdip_GraphicsFromHDC(hdc3)
    Gdip_SetSmoothingMode(G3, 4)
    pBrush4 := Gdip_BrushCreateSolid(0x11000000)
    pBrush5 := Gdip_BrushCreateSolid(0xFF00FF00)
    Gdip_FillRoundedRectangle(G3, pBrush4, PosCX, PosCY, Straal, Straal, Straal/2)
    Gdip_FillRoundedRectangle(G3, pBrush5, (PosCX+(Straal/2)), (PosCY+(Straal/2)) , 5, 5, 2.5)
    Gdip_DeleteBrush(pBrush4)
    Gdip_DeleteBrush(pBrush5)
    }
    While (ide < 64)
    	{
    		if Round(HexToFloat(Convert(ReadMemory(HealthComponent+0x20,PROGRAM),"H"))) < 1
    			continue
    		IdToPlayerMapOffset := ReadMemory(ClientPlayerManager+0x548,PROGRAM,5)
    		if IdToPlayerMapOffset != -1
    			{
    				ide ++
    				pPlayer := ReadMemory(IdToPlayerMapOffset+(ide * 0x8),PROGRAM,5)
    				if pPlayer != -1
    				{
    					pSoldierName := ReadMemoryStr(pPlayer+0x40,PROGRAM)
    					pPlayerTeamID := ReadMemory(pPlayer+0x13cc,PROGRAM)
    					pSoldier := ReadMemory(pPlayer+0x14D0,PROGRAM,5)
    					if pSoldier != -1
    					{
    						pHealthComponent := ReadMemory(pSoldier+0x140,PROGRAM,5)
    						if pHealthComponent != -1
    						{
    							pHealth := Round(HexToFloat(Convert(ReadMemory(pHealthComponent+0x20,PROGRAM),"H")))
    						}						
    						pReplication := ReadMemory(pSoldier+0x490,PROGRAM,5)
    						if pReplication != -1
    						{
    							pPositionX := HexToFloat(Convert(ReadMemory(pReplication+0x30,PROGRAM),"H"))
    							pPositionY := HexToFloat(Convert(ReadMemory(pReplication+0x34,PROGRAM),"H"))
    							pPositionZ := HexToFloat(Convert(ReadMemory(pReplication+0x38,PROGRAM),"H"))
    							;pVelocityX := HexToFLoat(Convert(ReadMemory(pReplication+0x50,PROGRAM),"H"))
    							;pVelocityY := HexToFloat(Convert(ReadMemory(pReplication+0x54,PROGRAM),"H"))
    							;pVelocityZ := HexToFloat(Convert(ReadMemory(pReplication+0x58,PROGRAM),"H"))
    							PositionX := HexToFloat(Convert(ReadMemory(ClientReplication+0x30,PROGRAM),"H"))
    							PositionY := HexToFloat(Convert(ReadMemory(ClientReplication+0x34,PROGRAM),"H")) ;Heigth in map
    							PositionZ := HexToFloat(Convert(ReadMemory(ClientReplication+0x38,PROGRAM),"H"))
    						}
    					}
    				}
    			}
    			Yaw := HexToFloat(Convert(ReadMemory(ClientSoldier+0x4D8,PROGRAM),"H"))
    			angle := -Yaw
    			if Spotting = 1
    			{
    			if pPlayerTeamID != %ClientPlayerTeamID%
    				{
    				SpottingTargetComponentData := Convert(ReadMemory(pSoldier+0xBF0,PROGRAM,5),"H")
    				SpotType := ReadMemory(SpottingTargetComponentData+0x50,PROGRAM)
    				if (SpotType = 0 && ClientHealth > 0)
    					WriteMemory(0x1,SpottingTargetComponentData+0x50,PROGRAM)
    				}	
    			}
    			if PlayerRadar = 1
    			{	
    				IfNotEqual, pPlayerTeamID,  %ClientPlayerTeamID% ; if other team 
    				{
    					RColor = 0xFFFF0000
    				}
    			else
    				{
    				if ShowTeam = 1
    					RColor = 0xFF0000FF
    				Else
    					RColor = 0x00000000
    				}
    				if pHealth <= 1
    				{
    					RColor = 0x00000000
    				}
    				Distance:
    				xD := Round(PositionX - pPositionX)	
    				yD := Round(PositionY - pPositionY)
    				zD := Round(PositionZ - pPositionZ)
    				pDistance := Round(sqrt((xD * xD) + (yD * yD) + (zD * zD)))
    				ArrayCount++
    				RC%ArrayCount% := RColor
    				xD%ArrayCount% := pPositionX
    				yD%ArrayCount% := pPositionY
    				zD%ArrayCount% := pPositionZ
    				%ArrayCount% := pDistance 
    				Ry := positionZ - zD%ArrayCount%
    				Rx := PositionX - xD%ArrayCount%
    				if (pDistance < 150)
    				{
    					if (pDistance = 0)
    						continue
    					xR%ArrayCount% := (Rx*Cos(angle)-Ry*Sin(angle))+(PosCX+(Straal/2))
    					yR%ArrayCount% := (Rx*Sin(angle)+Ry*Cos(angle))+(PosCY+(Straal/2))
    					pBrush6 := Gdip_BrushCreateSolid(RC%ArrayCount%)
    					Gdip_FillRoundedRectangle(G3, pBrush6, xR%ArrayCount%, yR%ArrayCount% , 5, 5, 2.5)
    					Gdip_DeleteBrush(pBrush6)
    				}
    			} 
    	}	;End While Loop
    if PlayerRadar = 1
    {
    UpdateLayeredWindow(hwnd3, hdc3, 0, 0, Width3, Height3)
    SelectObject(hdc3, obm3)
    DeleteObject(hbm3)
    DeleteDC(hdc3)
    Gdip_DeleteGraphics(G3)
    }
    if PlayerRadar = 0
    {
    	Gui, 4: Destroy
    }
    ArrayCount = 0
    ide = 0
    return
     
    Base:
    IfWinActive,Battlefield 4
    {
        Base := getProcessBaseAddress(PROGRAM)
    	DeployScreen := ReadMemory(Base+0x21c7e20+0xd2,PROGRAM,5)
    	if DeployScreen = 0
    	{
    		Angles := ReadMemory(Base+0x21c7e20,PROGRAM,5)
    		if Angles != -1
    		{
    			CFiring := ReadMemory(Angles+0x49c0,PROGRAM,5)
    			if CFiring != -1
    			{
    				CurrentWeaponName := ReadMemory(CFiring+0x01c8,PROGRAM,5)
    				if CurrentWeaponName != -1
    				{
    					CurrentWeaponName2 := ReadMemory(CurrentWeaponName+0x130,PROGRAM,5)
    					if CurrentWeaponName2 != -1
    					{				
    						CurrentWeaponName3 := ReadMemoryStr(CurrentWeaponName2+0x0,PROGRAM)	
    					}
    				}
    				PrimaryFire := 	ReadMemory(CFiring+0x0128,PROGRAM,5)
    				if PrimaryFire != -1
    				{
    					FiringFunctionData := ReadMemory(PrimaryFire+0x0010,PROGRAM,5)
    					if FiringFunctionData != -1
    					{
    						BulletEntityData := ReadMemory(FiringFunctionData+0x00B0,PROGRAM,5)
    					}
    				}
    				WeaponSway := ReadMemory(CFiring+0x0078,PROGRAM,5)
    				if WeaponSway != -1
    				{
    					WeaponSwayData := ReadMemory(WeaponSway+0x0008,PROGRAM,5)
    				}
    			}
    		}
    		GameContext := ReadMemory(Base+0x24a0e88,PROGRAM,5)
    		if (GameContext != -1)
    		{
    			ClientPlayerManager := ReadMemory(GameContext+0x60,PROGRAM,5)
    			if (ClientPlayerManager != -1)
    			{
    				ClientPlayer := ReadMemory(ClientPlayerManager+0x540,PROGRAM,5)
    				if ClientPlayer != -1
    				{
    					InVehicle := ReadMemory(ClientPlayer+0x14c0,PROGRAM)
    					PlayerName := ReadMemoryStr(ClientPlayer+0x40,PROGRAM)
    					ClientPlayerTeamID := ReadMemory(ClientPlayer+0x13cc,PROGRAM)
    					ClientSoldier := ReadMemory(ClientPlayer+0x14d0,PROGRAM,5)
    					if ClientSoldier != -1
    					{
    						SoldierWeaponComponent := ReadMemory(ClientSoldier+0x570,PROGRAM,5)
    						if SoldierWeaponCompnent != -1
    						{
    							ActiveSlot := ReadMemory(SoldierWeaponComponent+0x0a98,PROGRAM) +2
    							Done :=  ActiveSlot = 2 OR ActiveSlot = 3 OR ActiveSlot = 11
    						}
    						ClientReplication := ReadMemory(ClientSoldier+0x490,PROGRAM,5)
    						breathControlHandler := ReadMemory(ClientSoldier+0x588,PROGRAM,5)
    						HealthComponent := ReadMemory(ClientSoldier+0x140,PROGRAM,5) 
    					}
    				}
    			}
    		}
    	}
    }
    return
    /*
    	;----------------LocelPlayer--------------------
    	;ClientPlayer := Convert(ReadMemory(ClientPlayerManager+0x540,PROGRAM),"H") 
    	;ClientSoldier := Convert(ReadMemory(ClientPlayer+0x14d0,PROGRAM),"H")
    	;ClientReplication := Convert(ReadMemory(ClientSoldier+0x490,PROGRAM),"H")
    	;SoldierWeaponsComponent := Convert(ReadMemory(ClientSoldier+0x570,PROGRAM),"H")
    	;breathControlHandler := Convert(ReadMemory(ClientSoldier+0x588,PROGRAM),"H")
    	;HealthComponent := Convert(ReadMemory(ClientSoldier+0x140,PROGRAM),"H")
    	;ClientHealth := Convert(ReadMemory(HealthComponent+0x20,PROGRAM),"H")
    	;PlayerName := ReadMemoryStr(ClientPlayer+0x40,PROGRAM)
    	;ClientPlayerTeamID := ReadMemory(ClientPlayer+0x13cc,PROGRAM)
    	;cActiveSlot := Convert(ReadMemory(SoldierWeaponComponent+0x0a98,PROGRAM),"H")
    	;Done :=  ActiveSlot = 2 OR ActiveSlot = 3 OR ActiveSlot = 11
    	;InVehicle := Convert(ReadMemory(ClientPlayer+0x14c0,PROGRAM),"H")
    	;CorrectedFiring := Convert(ReadMemory(Angles+0x49c0,PROGRAM),"H")
    	;CurrentWeaponName := Convert(ReadMemory(CorrectedFiring+0x01c8,PROGRAM),"H")
    	;PrimaryFire := 	Convert(ReadMemory(CorrectedFiring+0x0128,PROGRAM),"H")
    	;WeaponSway := Convert(ReadMemory(CorrectedFiring+0x0078,PROGRAM),"H")
    	WeaponSwayData := Convert(ReadMemory(WeaponSway+0x0008,PROGRAM),"H")
    	SpreadBase := Round(HexToFLoat(Convert(ReadMemory(WeaponSwayData+0x0430,PROGRAM),"H"))*100)
    	Recoil1 := Convert(ReadMemory(WeaponSwayData+0x0440,PROGRAM),"H")
    	Recoil2 := Convert(ReadMemory(WeaponSwayData+0x0444,PROGRAM),"H")
    	FiringFunctionData := Convert(ReadMemory(PrimaryFire+0x0010,PROGRAM),"H")
    	MuzzleVelo := HexToFloat(Convert(ReadMemory(FiringFunctionData+0x0088,PROGRAM),"H"))
    	BulletEntityData := Convert(ReadMemory(FiringFunctionData+0x00B0,PROGRAM),"H")
    	Gravity := HexToFloat(Convert(ReadMemory(BulletEntityData+0x0130,PROGRAM),"H"))
    	ClientROFAuto := HexToFloat(Convert(ReadMemory(FiringFunctionData+0x1c8,PROGRAM),"H"))
    	ClientROFBurst := HexToFloat(Convert(ReadMemory(FiringFunctionData+0x1cc,PROGRAM),"H"))
    	;CurrentWeaponName2 := Convert(ReadMemory(CurrentWeaponName+0x130,PROGRAM),"H")
    	;CurrentWeaponName3 := ReadMemoryStr(CurrentWeaponName2+0x0,PROGRAM)	
    	MuzzleVelocity := Convert(ReadMemory(FiringFunctionData+0x88,PROGRAM),"H")
    	ROFSettings := Convert(ReadMemory(FiringFunctionData+0x1c8,PROGRAM),"H")
    	SpreadBase := Convert(ReadMemory(WeaponSwayData+0x0430,PROGRAM),"H")
    */
     
     
    WriteMemory(WVALUE,MADDRESS,PROGRAM) 
    { 
    winget, pid, PID, %PROGRAM% 
    ProcessHandle := DllCall("OpenProcess", "int", 2035711, "char", 0, "UInt", PID, "UInt") 
    DllCall("WriteProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "Uint*", WVALUE, "Uint", 4, "Uint *", 0) 
     
    return 
    }
     
    HexToFloat(x) {
       Return (1-2*(x>>31)) * (2**((x>>23 & 255)-150)) * (0x800000 | x & 0x7FFFFF)
    }
     
    HexToDouble(x) { ; may be wrong at extreme values
       Return (2*(x>0)-1) * (2**((x>>52 & 0x7FF)-1075)) * (0x10000000000000 | x & 0xFFFFFFFFFFFFF)
    }
     
    FloatToHex(f) {
       form := A_FormatInteger
       SetFormat Integer, HEX
       v := DllCall("MulDiv", Float,f, Int,1, Int,1, UInt)
       SetFormat Integer, %form%
       Return v
    }
     
    DoubleToHex(d) {
       form := A_FormatInteger
       SetFormat Integer, HEX
       v := DllCall("ntdll.dll\RtlLargeIntegerShiftLeft",Double,d, UChar,0, Int64)
       SetFormat Integer, %form%
       Return v
    }
     
    ReadMemory(MADDRESS=0,PROGRAM="",BYTE=4,MVALUE=" ")
    {
    	Static OLDPROC, ProcessHandle
    	if MVALUE := " " 
    	VarSetCapacity(MVALUE,4,0)
    	If PROGRAM != %OLDPROC%
    	{
    		WinGet, pid, pid, % OLDPROC := PROGRAM
    		ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
    		,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
    		,"Int",16,"Int",0,"UInt",pid) : 0)
    	}
    	If (ProcessHandle) && DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"str",MVALUE,"UInt",BYTE,"UInt *",0)
    	return *(&MVALUE+4)<<32 | *(&MVALUE+3)<<24 | *(&MVALUE+2)<<16 | *(&MVALUE+1)<<8 | *(&MVALUE)
    	return !ProcessHandle ? "Handle Closed: " closed : "-2"
    }
     
    getProcessBaseAddress(WindowTitle, windowMatchMode := "3")    ;WindowTitle can be anything ahk_exe ahk_class etc
    {
        if (windowMatchMode && A_TitleMatchMode != windowMatchMode)
        {
            mode := A_TitleMatchMode ; This is a string and will not contain the 0x prefix
            StringReplace, windowMatchMode, windowMatchMode, 0x ; remove hex prefix as SetTitleMatchMode will throw a run time error. This will occur if integer mode is set to hex and matchmode param is passed as an number not a string.
            SetTitleMatchMode, %windowMatchMode%    ;mode 3 is an exact match
        }
        WinGet, hWnd, ID, %WindowTitle%
        if mode
            SetTitleMatchMode, %mode%    ; In case executed in autoexec
        if !hWnd
            return ; return blank failed to find window
        return DllCall(A_PtrSize = 4     ; If DLL call fails, returned value will = 0
            ? "GetWindowLong"
            : "GetWindowLongPtr"
            , "Ptr", hWnd, "Int", -6, A_Is64bitOS ? "Int64" : "UInt")  
            ; For the returned value when the OS is 64 bit use Int64 to prevent negative overflow when AHK is 32 bit and target process is 64bit 
            ; however if the OS is 32 bit, must use UInt, otherwise the number will be huge (however it will still work as the lower 4 bytes are correct)      
            ; Note - it's the OS bitness which matters here, not the scripts/AHKs
    }   
     
    ReadMemoryStr(MADDRESS=0, PROGRAM = "", length = 0 , terminator = "")  ; "" = Null
    { 
        Static OLDPROC, ProcessHandle
     
        If (PROGRAM != OLDPROC || !ProcessHandle)
        {
            WinGet, pid, pid, % OLDPROC := PROGRAM
            ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
            ,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
            ,"Int",16,"Int",0,"UInt",pid) : 0) ;PID is stored in value pid
        }
        ; length depends on the encoding too
        VarSetCapacity(Output, length ? length : 1, 0)
        If !length ; read until terminator found or something goes wrong/error
    	{
            Loop
            { 
                success := DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS++, "str", Output, "Uint", 1, "Uint *", 0) 
                if (ErrorLevel || !success || Output = terminator) 
                    break
                teststr .= Output 
    		} 
    	}		
    	Else ; will read X length
    	{
            DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "str", Output, "Uint", length, "Uint *", 0) 
            ;  Loop % length
            ;     teststr .= chr(NumGet(Output, A_Index-1, "Char"))      
            teststr := StrGet(&Output, length, "UTF-8")
    	}
    	return teststr  
    }
     
    ;H for Hex D for Dec
    Convert(Number=0, ConvertTo="") {
    	TmpNum := Number
    	Ok := False
    	If TmpNum Is Integer
    		Ok := True
    	Else If TmpNum Is Xdigit
    	{
    		Ok := True
    		TmpNum := "0x" TmpNum
    	} Else If (InStr(TmpNum, "0x"))
    		Ok := True
    	Else
    		Return -1
    	If (Ok)
    		If (ConvertTo = "D" ) {
    			SetFormat Integer, D
    			TmpNum += 0
    			SetFormat Integer, H
    			Return TmpNum
    		} Else If (ConvertTo = "H") {
    			SetFormat Integer, H
    			TmpNum += 0
    			SetFormat Integer, D
    			Return TmpNum
    		} Else
    			Return -2
    	Else
    		Return -3
    }
     
    SaveSettings:
    IniWrite,%NoSpread%,Settings.dfd,Settings,Spread
    IniWrite,%NoRecoil%,Settings.dfd,Settings,Recoil
    IniWrite,%Overlay%,Settings.dfd,Settings,Overlay
    IniWrite,%Breath%,Settings.dfd,Settings,Breath
    IniWrite,%Spotting%,Settings.dfd,Settings,Spotting
    IniWrite,%PlayerRadar%,Settings.dfd,Settings,PlayerRadar
    IniWrite,%ShowTeam%,Settings.dfd,Settings,ShowTeam
    IniWrite,%PosCX1%,Settings.dfd,Settings,PosCX1
    IniWrite,%PosCY1%,Settings.dfd,Settings,PosCY1
    iniWrite,%ROFAuto%,Settings.dfd,Settings,ROFAuto
    IniWrite,%Auto%,Settings.dfd,Settings,Auto
    IniWrite,%GravitySet%,Settings.dfd,Settings,Gravity
    iniWrite,%MuzzleVel%,Settings.dfd,Settings,MuzzleSet
    iniWrite,%MuzzleV%,Settings.dfd,Settings,MuzzleVelocity
    return
    GDI+.ahk Библиотека

    Код:
    ; Gdip standard library v1.45 by tic (Tariq Porter) 07/09/11
    ; Modifed by Rseding91 using fincs 64 bit compatible Gdip library 5/1/2013
    ; Supports: Basic, _L ANSi, _L Unicode x86 and _L Unicode x64
    ;
    ; Updated 2/20/2014 - fixed Gdip_CreateRegion() and Gdip_GetClipRegion() on AHK Unicode x86
    ;
    ;#####################################################################################
    ;#####################################################################################
    ; 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	if ((x != "") && (y != ""))
    		VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")
     
    	if (w = "") ||(h = "")
    		WinGetPos,,, w, h, ahk_id %hwnd%
       
    	return DllCall("UpdateLayeredWindow"
    					, Ptr, hwnd
    					, Ptr, 0
    					, Ptr, ((x = "") && (y = "")) ? 0 : &pt
    					, "int64*", w|h<<32
    					, Ptr, 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="")
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdi32\BitBlt"
    					, Ptr, dDC
    					, "int", dx
    					, "int", dy
    					, "int", dw
    					, "int", dh
    					, Ptr, 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="")
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdi32\StretchBlt"
    					, Ptr, ddc
    					, "int", dx
    					, "int", dy
    					, "int", dw
    					, "int", dh
    					, Ptr, 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"
    					, A_PtrSize ? "UPtr" : "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, "UInt")
       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 (SubStr(Screen, 1, 5) = "hwnd:")
    	{
    		Screen := SubStr(Screen, 6)
    		if !WinExist( "ahk_id " Screen)
    			return -2
    		WinGetPos,,, w, h, ahk_id %Screen%
    		x := y := 0
    		hhdc := GetDCEx(Screen, 3)
    	}
    	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 := hhdc ? hhdc : GetDC()
    	BitBlt(chdc, 0, 0, w, h, hhdc, x, y, Raster)
    	ReleaseDC(hhdc)
    	
    	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
    	SelectObject(chdc, 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    			CreateRect
    ; Description			Creates a Rect 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
     
    CreateRect(ByRef Rect, x, y, w, h)
    {
    	VarSetCapacity(Rect, 16)
    	NumPut(x, Rect, 0, "uint"), NumPut(y, Rect, 4, "uint"), NumPut(w, Rect, 8, "uint"), NumPut(h, Rect, 12, "uint")
    }
    ;#####################################################################################
     
    ; 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	hdc2 := hdc ? hdc : GetDC()
    	VarSetCapacity(bi, 40, 0)
    	
    	NumPut(w, bi, 4, "uint")
    	, NumPut(h, bi, 8, "uint")
    	, NumPut(40, bi, 0, "uint")
    	, NumPut(1, bi, 12, "ushort")
    	, NumPut(0, bi, 16, "uInt")
    	, NumPut(bpp, bi, 14, "ushort")
    	
    	hbm := DllCall("CreateDIBSection"
    					, Ptr, hdc2
    					, Ptr, &bi
    					, "uint", 0
    					, A_PtrSize ? "UPtr*" : "uint*", ppvBits
    					, Ptr, 0
    					, "uint", 0, Ptr)
     
    	if !hdc
    		ReleaseDC(hdc2)
    	return hbm
    }
     
    ;#####################################################################################
     
    ; 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("PrintWindow", Ptr, hwnd, Ptr, hdc, "uint", Flags)
    }
     
    ;#####################################################################################
     
    ; 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", A_PtrSize ? "UPtr" : "UInt", hIcon)
    }
     
    ;#####################################################################################
     
    PaintDesktop(hdc)
    {
    	return DllCall("PaintDesktop", A_PtrSize ? "UPtr" : "UInt", hdc)
    }
     
    ;#####################################################################################
     
    CreateCompatibleBitmap(hdc, w, h)
    {
    	return DllCall("gdi32\CreateCompatibleBitmap", A_PtrSize ? "UPtr" : "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", A_PtrSize ? "UPtr" : "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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("SelectObject", Ptr, hdc, Ptr, 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", A_PtrSize ? "UPtr" : "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", A_PtrSize ? "UPtr" : "UInt", hwnd)
    }
     
    ;#####################################################################################
     
    ; DCX_CACHE = 0x2
    ; DCX_CLIPCHILDREN = 0x8
    ; DCX_CLIPSIBLINGS = 0x10
    ; DCX_EXCLUDERGN = 0x40
    ; DCX_EXCLUDEUPDATE = 0x100
    ; DCX_INTERSECTRGN = 0x80
    ; DCX_INTERSECTUPDATE = 0x200
    ; DCX_LOCKWINDOWUPDATE = 0x400
    ; DCX_NORECOMPUTE = 0x100000
    ; DCX_NORESETATTRS = 0x4
    ; DCX_PARENTCLIP = 0x20
    ; DCX_VALIDATE = 0x200000
    ; DCX_WINDOW = 0x1
     
    GetDCEx(hwnd, flags=0, hrgnClip=0)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
        return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
    }
     
    ;#####################################################################################
     
    ; 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("ReleaseDC", Ptr, hwnd, Ptr, 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", A_PtrSize ? "UPtr" : "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.45
    }
     
    ;#####################################################################################
     
    ; Function				Gdip_LibrarySubVersion
    ; Description			Get the current library sub version
    ;
    ; return				the library sub version
    ;
    ; notes					This is the sub-version currently maintained by Rseding91
    Gdip_LibrarySubVersion()
    {
    	return 1.46
    }
     
    ;#####################################################################################
     
    ; 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)
    {
    	Static FName = "ObjRelease"
    	
    	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, Ptr, FileInfo2, Ptr)
    	pData := DllCall("GlobalLock", Ptr, hData, Ptr)
    	DllCall("RtlMoveMemory", Ptr, pData, Ptr, &BRAFromMemIn+Info2+FileInfo1, Ptr, FileInfo2)
    	DllCall("GlobalUnlock", Ptr, hData)
    	DllCall("ole32\CreateStreamOnHGlobal", Ptr, hData, "int", 1, A_PtrSize ? "UPtr*" : "UInt*", pStream)
    	DllCall("gdiplus\GdipCreateBitmapFromStream", Ptr, pStream, A_PtrSize ? "UPtr*" : "UInt*", pBitmap)
    	If (A_PtrSize)
    		%FName%(pStream)
    	Else
    		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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipDrawRectangle", Ptr, pGraphics, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipDrawEllipse", Ptr, pGraphics, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipDrawBezier"
    					, Ptr, pgraphics
    					, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipDrawArc"
    					, Ptr, pGraphics
    					, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipDrawPie", Ptr, pGraphics, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipDrawLine"
    					, Ptr, pGraphics
    					, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	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", Ptr, pGraphics, Ptr, pPen, Ptr, &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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipFillRectangle"
    					, Ptr, pGraphics
    					, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	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", Ptr, pGraphics, Ptr, pBrush, Ptr, &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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipFillPie"
    					, Ptr, pGraphics
    					, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipFillEllipse", Ptr, pGraphics, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipFillRegion", Ptr, pGraphics, Ptr, pBrush, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipFillPath", Ptr, pGraphics, Ptr, pBrush, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	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"
    				, Ptr, pGraphics
    				, Ptr, pBitmap
    				, Ptr, &PointF
    				, "int", Points0
    				, "float", sx
    				, "float", sy
    				, "float", sw
    				, "float", sh
    				, "int", 2
    				, Ptr, ImageAttr
    				, Ptr, 0
    				, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	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"
    				, Ptr, pGraphics
    				, Ptr, pBitmap
    				, "float", dx
    				, "float", dy
    				, "float", dw
    				, "float", dh
    				, "float", sx
    				, "float", sy
    				, "float", sw
    				, "float", sh
    				, "int", 2
    				, Ptr, ImageAttr
    				, Ptr, 0
    				, Ptr, 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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	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", A_PtrSize ? "UPtr*" : "uint*", ImageAttr)
    	DllCall("gdiplus\GdipSetImageAttributesColorMatrix", Ptr, ImageAttr, "int", 1, "int", 1, Ptr, &ColourMatrix, Ptr, 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", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "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", A_PtrSize ? "UPtr" : "UInt", hdc, A_PtrSize ? "UPtr*" : "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", A_PtrSize ? "UPtr" : "UInt", pGraphics, A_PtrSize ? "UPtr*" : "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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipReleaseDC", Ptr, pGraphics, Ptr, 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", A_PtrSize ? "UPtr" : "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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	SplitPath, sOutput,,, Extension
    	if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
    		return -1
    	Extension := "." Extension
     
    	DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
    	VarSetCapacity(ci, nSize)
    	DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
    	if !(nCount && nSize)
    		return -2
    	
    	If (A_IsUnicode){
    		StrGet_Name := "StrGet"
    		Loop, %nCount%
    		{
    			sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
    			if !InStr(sString, "*" Extension)
    				continue
    			
    			pCodec := &ci+idx
    			break
    		}
    	} else {
    		Loop, %nCount%
    		{
    			Location := NumGet(ci, 76*(A_Index-1)+44)
    			nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
    			VarSetCapacity(sString, nSize)
    			DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
    			if !InStr(sString, "*" Extension)
    				continue
    			
    			pCodec := &ci+76*(A_Index-1)
    			break
    		}
    	}
    	
    	if !pCodec
    		return -3
     
    	if (Quality != 75)
    	{
    		Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
    		if Extension in .JPG,.JPEG,.JPE,.JFIF
    		{
    			DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
    			VarSetCapacity(EncoderParameters, nSize, 0)
    			DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
    			Loop, % NumGet(EncoderParameters, "UInt")      ;%
    			{
    				elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
    				if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
    				{
    					p := elem+&EncoderParameters-pad-4
    					NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
    					break
    				}
    			}      
    		}
    	}
     
    	if (!A_IsUnicode)
    	{
    		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
    		VarSetCapacity(wOutput, nSize*2)
    		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
    		VarSetCapacity(wOutput, -1)
    		if !VarSetCapacity(wOutput)
    			return -4
    		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", p ? p : 0)
    	}
    	else
    		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", p ? p : 0)
    	return E ? -5 : 0
    }
     
    ;#####################################################################################
     
    ; 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", A_PtrSize ? "UPtr" : "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", A_PtrSize ? "UPtr" : "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", A_PtrSize ? "UPtr" : "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", A_PtrSize ? "UPtr" : "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_GetImageDimensions(pBitmap, ByRef Width, ByRef Height)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	DllCall("gdiplus\GdipGetImageWidth", Ptr, pBitmap, "uint*", Width)
    	DllCall("gdiplus\GdipGetImageHeight", Ptr, pBitmap, "uint*", Height)
    }
     
    ;#####################################################################################
     
    Gdip_GetDimensions(pBitmap, ByRef Width, ByRef Height)
    {
    	Gdip_GetImageDimensions(pBitmap, Width, Height)
    }
     
    ;#####################################################################################
     
    Gdip_GetImagePixelFormat(pBitmap)
    {
    	DllCall("gdiplus\GdipGetImagePixelFormat", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "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", A_PtrSize ? "UPtr" : "uint", pGraphics, "float*", dpix)
    	return Round(dpix)
    }
     
    ;#####################################################################################
     
    Gdip_GetDpiY(pGraphics)
    {
    	DllCall("gdiplus\GdipGetDpiY", A_PtrSize ? "UPtr" : "uint", pGraphics, "float*", dpiy)
    	return Round(dpiy)
    }
     
    ;#####################################################################################
     
    Gdip_GetImageHorizontalResolution(pBitmap)
    {
    	DllCall("gdiplus\GdipGetImageHorizontalResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float*", dpix)
    	return Round(dpix)
    }
     
    ;#####################################################################################
     
    Gdip_GetImageVerticalResolution(pBitmap)
    {
    	DllCall("gdiplus\GdipGetImageVerticalResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float*", dpiy)
    	return Round(dpiy)
    }
     
    ;#####################################################################################
     
    Gdip_BitmapSetResolution(pBitmap, dpix, dpiy)
    {
    	return DllCall("gdiplus\GdipBitmapSetResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float", dpix, "float", dpiy)
    }
     
    ;#####################################################################################
     
    Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize="")
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	, PtrA := A_PtrSize ? "UPtr*" : "UInt*"
    	
    	SplitPath, sFile,,, ext
    	if ext in exe,dll
    	{
    		Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16
    		BufSize := 16 + (2*(A_PtrSize ? A_PtrSize : 4))
    		
    		VarSetCapacity(buf, BufSize, 0)
    		Loop, Parse, Sizes, |
    		{
    			DllCall("PrivateExtractIcons", "str", sFile, "int", IconNumber-1, "int", A_LoopField, "int", A_LoopField, PtrA, hIcon, PtrA, 0, "uint", 1, "uint", 0)
    			
    			if !hIcon
    				continue
     
    			if !DllCall("GetIconInfo", Ptr, hIcon, Ptr, &buf)
    			{
    				DestroyIcon(hIcon)
    				continue
    			}
    			
    			hbmMask  := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4))
    			hbmColor := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4) + (A_PtrSize ? A_PtrSize : 4))
    			if !(hbmColor && DllCall("GetObject", Ptr, hbmColor, "int", BufSize, Ptr, &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", Ptr, hdc, "int", 0, "int", 0, Ptr, hIcon, "uint", Width, "uint", Height, "uint", 0, Ptr, 0, "uint", 3)
    		{
    			DestroyIcon(hIcon)
    			return -2
    		}
    		
    		VarSetCapacity(dib, 104)
    		DllCall("GetObject", Ptr, hbm, "int", A_PtrSize = 8 ? 104 : 84, Ptr, &dib) ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize
    		Stride := NumGet(dib, 12, "Int"), Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0)) ; padding
    		DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", Stride, "int", 0x26200A, Ptr, Bits, PtrA, 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, 1024)
    			DllCall("kernel32\MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sFile, "int", -1, Ptr, &wFile, "int", 512)
    			DllCall("gdiplus\GdipCreateBitmapFromFile", Ptr, &wFile, PtrA, pBitmap)
    		}
    		else
    			DllCall("gdiplus\GdipCreateBitmapFromFile", Ptr, &sFile, PtrA, pBitmap)
    	}
    	
    	return pBitmap
    }
     
    ;#####################################################################################
     
    Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
    	return pBitmap
    }
     
    ;#####################################################################################
     
    Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)
    {
    	DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "uint*", hbm, "int", Background)
    	return hbm
    }
     
    ;#####################################################################################
     
    Gdip_CreateBitmapFromHICON(hIcon)
    {
    	DllCall("gdiplus\GdipCreateBitmapFromHICON", A_PtrSize ? "UPtr" : "UInt", hIcon, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
    	return pBitmap
    }
     
    ;#####################################################################################
     
    Gdip_CreateHICONFromBitmap(pBitmap)
    {
    	DllCall("gdiplus\GdipCreateHICONFromBitmap", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "uint*", hIcon)
    	return hIcon
    }
     
    ;#####################################################################################
     
    Gdip_CreateBitmap(Width, Height, Format=0x26200A)
    {
        DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", 0, "int", Format, A_PtrSize ? "UPtr" : "UInt", 0, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
        Return pBitmap
    }
     
    ;#####################################################################################
     
    Gdip_CreateBitmapFromClipboard()
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	if !DllCall("OpenClipboard", Ptr, 0)
    		return -1
    	if !DllCall("IsClipboardFormatAvailable", "uint", 8)
    		return -2
    	if !hBitmap := DllCall("GetClipboardData", "uint", 2, Ptr)
    		return -3
    	if !pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap)
    		return -4
    	if !DllCall("CloseClipboard")
    		return -5
    	DeleteObject(hBitmap)
    	return pBitmap
    }
     
    ;#####################################################################################
     
    Gdip_SetBitmapToClipboard(pBitmap)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	off1 := A_PtrSize = 8 ? 52 : 44, off2 := A_PtrSize = 8 ? 32 : 24
    	
    	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
    	DllCall("GetObject", Ptr, hBitmap, "int", VarSetCapacity(oi, A_PtrSize = 8 ? 96 : 84, 0), Ptr, &oi)
    	hdib := DllCall("GlobalAlloc", "uint", 2, Ptr, off1+NumGet(oi, off1, "UInt")-4, Ptr)
    	pdib := DllCall("GlobalLock", Ptr, hdib, Ptr)
    	DllCall("RtlMoveMemory", Ptr, pdib, "uint", &oi+off2, Ptr, 40)
    	DllCall("RtlMoveMemory", Ptr, pdib+40, Ptr, NumGet(oi, off2 - (A_PtrSize ? A_PtrSize : 4)), Ptr, NumGet(oi, off1, "UInt"))
    	DllCall("GlobalUnlock", Ptr, hdib)
    	DllCall("DeleteObject", Ptr, hBitmap)
    	DllCall("OpenClipboard", Ptr, 0)
    	DllCall("EmptyClipboard")
    	DllCall("SetClipboardData", "uint", 8, Ptr, 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
    					, A_PtrSize ? "UPtr" : "UInt", pBitmap
    					, A_PtrSize ? "UPtr*" : "UInt*", pBitmapDest)
    	return pBitmapDest
    }
     
    ;#####################################################################################
    ; Create resources
    ;#####################################################################################
     
    Gdip_CreatePen(ARGB, w)
    {
       DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)
       return pPen
    }
     
    ;#####################################################################################
     
    Gdip_CreatePenFromBrush(pBrush, w)
    {
    	DllCall("gdiplus\GdipCreatePen2", A_PtrSize ? "UPtr" : "UInt", pBrush, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)
    	return pPen
    }
     
    ;#####################################################################################
     
    Gdip_BrushCreateSolid(ARGB=0xff000000)
    {
    	DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, A_PtrSize ? "UPtr*" : "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, "UInt", ARGBfront, "UInt", ARGBback, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
    	return pBrush
    }
     
    ;#####################################################################################
     
    Gdip_CreateTextureBrush(pBitmap, WrapMode=1, x=0, y=0, w="", h="")
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	, PtrA := A_PtrSize ? "UPtr*" : "UInt*"
    	
    	if !(w && h)
    		DllCall("gdiplus\GdipCreateTexture", Ptr, pBitmap, "int", WrapMode, PtrA, pBrush)
    	else
    		DllCall("gdiplus\GdipCreateTexture2", Ptr, pBitmap, "int", WrapMode, "float", x, "float", y, "float", w, "float", h, PtrA, pBrush)
    	return pBrush
    }
     
    ;#####################################################################################
     
    ; WrapModeTile = 0
    ; WrapModeTileFlipX = 1
    ; WrapModeTileFlipY = 2
    ; WrapModeTileFlipXY = 3
    ; WrapModeClamp = 4
    Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode=1)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	CreatePointF(PointF1, x1, y1), CreatePointF(PointF2, x2, y2)
    	DllCall("gdiplus\GdipCreateLineBrush", Ptr, &PointF1, Ptr, &PointF2, "Uint", ARGB1, "Uint", ARGB2, "int", WrapMode, A_PtrSize ? "UPtr*" : "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", A_PtrSize ? "UPtr" : "UInt", &RectF, "int", ARGB1, "int", ARGB2, "int", LinearGradientMode, "int", WrapMode, A_PtrSize ? "UPtr*" : "UInt*", LGpBrush)
    	return LGpBrush
    }
     
    ;#####################################################################################
     
    Gdip_CloneBrush(pBrush)
    {
    	DllCall("gdiplus\GdipCloneBrush", A_PtrSize ? "UPtr" : "UInt", pBrush, A_PtrSize ? "UPtr*" : "UInt*", pBrushClone)
    	return pBrushClone
    }
     
    ;#####################################################################################
    ; Delete resources
    ;#####################################################################################
     
    Gdip_DeletePen(pPen)
    {
       return DllCall("gdiplus\GdipDeletePen", A_PtrSize ? "UPtr" : "UInt", pPen)
    }
     
    ;#####################################################################################
     
    Gdip_DeleteBrush(pBrush)
    {
       return DllCall("gdiplus\GdipDeleteBrush", A_PtrSize ? "UPtr" : "UInt", pBrush)
    }
     
    ;#####################################################################################
     
    Gdip_DisposeImage(pBitmap)
    {
       return DllCall("gdiplus\GdipDisposeImage", A_PtrSize ? "UPtr" : "UInt", pBitmap)
    }
     
    ;#####################################################################################
     
    Gdip_DeleteGraphics(pGraphics)
    {
       return DllCall("gdiplus\GdipDeleteGraphics", A_PtrSize ? "UPtr" : "UInt", pGraphics)
    }
     
    ;#####################################################################################
     
    Gdip_DisposeImageAttributes(ImageAttr)
    {
    	return DllCall("gdiplus\GdipDisposeImageAttributes", A_PtrSize ? "UPtr" : "UInt", ImageAttr)
    }
     
    ;#####################################################################################
     
    Gdip_DeleteFont(hFont)
    {
       return DllCall("gdiplus\GdipDeleteFont", A_PtrSize ? "UPtr" : "UInt", hFont)
    }
     
    ;#####################################################################################
     
    Gdip_DeleteStringFormat(hFormat)
    {
       return DllCall("gdiplus\GdipDeleteStringFormat", A_PtrSize ? "UPtr" : "UInt", hFormat)
    }
     
    ;#####################################################################################
     
    Gdip_DeleteFontFamily(hFamily)
    {
       return DllCall("gdiplus\GdipDeleteFontFamily", A_PtrSize ? "UPtr" : "UInt", hFamily)
    }
     
    ;#####################################################################################
     
    Gdip_DeleteMatrix(Matrix)
    {
       return DllCall("gdiplus\GdipDeleteMatrix", A_PtrSize ? "UPtr" : "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)NoWrap", NoWrap)
    	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)
    	FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
    	hFormat := Gdip_StringFormatCreate(FormatStyle)
    	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)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	if (!A_IsUnicode)
    	{
    		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, 0, "int", 0)
    		VarSetCapacity(wString, nSize*2)
    		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
    	}
    	
    	return DllCall("gdiplus\GdipDrawString"
    					, Ptr, pGraphics
    					, Ptr, A_IsUnicode ? &sString : &wString
    					, "int", -1
    					, Ptr, hFont
    					, Ptr, &RectF
    					, Ptr, hFormat
    					, Ptr, pBrush)
    }
     
    ;#####################################################################################
     
    Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	VarSetCapacity(RC, 16)
    	if !A_IsUnicode
    	{
    		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, "uint", 0, "int", 0)
    		VarSetCapacity(wString, nSize*2)   
    		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
    	}
    	
    	DllCall("gdiplus\GdipMeasureString"
    					, Ptr, pGraphics
    					, Ptr, A_IsUnicode ? &sString : &wString
    					, "int", -1
    					, Ptr, hFont
    					, Ptr, &RectF
    					, Ptr, hFormat
    					, Ptr, &RC
    					, "uint*", Chars
    					, "uint*", Lines)
    	
    	return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
    }
     
    ; Near = 0
    ; Center = 1
    ; Far = 2
    Gdip_SetStringFormatAlign(hFormat, Align)
    {
       return DllCall("gdiplus\GdipSetStringFormatAlign", A_PtrSize ? "UPtr" : "UInt", hFormat, "int", Align)
    }
     
    ; StringFormatFlagsDirectionRightToLeft    = 0x00000001
    ; StringFormatFlagsDirectionVertical       = 0x00000002
    ; StringFormatFlagsNoFitBlackBox           = 0x00000004
    ; StringFormatFlagsDisplayFormatControl    = 0x00000020
    ; StringFormatFlagsNoFontFallback          = 0x00000400
    ; StringFormatFlagsMeasureTrailingSpaces   = 0x00000800
    ; StringFormatFlagsNoWrap                  = 0x00001000
    ; StringFormatFlagsLineLimit               = 0x00002000
    ; StringFormatFlagsNoClip                  = 0x00004000 
    Gdip_StringFormatCreate(Format=0, Lang=0)
    {
       DllCall("gdiplus\GdipCreateStringFormat", "int", Format, "int", Lang, A_PtrSize ? "UPtr*" : "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", A_PtrSize ? "UPtr" : "UInt", hFamily, "float", Size, "int", Style, "int", 0, A_PtrSize ? "UPtr*" : "UInt*", hFont)
       return hFont
    }
     
    Gdip_FontFamilyCreate(Font)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	if (!A_IsUnicode)
    	{
    		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, "uint", 0, "int", 0)
    		VarSetCapacity(wFont, nSize*2)
    		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, Ptr, &wFont, "int", nSize)
    	}
    	
    	DllCall("gdiplus\GdipCreateFontFamilyFromName"
    					, Ptr, A_IsUnicode ? &Font : &wFont
    					, "uint", 0
    					, A_PtrSize ? "UPtr*" : "UInt*", hFamily)
    	
    	return hFamily
    }
     
    ;#####################################################################################
    ; 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, A_PtrSize ? "UPtr*" : "UInt*", Matrix)
       return Matrix
    }
     
    Gdip_CreateMatrix()
    {
       DllCall("gdiplus\GdipCreateMatrix", A_PtrSize ? "UPtr*" : "UInt*", Matrix)
       return Matrix
    }
     
    ;#####################################################################################
    ; GraphicsPath functions
    ;#####################################################################################
     
    ; Alternate = 0
    ; Winding = 1
    Gdip_CreatePath(BrushMode=0)
    {
    	DllCall("gdiplus\GdipCreatePath", "int", BrushMode, A_PtrSize ? "UPtr*" : "UInt*", Path)
    	return Path
    }
     
    Gdip_AddPathEllipse(Path, x, y, w, h)
    {
    	return DllCall("gdiplus\GdipAddPathEllipse", A_PtrSize ? "UPtr" : "UInt", Path, "float", x, "float", y, "float", w, "float", h)
    }
     
    Gdip_AddPathPolygon(Path, Points)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	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", Ptr, Path, Ptr, &PointF, "int", Points0)
    }
     
    Gdip_DeletePath(Path)
    {
    	return DllCall("gdiplus\GdipDeletePath", A_PtrSize ? "UPtr" : "UInt", Path)
    }
     
    ;#####################################################################################
    ; Quality functions
    ;#####################################################################################
     
    ; SystemDefault = 0
    ; SingleBitPerPixelGridFit = 1
    ; SingleBitPerPixel = 2
    ; AntiAliasGridFit = 3
    ; AntiAlias = 4
    Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
    {
    	return DllCall("gdiplus\GdipSetTextRenderingHint", A_PtrSize ? "UPtr" : "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", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", InterpolationMode)
    }
     
    ; Default = 0
    ; HighSpeed = 1
    ; HighQuality = 2
    ; None = 3
    ; AntiAlias = 4
    Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
    {
       return DllCall("gdiplus\GdipSetSmoothingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", SmoothingMode)
    }
     
    ; CompositingModeSourceOver = 0 (blended)
    ; CompositingModeSourceCopy = 1 (overwrite)
    Gdip_SetCompositingMode(pGraphics, CompositingMode=0)
    {
       return DllCall("gdiplus\GdipSetCompositingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", CompositingMode)
    }
     
    ;#####################################################################################
    ; Extra functions
    ;#####################################################################################
     
    Gdip_Startup()
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
    		DllCall("LoadLibrary", "str", "gdiplus")
    	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
    	DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
    	return pToken
    }
     
    Gdip_Shutdown(pToken)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
    	if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
    		DllCall("FreeLibrary", Ptr, hModule)
    	return 0
    }
     
    ; 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", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", Angle, "int", MatrixOrder)
    }
     
    Gdip_ScaleWorldTransform(pGraphics, x, y, MatrixOrder=0)
    {
    	return DllCall("gdiplus\GdipScaleWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "int", MatrixOrder)
    }
     
    Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder=0)
    {
    	return DllCall("gdiplus\GdipTranslateWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "int", MatrixOrder)
    }
     
    Gdip_ResetWorldTransform(pGraphics)
    {
    	return DllCall("gdiplus\GdipResetWorldTransform", A_PtrSize ? "UPtr" : "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)))
    }
     
    ; RotateNoneFlipNone   = 0
    ; Rotate90FlipNone     = 1
    ; Rotate180FlipNone    = 2
    ; Rotate270FlipNone    = 3
    ; RotateNoneFlipX      = 4
    ; Rotate90FlipX        = 5
    ; Rotate180FlipX       = 6
    ; Rotate270FlipX       = 7
    ; RotateNoneFlipY      = Rotate180FlipX
    ; Rotate90FlipY        = Rotate270FlipX
    ; Rotate180FlipY       = RotateNoneFlipX
    ; Rotate270FlipY       = Rotate90FlipX
    ; RotateNoneFlipXY     = Rotate180FlipNone
    ; Rotate90FlipXY       = Rotate270FlipNone
    ; Rotate180FlipXY      = RotateNoneFlipNone
    ; Rotate270FlipXY      = Rotate90FlipNone 
     
    Gdip_ImageRotateFlip(pBitmap, RotateFlipType=1)
    {
    	return DllCall("gdiplus\GdipImageRotateFlip", A_PtrSize ? "UPtr" : "UInt", pBitmap, "int", RotateFlipType)
    }
     
    ; 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",  A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
    }
     
    Gdip_SetClipPath(pGraphics, Path, CombineMode=0)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	return DllCall("gdiplus\GdipSetClipPath", Ptr, pGraphics, Ptr, Path, "int", CombineMode)
    }
     
    Gdip_ResetClip(pGraphics)
    {
       return DllCall("gdiplus\GdipResetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics)
    }
     
    Gdip_GetClipRegion(pGraphics)
    {
    	Region := Gdip_CreateRegion()
    	DllCall("gdiplus\GdipGetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics, "UInt*", Region)
    	return Region
    }
     
    Gdip_SetClipRegion(pGraphics, Region, CombineMode=0)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("gdiplus\GdipSetClipRegion", Ptr, pGraphics, Ptr, Region, "int", CombineMode)
    }
     
    Gdip_CreateRegion()
    {
    	DllCall("gdiplus\GdipCreateRegion", "UInt*", Region)
    	return Region
    }
     
    Gdip_DeleteRegion(Region)
    {
    	return DllCall("gdiplus\GdipDeleteRegion", A_PtrSize ? "UPtr" : "UInt", Region)
    }
     
    ;#####################################################################################
    ; BitmapLockBits
    ;#####################################################################################
     
    Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode = 3, PixelFormat = 0x26200a)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	CreateRect(Rect, x, y, w, h)
    	VarSetCapacity(BitmapData, 16+2*(A_PtrSize ? A_PtrSize : 4), 0)
    	E := DllCall("Gdiplus\GdipBitmapLockBits", Ptr, pBitmap, Ptr, &Rect, "uint", LockMode, "int", PixelFormat, Ptr, &BitmapData)
    	Stride := NumGet(BitmapData, 8, "Int")
    	Scan0 := NumGet(BitmapData, 16, Ptr)
    	return E
    }
     
    ;#####################################################################################
     
    Gdip_UnlockBits(pBitmap, ByRef BitmapData)
    {
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	return DllCall("Gdiplus\GdipBitmapUnlockBits", Ptr, pBitmap, Ptr, &BitmapData)
    }
     
    ;#####################################################################################
     
    Gdip_SetLockBitPixel(ARGB, Scan0, x, y, Stride)
    {
    	Numput(ARGB, Scan0+0, (x*4)+(y*Stride), "UInt")
    }
     
    ;#####################################################################################
     
    Gdip_GetLockBitPixel(Scan0, x, y, Stride)
    {
    	return NumGet(Scan0+0, (x*4)+(y*Stride), "UInt")
    }
     
    ;#####################################################################################
     
    Gdip_PixelateBitmap(pBitmap, ByRef pBitmapOut, BlockSize)
    {
    	static PixelateBitmap
    	
    	Ptr := A_PtrSize ? "UPtr" : "UInt"
    	
    	if (!PixelateBitmap)
    	{
    		if A_PtrSize != 8 ; x86 machine code
    		MCode_PixelateBitmap =
    		(LTrim Join
    		558BEC83EC3C8B4514538B5D1C99F7FB56578BC88955EC894DD885C90F8E830200008B451099F7FB8365DC008365E000894DC88955F08945E833FF897DD4
    		397DE80F8E160100008BCB0FAFCB894DCC33C08945F88945FC89451C8945143BD87E608B45088D50028BC82BCA8BF02BF2418945F48B45E02955F4894DC4
    		8D0CB80FAFCB03CA895DD08BD1895DE40FB64416030145140FB60201451C8B45C40FB604100145FC8B45F40FB604020145F883C204FF4DE475D6034D18FF
    		4DD075C98B4DCC8B451499F7F98945148B451C99F7F989451C8B45FC99F7F98945FC8B45F899F7F98945F885DB7E648B450C8D50028BC82BCA83C103894D
    		C48BC82BCA41894DF48B4DD48945E48B45E02955E48D0C880FAFCB03CA895DD08BD18BF38A45148B7DC48804178A451C8B7DF488028A45FC8804178A45F8
    		8B7DE488043A83C2044E75DA034D18FF4DD075CE8B4DCC8B7DD447897DD43B7DE80F8CF2FEFFFF837DF0000F842C01000033C08945F88945FC89451C8945
    		148945E43BD87E65837DF0007E578B4DDC034DE48B75E80FAF4D180FAFF38B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945CC0F
    		B6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604010145F883C104FF4DCC75D8FF45E4395DE47C9B8B4DF00FAFCB85C9740B8B451499F7
    		F9894514EB048365140033F63BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB
    		038975F88975E43BDE7E5A837DF0007E4C8B4DDC034DE48B75E80FAF4D180FAFF38B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955CC8A55
    		1488540E038A551C88118A55FC88540F018A55F888140183C104FF4DCC75DFFF45E4395DE47CA68B45180145E0015DDCFF4DC80F8594FDFFFF8B451099F7
    		FB8955F08945E885C00F8E450100008B45EC0FAFC38365DC008945D48B45E88945CC33C08945F88945FC89451C8945148945103945EC7E6085DB7E518B4D
    		D88B45080FAFCB034D108D50020FAF4D18034DDC8BF08BF88945F403CA2BF22BFA2955F4895DC80FB6440E030145140FB60101451C0FB6440F010145FC8B
    		45F40FB604080145F883C104FF4DC875D8FF45108B45103B45EC7CA08B4DD485C9740B8B451499F7F9894514EB048365140033F63BCE740B8B451C99F7F9
    		89451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975103975EC7E5585DB7E468B4DD88B450C
    		0FAFCB034D108D50020FAF4D18034DDC8BF08BF803CA2BF22BFA2BC2895DC88A551488540E038A551C88118A55FC88540F018A55F888140183C104FF4DC8
    		75DFFF45108B45103B45EC7CAB8BC3C1E0020145DCFF4DCC0F85CEFEFFFF8B4DEC33C08945F88945FC89451C8945148945103BC87E6C3945F07E5C8B4DD8
    		8B75E80FAFCB034D100FAFF30FAF4D188B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945C80FB6440E030145140FB60101451C0F
    		B6440F010145FC8B45F40FB604010145F883C104FF4DC875D833C0FF45108B4DEC394D107C940FAF4DF03BC874068B451499F7F933F68945143BCE740B8B
    		451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975083975EC7E63EB0233F639
    		75F07E4F8B4DD88B75E80FAFCB034D080FAFF30FAF4D188B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955108A551488540E038A551C8811
    		8A55FC88540F018A55F888140883C104FF4D1075DFFF45088B45083B45EC7C9F5F5E33C05BC9C21800
    		)
    		else ; x64 machine code
    		MCode_PixelateBitmap =
    		(LTrim Join
    		4489442418488954241048894C24085355565741544155415641574883EC28418BC1448B8C24980000004C8BDA99488BD941F7F9448BD0448BFA8954240C
    		448994248800000085C00F8E9D020000418BC04533E4458BF299448924244C8954241041F7F933C9898C24980000008BEA89542404448BE889442408EB05
    		4C8B5C24784585ED0F8E1A010000458BF1418BFD48897C2418450FAFF14533D233F633ED4533E44533ED4585C97E5B4C63BC2490000000418D040A410FAF
    		C148984C8D441802498BD9498BD04D8BD90FB642010FB64AFF4403E80FB60203E90FB64AFE4883C2044403E003F149FFCB75DE4D03C748FFCB75D0488B7C
    		24188B8C24980000004C8B5C2478418BC59941F7FE448BE8418BC49941F7FE448BE08BC59941F7FE8BE88BC69941F7FE8BF04585C97E4048639C24900000
    		004103CA4D8BC1410FAFC94863C94A8D541902488BCA498BC144886901448821408869FF408871FE4883C10448FFC875E84803D349FFC875DA8B8C249800
    		0000488B5C24704C8B5C24784183C20448FFCF48897C24180F850AFFFFFF8B6C2404448B2424448B6C24084C8B74241085ED0F840A01000033FF33DB4533
    		DB4533D24533C04585C97E53488B74247085ED7E42438D0C04418BC50FAF8C2490000000410FAFC18D04814863C8488D5431028BCD0FB642014403D00FB6
    		024883C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC17CB28BCD410FAFC985C9740A418BC299F7F98BF0EB0233F685C9740B418BC3
    		99F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585C97E4D4C8B74247885ED7E3841
    		8D0C14418BC50FAF8C2490000000410FAFC18D04814863C84A8D4431028BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2413BD17CBD
    		4C8B7424108B8C2498000000038C2490000000488B5C24704503E149FFCE44892424898C24980000004C897424100F859EFDFFFF448B7C240C448B842480
    		000000418BC09941F7F98BE8448BEA89942498000000896C240C85C00F8E3B010000448BAC2488000000418BCF448BF5410FAFC9898C248000000033FF33
    		ED33F64533DB4533D24533C04585FF7E524585C97E40418BC5410FAFC14103C00FAF84249000000003C74898488D541802498BD90FB642014403D00FB602
    		4883C2044403D80FB642FB03F00FB642FA03E848FFCB75DE488B5C247041FFC0453BC77CAE85C9740B418BC299F7F9448BE0EB034533E485C9740A418BC3
    		99F7F98BD8EB0233DB85C9740A8BC699F7F9448BD8EB034533DB85C9740A8BC599F7F9448BD0EB034533D24533C04585FF7E4E488B4C24784585C97E3541
    		8BC5410FAFC14103C00FAF84249000000003C74898488D540802498BC144886201881A44885AFF448852FE4883C20448FFC875E941FFC0453BC77CBE8B8C
    		2480000000488B5C2470418BC1C1E00203F849FFCE0F85ECFEFFFF448BAC24980000008B6C240C448BA4248800000033FF33DB4533DB4533D24533C04585
    		FF7E5A488B7424704585ED7E48418BCC8BC5410FAFC94103C80FAF8C2490000000410FAFC18D04814863C8488D543102418BCD0FB642014403D00FB60248
    		83C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC77CAB418BCF410FAFCD85C9740A418BC299F7F98BF0EB0233F685C9740B418BC399
    		F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585FF7E4E4585ED7E42418BCC8BC541
    		0FAFC903CA0FAF8C2490000000410FAFC18D04814863C8488B442478488D440102418BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2
    		413BD77CB233C04883C428415F415E415D415C5F5E5D5BC3
    		)
    		
    		VarSetCapacity(PixelateBitmap, StrLen(MCode_PixelateBitmap)//2)
    		Loop % StrLen(MCode_PixelateBitmap)//2		;%
    			NumPut("0x" SubStr(MCode_PixelateBitmap, (2*A_Index)-1, 2), PixelateBitmap, A_Index-1, "UChar")
    		DllCall("VirtualProtect", Ptr, &PixelateBitmap, Ptr, VarSetCapacity(PixelateBitmap), "uint", 0x40, A_PtrSize ? "UPtr*" : "UInt*", 0)
    	}
     
    	Gdip_GetImageDimensions(pBitmap, Width, Height)
    	
    	if (Width != Gdip_GetImageWidth(pBitmapOut) || Height != Gdip_GetImageHeight(pBitmapOut))
    		return -1
    	if (BlockSize > Width || BlockSize > Height)
    		return -2
     
    	E1 := Gdip_LockBits(pBitmap, 0, 0, Width, Height, Stride1, Scan01, BitmapData1)
    	E2 := Gdip_LockBits(pBitmapOut, 0, 0, Width, Height, Stride2, Scan02, BitmapData2)
    	if (E1 || E2)
    		return -3
     
    	E := DllCall(&PixelateBitmap, Ptr, Scan01, Ptr, Scan02, "int", Width, "int", Height, "int", Stride1, "int", BlockSize)
    	
    	Gdip_UnlockBits(pBitmap, BitmapData1), Gdip_UnlockBits(pBitmapOut, BitmapData2)
    	return 0
    }
     
    ;#####################################################################################
     
    Gdip_ToARGB(A, R, G, B)
    {
    	return (A << 24) | (R << 16) | (G << 8) | B
    }
     
    ;#####################################################################################
     
    Gdip_FromARGB(ARGB, ByRef A, ByRef R, ByRef G, ByRef B)
    {
    	A := (0xff000000 & ARGB) >> 24
    	R := (0x00ff0000 & ARGB) >> 16
    	G := (0x0000ff00 & ARGB) >> 8
    	B := 0x000000ff & ARGB
    }
     
    ;#####################################################################################
     
    Gdip_AFromARGB(ARGB)
    {
    	return (0xff000000 & ARGB) >> 24
    }
     
    ;#####################################################################################
     
    Gdip_RFromARGB(ARGB)
    {
    	return (0x00ff0000 & ARGB) >> 16
    }
     
    ;#####################################################################################
     
    Gdip_GFromARGB(ARGB)
    {
    	return (0x0000ff00 & ARGB) >> 8
    }
     
    ;#####################################################################################
     
    Gdip_BFromARGB(ARGB)
    {
    	return 0x000000ff & ARGB
    }
     
    ;#####################################################################################
     
    StrGetB(Address, Length=-1, Encoding=0)
    {
    	; Flexible parameter handling:
    	if Length is not integer
    	Encoding := Length,  Length := -1
     
    	; Check for obvious errors.
    	if (Address+0 < 1024)
    		return
     
    	; Ensure 'Encoding' contains a numeric identifier.
    	if Encoding = UTF-16
    		Encoding = 1200
    	else if Encoding = UTF-8
    		Encoding = 65001
    	else if SubStr(Encoding,1,2)="CP"
    		Encoding := SubStr(Encoding,3)
     
    	if !Encoding ; "" or 0
    	{
    		; No conversion necessary, but we might not want the whole string.
    		if (Length == -1)
    			Length := DllCall("lstrlen", "uint", Address)
    		VarSetCapacity(String, Length)
    		DllCall("lstrcpyn", "str", String, "uint", Address, "int", Length + 1)
    	}
    	else if Encoding = 1200 ; UTF-16
    	{
    		char_count := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0x400, "uint", Address, "int", Length, "uint", 0, "uint", 0, "uint", 0, "uint", 0)
    		VarSetCapacity(String, char_count)
    		DllCall("WideCharToMultiByte", "uint", 0, "uint", 0x400, "uint", Address, "int", Length, "str", String, "int", char_count, "uint", 0, "uint", 0)
    	}
    	else if Encoding is integer
    	{
    		; Convert from target encoding to UTF-16 then to the active code page.
    		char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", 0, "int", 0)
    		VarSetCapacity(String, char_count * 2)
    		char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", &String, "int", char_count * 2)
    		String := StrGetB(&String, char_count, 1200)
    	}
    	
    	return String
    }