From 915dedec1a50b38ee0fcd53867ae071e8fe97980 Mon Sep 17 00:00:00 2001 From: Teo <106943092+t3ohm@users.noreply.github.com> Date: Sat, 1 Oct 2022 17:22:52 -0700 Subject: [PATCH 01/12] Settings Panel, Splash, and other adjustments --- src/d2r-map.ahk | 276 +++----------------------------------- src/init/hotkeys.ahk | 155 +++++++++++++++++++-- src/init/readSettings.ahk | 11 +- src/localization.ahk | 2 +- src/splashrc2.png | Bin 0 -> 171546 bytes src/ui/map/Drawing.ahk | 4 +- src/ui/settingsPanel.ahk | Bin 87168 -> 91576 bytes src/ui/splash/splash.ahk | 51 +++++++ 8 files changed, 218 insertions(+), 281 deletions(-) create mode 100644 src/splashrc2.png create mode 100644 src/ui/splash/splash.ahk diff --git a/src/d2r-map.ahk b/src/d2r-map.ahk index b091fa1..c9b6f1d 100644 --- a/src/d2r-map.ahk +++ b/src/d2r-map.ahk @@ -17,6 +17,10 @@ SetControlDelay, -1 SendMode Input SetWorkingDir, %A_ScriptDir% SetTitleMatchMode, 2 + +global version := "3.0.3" +Splash() + #Include %A_ScriptDir%\include\classMemory.ahk #Include %A_ScriptDir%\include\logging.ahk #Include %A_ScriptDir%\include\Yaml.ahk @@ -60,6 +64,7 @@ SetTitleMatchMode, 2 #Include %A_ScriptDir%\ui\gdip\ItemLogLayer.ahk #Include %A_ScriptDir%\ui\gdip\ItemCounterLayer.ahk #Include %A_ScriptDir%\ui\gdip\BuffBarLayer.ahk +#Include %A_ScriptDir%\ui\splash\splash.ahk #Include %A_ScriptDir%\mapFunctions.ahk ;Add right click menu in tray @@ -71,7 +76,6 @@ Menu, Tray, Add, Reload, Reload Menu, Tray, Add Menu, Tray, Add, Exit, ExitMH -global version := "3.0.4" WriteLog("*******************************************************************") WriteLog("* Map overlay started https://github.com/joffreybesos/d2r-mapview *") @@ -80,6 +84,7 @@ WriteLog("Version: " version) WriteLog("Working folder: " A_ScriptDir) WriteLog("Please report issues in #support on discord: https://discord.gg/qEgqyVW3uj") ClearCache(A_Temp) +global gameWindowId global settings global defaultSettings readSettings("settings.ini", settings) @@ -89,7 +94,7 @@ checkServer(settings) lastMap := "" exitArray := [] helpToggle:= true -historyToggle := true +Global historyToggle := true global lastlevel:="" lastSeed:="" session := @@ -102,7 +107,7 @@ performanceMode := settings["performanceMode"] if (performanceMode != 0) { SetBatchLines, %performanceMode% } - +global pToken global sp := A_ScriptFullPath global isMapShowing:=1 global debug := settings["debug"] @@ -121,12 +126,9 @@ global offsets := [] global hudBitmaps := loadBitmaps() global buffBitmaps := loadBuffIcons() - -CreateSettingsGUI(settings, localizedStrings) +CreateSettingsGUI() settingupGUI := false -SetupHotKeys(gameWindowId, settings) - ; check that game is running if (not WinExist(gameWindowId)) { errornogame := localizedStrings["errormsg10"] @@ -138,9 +140,7 @@ if (not WinExist(gameWindowId)) { ; initialise memory reading global d2rprocess := initMemory(gameWindowId) patternScan(d2rprocess, offsets) -Gdip_Startup() - - +(pToken?:(pToken:=Gdip_Startup())) ; performance counters global ticktock := 0 @@ -161,8 +161,6 @@ uiAssistLayer := new UIAssistLayer(settings) buffBarLayer := new BuffBarLayer(settings) mapGuis := new MapGUIs(settings) unitsGui := new UnitsGUI(settings) - -OnMessage(0x0201, "WM_LBUTTONDOWN") ; main loop While 1 { @@ -359,252 +357,10 @@ While 1 { Sleep, ticksPerFrame - frameDuration } } - - -+F10::Gosub, ExitMH - -MapAlwaysShow: -{ - MapAlwaysShow(settings, gameMemoryData, mapGuis, unitsGui) - return -} - -MapSizeIncrease: -{ - MapSizeIncrease(settings, gameMemoryData) - mapGuis.setScale(settings) - unitsGui.setScale(settings) - mapGuis.setOffsetPosition(settings) - unitsGui.setOffsetPosition(settings) - return -} - -MapSizeDecrease: -{ - MapSizeDecrease(settings, gameMemoryData) - mapGuis.setScale(settings) - unitsGui.setScale(settings) - mapGuis.setOffsetPosition(settings) - unitsGui.setOffsetPosition(settings) - return -} - -SwitchMapMode: -{ - SwitchMapMode(settings, mapImageList, gameMemoryData, uiData) - mapGuis.setScale(settings) - unitsGui.setScale(settings) - mapGuis.setOffsetPosition(settings) - unitsGui.setOffsetPosition(settings) - return -} - -MoveMapLeft: -{ - MoveMapLeft(settings) - mapGuis.setScale(settings) - unitsGui.setScale(settings) - mapGuis.setOffsetPosition(settings) - unitsGui.setOffsetPosition(settings) - return -} -MoveMapRight: -{ - MoveMapRight(settings) - mapGuis.setScale(settings) - unitsGui.setScale(settings) - mapGuis.setOffsetPosition(settings) - unitsGui.setOffsetPosition(settings) - return -} -MoveMapUp: -{ - MoveMapUp(settings) - mapGuis.setScale(settings) - unitsGui.setScale(settings) - mapGuis.setOffsetPosition(settings) - unitsGui.setOffsetPosition(settings) - return -} -MoveMapDown: -{ - MoveMapDown(settings) - mapGuis.setScale(settings) - unitsGui.setScale(settings) - mapGuis.setOffsetPosition(settings) - unitsGui.setOffsetPosition(settings) - return -} -HistoryToggle: -{ - historyToggle := !historyToggle - ; settings["showGameInfo"] := historyToggle - ; IniWrite, %historyToggle%, settings.ini, Settings, showGameInfo - return -} - #IfWinActive ahk_exe D2R.exe -^H:: -{ - if (helpToggle) { - ShowHelpText(settings) - WriteLog("Show Help") - } else { - Gui, HelpText: Hide - WriteLog("Hide Help") - } - helpToggle := !helpToggle - return -} - -~Esc:: -{ - Gui, HelpText: Hide - helpToggle := 1 - return -} - -~+F11:: -{ - WriteLog("Reloading script!") - Reload - return -} - - -~+F9:: -{ - WriteLog("Debug mode set to " debug) - debug := !debug - return -} - -^O:: -{ - Gosub, ShowSettings - return -} - -^L:: -{ - if (buffBarLayer.locked) { - buffBarLayer.unlock() - } else { - buffBarLayer.lock() - } - - if (itemCounterLayer.locked) { - itemCounterLayer.unlock() - } else { - itemCounterLayer.lock() - } - return -} - -ExitMH: -{ - WriteLog("Pressed Shift+F10, exiting...") - session.saveEntry() - - ; performance stats - alreadyseenperf := [] - for k, perf in perfdata - { - - thisName := perf["name"] - if (!HasVal(alreadyseenperf, thisName)) { - averageVal := 0 - count := 0 - for k, perf2 in perfdata - { - thisName2 := perf2["name"] - if (thisName2 == thisName) { - averageVal := averageVal + perf2["duration"] - ++count - } - } - OutputDebug, % thisName " " Round(averageVal / count / 1000.0, 2) "ms, last measurement " Round(perf2["duration"] / 1000.0, 2) "ms `n" - alreadyseenperf.Push(thisName) - } - } - ExitApp - return -} - -; open the settings window and a given position -ShowSettings: -{ - uix := settings["settingsUIX"] - uiy := settings["settingsUIY"] - if (!uix) - uix := 100 - if (!uiy) - uiy := 100 - Gui, Settings: Show, x%uix% y%uiy% h482 w362, d2r-mapview settings - return -} - -; update settings (triggered when clicking save settings)` -Update: -{ - WriteLog("Applying new settings...") - UpdateSettings(settings, defaultSettings) - historyText.delete() - historyText := new SessionTableLayer(settings) - gameInfoLayer.delete() - gameInfoLayer := new GameInfoLayer(settings) - partyInfoLayer.delete() - partyInfoLayer := new PartyInfoLayer(settings) - uiAssistLayer.delete() - uiAssistLayer := new UIAssistLayer(settings) - itemLogLayer.delete() - itemLogLayer := new ItemLogLayer(settings) - itemCounterLayer.delete() - itemCounterLayer := new ItemCounterLayer(settings) - buffBarLayer.delete() - buffBarLayer := new BuffBarLayer(settings) - SetupHotKeys(gameWindowId, settings) - lastlevel := "INVALIDATED" - mapGuis.setScale(settings) - unitsGui.setScale(settings) - mapGuis.setOffsetPosition(settings) - unitsGui.setOffsetPosition(settings) - mapShowing := 0 - GuiControl, Hide, Unsaved - GuiControl, Disable, UpdateBtn - redrawMap := 1 - return -} - -UpdateFlag: -{ - if (!settingupGUI) { - GuiControl, Show, Unsaved6 - GuiControl, Enable, UpdateBtn - } - return -} - -Reload: -{ - Reload - return -} - -WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) { - if (buffBarLayer.buffBarLayerHwnd = hwnd) { - PostMessage, 0xA1, 2,,, A - keywait, lbutton - WinGetPos, X1,Y1, uptime - buffBarLayer.leftMargin := X1 - buffBarLayer.topMargin := Y1 - } - - if (itemCounterLayer.ItemCounterLayerHwnd = hwnd) { - PostMessage, 0xA1, 2,,, A - keywait, lbutton - WinGetPos, X1,Y1, uptime - itemCounterLayer.leftMargin := X1 - itemCounterLayer.topMargin := Y1 - } -} +~^H:: +~Esc::Help(A_ThisHotkey) +~^O::ShowSettings() +~+F9::debug() +~+F10::ExitMH(A_ThisHotkey) +~+F11::Reload() diff --git a/src/init/hotkeys.ahk b/src/init/hotkeys.ahk index 156c713..64a4b97 100644 --- a/src/init/hotkeys.ahk +++ b/src/init/hotkeys.ahk @@ -1,54 +1,189 @@ -SetupHotKeys(ByRef gameWindowId, ByRef settings) { +SetupHotKeys() { switchMapModeKey := settings["switchMapMode"] if (switchMapModeKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %switchMapModeKey%, SwitchMapMode + Hotkey, ~%switchMapModeKey%, SwitchMapMode } historyToggleKey := settings["historyToggleKey"] if (historyToggleKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %historyToggleKey%, HistoryToggle + Hotkey, ~%historyToggleKey%, HistoryToggle } alwaysShowKey := settings["alwaysShowKey"] if (alwaysShowKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %alwaysShowKey%, MapAlwaysShow + Hotkey, ~%alwaysShowKey%, MapAlwaysShow } increaseMapSizeKey := settings["increaseMapSizeKey"] if (increaseMapSizeKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %increaseMapSizeKey%, MapSizeIncrease + Hotkey, ~%increaseMapSizeKey%, MapSizeIncrease } decreaseMapSizeKey := settings["decreaseMapSizeKey"] if (decreaseMapSizeKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %decreaseMapSizeKey%, MapSizeDecrease + Hotkey, ~%decreaseMapSizeKey%, MapSizeDecrease } moveMapLeftKey := settings["moveMapLeft"] if (moveMapLeftKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %moveMapLeftKey%, MoveMapLeft + Hotkey, ~%moveMapLeftKey%, hkMoveMapLeft } moveMapRightKey := settings["moveMapRight"] if (moveMapLeftKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %moveMapRightKey%, MoveMapRight + Hotkey, ~%moveMapRightKey%, hkMoveMapRight } moveMapUpKey := settings["moveMapUp"] if (moveMapLeftKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %moveMapUpKey%, MoveMapUp + Hotkey, ~%moveMapUpKey%, hkMoveMapUp } moveMapDownKey := settings["moveMapDown"] if (moveMapLeftKey) { Hotkey, IfWinActive, % gameWindowId - Hotkey, %moveMapDownKey%, MoveMapDown + Hotkey, ~%moveMapDownKey%, hkMoveMapDown } } +HistoryToggle(){ + global + historyToggle := !historyToggle + ; settings["showGameInfo"] := historyToggle + ; IniWrite, %historyToggle%, settings.ini, Settings, showGameInfo +} + +hkMoveMapLeft(){ + MoveMapLeft(settings) + mapGuis.setScale(settings) + unitsGui.setScale(settings) + mapGuis.setOffsetPosition(settings) + unitsGui.setOffsetPosition(settings) + return +} + +hkMoveMapRight(){ + MoveMapRight(settings) + mapGuis.setScale(settings) + unitsGui.setScale(settings) + mapGuis.setOffsetPosition(settings) + unitsGui.setOffsetPosition(settings) + return +} + +hkMoveMapUp(){ + MoveMapUp(settings) + mapGuis.setScale(settings) + unitsGui.setScale(settings) + mapGuis.setOffsetPosition(settings) + unitsGui.setOffsetPosition(settings) + return +} + +hkMoveMapDown(){ + MoveMapDown(settings) + mapGuis.setScale(settings) + unitsGui.setScale(settings) + mapGuis.setOffsetPosition(settings) + unitsGui.setOffsetPosition(settings) + return +} + +debug(){ + WriteLog("Debug mode set to " debug) + debug := !debug +} + +Help(ThisHotkey){ + static helpToggle:= False + if (!(ThisHotkey ~= "Esc") and helpToggle := !helpToggle ) { + ShowHelpText(settings) + WriteLog("Show Help") + } else { + helpToggle := False + Gui, HelpText: Hide + WriteLog("Hide Help") + } + + return +} + +ExitMH(ThisHotkey=""){ + if ThisHotkey ~= "F10" + WriteLog("Pressed Shift+F10, exiting...") + session.saveEntry() + + ; performance stats + alreadyseenperf := [] + for k, perf in perfdata + { + + thisName := perf["name"] + if (!HasVal(alreadyseenperf, thisName)) { + averageVal := 0 + count := 0 + for k, perf2 in perfdata + { + thisName2 := perf2["name"] + if (thisName2 == thisName) { + averageVal := averageVal + perf2["duration"] + ++count + } + } + OutputDebug, % thisName " " Round(averageVal / count / 1000.0, 2) "ms, last measurement " Round(perf2["duration"] / 1000.0, 2) "ms `n" + alreadyseenperf.Push(thisName) + } + } + ExitApp +} + +Reload(){ + WriteLog("Reloading script!") + Reload +} + + +if false { +MapAlwaysShow: +{ + MapAlwaysShow(settings, gameMemoryData, mapGuis, unitsGui) + return +} + +MapSizeIncrease: +{ + MapSizeIncrease(settings, gameMemoryData) + mapGuis.setScale(settings) + unitsGui.setScale(settings) + mapGuis.setOffsetPosition(settings) + unitsGui.setOffsetPosition(settings) + return +} + +MapSizeDecrease: +{ + MapSizeDecrease(settings, gameMemoryData) + mapGuis.setScale(settings) + unitsGui.setScale(settings) + mapGuis.setOffsetPosition(settings) + unitsGui.setOffsetPosition(settings) + return +} + +SwitchMapMode: +{ + SwitchMapMode(settings, mapImageList, gameMemoryData, uiData) + mapGuis.setScale(settings) + unitsGui.setScale(settings) + mapGuis.setOffsetPosition(settings) + unitsGui.setOffsetPosition(settings) + return +} + +} \ No newline at end of file diff --git a/src/init/readSettings.ahk b/src/init/readSettings.ahk index c1bfe80..53d29b4 100644 --- a/src/init/readSettings.ahk +++ b/src/init/readSettings.ahk @@ -68,11 +68,6 @@ readSettings(settingsFile, ByRef settings) { settings["lastActiveGUITab"] := "Info" settings["settingsUIX"] := 100 settings["settingsUIY"] := 100 - - settings["buffBarX"] := 0 - settings["buffBarY"] := 0 - settings["itemCounterX"] := 0 - settings["itemCounterY"] := 0 settings["enableItemFilter"] := 1 settings["itemFontSize"] := 12 @@ -130,7 +125,7 @@ readSettings(settingsFile, ByRef settings) { settings["moveMapRight"] := "#Right" settings["moveMapUp"] := "#Up" settings["moveMapDown"] := "#Down" - settings["switchMapMode"] := "~\" + settings["switchMapMode"] := "\" settings["historyToggleKey"] := "^g" settings["performanceMode"] := "-1" settings["enableD2ML"] := 0 @@ -141,8 +136,8 @@ readSettings(settingsFile, ByRef settings) { settings["showPlayerMissiles"] := 1 settings["showEnemyMissiles"] := 1 settings["missileOpacity"] := "0x77" - settings["missileColorPhysicalMajor"] := "FFC2C2" - settings["missileColorPhysicalMinor"] := "C99D9D" + settings["missilePhysicalMajorColor"] := "FFC2C2" + settings["missilePhysicalMinorColor"] := "C99D9D" settings["missileFireMajorColor"] := "FF0000" settings["missileFireMinorColor"] := "C20000" settings["missileIceMajorColor"] := "00D0FF" diff --git a/src/localization.ahk b/src/localization.ahk index fab703d..6cc8d5f 100644 --- a/src/localization.ahk +++ b/src/localization.ahk @@ -20,7 +20,7 @@ LoadLocalization(ByRef settings) { if (settings["locale"] == "") { locale := GetLocale() settings["locale"] := locale - writeIniVar("locale", settings, defaultsettings) + writeIniVar("locale") } else { locale := settings["locale"] } diff --git a/src/splashrc2.png b/src/splashrc2.png new file mode 100644 index 0000000000000000000000000000000000000000..e4642e3d2158cdc5459d65c1321ed253e5a567b2 GIT binary patch literal 171546 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%0Aa(KpIY1SYhSC={ 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 z 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
  • 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 G?f(FPAHdrH diff --git a/src/ui/splash/splash.ahk b/src/ui/splash/splash.ahk new file mode 100644 index 0000000..f34898a --- /dev/null +++ b/src/ui/splash/splash.ahk @@ -0,0 +1,51 @@ +Splash(){ + global + (pToken?:(pToken:=Gdip_Startup())) + Gui, Splash:New, -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs + Gui, Splash:Default + Gui, Show, NA + OnMessage(0x201, "StartSettings") + Gui, hide + local hwnd1:= WinExist() + local pBitmap := Gdip_CreateBitmapFromFile(splashimg:="splashrc2.png") + if !pBitmap + exit + local Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap) + local (canvasWidth:=Width//2) , (canvasHeight:=Height//2) , (canvasCenterX:=canvasWidth/2) , (canvasCenterY:=canvasHeight/2) + local hbm := CreateDIBSection(canvasWidth, canvasHeight) + local hdc := CreateCompatibleDC() + local obm := SelectObject(hdc, hbm) + local G := Gdip_GraphicsFromHDC(hdc) + if (FileExist(exoFont:=(A_ScriptDir . "\exocetblizzardot-medium.otf"))){ + Font:=exoFont + } else if !Gdip_FontFamilyCreate(Font){ + Outputdebug, Font error!, The font you have specified does not exist on the system + Exit + } else { + exoFont := "ExocetBlizzardMixedCapsOTMedium" + } + Gdip_SetInterpolationMode(G, 7) + scarlet:=0xFF85000F + White:=0xFFFFFFFF + Black:=0xFF000000 + pBrush1 := Gdip_BrushCreateSolid(scarlet) + pBrush := Gdip_BrushCreateSolid(0xFF000000) + VersionSize:=Gdip_SizeObj(Gdip_TextToGraphics(G,version, "x" (canvasCenterX/1.5) " y" (canvasHeight-38) " c00FFFFFF s" 36, Font, Width, Height)) + + Gdip_FillRoundedRectangle(G,pBrush1,(canvasCenterX-VersionSize.centeroffset), canvasHeight-VersionSize.height-2,VersionSize.width-5, VersionSize.height,7) + Gdip_TextToGraphics(G,version, "x" (canvasCenterX-VersionSize.centeroffset)-2 " y" (canvasHeight-38)-3 " c" Strip0x(Black) " s" 36, Font, Width, Height) + Gdip_TextToGraphics(G,version, "x" (canvasCenterX-VersionSize.centeroffset) " y" (canvasHeight-38)-5 " c" Strip0x(White) " center s" 36, Font, Width, Height) + Gdip_DrawImage(G, pBitmap, 0, 0, canvasWidth, canvasHeight, 0, 0, Width, Height) + UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth/2)-(canvasWidth/2), (A_ScreenHeight/2)-(canvasHeight/2), canvasWidth, canvasHeight) + Gui, Show, NA + + SelectObject(hdc, obm) + DeleteObject(hbm) + DeleteDC(hdc) + Gdip_DeleteGraphics(G) + Gdip_DisposeImage(pBitmap) + SetTimer, SplashClose, -2000 +} +SplashClose(){ + Gui, Splash:Destroy +} \ No newline at end of file From feaadb5bae5d709c4c7ad122d70cf1400af018e6 Mon Sep 17 00:00:00 2001 From: Teo <106943092+t3ohm@users.noreply.github.com> Date: Sun, 2 Oct 2022 22:26:25 -0700 Subject: [PATCH 02/12] update --- src/d2r-map.ahk | 27 +++++++++++++-------------- src/init/readSettings.ahk | 5 +++++ src/ui/splash/splash.ahk | 22 +++++++++++++++------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/d2r-map.ahk b/src/d2r-map.ahk index c9b6f1d..cda6fbe 100644 --- a/src/d2r-map.ahk +++ b/src/d2r-map.ahk @@ -18,8 +18,8 @@ SendMode Input SetWorkingDir, %A_ScriptDir% SetTitleMatchMode, 2 -global version := "3.0.3" -Splash() +global version := "3.0._" +Splash(version,0,"StartSettings") #Include %A_ScriptDir%\include\classMemory.ahk #Include %A_ScriptDir%\include\logging.ahk @@ -125,7 +125,6 @@ global redrawMap := 1 global offsets := [] global hudBitmaps := loadBitmaps() global buffBitmaps := loadBuffIcons() - CreateSettingsGUI() settingupGUI := false @@ -152,16 +151,16 @@ fpsTimer := A_TickCount currentFPS := 0 ; ui layers -historyText := new SessionTableLayer(settings) -gameInfoLayer := new GameInfoLayer(settings) -partyInfoLayer := new PartyInfoLayer(settings) -itemLogLayer := new ItemLogLayer(settings) -itemCounterLayer := new ItemCounterLayer(settings) -uiAssistLayer := new UIAssistLayer(settings) -buffBarLayer := new BuffBarLayer(settings) +global historyText := new SessionTableLayer(settings) +global gameInfoLayer := new GameInfoLayer(settings) +global partyInfoLayer := new PartyInfoLayer(settings) +global itemLogLayer := new ItemLogLayer(settings) +global itemCounterLayer := new ItemCounterLayer(settings) +global uiAssistLayer := new UIAssistLayer(settings) +global buffBarLayer := new BuffBarLayer(settings) mapGuis := new MapGUIs(settings) unitsGui := new UnitsGUI(settings) - +ShowSettings() ; main loop While 1 { frameStart:=A_TickCount @@ -269,13 +268,13 @@ While 1 { mapLoading := 1 mapGuis.hide() unitsGui.hide() - - ShowText(settings, "Loading map data...`nPlease wait`nPress Ctrl+H for help`nPress Ctrl+O for settings", "44") ; 44 is opacity + Splash("loading",0) + ;ShowText(settings, "Loading map data...`nPlease wait`nPress Ctrl+H for help`nPress Ctrl+O for settings", "44") ; 44 is opacity ; Show Map mapGuis.downloadMapImages(mapList, gameMemoryData) mapLoading := 0 - Gui, LoadingText: Destroy ; remove loading text + SplashClose() ; remove loading text redrawMap := 1 } diff --git a/src/init/readSettings.ahk b/src/init/readSettings.ahk index 53d29b4..dbdecb5 100644 --- a/src/init/readSettings.ahk +++ b/src/init/readSettings.ahk @@ -152,6 +152,11 @@ readSettings(settingsFile, ByRef settings) { settings["missileMajorDotSize"] := "4" settings["missileMinorDotSize"] := "2" + settings["CustomSettings"] := 0 + settings["InvertedColors"] := 0 + settings["WindowColor"] := SySC.GetColor(SySC.COLOR_WINDOW) + settings["FontColor"] := SySC.GetColor(SySC.COLOR_WINDOWTEXT) + defaultSettings := settings.clone() ; read from the ini file and overwrite any of the above values diff --git a/src/ui/splash/splash.ahk b/src/ui/splash/splash.ahk index f34898a..f42d866 100644 --- a/src/ui/splash/splash.ahk +++ b/src/ui/splash/splash.ahk @@ -1,10 +1,10 @@ -Splash(){ +Splash(text:="",time:=1000,onclickcmd:=""){ global (pToken?:(pToken:=Gdip_Startup())) Gui, Splash:New, -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs Gui, Splash:Default Gui, Show, NA - OnMessage(0x201, "StartSettings") + OnMessage(0x201, onclickcmd?onclickcmd:"SplashClose") Gui, hide local hwnd1:= WinExist() local pBitmap := Gdip_CreateBitmapFromFile(splashimg:="splashrc2.png") @@ -30,12 +30,15 @@ Splash(){ Black:=0xFF000000 pBrush1 := Gdip_BrushCreateSolid(scarlet) pBrush := Gdip_BrushCreateSolid(0xFF000000) - VersionSize:=Gdip_SizeObj(Gdip_TextToGraphics(G,version, "x" (canvasCenterX/1.5) " y" (canvasHeight-38) " c00FFFFFF s" 36, Font, Width, Height)) + if (text = ""){ + text:=version + } + textSize:=Gdip_SizeObj(Gdip_TextToGraphics(G,text, "x" (canvasCenterX/1.5) " y" (canvasHeight-38) " c00FFFFFF s" 36, Font, Width, Height)) - Gdip_FillRoundedRectangle(G,pBrush1,(canvasCenterX-VersionSize.centeroffset), canvasHeight-VersionSize.height-2,VersionSize.width-5, VersionSize.height,7) - Gdip_TextToGraphics(G,version, "x" (canvasCenterX-VersionSize.centeroffset)-2 " y" (canvasHeight-38)-3 " c" Strip0x(Black) " s" 36, Font, Width, Height) - Gdip_TextToGraphics(G,version, "x" (canvasCenterX-VersionSize.centeroffset) " y" (canvasHeight-38)-5 " c" Strip0x(White) " center s" 36, Font, Width, Height) + Gdip_FillRoundedRectangle(G,pBrush1,(canvasCenterX-textSize.centeroffset), canvasHeight-textSize.height-2,textSize.width-5, textSize.height,7) Gdip_DrawImage(G, pBitmap, 0, 0, canvasWidth, canvasHeight, 0, 0, Width, Height) + Gdip_TextToGraphics(G,text, "x" (canvasCenterX-textSize.centeroffset)-2 " y" (canvasHeight-38)-3 " c" Strip0x(Black) " s" 36, Font, Width, Height) + Gdip_TextToGraphics(G,text, "x" (canvasCenterX-textSize.centeroffset) " y" (canvasHeight-38)-5 " c" Strip0x(White) " center s" 36, Font, Width, Height) UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth/2)-(canvasWidth/2), (A_ScreenHeight/2)-(canvasHeight/2), canvasWidth, canvasHeight) Gui, Show, NA @@ -44,7 +47,12 @@ Splash(){ DeleteDC(hdc) Gdip_DeleteGraphics(G) Gdip_DisposeImage(pBitmap) - SetTimer, SplashClose, -2000 + if time !=0 + { + OutputDebug, % time + SetTimer, SplashClose, % time + + } } SplashClose(){ Gui, Splash:Destroy From 962f9d642a8b423fa43ad22409edfb61a4cd462f Mon Sep 17 00:00:00 2001 From: Teo <106943092+t3ohm@users.noreply.github.com> Date: Mon, 10 Oct 2022 18:30:10 -0700 Subject: [PATCH 03/12] update/fixes to panel and splash --- src/d2r-map.ahk | 7 +- src/lib/colorpicker.ahk | 162 +++++++++++++++++++++++++++++++ src/ui/gdip/BuffBarLayer.ahk | 4 +- src/ui/gdip/ItemCounterLayer.ahk | 4 +- src/ui/image/clearCache.ahk | 4 - src/ui/settingsPanel.ahk | Bin 91576 -> 104912 bytes src/ui/splash/splash.ahk | 25 ++--- 7 files changed, 184 insertions(+), 22 deletions(-) create mode 100644 src/lib/colorpicker.ahk diff --git a/src/d2r-map.ahk b/src/d2r-map.ahk index cda6fbe..df84d81 100644 --- a/src/d2r-map.ahk +++ b/src/d2r-map.ahk @@ -1,3 +1,4 @@ +#Include, #SingleInstance, Force #Persistent #NoEnv @@ -19,7 +20,7 @@ SetWorkingDir, %A_ScriptDir% SetTitleMatchMode, 2 global version := "3.0._" -Splash(version,0,"StartSettings") +Splash(version,3000,"StartSettings") #Include %A_ScriptDir%\include\classMemory.ahk #Include %A_ScriptDir%\include\logging.ahk @@ -160,7 +161,7 @@ global uiAssistLayer := new UIAssistLayer(settings) global buffBarLayer := new BuffBarLayer(settings) mapGuis := new MapGUIs(settings) unitsGui := new UnitsGUI(settings) -ShowSettings() + ;ShowSettings() ; main loop While 1 { frameStart:=A_TickCount @@ -268,7 +269,7 @@ While 1 { mapLoading := 1 mapGuis.hide() unitsGui.hide() - Splash("loading",0) + Splash("loading",0,,0.25) ;ShowText(settings, "Loading map data...`nPlease wait`nPress Ctrl+H for help`nPress Ctrl+O for settings", "44") ; 44 is opacity ; Show Map mapGuis.downloadMapImages(mapList, gameMemoryData) diff --git a/src/lib/colorpicker.ahk b/src/lib/colorpicker.ahk new file mode 100644 index 0000000..6df1e9f --- /dev/null +++ b/src/lib/colorpicker.ahk @@ -0,0 +1,162 @@ +colorpicker(){ + global + Gui, ColorPicker:Default + Gui, -MinimizeBox + local progressX:=0 + local progressY:=5 + local progressS:=50 + glable:="gColorPickerUpdate" + Gui, Add, Progress, % "x" progressX " y"progressY " w" progressS " h" progressS " +C0xFF0000 vProg", 100 + Gui, Add, Edit, % "x" (progressX+=progressS) " y" (progressY) " w" 70 " h20 vHex " glable, 0xFFFF0000 + Gui, Font, s9 + local buttony:=progressY + Gui, Add, Button, % "x" progressX " y" (buttony+=20) " w" 70 " h" 15, CopyRGB + Gui, Add, Button, % "x" progressX " y" (buttony+=15 )" w" 70 " h" 15, CopyAlpha + ;Gui, Add, Button, % "x" 165 " y" buttony " w75 h23", Close + rgbtX:=13 , rgbty:=buttony+25 + Gui, Font, s12 + Gui, Add, Text, % "x" rgbtX " y" rgbty " w20 h20 Center", R + Gui, Font, s9 + Gui, Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vR " glable, 255 + Gui, Font, s12 + Gui, Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", G + Gui, Font, s9 + Gui, Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vG " glable, 0 + Gui, Font, s12 + Gui, Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", B + Gui, Font, s9 + Gui, Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vB " glable, 0 + Gui, Font, s12 + Gui, Add, Text, % "x" (rgbtX+=25) " y"rgbty " w25 h25 Center", A + Gui, Font, s9 + Gui, Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vA " glable, 255 + local sliderh:=150 + local sliderw:=25 + local sliderx:=10 + local slidery:=rgbty+50 + options:=" TickInterval1 +Vertical +0x20 +0x200 +Vertical +Invert +Center +Range0-255 -Tabstop AltSubmit " glable + Gui, Add, Slider, % "x" sliderx " y" slidery " w" sliderw " h" sliderh options " vRS", 255 + Gui, Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vGS", 0 + Gui, Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vBS", 0 + Gui, Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vAS", 255 + Gui, Show,, % "Color Picker" + +} + +ColorPickerGuiEscape(){ + ColorPickerGuiClose() +} +ColorPickerGuiClose(){ + Gui, ColorPicker:Destroy +} +ColorPickerButtonClose(){ + ColorPickerGuiClose() +} +ColorPickerUpdate(){ + GuiControlGet, RS + GuiControlGet, GS + GuiControlGet, BS + GuiControlGet, AS + + GuiControlGet, R + GuiControlGet, G + GuiControlGet, B + GuiControlGet, A + GuiControlGet, Hex + GuiControlGet, Prog + + ColorPickerSet("R", RS) + ColorPickerSet("G", GS) + ColorPickerSet("B", BS) + ColorPickerSet("A", AS) + ColorPickerSet("RS", R, "+Range0-255") + ColorPickerSet("GS", G, "+Range0-255") + ColorPickerSet("BS", B, "+Range0-255") + ColorPickerSet("AS", A, "+Range1-255") + ColorPickerSet("Hex", ARGB(R, G, B, A)) + ColorPickerSet("Prog",, "+C" ARGB(R, G, B)) +} + +ColorPickerButtonCopyRGB(){ + GuiControlGet, Hex + return Clipboard:=SubStr(Hex, 5) +} +ColorPickerButtonCopyAlpha(){ + GuiControlGet, R + GuiControlGet, G + GuiControlGet, B + GuiControlGet, A + return clipboard:=SubStr(ARGB(R, G, B, A), 1 , 4) +} + +ARGB(R, G, B, A := 00) { + lastformat:=A_FormatInteger + SetFormat, Integer, Hex + ARGB:=(A << 24) | (R << 16) | (G << 8) | B + setformat, integer, % lastformat + Return ARGB +} + +ColorPickerSet(Control, Data := "", AddOpt := "") { + GuiControl, %AddOpt%, %Control%, % Data + return !ErrorLevel +} +RGB300(Val_0_300){ + ; aa 0-300 for full hue + Max := 255 + a2 := 0 + a3 := 0 + n := Round(max/50,0) + if (aa:=Val_0_300) between 1 and 50 + { + a1 := Color300(max) + ab := aa*n + a2 := Color300(ab) + a3 := Color300(0) + } + if aa between 51 and 100 + { + a2 := Color300(max) + ab := (max-aa)*n + a1 := Color300(ab) + a3 := Color300(0) + } + if aa between 101 and 150 + { + a2 := Color300(max) + ab := (aa-100)*n + a3 := Color300(ab) + a1 := Color300(0) + } + if aa between 151 and 200 + { + a3 := Color300(max) + ab := (max-(aa-150))*n + a2 := Color300(ab) + a1 := Color300(0) + } + if aa between 201 and 250 + { + a3 := Color300(max) + ab := (aa-200)*n + a1 := Color300(ab) + a2 := Color300(0) + } + if aa between 251 and 300 + { + a1 := Color300(max) + ab := (max-(aa-250))*n + a3 := Color300(ab) + a2 := Color300(0) + } + return a1 a2 a3 +} +Color300(N) { ; Function borrowed from Wicked (http://www.autohotkey.com/forum/viewtopic.php?t=57368&postdays=0&postorder=asc&start=0) + SetFormat, Integer, Hex + N += 0 + SetFormat, Integer, D + StringTrimLeft, N, N, 2 + If(StrLen(N) < 2) + N = 0%N% + Return N +} \ No newline at end of file diff --git a/src/ui/gdip/BuffBarLayer.ahk b/src/ui/gdip/BuffBarLayer.ahk index 5c16290..9a7803a 100644 --- a/src/ui/gdip/BuffBarLayer.ahk +++ b/src/ui/gdip/BuffBarLayer.ahk @@ -67,8 +67,8 @@ class BuffBarLayer { this.locked := 1 settings["buffBarX"] := this.leftMargin settings["buffBarY"] := this.topMargin - writeIniVar("buffBarX", settings, 0) - writeIniVar("buffBarY", settings, 0) + writeIniVar("buffBarX") + writeIniVar("buffBarX") } checkHover(mouseX, mouseY) { diff --git a/src/ui/gdip/ItemCounterLayer.ahk b/src/ui/gdip/ItemCounterLayer.ahk index 1dfae27..2f20023 100644 --- a/src/ui/gdip/ItemCounterLayer.ahk +++ b/src/ui/gdip/ItemCounterLayer.ahk @@ -58,8 +58,8 @@ class ItemCounterLayer { this.locked := 1 settings["itemCounterX"] := this.leftMargin settings["itemCounterY"] := this.topMargin - writeIniVar("itemCounterX", settings, 0) - writeIniVar("itemCounterY", settings, 0) + writeIniVar("itemCounterX") + writeIniVar("itemCounterX") } drawItemCounter(ByRef HUDItems) { diff --git a/src/ui/image/clearCache.ahk b/src/ui/image/clearCache.ahk index e075317..4183d15 100644 --- a/src/ui/image/clearCache.ahk +++ b/src/ui/image/clearCache.ahk @@ -1,7 +1,3 @@ -#SingleInstance, Force -SendMode Input -SetWorkingDir, %A_ScriptDir% - ClearCache(folder) { files := 0 Loop Files, %folder%\*.png diff --git a/src/ui/settingsPanel.ahk b/src/ui/settingsPanel.ahk index 2927478c458137fe68b19049344a68de00abf065..52c40a0db4c10dd2e3c232182a6a94e04f5b2a8b 100644 GIT binary patch literal 104912 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 IUwIkxwl@B5N`F`>Hq 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 Date: Tue, 11 Oct 2022 18:32:38 -0700 Subject: [PATCH 04/12] Settings and Splash Update recommit --- src/d2r-map.ahk | 54 +- src/init/hotkeys.ahk | 30 +- src/init/readSettings.ahk | 13 +- src/lib/Gdip.ahk | 8414 +++++++++++++++++++ src/lib/SysC.ahk | 73 + src/lib/colorpicker.ahk | 162 - src/localization.ahk | 2 +- src/ui/gdip/BuffBarLayer.ahk | 4 +- src/ui/gdip/ItemCounterLayer.ahk | 4 +- src/ui/helper.ahk | 100 +- src/ui/image/clearCache.ahk | 4 + src/ui/map/Drawing.ahk | 4 +- src/ui/settingsPanel.ahk | Bin 87336 -> 111830 bytes src/ui/splash/splash.ahk | 23 +- src/{splashrc2.png => ui/splash/splash.png} | Bin 15 files changed, 8686 insertions(+), 201 deletions(-) create mode 100644 src/lib/Gdip.ahk create mode 100644 src/lib/SysC.ahk delete mode 100644 src/lib/colorpicker.ahk rename src/{splashrc2.png => ui/splash/splash.png} (100%) diff --git a/src/d2r-map.ahk b/src/d2r-map.ahk index df84d81..e55c8cf 100644 --- a/src/d2r-map.ahk +++ b/src/d2r-map.ahk @@ -1,4 +1,3 @@ -#Include, #SingleInstance, Force #Persistent #NoEnv @@ -19,14 +18,12 @@ SendMode Input SetWorkingDir, %A_ScriptDir% SetTitleMatchMode, 2 -global version := "3.0._" -Splash(version,3000,"StartSettings") - #Include %A_ScriptDir%\include\classMemory.ahk #Include %A_ScriptDir%\include\logging.ahk #Include %A_ScriptDir%\include\Yaml.ahk #Include %A_ScriptDir%\include\JSON.ahk -#Include %A_ScriptDir%\include\Gdip_All.ahk +;#Include %A_ScriptDir%\include\Gdip_All.ahk +#Include #Include %A_ScriptDir%\itemfilter\AlertList.ahk #Include %A_ScriptDir%\itemfilter\ItemAlert.ahk #Include %A_ScriptDir%\types\Areas.ahk @@ -68,6 +65,7 @@ Splash(version,3000,"StartSettings") #Include %A_ScriptDir%\ui\splash\splash.ahk #Include %A_ScriptDir%\mapFunctions.ahk + ;Add right click menu in tray Menu, Tray, NoStandard ; to remove default menu Menu, Tray, Tip, d2r-mapview @@ -77,7 +75,7 @@ Menu, Tray, Add, Reload, Reload Menu, Tray, Add Menu, Tray, Add, Exit, ExitMH - +global version := "3.0.4" WriteLog("*******************************************************************") WriteLog("* Map overlay started https://github.com/joffreybesos/d2r-mapview *") WriteLog("*******************************************************************") @@ -85,17 +83,19 @@ WriteLog("Version: " version) WriteLog("Working folder: " A_ScriptDir) WriteLog("Please report issues in #support on discord: https://discord.gg/qEgqyVW3uj") ClearCache(A_Temp) -global gameWindowId global settings global defaultSettings readSettings("settings.ini", settings) global localizedStrings := LoadLocalization(settings) + +StartSplash() ; moved to after settings init + CheckForUpdates() checkServer(settings) lastMap := "" exitArray := [] helpToggle:= true -Global historyToggle := true +historyToggle := true global lastlevel:="" lastSeed:="" session := @@ -108,7 +108,7 @@ performanceMode := settings["performanceMode"] if (performanceMode != 0) { SetBatchLines, %performanceMode% } -global pToken + global sp := A_ScriptFullPath global isMapShowing:=1 global debug := settings["debug"] @@ -126,9 +126,13 @@ global redrawMap := 1 global offsets := [] global hudBitmaps := loadBitmaps() global buffBitmaps := loadBuffIcons() + + CreateSettingsGUI() settingupGUI := false +SetupHotKeys(gameWindowId, settings) + ; check that game is running if (not WinExist(gameWindowId)) { errornogame := localizedStrings["errormsg10"] @@ -140,7 +144,9 @@ if (not WinExist(gameWindowId)) { ; initialise memory reading global d2rprocess := initMemory(gameWindowId) patternScan(d2rprocess, offsets) -(pToken?:(pToken:=Gdip_Startup())) +Gdip_Startup() + + ; performance counters global ticktock := 0 @@ -152,16 +158,18 @@ fpsTimer := A_TickCount currentFPS := 0 ; ui layers -global historyText := new SessionTableLayer(settings) -global gameInfoLayer := new GameInfoLayer(settings) -global partyInfoLayer := new PartyInfoLayer(settings) -global itemLogLayer := new ItemLogLayer(settings) -global itemCounterLayer := new ItemCounterLayer(settings) -global uiAssistLayer := new UIAssistLayer(settings) -global buffBarLayer := new BuffBarLayer(settings) +historyText := new SessionTableLayer(settings) +gameInfoLayer := new GameInfoLayer(settings) +partyInfoLayer := new PartyInfoLayer(settings) +itemLogLayer := new ItemLogLayer(settings) +itemCounterLayer := new ItemCounterLayer(settings) +uiAssistLayer := new UIAssistLayer(settings) +buffBarLayer := new BuffBarLayer(settings) mapGuis := new MapGUIs(settings) unitsGui := new UnitsGUI(settings) - ;ShowSettings() + +OnMessage(0x0201, "WM_LBUTTONDOWN") + ; main loop While 1 { frameStart:=A_TickCount @@ -269,13 +277,13 @@ While 1 { mapLoading := 1 mapGuis.hide() unitsGui.hide() - Splash("loading",0,,0.25) - ;ShowText(settings, "Loading map data...`nPlease wait`nPress Ctrl+H for help`nPress Ctrl+O for settings", "44") ; 44 is opacity + + LoadingSplash() ; Show Map mapGuis.downloadMapImages(mapList, gameMemoryData) mapLoading := 0 - SplashClose() ; remove loading text + Gui, LoadingText: Destroy ; remove loading text redrawMap := 1 } @@ -357,6 +365,10 @@ While 1 { Sleep, ticksPerFrame - frameDuration } } + + + +^L::buffbarLocker() #IfWinActive ahk_exe D2R.exe ~^H:: ~Esc::Help(A_ThisHotkey) diff --git a/src/init/hotkeys.ahk b/src/init/hotkeys.ahk index 64a4b97..b18a36d 100644 --- a/src/init/hotkeys.ahk +++ b/src/init/hotkeys.ahk @@ -1,5 +1,5 @@ -SetupHotKeys() { +SetupHotKeys(ByRef gameWindowId, ByRef settings){ switchMapModeKey := settings["switchMapMode"] if (switchMapModeKey) { Hotkey, IfWinActive, % gameWindowId @@ -52,6 +52,34 @@ SetupHotKeys() { } } +WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) { + if (buffBarLayer.buffBarLayerHwnd = hwnd) { + PostMessage, 0xA1, 2,,, A + keywait, lbutton + WinGetPos, X1,Y1, uptime + buffBarLayer.leftMargin := X1 + buffBarLayer.topMargin := Y1 + } + + if (itemCounterLayer.ItemCounterLayerHwnd = hwnd) { + PostMessage, 0xA1, 2,,, A + keywait, lbutton + WinGetPos, X1,Y1, uptime + itemCounterLayer.leftMargin := X1 + itemCounterLayer.topMargin := Y1 + } +} + +buffbarLocker(){ + + if (buffBarLayer.locked and itemCounterLayer.locked) { + buffBarLayer.unlock() + itemCounterLayer.unlock() + } else { + buffBarLayer.lock() + itemCounterLayer.lock() + } +} HistoryToggle(){ global historyToggle := !historyToggle diff --git a/src/init/readSettings.ahk b/src/init/readSettings.ahk index 3c23923..22a0026 100644 --- a/src/init/readSettings.ahk +++ b/src/init/readSettings.ahk @@ -68,6 +68,11 @@ readSettings(settingsFile, ByRef settings) { settings["lastActiveGUITab"] := "Info" settings["settingsUIX"] := 100 settings["settingsUIY"] := 100 + + settings["buffBarX"] := 0 + settings["buffBarY"] := 0 + settings["itemCounterX"] := 0 + settings["itemCounterY"] := 0 settings["enableItemFilter"] := 1 settings["itemFontSize"] := 12 @@ -127,7 +132,7 @@ readSettings(settingsFile, ByRef settings) { settings["moveMapRight"] := "#Right" settings["moveMapUp"] := "#Up" settings["moveMapDown"] := "#Down" - settings["switchMapMode"] := "\" + settings["switchMapMode"] := "~\" settings["historyToggleKey"] := "^g" settings["performanceMode"] := "-1" settings["enableD2ML"] := 0 @@ -159,6 +164,12 @@ readSettings(settingsFile, ByRef settings) { settings["WindowColor"] := SySC.GetColor(SySC.COLOR_WINDOW) settings["FontColor"] := SySC.GetColor(SySC.COLOR_WINDOWTEXT) + + + settings["StartSplash"] := 1 + settings["LoadingSplash"] := 1 + settings["SplashImg"] := A_ScriptDir "\ui\splash\splash.png" + defaultSettings := settings.clone() ; read from the ini file and overwrite any of the above values diff --git a/src/lib/Gdip.ahk b/src/lib/Gdip.ahk new file mode 100644 index 0000000..5057602 --- /dev/null +++ b/src/lib/Gdip.ahk @@ -0,0 +1,8414 @@ +; Link: https://raw.githubusercontent.com/marius-sucan/AHK-GDIp-Library-Compilation/master/ahk-v1-1/Gdip_All.ahk +; Author: +; Date: +; for: AHK_L + +/* + + +*/ + +; Gdip_All.ahk - GDI+ library compilation of user contributed GDI+ functions +; made by Marius Șucan: https://github.com/marius-sucan/AHK-GDIp-Library-Compilation +; a fork from: https://github.com/mmikeww/AHKv2-Gdip +; based on https://github.com/tariqporter/Gdip +; Supports: AHK_L / AHK_H Unicode/ANSI x86/x64 and AHK v2 alpha +; This file is the AHK v1.1 edition; for AHK v2 compatible edition, please see the repository. +; +; NOTES: The drawing of GDI+ Bitmaps is limited to a size +; of 32767 pixels in either direction (width, height). +; To calculate the largest bitmap you can create: +; The maximum object size is 2GB = 2,147,483,648 bytes +; Default bitmap is 32bpp (4 bytes), the largest area we can have is 2GB / 4 = 536,870,912 bytes +; If we want a square, the largest we can get is sqrt(2GB/4) = 23,170 pixels +; +; Gdip standard library versions: +; by Marius Șucan - gathered user-contributed functions and implemented hundreds of new functions +; - v1.85 on 24/08/2020 +; - v1.84 on 05/06/2020 +; - v1.83 on 24/05/2020 +; - v1.82 on 11/03/2020 +; - v1.81 on 25/02/2020 +; - v1.80 on 11/01/2019 +; - v1.79 on 10/28/2019 +; - v1.78 on 10/27/2019 +; - v1.77 on 10/06/2019 +; - v1.76 on 09/27/2019 +; - v1.75 on 09/23/2019 +; - v1.74 on 09/19/2019 +; - v1.73 on 09/17/2019 +; - v1.72 on 09/16/2019 +; - v1.71 on 09/15/2019 +; - v1.70 on 09/13/2019 +; - v1.69 on 09/12/2019 +; - v1.68 on 09/11/2019 +; - v1.67 on 09/10/2019 +; - v1.66 on 09/09/2019 +; - v1.65 on 09/08/2019 +; - v1.64 on 09/07/2019 +; - v1.63 on 09/06/2019 +; - v1.62 on 09/05/2019 +; - v1.61 on 09/04/2019 +; - v1.60 on 09/03/2019 +; - v1.59 on 09/01/2019 +; - v1.58 on 08/29/2019 +; - v1.57 on 08/23/2019 +; - v1.56 on 08/21/2019 +; - v1.55 on 08/14/2019 +; +; bug fixes and AHK v2 compatibility by mmikeww and others +; - v1.54 on 11/15/2017 +; - v1.53 on 06/19/2017 +; - v1.52 on 06/11/2017 +; - v1.51 on 01/27/2017 +; - v1.50 on 11/20/2016 +; +; - v1.47 on 02/20/2014 [?] +; +; modified by Rseding91 using fincs 64 bit compatible +; - v1.45 on 05/01/2013 +; +; by tic (Tariq Porter) +; - v1.45 on 07/09/2011 +; - v1.01 on 31/05/2008 +; +; Detailed history: +; - 24/08/2020 = Bug fixes and added Gdip_BlendBitmaps() and Gdip_SetAlphaChannel() +; - 05/06/2020 = Synchronized with mmikeww's repository and fixed a few bugs +; - 24/05/2020 = Added a few more functions and fixed or improved already exiting functions +; - 11/02/2020 = Imported updated MDMF functions from mmikeww, and AHK v2 examples, and other minor changes +; - 25/02/2020 = Added several new functions, including for color conversions [from Tidbit], improved/fixed several functions +; - 11/01/2019 = Implemented support for a private font file for Gdip_AddPathStringSimplified() +; - 10/28/2019 = Added 7 new GDI+ functions and fixes related to Gdip_CreateFontFamilyFromFile() +; - 10/27/2019 = Added 5 new GDI+ functions and bug fixes for Gdip_TestBitmapUniformity(), Gdip_RotateBitmapAtCenter() and Gdip_ResizeBitmap() +; - 10/06/2019 = Added more parameters to Gdip_GraphicsFromImage/HDC/HWND and added Gdip_GetPixelColor() +; - 09/27/2019 = bug fixes... +; - 09/23/2019 = Added 4 new functions and improved Gdip_CreateBitmap() [ Marius Șucan ] +; - 09/19/2019 = Added 4 new functions and improved Gdip_RotateBitmapAtCenter() [ Marius Șucan ] +; - 09/17/2019 = Added 6 new GDI+ functions and renamed curve related functions [ Marius Șucan ] +; - 09/16/2019 = Added 10 new GDI+ functions [ Marius Șucan ] +; - 09/15/2019 = Added 3 new GDI+ functions and improved Gdip_DrawStringAlongPolygon() [ Marius Șucan ] +; - 09/13/2019 = Added 10 new GDI+ functions [ Marius Șucan ] +; - 09/12/2019 = Added 6 new GDI+ functions [ Marius Șucan ] +; - 09/11/2019 = Added 10 new GDI+ functions [ Marius Șucan ] +; - 09/10/2019 = Added 17 new GDI+ functions [ Marius Șucan ] +; - 09/09/2019 = Added 14 new GDI+ functions [ Marius Șucan ] +; - 09/08/2019 = Added 3 new functions and fixed Gdip_SetPenDashArray() [ Marius Șucan ] +; - 09/07/2019 = Added 12 new functions [ Marius Șucan ] +; - 09/06/2019 = Added 14 new GDI+ functions [ Marius Șucan ] +; - 09/05/2019 = Added 27 new GDI+ functions [ Marius Șucan ] +; - 09/04/2019 = Added 36 new GDI+ functions [ Marius Șucan ] +; - 09/03/2019 = Added about 37 new GDI+ functions [ Marius Șucan ] +; - 08/29/2019 = Fixed Gdip_GetPropertyTagName() [on AHK v2], Gdip_GetPenColor() and Gdip_GetSolidFillColor(), added Gdip_LoadImageFromFile() +; - 08/23/2019 = Added Gdip_FillRoundedRectangle2() and Gdip_DrawRoundedRectangle2(); extracted from Gdip2 by Tariq [tic] and corrected functions names +; - 08/21/2019 = Added GenerateColorMatrix() by Marius Șucan +; - 08/19/2019 = Added 12 functions. Extracted from a class wrapper for GDI+ written by nnnik in 2017. +; - 08/18/2019 = Added Gdip_AddPathRectangle() and eight PathGradient related functions by JustMe +; - 08/16/2019 = Added Gdip_DrawImageFX(), Gdip_CreateEffect() and other related functions [ Marius Șucan ] +; - 08/15/2019 = Added Gdip_DrawRoundedLine() by DevX and Rabiator +; - 08/15/2019 = Added 11 GraphicsPath related functions by "Learning one" and updated by Marius Șucan +; - 08/14/2019 = Added Gdip_IsVisiblePathPoint() and RotateAtCenter() by RazorHalo +; - 08/08/2019 = Added Gdi_GetDIBits() and Gdi_CreateDIBitmap() by Marius Șucan +; - 07/19/2019 = Added Gdip_GetHistogram() by swagfag and GetProperty GDI+ functions by JustMe +; - 11/15/2017 = compatibility with both AHK v2 and v1, restored by nnnik +; - 06/19/2017 = Fixed few bugs from old syntax by Bartlomiej Uliasz +; - 06/11/2017 = made code compatible with new AHK v2.0-a079-be5df98 by Bartlomiej Uliasz +; - 01/27/2017 = fixed some bugs and made #Warn All compatible by Bartlomiej Uliasz +; - 11/20/2016 = fixed Gdip_BitmapFromBRA() by 'just me' +; - 11/18/2016 = backward compatible support for both AHK v1.1 and AHK v2 +; - 11/15/2016 = initial AHK v2 support by guest3456 +; - 02/20/2014 = fixed Gdip_CreateRegion() and Gdip_GetClipRegion() on AHK Unicode x86 +; - 05/13/2013 = fixed Gdip_SetBitmapToClipboard() on AHK Unicode x64 +; - 07/09/2011 = v1.45 release by tic (Tariq Porter) +; - 31/05/2008 = v1.01 release by tic (Tariq Porter) +; +;##################################################################################### +; 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 LIST +; See functions-list.txt file. +;##################################################################################### + + +UpdateLayeredWindow(hwnd, hdc, x:="", y:="", w:="", h:="", Alpha:=255) { +; 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 +; x, y x, y coordinates to place the window +; w, h Width and 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 are omitted, the layered window will use its current coordinates +; If w or h are omitted, the current width and height will be used + Static Ptr := "UPtr" + if ((x != "") && (y != "")) + VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt") + + if (w = "") || (h = "") + GetWindowRect(hwnd, W, H) + + 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) +} + +BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, raster:="") { +;##################################################################################### + +; 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, dY x, y coordinates of the destination upper-left corner +; dW, dH width and height of the area to copy +; sDC handle to source DC +; sX, sY x, y coordinates of the 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 +; +; Raster operation codes: +; 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 +; This function works only with GDI hBitmaps that +; are Device-Dependent Bitmaps [DDB]. + + Static Ptr := "UPtr" + return DllCall("gdi32\BitBlt" + , Ptr, dDC + , "int", dX, "int", dY + , "int", dW, "int", dH + , Ptr, sDC + , "int", sX, "int", sY + , "uint", Raster ? Raster : 0x00CC0020) +} + +StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster:="") { +;##################################################################################### + +; 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, dY x, y coordinates of the destination upper-left corner +; dW, dH width and height of the destination rectangle +; sdc handle to source DC +; sX, sY x, y coordinates of the source upper-left corner +; sW, sH width and height of the 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 + Static Ptr := "UPtr" + + 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 +; + +SetStretchBltMode(hdc, iStretchMode:=4) { +; iStretchMode options: +; BLACKONWHITE = 1 +; COLORONCOLOR = 3 +; HALFTONE = 4 +; WHITEONBLACK = 2 +; STRETCH_ANDSCANS = BLACKONWHITE +; STRETCH_DELETESCANS = COLORONCOLOR +; STRETCH_HALFTONE = HALFTONE +; STRETCH_ORSCANS = WHITEONBLACK + + return DllCall("gdi32\SetStretchBltMode" + , "UPtr", 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) { +; STM_SETIMAGE = 0x172 +; Example: Gui, Add, Text, 0xE w500 h300 hwndhPic ; SS_Bitmap = 0xE + + Static Ptr := "UPtr" + E := DllCall("SendMessage", Ptr, hwnd, "UInt", 0x172, "UInt", 0x0, Ptr, hBitmap ) + 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 + +SetSysColorToControl(hwnd, SysColor:=15) { +; SysColor options: +; 3DDKSHADOW = 21 +; 3DFACE = 15 +; 3DHIGHLIGHT = 20 +; 3DHILIGHT = 20 +; 3DLIGHT = 22 +; 3DSHADOW = 16 +; ACTIVEBORDER = 10 +; ACTIVECAPTION = 2 +; APPWORKSPACE = 12 +; BACKGROUND = 1 +; BTNFACE = 15 +; BTNHIGHLIGHT = 20 +; BTNHILIGHT = 20 +; BTNSHADOW = 16 +; BTNTEXT = 18 +; CAPTIONTEXT = 9 +; DESKTOP = 1 +; GRADIENTACTIVECAPTION 27 +; GRADIENTINACTIVECAPTION = 28 +; GRAYTEXT = 17 +; HIGHLIGHT = 13 +; HIGHLIGHTTEXT = 14 +; HOTLIGHT = 26 +; INACTIVEBORDER = 11 +; INACTIVECAPTION = 3 +; INACTIVECAPTIONTEXT = 19 +; INFOBK = 24 +; INFOTEXT = 23 +; MENU = 4 +; MENUHILIGHT = 29 +; MENUBAR = 30 +; MENUTEXT = 7 +; SCROLLBAR = 0 +; WINDOW = 5 +; WINDOWFRAME = 6 +; WINDOWTEXT = 8 + Static Ptr := "UPtr" + GetWindowRect(hwnd, W, H) + 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 parameters were not passed properly +; +; notes If no raster operation is specified, then SRCCOPY is used to the returned bitmap + +Gdip_BitmapFromScreen(Screen:=0, Raster:="") { + hhdc := 0 + Static Ptr := "UPtr" + if (Screen = 0) + { + _x := DllCall("GetSystemMetrics", "Int", 76 ) + _y := DllCall("GetSystemMetrics", "Int", 77 ) + _w := DllCall("GetSystemMetrics", "Int", 78 ) + _h := DllCall("GetSystemMetrics", "Int", 79 ) + } else if (SubStr(Screen, 1, 5) = "hwnd:") + { + hwnd := SubStr(Screen, 6) + if !WinExist("ahk_id " hwnd) + return -2 + + GetWindowRect(hwnd, _w, _h) + _x := _y := 0 + hhdc := GetDCEx(hwnd, 3) + } else if IsInteger(Screen) + { + M := GetMonitorInfo(Screen) + _x := M.Left, _y := M.Top, _w := M.Right-M.Left, _h := M.Bottom-M.Top + } else + { + S := StrSplit(Screen, "|") + _x := S[1], _y := S[2], _w := S[3], _h := S[4] + } + + 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 +; clientOnly capture only the client area of the window, without title bar and border +; +; return If the function succeeds, the return value is a pointer to a gdi+ bitmap + +Gdip_BitmapFromHWND(hwnd, clientOnly:=0) { + ; Restore the window if minimized! Must be visible for capture. + if DllCall("IsIconic", "ptr", hwnd) + DllCall("ShowWindow", "ptr", hwnd, "int", 4) + + Static Ptr := "UPtr" + thisFlag := 0 + If (clientOnly=1) + { + VarSetCapacity(rc, 16, 0) + DllCall("GetClientRect", "ptr", hwnd, "ptr", &rc) + Width := NumGet(rc, 8, "int") + Height := NumGet(rc, 12, "int") + thisFlag := 1 + } Else GetWindowRect(hwnd, Width, Height) + + hbm := CreateDIBSection(Width, Height) + hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm) + PrintWindow(hwnd, hdc, 2 + thisFlag) + 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, y x, y coordinates of the upper left corner of the rectangle +; w, h Width and 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 +; +; Rect Name to call the Rect object +; x, y x, y coordinates of the upper left corner of the rectangle +; x2, y2 x, y coordinates of the bottom right corner of the rectangle + +; return No return value + +CreateRect(ByRef Rect, x, y, x2, y2) { +; modified by Marius Șucan according to dangerdogL2121 +; found on https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-93 + + VarSetCapacity(Rect, 16) + NumPut(x, Rect, 0, "uint"), NumPut(y, Rect, 4, "uint") + NumPut(x2, Rect, 8, "uint"), NumPut(y2, Rect, 12, "uint") +} +;##################################################################################### + +; Function CreateSizeF +; Description Creates a SizeF object, containing an 2 values +; +; SizeF Name to call the SizeF object +; w, h width and height values 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 two values +; +; SizeF Name to call the SizeF object +; x, y x, y values 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") +} + +CreatePointsF(ByRef PointsF, inPoints) { + Points := StrSplit(inPoints, "|") + PointsCount := Points.Length() + VarSetCapacity(PointsF, 8 * PointsCount, 0) + for eachPoint, Point in Points + { + Coord := StrSplit(Point, ",") + NumPut(Coord[1], &PointsF, 8*(A_Index-1), "float") + NumPut(Coord[2], &PointsF, (8*(A_Index-1))+4, "float") + } + Return PointsCount +} + +;##################################################################################### + +; Function CreateDIBSection +; Description The CreateDIBSection function creates a DIB (Device Independent Bitmap) that applications can write to directly +; +; w, h width and 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, Usage:=0, hSection:=0, Offset:=0) { +; A GDI function that creates a new hBitmap, +; a device-independent bitmap [DIB]. +; A DIB consists of two distinct parts: +; a BITMAPINFO structure describing the dimensions +; and colors of the bitmap, and an array of bytes +; defining the pixels of the bitmap. + + Static Ptr := "UPtr" + hdc2 := hdc ? hdc : GetDC() + VarSetCapacity(bi, 40, 0) + NumPut(40, bi, 0, "uint") + NumPut(w, bi, 4, "uint") + NumPut(h, bi, 8, "uint") + NumPut(1, bi, 12, "ushort") + NumPut(bpp, bi, 14, "ushort") + NumPut(0, bi, 16, "uInt") + + hbm := DllCall("CreateDIBSection" + , Ptr, hdc2 + , Ptr, &bi ; BITMAPINFO + , "uint", Usage + , "UPtr*", ppvBits + , Ptr, hSection + , "uint", OffSet, 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:=2) { +; set Flags to 2, to capture hardware accelerated windows +; this only applies on Windows 8.1 and later versions. + + Static Ptr := "UPtr" + 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", "UPtr", hIcon) +} + +;##################################################################################### + +; Function: GetIconDimensions +; Description: Retrieves a given icon/cursor's width and height +; +; hIcon Pointer to an icon or cursor +; Width, Height ByRef variables. These variables are set to the icon's width and height +; +; return If the function succeeds, the return value is zero, otherwise: +; -1 = Could not retrieve the icon's info. Check A_LastError for extended information +; -2 = Could not delete the icon's bitmask bitmap +; -3 = Could not delete the icon's color bitmap + +GetIconDimensions(hIcon, ByRef Width, ByRef Height) { + Static Ptr := "UPtr" + Width := Height := 0 + + VarSetCapacity(ICONINFO, size := 16 + 2 * A_PtrSize, 0) + if !DllCall("user32\GetIconInfo", Ptr, hIcon, Ptr, &ICONINFO) + return -1 + + hbmMask := NumGet(&ICONINFO, 16, Ptr) + hbmColor := NumGet(&ICONINFO, 16 + A_PtrSize, Ptr) + VarSetCapacity(BITMAP, size, 0) + + if DllCall("gdi32\GetObject", Ptr, hbmColor, "Int", size, Ptr, &BITMAP) + { + Width := NumGet(&BITMAP, 4, "Int") + Height := NumGet(&BITMAP, 8, "Int") + } + + if !DeleteObject(hbmMask) + return -2 + + if !DeleteObject(hbmColor) + return -3 + + return 0 +} + +PaintDesktop(hdc) { + return DllCall("PaintDesktop", "UPtr", hdc) +} + +;##################################################################################### + +; 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", "UPtr", 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) { + Static Ptr := "UPtr" + 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", "UPtr", 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", "UPtr", hwnd) +} + +GetDCEx(hwnd, flags:=0, hrgnClip:=0) { +; Device Context extended flags: +; 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 + + Static Ptr := "UPtr" + 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) { + Static Ptr := "UPtr" + 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", "UPtr", 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 +; Updated by guest3456 preliminary AHK v2 support +; Updated by Marius Șucan reflecting the work on Gdip_all extended compilation + +Gdip_LibrarySubVersion() { + return 1.85 +} + +;##################################################################################### + +; 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) { + pBitmap := 0 + pStream := 0 + + If !(BRAFromMemIn) + Return -1 + Headers := StrSplit(StrGet(&BRAFromMemIn, 256, "CP0"), "`n") + Header := StrSplit(Headers.1, "|") + If (Header.Length() != 4) || (Header.2 != "BRA!") + Return -2 + _Info := StrSplit(Headers.2, "|") + If (_Info.Length() != 3) + Return -3 + OffsetTOC := StrPut(Headers.1, "CP0") + StrPut(Headers.2, "CP0") ; + 2 + OffsetData := _Info.2 + SearchIndex := Alternate ? 1 : 2 + TOC := StrGet(&BRAFromMemIn + OffsetTOC, OffsetData - OffsetTOC - 1, "CP0") + RX1 := A_AhkVersion < "2" ? "mi`nO)^" : "mi`n)^" + Offset := Size := 0 + If RegExMatch(TOC, RX1 . (Alternate ? File "\|.+?" : "\d+\|" . File) . "\|(\d+)\|(\d+)$", FileInfo) { + Offset := OffsetData + FileInfo.1 + Size := FileInfo.2 + } + If (Size=0) + Return -4 + hData := DllCall("GlobalAlloc", "UInt", 2, "UInt", Size, "UPtr") + pData := DllCall("GlobalLock", "Ptr", hData, "UPtr") + DllCall("RtlMoveMemory", "Ptr", pData, "Ptr", &BRAFromMemIn + Offset, "Ptr", Size) + DllCall("GlobalUnlock", "Ptr", hData) + DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", 1, "PtrP", pStream) + pBitmap := Gdip_CreateBitmapFromStream(pStream) + ObjRelease(pStream) + Return pBitmap +} + +;##################################################################################### + +; Function: Gdip_BitmapFromBase64 +; Description: Creates a bitmap from a Base64 encoded string +; +; Base64 ByRef variable. Base64 encoded string. Immutable, ByRef to avoid performance overhead of passing long strings. +; +; return If the function succeeds, the return value is a pointer to a bitmap, otherwise: +; -1 = Could not calculate the length of the required buffer +; -2 = Could not decode the Base64 encoded string +; -3 = Could not create a memory stream + +Gdip_BitmapFromBase64(ByRef Base64) { + Static Ptr := "UPtr" + pBitmap := 0 + DecLen := 0 + + ; calculate the length of the buffer needed + if !(DllCall("crypt32\CryptStringToBinary", Ptr, &Base64, "UInt", 0, "UInt", 0x01, Ptr, 0, "UIntP", DecLen, Ptr, 0, Ptr, 0)) + return -1 + + VarSetCapacity(Dec, DecLen, 0) + + ; decode the Base64 encoded string + if !(DllCall("crypt32\CryptStringToBinary", Ptr, &Base64, "UInt", 0, "UInt", 0x01, Ptr, &Dec, "UIntP", DecLen, Ptr, 0, Ptr, 0)) + return -2 + + ; create a memory stream + if !(pStream := DllCall("shlwapi\SHCreateMemStream", Ptr, &Dec, "UInt", DecLen, "UPtr")) + return -3 + + pBitmap := Gdip_CreateBitmapFromStream(pStream, 1) + ObjRelease(pStream) + + return pBitmap +} + +Gdip_CreateBitmapFromStream(pStream, ICM:=0) { + pBitmap := 0 + If (ICM=1) + DllCall("gdiplus\GdipCreateBitmapFromStreamICM", "UPtr", pStream, "PtrP", pBitmap) + Else + DllCall("gdiplus\GdipCreateBitmapFromStream", "UPtr", pStream, "PtrP", pBitmap) + 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, y x, y coordinates of the top left of the rectangle +; w, h width and 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) { + Static Ptr := "UPtr" + 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, y x, y coordinates of the top left of the rounded rectangle +; w, h width and height of the rectanlge +; 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 +} + +Gdip_DrawRoundedRectangle2(pGraphics, pPen, x, y, w, h, r, Angle:=0) { +; extracted from: https://github.com/tariqporter/Gdip2/blob/master/lib/Object.ahk +; and adapted by Marius Șucan + + penWidth := Gdip_GetPenWidth(pPen) + pw := penWidth / 2 + if (w <= h && (r + pw > w / 2)) + { + r := (w / 2 > pw) ? w / 2 - pw : 0 + } else if (h < w && r + pw > h / 2) + { + r := (h / 2 > pw) ? h / 2 - pw : 0 + } else if (r < pw / 2) + { + r := pw / 2 + } + + r2 := r * 2 + path1 := Gdip_CreatePath(0) + Gdip_AddPathArc(path1, x + pw, y + pw, r2, r2, 180, 90) + Gdip_AddPathLine(path1, x + pw + r, y + pw, x + w - r - pw, y + pw) + Gdip_AddPathArc(path1, x + w - r2 - pw, y + pw, r2, r2, 270, 90) + Gdip_AddPathLine(path1, x + w - pw, y + r + pw, x + w - pw, y + h - r - pw) + Gdip_AddPathArc(path1, x + w - r2 - pw, y + h - r2 - pw, r2, r2, 0, 90) + Gdip_AddPathLine(path1, x + w - r - pw, y + h - pw, x + r + pw, y + h - pw) + Gdip_AddPathArc(path1, x + pw, y + h - r2 - pw, r2, r2, 90, 90) + Gdip_AddPathLine(path1, x + pw, y + h - r - pw, x + pw, y + r + pw) + Gdip_ClosePathFigure(path1) + If (Angle>0) + Gdip_RotatePathAtCenter(path1, Angle) + _E := Gdip_DrawPath(pGraphics, pPen, path1) + Gdip_DeletePath(path1) + 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, y x, y coordinates of the top left of the rectangle the ellipse will be drawn into +; w, h width and 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) { + Static Ptr := "UPtr" + 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 +; A Bezier spline does not pass through its control points. The control points act as magnets, pulling the curve +; in certain directions to influence the way the spline bends. + +; pGraphics Pointer to the Graphics of a bitmap +; pPen Pointer to a pen +; x1, y1 x, y coordinates of the start of the bezier +; x2, y2 x, y coordinates of the first arc of the bezier +; x3, y3 x, y coordinates of the second arc of the bezier +; x4, y4 x, y coordinates 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) { + Static Ptr := "UPtr" + 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_DrawBezierCurve +; Description This function uses a pen to draw beziers +; Parameters: +; pGraphics Pointer to the Graphics of a bitmap +; pPen Pointer to a pen +; Points +; An array of starting and control points of a Bezier line +; A single Bezier line consists of 4 points a starting point 2 control +; points and an end point. +; The line never actually goes through the control points. +; The control points define the tangent in the starting and end points and their +; distance controls how strongly the curve follows there. +; +; Return: status enumeration. 0 = success +; +; This function was extracted and modified by Marius Șucan from +; a class based wrapper around the GDI+ API made by nnnik. +; Source: https://github.com/nnnik/classGDIp +; +; Points array format: +; Points := "x1,y1|x2,y2|x3,y3|x4,y4" [... and so on] + +Gdip_DrawBezierCurve(pGraphics, pPen, Points) { + iCount := CreatePointsF(PointsF, Points) + return DllCall("gdiplus\GdipDrawBeziers", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount) +} + +Gdip_DrawClosedCurve(pGraphics, pPen, Points, Tension:="") { +; Draws a closed cardinal spline on a pGraphics object using a pPen object. +; A cardinal spline is a curve that passes through each point in the array. + +; Tension: Non-negative real number that controls the length of the curve and how the curve bends. A value of +; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller. +; Number that specifies how tightly the curve bends through the coordinates of the closed cardinal spline. + +; Example points array: +; Points := "x1,y1|x2,y2|x3,y3" [and so on] +; At least three points must be defined. + + iCount := CreatePointsF(PointsF, Points) + If Tension + return DllCall("gdiplus\GdipDrawClosedCurve2", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount, "float", Tension) + Else + return DllCall("gdiplus\GdipDrawClosedCurve", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount) +} + +Gdip_DrawCurve(pGraphics, pPen, Points, Tension:="") { +; Draws an open spline on a pGraphics object using a pPen object. +; A cardinal spline is a curve that passes through each point in the array. + +; Tension: Non-negative real number that controls the length of the curve and how the curve bends. A value of +; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller. +; Number that specifies how tightly the curve bends through the coordinates of the closed cardinal spline. + +; Example points array: +; Points := "x1,y1|x2,y2|x3,y3" [and so on] +; At least three points must be defined. + + iCount := CreatePointsF(PointsF, Points) + If Tension + return DllCall("gdiplus\GdipDrawCurve2", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount, "float", Tension) + Else + return DllCall("gdiplus\GdipDrawCurve", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount) +} + +Gdip_DrawPolygon(pGraphics, pPen, Points) { +; Draws a closed polygonal line on a pGraphics object using a pPen object. +; +; Example points array: +; Points := "x1,y1|x2,y2|x3,y3" [and so on] + iCount := CreatePointsF(PointsF, Points) + return DllCall("gdiplus\GdipDrawPolygon", "UPtr", pGraphics, "UPtr", pPen, "UPtr", &PointsF, "UInt", iCount) +} + +;##################################################################################### + +; 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, y x, y coordinates of the start of the arc +; w, h width and 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) { + Static Ptr := "UPtr" + 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, y x, y coordinates of the start of the pie +; w, h width and 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) { + Static Ptr := "UPtr" + + 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, y1 x, y coordinates of the start of the line +; x2, y2 x, y coordinates of the end of the line +; +; return status enumeration. 0 = success + +Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2) { + Static Ptr := "UPtr" + 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) { + Static Ptr := "UPtr" + iCount := CreatePointsF(PointsF, Points) + return DllCall("gdiplus\GdipDrawLines", Ptr, pGraphics, Ptr, pPen, Ptr, &PointsF, "int", iCount) +} + +;##################################################################################### + +; 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, y x, y coordinates of the top left of the rectangle +; w, h width and height of the rectangle +; +; return status enumeration. 0 = success + +Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h) { + Static Ptr := "UPtr" + 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, y x, y coordinates of the top left of the rounded rectangle +; w, h width and height of the rectanlge +; r radius of the rounded corners +; +; return status enumeration. 0 = success + +Gdip_FillRoundedRectangle2(pGraphics, pBrush, x, y, w, h, r) { +; extracted from: https://github.com/tariqporter/Gdip2/blob/master/lib/Object.ahk +; and adapted by Marius Șucan + + r := (w <= h) ? (r < w // 2) ? r : w // 2 : (r < h // 2) ? r : h // 2 + path1 := Gdip_CreatePath(0) + Gdip_AddPathRectangle(path1, x+r, y, w-(2*r), r) + Gdip_AddPathRectangle(path1, x+r, y+h-r, w-(2*r), r) + Gdip_AddPathRectangle(path1, x, y+r, r, h-(2*r)) + Gdip_AddPathRectangle(path1, x+w-r, y+r, r, h-(2*r)) + Gdip_AddPathRectangle(path1, x+r, y+r, w-(2*r), h-(2*r)) + Gdip_AddPathPie(path1, x, y, 2*r, 2*r, 180, 90) + Gdip_AddPathPie(path1, x+w-(2*r), y, 2*r, 2*r, 270, 90) + Gdip_AddPathPie(path1, x, y+h-(2*r), 2*r, 2*r, 90, 90) + Gdip_AddPathPie(path1, x+w-(2*r), y+h-(2*r), 2*r, 2*r, 0, 90) + E := Gdip_FillPath(pGraphics, pBrush, path1) + Gdip_DeletePath(path1) + return E +} + +Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r) { + Region := Gdip_GetClipRegion(pGraphics) + Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4) + Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4) + Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4) + Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4) + _E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h) + Gdip_SetClipRegion(pGraphics, Region, 0) + Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4) + Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4) + Gdip_FillEllipse(pGraphics, pBrush, x, y, 2*r, 2*r) + Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r) + Gdip_FillEllipse(pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r) + Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r) + Gdip_SetClipRegion(pGraphics, Region, 0) + Gdip_DeleteRegion(Region) + return _E +} + +;##################################################################################### + +; 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) { + Static Ptr := "UPtr" + iCount := CreatePointsF(PointsF, Points) + return DllCall("gdiplus\GdipFillPolygon", Ptr, pGraphics, Ptr, pBrush, Ptr, &PointsF, "int", iCount, "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, y x, y coordinates of the top left of the pie +; w, h width and 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) { + Static Ptr := "UPtr" + 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, y x, y coordinates of the top left of the ellipse +; w, h width and height of the ellipse +; +; return status enumeration. 0 = success + +Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h) { + Static Ptr := "UPtr" + 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) { + Static Ptr := "UPtr" + 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, pPath) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipFillPath", Ptr, pGraphics, Ptr, pBrush, Ptr, pPath) +} +;##################################################################################### + +; Function Gdip_FillClosedCurve +; Description This function fills a closed cardinal spline on a pGraphics object +; using a pBrush object. +; A cardinal spline is a curve that passes through each point in the array. +; +; pGraphics Pointer to the Graphics of a bitmap +; pBrush Pointer to a brush +; +; Points array format: +; Points := "x1,y1|x2,y2|x3,y3|x4,y4" [... and so on] +; +; Tension Non-negative real number that controls the length of the curve and how the curve bends. A value of +; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller. +; Number that specifies how tightly the curve bends through the coordinates of the closed cardinal spline. +; +; Fill mode: 0 - [Alternate] The areas are filled according to the even-odd parity rule +; 1 - [Winding] The areas are filled according to the non-zero winding rule +; +; return status enumeration. 0 = success + +Gdip_FillClosedCurve(pGraphics, pBrush, Points, Tension:="", FillMode:=0) { + Static Ptr := "UPtr" + iCount := CreatePointsF(PointsF, Points) + If Tension + Return DllCall("gdiplus\GdipFillClosedCurve2", Ptr, pGraphics, Ptr, pBrush, "UPtr", &PointsF, "int", iCount, "float", Tension, "int", FillMode) + Else + Return DllCall("gdiplus\GdipFillClosedCurve", Ptr, pGraphics, Ptr, pBrush, "UPtr", &PointsF, "int", iCount) +} + +;##################################################################################### + +; 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, sY x, y coordinates of the source upper-left corner +; sW, sH width and height of the source rectangle +; Matrix a color matrix used to alter image attributes when drawing +; Unit see Gdip_DrawImage() +; Return status enumeration. 0 = success +; +; Notes If sx, sy, sw, sh are omitted 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 "|" delimiter. +; To generate a color matrix using user-friendly parameters, +; use GenerateColorMatrix() + +Gdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx:="", sy:="", sw:="", sh:="", Matrix:=1, Unit:=2, ImageAttr:=0) { + Static Ptr := "UPtr" + If !ImageAttr + { + if !IsNumber(Matrix) + 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") + } Else usrImageAttr := 1 + + if (sx="" && sy="" && sw="" && sh="") + { + sx := sy := 0 + Gdip_GetImageDimensions(pBitmap, sw, sh) + } + + iCount := CreatePointsF(PointsF, Points) + _E := DllCall("gdiplus\GdipDrawImagePointsRect" + , Ptr, pGraphics + , Ptr, pBitmap + , Ptr, &PointsF + , "int", iCount + , "float", sX + , "float", sY + , "float", sW + , "float", sH + , "int", Unit + , Ptr, ImageAttr ? ImageAttr : 0 + , Ptr, 0 + , Ptr, 0) + + if (ImageAttr && usrImageAttr!=1) + 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, dY x, y coordinates of the destination upper-left corner +; dW, dH width and height of the destination image +; sX, sY x, y coordinates of the source upper-left corner +; sW, sH width and height of the source image +; Matrix a color matrix used to alter image attributes when drawing +; Unit Unit of measurement: +; 0 - World coordinates, a nonphysical unit +; 1 - Display units +; 2 - A unit is 1 pixel +; 3 - A unit is 1 point or 1/72 inch +; 4 - A unit is 1 inch +; 5 - A unit is 1/300 inch +; 6 - A unit is 1 millimeter +; +; return status enumeration. 0 = success +; +; notes When sx,sy,sw,sh are omitted 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.0 - 1.0 to change just transparency +; Matrix can be passed as a matrix with "|" as 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 +; ) +; +; example color matrix: +; 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|1|1|1|0|1 +; To generate a color matrix using user-friendly parameters, +; use GenerateColorMatrix() + +Gdip_DrawImage(pGraphics, pBitmap, dx:="", dy:="", dw:="", dh:="", sx:="", sy:="", sw:="", sh:="", Matrix:=1, Unit:=2, ImageAttr:=0) { + Static Ptr := "UPtr" + If !ImageAttr + { + if !IsNumber(Matrix) + 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") + } Else usrImageAttr := 1 + + If (dx!="" && dy!="" && dw="" && dh="" && sx="" && sy="" && sw="" && sh="") + { + sx := sy := 0 + sw := dw := Gdip_GetImageWidth(pBitmap) + sh := dh := Gdip_GetImageHeight(pBitmap) + } Else 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 + Gdip_GetImageDimensions(pBitmap, sw, sh) + } + } + + _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", Unit + , Ptr, ImageAttr ? ImageAttr : 0 + , Ptr, 0, Ptr, 0) + + if (ImageAttr && usrImageAttr!=1) + Gdip_DisposeImageAttributes(ImageAttr) + + return _E +} + +Gdip_DrawImageFast(pGraphics, pBitmap, X:=0, Y:=0) { +; This function performs faster than Gdip_DrawImage(). +; X, Y - the coordinates of the destination upper-left corner +; where the pBitmap will be drawn. + + Static Ptr := "UPtr" + _E := DllCall("gdiplus\GdipDrawImage" + , Ptr, pGraphics + , Ptr, pBitmap + , "float", X + , "float", Y) + return _E +} + +Gdip_DrawImageRect(pGraphics, pBitmap, X, Y, W, H) { +; X, Y - the coordinates of the destination upper-left corner +; where the pBitmap will be drawn. +; W, H - the width and height of the destination rectangle, where the pBitmap will be drawn. + + Static Ptr := "UPtr" + _E := DllCall("gdiplus\GdipDrawImageRect" + , Ptr, pGraphics + , Ptr, pBitmap + , "float", X, "float", Y + , "float", W, "float", H) + return _E +} + +;##################################################################################### + +; Function Gdip_SetImageAttributesColorMatrix +; Description This function creates an image color matrix ready for drawing if no ImageAttr is given. +; It can set or clear the color and/or grayscale-adjustment matrices for a specified ImageAttr object. +; +; clrMatrix A color-adjustment matrix used to alter image attributes when drawing +; passed with "|" as delimeter. +; grayMatrix A grayscale-adjustment matrix used to alter image attributes when drawing +; passed with "|" as delimeter. This applies only when ColorMatrixFlag=2. +; +; ColorAdjustType The category for which the color and grayscale-adjustment matrices are set or cleared. +; 0 - adjustments apply to all categories that do not have adjustment settings of their own +; 1 - adjustments apply to bitmapped images +; 2 - adjustments apply to brush operations in metafiles +; 3 - adjustments apply to pen operations in metafiles +; 4 - adjustments apply to text drawn in metafiles +; +; fEnable If True, the specified matrices (color, grayscale or both) adjustments for the specified +; category are applied; otherwise the category is cleared +; +; ColorMatrixFlag Type of image and color that will be affected by the adjustment matrices: +; 0 - All color values (including grays) are adjusted by the same color-adjustment matrix. +; 1 - Colors are adjusted but gray shades are not adjusted. +; A gray shade is any color that has the same value for its red, green, and blue components. +; 2 - Colors are adjusted by one matrix and gray shades are adjusted by another matrix. + +; ImageAttr A pointer to an ImageAttributes object. +; If this parameter is omitted, a new one is created. + +; return It return 0 on success, if an ImageAttr object was given, +; otherwise, it returns the handle of a new ImageAttr object [if succesful]. +; +; 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|1|1|1|0|1 +; To generate a color matrix using user-friendly parameters, +; use GenerateColorMatrix() +; additional remarks: +; In my tests, it seems that the grayscale matrix is not functioning properly. +; Grayscale images are rendered invisible [with zero opacity] for some reason... +; TO DO: fix this? + +Gdip_SetImageAttributesColorMatrix(clrMatrix, ImageAttr:=0, grayMatrix:=0, ColorAdjustType:=1, fEnable:=1, ColorMatrixFlag:=0) { + Static Ptr := "UPtr" + If (StrLen(clrMatrix)<5 && ImageAttr) + Return -1 + + If StrLen(clrMatrix)<5 + Return + + VarSetCapacity(ColourMatrix, 100, 0) + Matrix := RegExReplace(RegExReplace(clrMatrix, "^[^\d-\.]+([\d\.])", "$1", , 1), "[^\d-\.]+", "|") + Matrix := StrSplit(Matrix, "|") + Loop 25 + { + M := (Matrix[A_Index] != "") ? Matrix[A_Index] : Mod(A_Index-1, 6) ? 0 : 1 + NumPut(M, ColourMatrix, (A_Index-1)*4, "float") + } + + Matrix := "" + Matrix := RegExReplace(RegExReplace(grayMatrix, "^[^\d-\.]+([\d\.])", "$1", , 1), "[^\d-\.]+", "|") + Matrix := StrSplit(Matrix, "|") + If (StrLen(Matrix)>2 && ColorMatrixFlag=2) + { + VarSetCapacity(GrayscaleMatrix, 100, 0) + Loop 25 + { + M := (Matrix[A_Index] != "") ? Matrix[A_Index] : Mod(A_Index-1, 6) ? 0 : 1 + NumPut(M, GrayscaleMatrix, (A_Index-1)*4, "float") + } + } + + If !ImageAttr + { + created := 1 + ImageAttr := Gdip_CreateImageAttributes() + } + + E := DllCall("gdiplus\GdipSetImageAttributesColorMatrix" + , Ptr, ImageAttr + , "int", ColorAdjustType + , "int", fEnable + , Ptr, &ColourMatrix + , Ptr, &GrayscaleMatrix + , "int", ColorMatrixFlag) + + E := created=1 ? ImageAttr : E + return E +} + +Gdip_CreateImageAttributes() { + ImageAttr := 0 + DllCall("gdiplus\GdipCreateImageAttributes", "UPtr*", ImageAttr) + return ImageAttr +} + +Gdip_CloneImageAttributes(ImageAttr) { + Static Ptr := "UPtr" + newImageAttr := 0 + DllCall("gdiplus\GdipCloneImageAttributes", Ptr, ImageAttr, "UPtr*", newImageAttr) + return newImageAttr +} + +Gdip_SetImageAttributesThreshold(ImageAttr, Threshold, ColorAdjustType:=1, fEnable:=1) { +; Sets or clears the threshold (transparency range) for a specified category by ColorAdjustType +; The threshold is a value from 0 through 1 that specifies a cutoff point for each color component. For example, +; suppose the threshold is set to 0.7, and suppose you are rendering a color whose red, green, and blue +; components are 230, 50, and 220. The red component, 230, is greater than 0.7ª255, so the red component will +; be changed to 255 (full intensity). The green component, 50, is less than 0.7ª255, so the green component will +; be changed to 0. The blue component, 220, is greater than 0.7ª255, so the blue component will be changed to 255. + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetImageAttributesThreshold", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable, "float", Threshold) +} + +Gdip_SetImageAttributesResetMatrix(ImageAttr, ColorAdjustType) { +; Sets the color-adjustment matrix of a specified category to the identity matrix. + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetImageAttributesToIdentity", Ptr, ImageAttr, "int", ColorAdjustType) +} + +Gdip_SetImageAttributesGamma(ImageAttr, Gamma, ColorAdjustType:=1, fEnable:=1) { +; Gamma from 0.1 to 5.0 + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetImageAttributesGamma", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable, "float", Gamma) +} + +Gdip_SetImageAttributesToggle(ImageAttr, ColorAdjustType, fEnable) { +; Turns on or off color adjustment for a specified category defined by ColorAdjustType +; fEnable - 0 or 1 + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetImageAttributesNoOp", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable) +} + +Gdip_SetImageAttributesOutputChannel(ImageAttr, ColorChannelFlags, ColorAdjustType:=1, fEnable:=1) { +; ColorChannelFlags - The output channel, can be any combination: +; 0 - Cyan color channel +; 1 - Magenta color channel +; 2 - Yellow color channel +; 3 - Black color channel +; 4 - The previous selected channel + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetImageAttributesOutputChannel", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable, "int", ColorChannelFlags) +} + +Gdip_SetImageAttributesColorKeys(ImageAttr, ARGBLow, ARGBHigh, ColorAdjustType:=1, fEnable:=1) { +; initial tests of this function lead to a crash of the application ... + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetImageAttributesColorKeys", Ptr, ImageAttr, "int", ColorAdjustType, "int", fEnable, "uint", ARGBLow, "uint", ARGBHigh) +} + +Gdip_SetImageAttributesWrapMode(ImageAttr, WrapMode, ARGB) { +; ImageAttr - Pointer to an ImageAttribute object +; WrapMode - Specifies how repeated copies of an image are used to tile an area: +; 0 - Tile - Tiling without flipping +; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row +; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column +; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column +; 4 - Clamp - No tiling takes place +; ARGB - Alpha, Red, Green and Blue components of the color of pixels outside of a rendered image. +; This color is visible if the wrap mode is set to 4 and the source rectangle of the image is greater than the +; image itself. + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetImageAttributesWrapMode", Ptr, ImageAttr, "int", WrapMode, "uint", ARGB, "int", 0) +} + +Gdip_ResetImageAttributes(ImageAttr, ColorAdjustType) { +; Clears all color and grayscale-adjustment settings for a specified category defined by ColorAdjustType. +; +; ImageAttr - a pointer to an ImageAttributes object. +; ColorAdjustType - The category for which color adjustment is reset: +; see Gdip_SetImageAttributesColorMatrix() for details. + + Static Ptr := "UPtr" + DllCall("gdiplus\GdipResetImageAttributes", Ptr, ImageAttr, "int", ColorAdjustType) +} + +;##################################################################################### + +; 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, InterpolationMode:="", SmoothingMode:="", PageUnit:="", CompositingQuality:="") { + pGraphics := 0 + DllCall("gdiplus\GdipGetImageGraphicsContext", "UPtr", pBitmap, "UPtr*", pGraphics) + If pGraphics + { + If (InterpolationMode!="") + Gdip_SetInterpolationMode(pGraphics, InterpolationMode) + If (SmoothingMode!="") + Gdip_SetSmoothingMode(pGraphics, SmoothingMode) + If (PageUnit!="") + Gdip_SetPageUnit(pGraphics, PageUnit) + If (CompositingQuality!="") + Gdip_SetCompositingQuality(pGraphics, CompositingQuality) + } + return pGraphics +} + +;##################################################################################### + +; Function Gdip_GraphicsFromHDC +; Description This function gets the graphics from the handle of a device context. +; +; hDC The handle to the device context. +; hDevice Handle to a device that will be associated with the new Graphics object. +; +; return A pointer to the graphics of a bitmap. +; +; notes You can draw a bitmap into the graphics of another bitmap. + +Gdip_GraphicsFromHDC(hDC, hDevice:="", InterpolationMode:="", SmoothingMode:="", PageUnit:="", CompositingQuality:="") { + pGraphics := 0 + If hDevice + DllCall("Gdiplus\GdipCreateFromHDC2", "UPtr", hDC, "UPtr", hDevice, "UPtr*", pGraphics) + Else + DllCall("gdiplus\GdipCreateFromHDC", "UPtr", hdc, "UPtr*", pGraphics) + + If pGraphics + { + If (InterpolationMode!="") + Gdip_SetInterpolationMode(pGraphics, InterpolationMode) + If (SmoothingMode!="") + Gdip_SetSmoothingMode(pGraphics, SmoothingMode) + If (PageUnit!="") + Gdip_SetPageUnit(pGraphics, PageUnit) + If (CompositingQuality!="") + Gdip_SetCompositingQuality(pGraphics, CompositingQuality) + } + + return pGraphics +} + +Gdip_GraphicsFromHWND(HWND, useICM:=0, InterpolationMode:="", SmoothingMode:="", PageUnit:="", CompositingQuality:="") { +; Creates a pGraphics object that is associated with a specified window handle [HWND] +; If useICM=1, the created graphics uses ICM [color management - (International Color Consortium = ICC)]. + pGraphics := 0 + function2call := (useICM=1) ? "GdipCreateFromHWNDICM" : "GdipCreateFromHWND" + DllCall("gdiplus\" function2call, "UPtr", HWND, "UPtr*", pGraphics) + + If pGraphics + { + If (InterpolationMode!="") + Gdip_SetInterpolationMode(pGraphics, InterpolationMode) + If (SmoothingMode!="") + Gdip_SetSmoothingMode(pGraphics, SmoothingMode) + If (PageUnit!="") + Gdip_SetPageUnit(pGraphics, PageUnit) + If (CompositingQuality!="") + Gdip_SetCompositingQuality(pGraphics, CompositingQuality) + } + 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) { + hDC := 0 + DllCall("gdiplus\GdipGetDC", "UPtr", pGraphics, "UPtr*", 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) { + Static Ptr := "UPtr" + 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", "UPtr", pGraphics, "int", ARGB) +} + +Gdip_GraphicsFlush(pGraphics, intent) { +; intent - Specifies whether the method returns immediately or waits for any existing operations to finish: +; 0 - Flush all batched rendering operations and return immediately +; 1 - Flush all batched rendering operations and wait for them to complete + + return DllCall("gdiplus\GdipFlush", "UPtr", pGraphics, "int", intent) +} + +;##################################################################################### + +; 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 +; BlurAmount 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, BlurAmount, usePARGB:=0, quality:=7) { + ; suggested quality is 6; + ; quality 7 creates sharpening effect + ; for higher speed set usePARGB to 1 + + If (BlurAmount>100) + BlurAmount := 100 + Else If (BlurAmount<1) + BlurAmount := 1 + + PixelFormat := (usePARGB=1) ? "0xE200B" : "0x26200A" + Gdip_GetImageDimensions(pBitmap, sWidth, sHeight) + dWidth := sWidth//BlurAmount + dHeight := sHeight//BlurAmount + + pBitmap1 := Gdip_CreateBitmap(dWidth, dHeight, PixelFormat) + G1 := Gdip_GraphicsFromImage(pBitmap1) + Gdip_SetInterpolationMode(G1, quality) + Gdip_DrawImage(G1, pBitmap, 0, 0, dWidth, dHeight, 0, 0, sWidth, sHeight) + + Gdip_DeleteGraphics(G1) + pBitmap2 := Gdip_CreateBitmap(sWidth, sHeight, PixelFormat) + G2 := Gdip_GraphicsFromImage(pBitmap2) + Gdip_SetInterpolationMode(G2, quality) + 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 +; toBase64 If set to 1, instead of saving the file to disk, the function will return on success the base64 data +; A "base64" string is the binary image data encoded into text using only 64 characters. +; To convert it back into an image use: Gdip_BitmapFromBase64() +; +; 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 +; -6 = Could not save image to stream [for base64] +; -7 = Could not convert to base64 +; +; notes This function will use the extension supplied from the sOutput parameter to determine the output format + +Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality:=75, toBase64:=0) { + Static Ptr := "UPtr" + nCount := 0 + nSize := 0 + _p := 0 + + SplitPath sOutput,,, Extension + If !RegExMatch(Extension, "^(?i: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" + N := (A_AhkVersion < 2) ? nCount : "nCount" + Loop %N% + { + 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 + { + N := (A_AhkVersion < 2) ? nCount : "nCount" + Loop %N% + { + 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 (quality>90 && toBase64=1) + Quality := 90 + + If RegExMatch(Extension, "^\.(?i: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) + nCount := NumGet(EncoderParameters, "UInt") + N := (A_AhkVersion < 2) ? nCount : "nCount" + Loop %N% + { + elem := (24+A_PtrSize)*(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 (toBase64=1) + { + ; part of the function extracted from ImagePut by iseahound + ; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=76301&sid=bfb7c648736849c3c53f08ea6b0b1309 + DllCall("ole32\CreateStreamOnHGlobal", "ptr",0, "int",true, "ptr*",pStream) + _E := DllCall("gdiplus\GdipSaveImageToStream", "ptr",pBitmap, "ptr",pStream, "ptr",pCodec, "uint", _p ? _p : 0) + If _E + Return -6 + + DllCall("ole32\GetHGlobalFromStream", "ptr",pStream, "uint*",hData) + pData := DllCall("GlobalLock", "ptr",hData, "ptr") + nSize := DllCall("GlobalSize", "uint",pData) + + VarSetCapacity(bin, nSize, 0) + DllCall("RtlMoveMemory", "ptr",&bin, "ptr",pData, "uptr",nSize) + DllCall("GlobalUnlock", "ptr",hData) + ObjRelease(pStream) + DllCall("GlobalFree", "ptr",hData) + + ; Using CryptBinaryToStringA saves about 2MB in memory. + DllCall("Crypt32.dll\CryptBinaryToStringA", "ptr",&bin, "uint",nSize, "uint",0x40000001, "ptr",0, "uint*",base64Length) + VarSetCapacity(base64, base64Length, 0) + _E := DllCall("Crypt32.dll\CryptBinaryToStringA", "ptr",&bin, "uint",nSize, "uint",0x40000001, "ptr",&base64, "uint*",base64Length) + If !_E + Return -7 + + VarSetCapacity(bin, 0) + Return StrGet(&base64, base64Length, "CP0") + } + + _E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, "WStr", 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, y x, y coordinates of the pixel +; +; return Returns the ARGB value of the pixel + +Gdip_GetPixel(pBitmap, x, y) { + ARGB := 0 + DllCall("gdiplus\GdipBitmapGetPixel", "UPtr", pBitmap, "int", x, "int", y, "uint*", ARGB) + return ARGB + ; should use Format("{1:#x}", ARGB) +} + +Gdip_GetPixelColor(pBitmap, x, y, Format) { + ARGBdec := Gdip_GetPixel(pBitmap, x, y) + If (format=1) ; in ARGB [HEX; 00-FF] with 0x prefix + { + Return Format("{1:#x}", ARGBdec) + } Else If (format=2) ; in RGBA [0-255] + { + Gdip_FromARGB(ARGBdec, A, R, G, B) + Return R "," G "," B "," A + } Else If (format=3) ; in BGR [HEX; 00-FF] with 0x prefix + { + clr := Format("{1:#x}", ARGBdec) + Return "0x" SubStr(clr, -1) SubStr(clr, 7, 2) SubStr(clr, 5, 2) + } Else If (format=4) ; in RGB [HEX; 00-FF] with no prefix + { + Return SubStr(Format("{1:#x}", ARGBdec), 5) + } Else Return ARGBdec +} + +;##################################################################################### + +; Function Gdip_SetPixel +; Description Sets the ARGB of a pixel in a bitmap +; +; pBitmap Pointer to a bitmap +; x, y x, y coordinates of the pixel +; +; return status enumeration. 0 = success + +Gdip_SetPixel(pBitmap, x, y, ARGB) { + return DllCall("gdiplus\GdipBitmapSetPixel", "UPtr", 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) { + Width := 0 + DllCall("gdiplus\GdipGetImageWidth", "UPtr", pBitmap, "uint*", Width) + return Width +} + +Gdip_GetImageHeight(pBitmap) { + + ;##################################################################################### + + ; 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 + + Height := 0 + DllCall("gdiplus\GdipGetImageHeight", "UPtr", pBitmap, "uint*", Height) + return Height +} + +;##################################################################################### + +; Function Gdip_GetImageDimensions +; 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 GDI+ status enumeration return value + +Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height) { + If StrLen(pBitmap)<3 + Return -1 + + Width := 0, Height := 0 + E := Gdip_GetImageDimension(pBitmap, Width, Height) + Width := Round(Width) + Height := Round(Height) + return E +} + +Gdip_GetImageDimension(pBitmap, ByRef w, ByRef h) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipGetImageDimension", Ptr, pBitmap, "float*", w, "float*", h) +} + +Gdip_GetImageBounds(pBitmap) { + + rData := {} + VarSetCapacity(RectF, 16, 0) + status := DllCall("gdiplus\GdipGetImageBounds", "UPtr", pBitmap, "UPtr", &RectF, "Int*", 0) + + If (!status) { + rData.x := NumGet(&RectF, 0, "float") + , rData.y := NumGet(&RectF, 4, "float") + , rData.w := NumGet(&RectF, 8, "float") + , rData.h := NumGet(&RectF, 12, "float") + } Else { + Return status + } + + return rData +} + +Gdip_GetImageFlags(pBitmap) { +; Gets a set of flags that indicate certain attributes of this Image object. +; Returns an element of the ImageFlags Enumeration that holds a set of single-bit flags. +; ImageFlags enumeration + ; None := 0x0000 ; Specifies no format information. + ; ; Low-word: shared with SINKFLAG_x: + ; Scalable := 0x00001 ; the image can be scaled. + ; HasAlpha := 0x00002 ; the pixel data contains alpha values. + ; HasTranslucent := 0x00004 ; the pixel data has alpha values other than 0 (transparent) and 255 (opaque). + ; PartiallyScalable := 0x00008 ; the pixel data is partially scalable with some limitations. + ; ; Low-word: color space definition: + ; ColorSpaceRGB := 0x00010 ; the image is stored using an RGB color space. + ; ColorSpaceCMYK := 0x00020 ; the image is stored using a CMYK color space. + ; ColorSpaceGRAY := 0x00040 ; the image is a grayscale image. + ; ColorSpaceYCBCR := 0x00080 ; the image is stored using a YCBCR color space. + ; ColorSpaceYCCK := 0x00100 ; the image is stored using a YCCK color space. + ; ; Low-word: image size info: + ; HasRealDPI := 0x01000 ; dots per inch information is stored in the image. + ; HasRealPixelSize := 0x02000 ; the pixel size is stored in the image. + ; ; High-word: + ; ReadOnly := 0x10000 ; the pixel data is read-only. + ; Caching := 0x20000 ; the pixel data can be cached for faster access. +; function extracted from : https://github.com/flipeador/Library-AutoHotkey/tree/master/graphics +; by flipeador + + Flags := 0 + DllCall("gdiplus\GdipGetImageFlags", "UPtr", pBitmap, "UInt*", Flags) + Return Flags +} + +Gdip_GetImageRawFormat(pBitmap) { +; retrieves the pBitmap [file] format + + Static RawFormatsList := {"{B96B3CA9-0728-11D3-9D7B-0000F81EF32E}":"Undefined", "{B96B3CAA-0728-11D3-9D7B-0000F81EF32E}":"MemoryBMP", "{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}":"BMP", "{B96B3CAC-0728-11D3-9D7B-0000F81EF32E}":"EMF", "{B96B3CAD-0728-11D3-9D7B-0000F81EF32E}":"WMF", "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}":"JPEG", "{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}":"PNG", "{B96B3CB0-0728-11D3-9D7B-0000F81EF32E}":"GIF", "{B96B3CB1-0728-11D3-9D7B-0000F81EF32E}":"TIFF", "{B96B3CB2-0728-11D3-9D7B-0000F81EF32E}":"EXIF", "{B96B3CB5-0728-11D3-9D7B-0000F81EF32E}":"Icon"} + VarSetCapacity(pGuid, 16, 0) + E1 := DllCall("gdiplus\GdipGetImageRawFormat", "UPtr", pBitmap, "Ptr", &pGuid) + + size := VarSetCapacity(sguid, (38 << !!A_IsUnicode) + 1, 0) + E2 := DllCall("ole32.dll\StringFromGUID2", "ptr", &pguid, "ptr", &sguid, "int", size) + R1 := E2 ? StrGet(&sguid) : E2 + R2 := RawFormatsList[R1] + Return R2 ? R2 : R1 +} + +Gdip_GetImagePixelFormat(pBitmap, mode:=0) { +; Mode options +; 0 - in decimal +; 1 - in hex +; 2 - in human readable format +; +; PXF01INDEXED = 0x00030101 ; 1 bpp, indexed +; PXF04INDEXED = 0x00030402 ; 4 bpp, indexed +; PXF08INDEXED = 0x00030803 ; 8 bpp, indexed +; PXF16GRAYSCALE = 0x00101004; 16 bpp, grayscale +; PXF16RGB555 = 0x00021005 ; 16 bpp; 5 bits for each RGB +; PXF16RGB565 = 0x00021006 ; 16 bpp; 5 bits red, 6 bits green, and 5 bits blue +; PXF16ARGB1555 = 0x00061007 ; 16 bpp; 1 bit for alpha and 5 bits for each RGB component +; PXF24RGB = 0x00021808 ; 24 bpp; 8 bits for each RGB +; PXF32RGB = 0x00022009 ; 32 bpp; 8 bits for each RGB, no alpha. +; PXF32ARGB = 0x0026200A ; 32 bpp; 8 bits for each RGB and alpha +; PXF32PARGB = 0x000E200B ; 32 bpp; 8 bits for each RGB and alpha, pre-mulitiplied +; PXF48RGB = 0x0010300C ; 48 bpp; 16 bits for each RGB +; PXF64ARGB = 0x0034400D ; 64 bpp; 16 bits for each RGB and alpha +; PXF64PARGB = 0x001A400E ; 64 bpp; 16 bits for each RGB and alpha, pre-multiplied + +; INDEXED [1-bits, 4-bits and 8-bits] pixel formats rely on color palettes. +; The color information for the pixels is stored in palettes. +; Indexed images always contain a palette - a special table of colors. +; Each pixel is an index in this table. Usually a palette contains 256 +; or less entries. That's why the maximum depth of an indexed pixel is 8 bpp. +; Using palettes is a common practice when working with small color depths. + +; modified by Marius Șucan + + Static PixelFormatsList := {0x30101:"1-INDEXED", 0x30402:"4-INDEXED", 0x30803:"8-INDEXED", 0x101004:"16-GRAYSCALE", 0x021005:"16-RGB555", 0x21006:"16-RGB565", 0x61007:"16-ARGB1555", 0x21808:"24-RGB", 0x22009:"32-RGB", 0x26200A:"32-ARGB", 0xE200B:"32-PARGB", 0x10300C:"48-RGB", 0x34400D:"64-ARGB", 0x1A400E:"64-PARGB"} + PixelFormat := 0 + E := DllCall("gdiplus\GdipGetImagePixelFormat", "UPtr", pBitmap, "UPtr*", PixelFormat) + If E + Return -1 + + If (mode=0) + Return PixelFormat + + inHEX := Format("{1:#x}", PixelFormat) + If (PixelFormatsList.Haskey(inHEX) && mode=2) + result := PixelFormatsList[inHEX] + Else + result := inHEX + return result +} + +Gdip_GetImageType(pBitmap) { +; RETURN VALUES: +; UNKNOWN = 0 +; BITMAP = 1 +; METAFILE = 2 +; ERROR = -1 + result := 0 + E := DllCall("gdiplus\GdipGetImageType", Ptr, pBitmap, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetDPI(pGraphics, ByRef DpiX, ByRef DpiY) { + DpiX := Gdip_GetDpiX(pGraphics) + DpiY := Gdip_GetDpiY(pGraphics) +} + +Gdip_GetDpiX(pGraphics) { + dpix := 0 + DllCall("gdiplus\GdipGetDpiX", "UPtr", pGraphics, "float*", dpix) + return Round(dpix) +} + +Gdip_GetDpiY(pGraphics) { + dpiy := 0 + DllCall("gdiplus\GdipGetDpiY", "UPtr", pGraphics, "float*", dpiy) + return Round(dpiy) +} + +Gdip_GetImageHorizontalResolution(pBitmap) { + dpix := 0 + DllCall("gdiplus\GdipGetImageHorizontalResolution", "UPtr", pBitmap, "float*", dpix) + return Round(dpix) +} + +Gdip_GetImageVerticalResolution(pBitmap) { + dpiy := 0 + DllCall("gdiplus\GdipGetImageVerticalResolution", "UPtr", pBitmap, "float*", dpiy) + return Round(dpiy) +} + +Gdip_BitmapSetResolution(pBitmap, dpix, dpiy) { + return DllCall("gdiplus\GdipBitmapSetResolution", "UPtr", pBitmap, "float", dpix, "float", dpiy) +} + +Gdip_BitmapGetDPIResolution(pBitmap, ByRef dpix, ByRef dpiy) { + dpix := dpiy := 0 + If StrLen(pBitmap)<3 + Return + + dpix := Gdip_GetImageHorizontalResolution(pBitmap) + dpiy := Gdip_GetImageVerticalResolution(pBitmap) +} + +Gdip_CreateBitmapFromGraphics(pGraphics, Width, Height) { + pBitmap := 0 + DllCall("gdiplus\GdipCreateBitmapFromGraphics", "int", Width, "int", Height, "UPtr", pGraphics, "UPtr*", pBitmap) + Return pBitmap +} + +Gdip_CreateBitmapFromFile(sFile, IconNumber:=1, IconSize:="", useICM:=0) { + Static Ptr := "UPtr" + PtrA := "UPtr*" + pBitmap := 0 + pBitmapOld := 0 + hIcon := 0 + + SplitPath sFile,,, Extension + if RegExMatch(Extension, "^(?i:exe|dll)$") + { + Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16 + BufSize := 16 + (2*A_PtrSize) + + VarSetCapacity(buf, BufSize, 0) + For eachSize, Size in StrSplit( Sizes, "|" ) + { + DllCall("PrivateExtractIcons", "str", sFile, "int", IconNumber-1, "int", Size, "int", Size, 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 - 4)) + hbmColor := NumGet(buf, 12 + (A_PtrSize - 4) + A_PtrSize) + 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 + pBitmapOld := Gdip_CreateBitmap(Width, Height, 0, Stride, Bits) + 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 + { + function2call := (useICM=1) ? "GdipCreateBitmapFromFileICM" : "GdipCreateBitmapFromFile" + E := DllCall("gdiplus\" function2call, "WStr", sFile, PtrA, pBitmap) + } + + return pBitmap +} + +Gdip_CreateARGBBitmapFromHBITMAP(hImage) { +; function by iseahound found on: +; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=63345 +; part of https://github.com/iseahound/Graphics/blob/master/lib/Graphics.ahk + + ; struct BITMAP - https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-tagbitmap + DllCall("GetObject" + , "ptr", hImage + , "int", VarSetCapacity(dib, 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize) + , "ptr", &dib) ; sizeof(DIBSECTION) = x86:84, x64:104 + width := NumGet(dib, 4, "uint") + height := NumGet(dib, 8, "uint") + bpp := NumGet(dib, 18, "ushort") + + ; Fallback to built-in method if pixels are not ARGB. + if (bpp!=32) + return Gdip_CreateBitmapFromHBITMAP(hImage) + + ; Create a handle to a device context and associate the hImage. + hdc := CreateCompatibleDC() + obm := SelectObject(hdc, hImage) + + ; Buffer the hImage with a top-down device independent bitmap via negative height. + ; Note that a DIB is an hBitmap, pixels are formatted as pARGB, and has a pointer to the bits. + cdc := CreateCompatibleDC(hdc) + hbm := CreateDIBSection(width, -height, hdc, 32, pBits) + ob2 := SelectObject(cdc, hbm) + + ; Create a new Bitmap (different from an hBitmap) which holds ARGB pixel values. + pBitmap := Gdip_CreateBitmap(width, height) + + ; Create a Scan0 buffer pointing to pBits. The buffer has pixel format pARGB. + CreateRect(Rect, 0, 0, width, height) + VarSetCapacity(BitmapData, 16+2*A_PtrSize, 0) + , NumPut( width, BitmapData, 0, "uint") ; Width + , NumPut( height, BitmapData, 4, "uint") ; Height + , NumPut( 4 * width, BitmapData, 8, "int") ; Stride + , NumPut( 0xE200B, BitmapData, 12, "int") ; PixelFormat + , NumPut( pBits, BitmapData, 16, "ptr") ; Scan0 + DllCall("gdiplus\GdipBitmapLockBits" + , "ptr", pBitmap + , "ptr", &Rect + , "uint", 6 ; ImageLockMode.UserInputBuffer | ImageLockMode.WriteOnly + , "int", 0xE200B ; Format32bppPArgb + , "ptr", &BitmapData) + + ; Ensure that our hBitmap (hImage) is top-down by copying it to a top-down bitmap. + BitBlt(cdc, 0, 0, width, height, hdc, 0, 0) + + ; Convert the pARGB pixels copied into the device independent bitmap (hbm) to ARGB. + DllCall("gdiplus\GdipBitmapUnlockBits", "ptr",pBitmap, "ptr",&BitmapData) + + ; Cleanup the buffer and device contexts. + SelectObject(cdc, ob2) + DeleteObject(hbm), DeleteDC(cdc) + SelectObject(hdc, obm), DeleteDC(hdc) + + return pBitmap +} + +Gdip_CreateBitmapFromHBITMAP(hBitmap, hPalette:=0) { +; Creates a Bitmap GDI+ object from a GDI bitmap handle. +; hPalette - Handle to a GDI palette used to define the bitmap colors +; if the hBitmap is a device-dependent bitmap [DDB]. + + Static Ptr := "UPtr" + pBitmap := 0 + DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, hPalette, "UPtr*", pBitmap) + return pBitmap +} + +Gdip_CreateHBITMAPFromBitmap(pBitmap, Background:=0xffffffff) { +; background should be zero, to not alter alpha channel of the image + hBitmap := 0 + DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "UPtr", pBitmap, "UPtr*", hBitmap, "int", Background) + return hBitmap +} + +Gdip_CreateARGBHBITMAPFromBitmap(ByRef pBitmap) { + ; function by iseahound ; source: https://github.com/mmikeww/AHKv2-Gdip + ; modified to rely on already present functions [within the library] + + ; This version is about 25% faster than Gdip_CreateHBITMAPFromBitmap(). + ; Get Bitmap width and height. + + Gdip_GetImageDimensions(pBitmap, Width, Height) + + ; Convert the source pBitmap into a hBitmap manually. + ; struct BITMAPINFOHEADER - https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader + hdc := CreateCompatibleDC() + hbm := CreateDIBSection(width, -height, hdc, 32, pBits) + obm := SelectObject(hdc, hbm) + + ; Transfer data from source pBitmap to an hBitmap manually. + CreateRect(Rect, 0, 0, width, height) + VarSetCapacity(BitmapData, 16+2*A_PtrSize, 0) ; sizeof(BitmapData) = 24, 32 + , NumPut( width, BitmapData, 0, "uint") ; Width + , NumPut( height, BitmapData, 4, "uint") ; Height + , NumPut( 4 * width, BitmapData, 8, "int") ; Stride + , NumPut( 0xE200B, BitmapData, 12, "int") ; PixelFormat + , NumPut( pBits, BitmapData, 16, "ptr") ; Scan0 + DllCall("gdiplus\GdipBitmapLockBits" + , "ptr", pBitmap + , "ptr", &Rect + , "uint", 5 ; ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly + , "int", 0xE200B ; Format32bppPArgb + , "ptr", &BitmapData) ; Contains the pointer (pBits) to the hbm. + DllCall("gdiplus\GdipBitmapUnlockBits", "ptr", pBitmap, "ptr", &BitmapData) + + ; Cleanup the hBitmap and device contexts. + SelectObject(hdc, obm) + DeleteObject(hdc) + return hbm +} + +Gdip_CreateBitmapFromHICON(hIcon) { + pBitmap := 0 + DllCall("gdiplus\GdipCreateBitmapFromHICON", "UPtr", hIcon, "UPtr*", pBitmap) + return pBitmap +} + +Gdip_CreateHICONFromBitmap(pBitmap) { + hIcon := 0 + DllCall("gdiplus\GdipCreateHICONFromBitmap", "UPtr", pBitmap, "UPtr*", hIcon) + return hIcon +} + +Gdip_CreateBitmap(Width, Height, PixelFormat:=0, Stride:=0, Scan0:=0) { +; By default, this function creates a new 32-ARGB bitmap. +; modified by Marius Șucan + + pBitmap := 0 + If !PixelFormat + PixelFormat := 0x26200A ; 32-ARGB + + DllCall("gdiplus\GdipCreateBitmapFromScan0" + , "int", Width + , "int", Height + , "int", Stride + , "int", PixelFormat + , "UPtr", Scan0 + , "UPtr*", pBitmap) + Return pBitmap +} + +Gdip_CreateBitmapFromClipboard() { +; modified by Marius Șucan + + Static Ptr := "UPtr" + pid := DllCall("GetCurrentProcessId","uint") + hwnd := WinExist("ahk_pid " . pid) + if !DllCall("IsClipboardFormatAvailable", "uint", 8) ; CF_DIB = 8 + { + if DllCall("IsClipboardFormatAvailable", "uint", 2) ; CF_BITMAP = 2 + { + if !DllCall("OpenClipboard", Ptr, hwnd) + return -1 + + hData := DllCall("User32.dll\GetClipboardData", "UInt", 0x0002, "UPtr") + hBitmap := DllCall("User32.dll\CopyImage", "UPtr", hData, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2004, "Ptr") + DllCall("CloseClipboard") + pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap) + DeleteObject(hBitmap) + return pBitmap + } + return -2 + } + + if !DllCall("OpenClipboard", Ptr, hwnd) + return -1 + + hBitmap := DllCall("GetClipboardData", "uint", 2, Ptr) + if !hBitmap + { + DllCall("CloseClipboard") + return -3 + } + + DllCall("CloseClipboard") + If hBitmap + { + pBitmap := Gdip_CreateARGBBitmapFromHBITMAP(hBitmap) ; this function can return a completely empty/transparent bitmap + If pBitmap + isUniform := Gdip_TestBitmapUniformity(pBitmap, 7, maxLevelIndex) + + If (pBitmap && isUniform=1 && maxLevelIndex<=2) + { + Gdip_DisposeImage(pBitmap) + pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap) + } + DeleteObject(hBitmap) + } + + if !pBitmap + return -4 + + return pBitmap +} + +Gdip_SetBitmapToClipboard(pBitmap) { +; modified by Marius Șucan to have this function report errors + + Static Ptr := "UPtr" + off1 := A_PtrSize = 8 ? 52 : 44 + off2 := A_PtrSize = 8 ? 32 : 24 + + pid := DllCall("GetCurrentProcessId","uint") + hwnd := WinExist("ahk_pid " . pid) + r1 := DllCall("OpenClipboard", Ptr, hwnd) + If !r1 + Return -1 + + hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap, 0) + If !hBitmap + { + DllCall("CloseClipboard") + Return -3 + } + + r2 := DllCall("EmptyClipboard") + If !r2 + { + DeleteObject(hBitmap) + DllCall("CloseClipboard") + Return -2 + } + + DllCall("GetObject", Ptr, hBitmap, "int", VarSetCapacity(oi, A_PtrSize = 8 ? 104 : 84, 0), Ptr, &oi) + hdib := DllCall("GlobalAlloc", "uint", 2, Ptr, 40+NumGet(oi, off1, "UInt"), Ptr) + pdib := DllCall("GlobalLock", Ptr, hdib, Ptr) + DllCall("RtlMoveMemory", Ptr, pdib, Ptr, &oi+off2, Ptr, 40) + DllCall("RtlMoveMemory", Ptr, pdib+40, Ptr, NumGet(oi, off2 - A_PtrSize, Ptr), Ptr, NumGet(oi, off1, "UInt")) + DllCall("GlobalUnlock", Ptr, hdib) + DeleteObject(hBitmap) + r3 := DllCall("SetClipboardData", "uint", 8, Ptr, hdib) ; CF_DIB = 8 + DllCall("CloseClipboard") + DllCall("GlobalFree", Ptr, hdib) + E := r3 ? 0 : -4 ; 0 - success + Return E +} + +Gdip_CloneBitmapArea(pBitmap, x:="", y:="", w:=0, h:=0, PixelFormat:=0, KeepPixelFormat:=0) { +; The new pBitmap is by default in the 32-ARGB PixelFormat. +; +; If the specified coordinates exceed the boundaries of pBitmap +; the resulted pBitmap is erroneuous / defective. + pBitmapDest := 0 + If !PixelFormat + PixelFormat := 0x26200A ; 32-ARGB + + If (KeepPixelFormat=1) + PixelFormat := Gdip_GetImagePixelFormat(pBitmap, 1) + + If (y="") + y := 0 + + If (x="") + x := 0 + + If (!w && !h) + Gdip_GetImageDimensions(pBitmap, w, h) + + E := DllCall("gdiplus\GdipCloneBitmapArea" + , "float", x, "float", y + , "float", w, "float", h + , "int", PixelFormat + , "UPtr", pBitmap + , "UPtr*", pBitmapDest) + return pBitmapDest +} + +Gdip_CloneBitmap(pBitmap) { +; the new pBitmap will have the same PixelFormat, unchanged. + + pBitmapDest := 0 + E := DllCall("gdiplus\GdipCloneImage" + , "UPtr", pBitmap + , "UPtr*", pBitmapDest) + return pBitmapDest +} + +Gdip_BitmapSelectActiveFrame(pBitmap, FrameIndex) { +; Selects as the active frame the given FrameIndex +; within an animated GIF or a multi-paged TIFF. +; On succes, it returns the frames count. +; On fail, the return value is -1. + + Countu := 0 + CountFrames := 0 + Static Ptr := "UPtr" + DllCall("gdiplus\GdipImageGetFrameDimensionsCount", Ptr, pBitmap, "UInt*", Countu) + VarSetCapacity(dIDs, 16, 0) + DllCall("gdiplus\GdipImageGetFrameDimensionsList", Ptr, pBitmap, "Uint", &dIDs, "UInt", Countu) + DllCall("gdiplus\GdipImageGetFrameCount", Ptr, pBitmap, "Uint", &dIDs, "UInt*", CountFrames) + If (FrameIndex>CountFrames) + FrameIndex := CountFrames + Else If (FrameIndex<1) + FrameIndex := 0 + + E := DllCall("gdiplus\GdipImageSelectActiveFrame", Ptr, pBitmap, Ptr, &dIDs, "uint", FrameIndex) + If E + Return -1 + Return CountFrames +} + +Gdip_GetBitmapFramesCount(pBitmap) { +; The function returns the number of frames or pages a given pBitmap has. +; GDI+ only supports multi-frames/pages for GIFs and TIFFs. +; Function written by SBC in September 2010 and +; extracted from his «Picture Viewer» script. +; https://autohotkey.com/board/topic/58226-ahk-picture-viewer/ + + Countu := 0 + CountFrames := 0 + Static Ptr := "UPtr" + DllCall("gdiplus\GdipImageGetFrameDimensionsCount", Ptr, pBitmap, "UInt*", Countu) + VarSetCapacity(dIDs, 16, 0) + DllCall("gdiplus\GdipImageGetFrameDimensionsList", Ptr, pBitmap, "Uint", &dIDs, "UInt", Countu) + DllCall("gdiplus\GdipImageGetFrameCount", Ptr, pBitmap, "Uint", &dIDs, "UInt*", CountFrames) + Return CountFrames +} + +Gdip_CreateCachedBitmap(pBitmap, pGraphics) { +; Creates a CachedBitmap object based on a Bitmap object and a pGraphics object. The cached bitmap takes +; the pixel data from the Bitmap object and stores it in a format that is optimized for the display device +; associated with the pGraphics object. + + pCachedBitmap := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipCreateCachedBitmap", Ptr, pBitmap, Ptr, pGraphics, "Ptr*", pCachedBitmap) + return pCachedBitmap +} + +Gdip_DeleteCachedBitmap(pCachedBitmap) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipDeleteCachedBitmap", Ptr, pCachedBitmap) +} + +Gdip_DrawCachedBitmap(pGraphics, pCachedBitmap, X, Y) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipDrawCachedBitmap", Ptr, pGraphics, Ptr, pCachedBitmap, "int", X, "int", Y) +} + +Gdip_ImageRotateFlip(pBitmap, RotateFlipType:=1) { +; RotateFlipType options: +; 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 + + return DllCall("gdiplus\GdipImageRotateFlip", "UPtr", pBitmap, "int", RotateFlipType) +} + +Gdip_RotateBitmapAtCenter(pBitmap, Angle, pBrush:=0, InterpolationMode:=7, PixelFormat:=0) { +; the pBrush will be used to fill the background of the image +; by default, it is black. +; It returns the pointer to a new pBitmap. + + If !Angle + { + newBitmap := Gdip_CloneBitmap(pBitmap) + Return newBitmap + } + + Gdip_GetImageDimensions(pBitmap, Width, Height) + Gdip_GetRotatedDimensions(Width, Height, Angle, RWidth, RHeight) + Gdip_GetRotatedTranslation(Width, Height, Angle, xTranslation, yTranslation) + If (RWidth*RHeight>536848912) || (Rwidth>32100) || (RHeight>32100) + Return + + + PixelFormatReadable := Gdip_GetImagePixelFormat(pBitmap, 2) + If InStr(PixelFormatReadable, "indexed") + { + hbm := CreateDIBSection(RWidth, RHeight,,24) + hdc := CreateCompatibleDC() + obm := SelectObject(hdc, hbm) + G := Gdip_GraphicsFromHDC(hdc) + indexedMode := 1 + } Else + { + If (PixelFormat=-1) + PixelFormat := "0xE200B" + + newBitmap := Gdip_CreateBitmap(RWidth, RHeight, PixelFormat) + G := Gdip_GraphicsFromImage(newBitmap) + } + + Gdip_SetInterpolationMode(G, InterpolationMode) + Gdip_SetSmoothingMode(G, 4) + Gdip_TranslateWorldTransform(G, xTranslation, yTranslation) + Gdip_RotateWorldTransform(G, Angle) + Gdip_DrawImageRect(G, pBitmap, 0, 0, Width, Height) + + If (indexedMode=1) + { + newBitmap := Gdip_CreateBitmapFromHBITMAP(hbm) + SelectObject(hdc, obm) + DeleteObject(hbm) + DeleteDC(hdc) + } + + Gdip_DeleteGraphics(G) + If (defaultBrush=1) + Gdip_DeleteBrush(pBrush) + + Return newBitmap +} + +Gdip_ResizeBitmap(pBitmap, givenW, givenH, KeepRatio, InterpolationMode:="", KeepPixelFormat:=0, checkTooLarge:=0) { +; KeepPixelFormat can receive a specific PixelFormat. +; The function returns a pointer to a new pBitmap. +; Default is 0 = 32-ARGB. +; For maximum speed, use 0xE200B - 32-PARGB pixel format. + + Gdip_GetImageDimensions(pBitmap, Width, Height) + If (KeepRatio=1) + { + calcIMGdimensions(Width, Height, givenW, givenH, ResizedW, ResizedH) + } Else + { + ResizedW := givenW + ResizedH := givenH + } + + If (((ResizedW*ResizedH>536848912) || (ResizedW>32100) || (ResizedH>32100)) && checkTooLarge=1) + Return + + PixelFormatReadable := Gdip_GetImagePixelFormat(pBitmap, 2) + If (KeepPixelFormat=1) + PixelFormat := Gdip_GetImagePixelFormat(pBitmap, 1) + Else If (KeepPixelFormat=-1) + PixelFormat := "0xE200B" + Else If Strlen(KeepPixelFormat)>3 + PixelFormat := KeepPixelFormat + + If InStr(PixelFormatReadable, "indexed") + { + hbm := CreateDIBSection(ResizedW, ResizedH,,24) + hdc := CreateCompatibleDC() + obm := SelectObject(hdc, hbm) + G := Gdip_GraphicsFromHDC(hdc, InterpolationMode, 4) + Gdip_DrawImageRect(G, pBitmap, 0, 0, ResizedW, ResizedH) + newBitmap := Gdip_CreateBitmapFromHBITMAP(hbm) + If (KeepPixelFormat=1) + Gdip_BitmapSetColorDepth(newBitmap, SubStr(PixelFormatReadable, 1, 1), 1) + SelectObject(hdc, obm) + DeleteObject(hbm) + DeleteDC(hdc) + Gdip_DeleteGraphics(G) + } Else + { + newBitmap := Gdip_CreateBitmap(ResizedW, ResizedH, PixelFormat) + G := Gdip_GraphicsFromImage(newBitmap, InterpolationMode) + Gdip_DrawImageRect(G, pBitmap, 0, 0, ResizedW, ResizedH) + Gdip_DeleteGraphics(G) + } + + Return newBitmap +} + +;##################################################################################### +; pPen functions +; With Gdip_SetPenBrushFill() or Gdip_CreatePenFromBrush() functions, +; pPen objects can have gradients or textures. +;##################################################################################### + +Gdip_CreatePen(ARGB, w, Unit:=2) { + pPen := 0 + E := DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "float", w, "int", Unit, "UPtr*", pPen) + return pPen +} + +Gdip_CreatePenFromBrush(pBrush, w, Unit:=2) { +; Unit - Unit of measurement for the pen size: +; 0 - World coordinates, a non-physical unit +; 1 - Display units +; 2 - A unit is 1 pixel [default] +; 3 - A unit is 1 point or 1/72 inch +; 4 - A unit is 1 inch +; 5 - A unit is 1/300 inch +; 6 - A unit is 1 millimeter + + pPen := 0 + E := DllCall("gdiplus\GdipCreatePen2", "UPtr", pBrush, "float", w, "int", 2, "UPtr*", pPen, "int", Unit) + return pPen +} + +Gdip_SetPenWidth(pPen, width) { + return DllCall("gdiplus\GdipSetPenWidth", "UPtr", pPen, "float", width) +} + +Gdip_GetPenWidth(pPen) { + width := 0 + E := DllCall("gdiplus\GdipGetPenWidth", "UPtr", pPen, "float*", width) + If E + return -1 + return width +} + +Gdip_GetPenDashStyle(pPen) { + DashStyle := 0 + E := DllCall("gdiplus\GdipGetPenDashStyle", "UPtr", pPen, "float*", DashStyle) + If E + return -1 + return DashStyle +} + +Gdip_SetPenColor(pPen, ARGB) { + return DllCall("gdiplus\GdipSetPenColor", "UPtr", pPen, "UInt", ARGB) +} + +Gdip_GetPenColor(pPen) { + ARGB := 0 + E := DllCall("gdiplus\GdipGetPenColor", "UPtr", pPen, "UInt*", ARGB) + If E + return -1 + return Format("{1:#x}", ARGB) +} + +Gdip_SetPenBrushFill(pPen, pBrush) { + return DllCall("gdiplus\GdipSetPenBrushFill", "UPtr", pPen, "UPtr", pBrush) +} + +Gdip_ResetPenTransform(pPen) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipResetPenTransform", Ptr, pPen) +} + +Gdip_MultiplyPenTransform(pPen, hMatrix, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipMultiplyPenTransform", Ptr, pPen, Ptr, hMatrix, "int", matrixOrder) +} + +Gdip_RotatePenTransform(pPen, Angle, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipRotatePenTransform", Ptr, pPen, "float", Angle, "int", matrixOrder) +} + +Gdip_ScalePenTransform(pPen, ScaleX, ScaleY, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipScalePenTransform", Ptr, pPen, "float", ScaleX, "float", ScaleY, "int", matrixOrder) +} + +Gdip_TranslatePenTransform(pPen, X, Y, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipTranslatePenTransform", Ptr, pPen, "float", X, "float", Y, "int", matrixOrder) +} + +Gdip_SetPenTransform(pPen, pMatrix) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetPenTransform", Ptr, pPen, Ptr, pMatrix) +} + +Gdip_GetPenTransform(pPen) { + Static Ptr := "UPtr" + pMatrix := 0 + DllCall("gdiplus\GdipGetPenTransform", Ptr, pPen, "UPtr*", pMatrix) + Return pMatrix +} + +Gdip_GetPenBrushFill(pPen) { +; Gets the pBrush object that is currently set for the pPen object + Static Ptr := "UPtr" + pBrush := 0 + E := DllCall("gdiplus\GdipGetPenBrushFill", Ptr, pPen, "int*", pBrush) + Return pBrush +} + +Gdip_GetPenFillType(pPen) { +; Description: Gets the type of brush fill currently set for a Pen object +; Return values: +; 0 - The pen draws with a solid color +; 1 - The pen draws with a hatch pattern that is specified by a HatchBrush object +; 2 - The pen draws with a texture that is specified by a TextureBrush object +; 3 - The pen draws with a color gradient that is specified by a PathGradientBrush object +; 4 - The pen draws with a color gradient that is specified by a LinearGradientBrush object +; -1 - The pen type is unknown +; -2 - Error + + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPenFillType", Ptr, pPen, "int*", result) + If E + return -2 + Return result +} + +Gdip_GetPenStartCap(pPen) { + result := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipGetPenStartCap", Ptr, pPen, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetPenEndCap(pPen) { + result := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipGetPenEndCap", Ptr, pPen, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetPenDashCaps(pPen) { + result := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipGetPenDashCap197819", Ptr, pPen, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetPenAlignment(pPen) { + result := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipGetPenMode", Ptr, pPen, "int*", result) + If E + return -1 + Return result +} + +;##################################################################################### +; Function - Gdip_SetPenLineCaps +; Description - Sets the cap styles for the start, end, and dashes in a line drawn with the pPen object +; Parameters +; pPen - Pointer to a Pen object. Start and end caps do not apply to closed lines. +; - StartCap - Line cap style for the start cap: +; 0x00 - Line ends at the last point. The end is squared off +; 0x01 - Square cap. The center of the square is the last point in the line. The height and width of the square are the line width. +; 0x02 - Circular cap. The center of the circle is the last point in the line. The diameter of the circle is the line width. +; 0x03 - Triangular cap. The base of the triangle is the last point in the line. The base of the triangle is the line width. +; 0x10 - Line ends are not anchored. +; 0x11 - Line ends are anchored with a square. The center of the square is the last point in the line. The height and width of the square are the line width. +; 0x12 - Line ends are anchored with a circle. The center of the circle is at the last point in the line. The circle is wider than the line. +; 0x13 - Line ends are anchored with a diamond (a square turned at 45 degrees). The center of the diamond is at the last point in the line. The diamond is wider than the line. +; 0x14 - Line ends are anchored with arrowheads. The arrowhead point is located at the last point in the line. The arrowhead is wider than the line. +; 0xff - Line ends are made from a CustomLineCap object. +; EndCap - Line cap style for the end cap (same values as StartCap) +; DashCap - Start and end caps for a dashed line: +; 0 - A square cap that squares off both ends of each dash +; 2 - A circular cap that rounds off both ends of each dash +; 3 - A triangular cap that points both ends of each dash +; Return value: status enumeration + +Gdip_SetPenLineCaps(pPen, StartCap, EndCap, DashCap) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenLineCap197819", Ptr, pPen, "int", StartCap, "int", EndCap, "int", DashCap) +} + +Gdip_SetPenStartCap(pPen, LineCap) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenStartCap", Ptr, pPen, "int", LineCap) +} + +Gdip_SetPenEndCap(pPen, LineCap) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenEndCap", Ptr, pPen, "int", LineCap) +} + +Gdip_SetPenDashCaps(pPen, LineCap) { +; If you set the alignment of a Pen object to +; Pen Alignment Inset, you cannot use that pen +; to draw triangular dash caps. + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenDashCap197819", Ptr, pPen, "int", LineCap) +} + +Gdip_SetPenAlignment(pPen, Alignment) { +; Specifies the alignment setting of the pen relative to the line that is drawn. The default value is Center. +; If you set the alignment of a Pen object to Inset, you cannot use that pen to draw compound lines or triangular dash caps. +; Alignment options: +; 0 [Center] - Specifies that the pen is aligned on the center of the line that is drawn. +; 1 [Inset] - Specifies, when drawing a polygon, that the pen is aligned on the inside of the edge of the polygon. + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenMode", Ptr, pPen, "int", Alignment) +} + +Gdip_GetPenCompoundCount(pPen) { + result := 0 + E := DllCall("gdiplus\GdipGetPenCompoundCount", Ptr, pPen, "int*", result) + If E + Return -1 + Return result +} + +Gdip_SetPenCompoundArray(pPen, inCompounds) { +; Parameters - pPen - Pointer to a pPen object +; inCompounds - A string of compound values: +; "value1|value2|value3" [and so on] +; ExampleCompounds := "0.0|0.2|0.7|1.0" +; Remarks - The elements in the string array must be in increasing order, between 0 and not greater than 1. +; Suppose you want a pen to draw two parallel lines where the width of the first line is 20 percent of the pen's +; width, the width of the space that separates the two lines is 50 percent of the pen's width, and the width +; of the second line is 30 percent of the pen's width. Start by creating a pPen object and an array of compound +; values. For this, you can then set the compound array by passing the array with the values "0.0|0.2|0.7|1.0". +; Return status enumeration + + arrCompounds := StrSplit(inCompounds, "|") + totalCompounds := arrCompounds.Length() + VarSetCapacity(pCompounds, 8 * totalCompounds, 0) + Loop %totalCompounds% + NumPut(arrCompounds[A_Index], &pCompounds, 4*(A_Index - 1), "float") + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenCompoundArray", Ptr, pPen, Ptr, &pCompounds, "int", totalCompounds) +} + +Gdip_SetPenDashStyle(pPen, DashStyle) { +; DashStyle options: +; Solid = 0 +; Dash = 1 +; Dot = 2 +; DashDot = 3 +; DashDotDot = 4 +; Custom = 5 +; https://technet.microsoft.com/pt-br/ms534104(v=vs.71).aspx +; function by IPhilip + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenDashStyle", Ptr, pPen, "Int", DashStyle) +} + +Gdip_SetPenDashArray(pPen, Dashes) { +; Description Sets custom dashes and spaces for the pPen object. +; +; Parameters pPen - Pointer to a Pen object +; Dashes - The string that specifies the length of the custom dashes and spaces: +; Format: "dL1,sL1,dL2,sL2,dL3,sL3" [... and so on] +; dLn - Dash N length +; sLn - Space N length +; ExampleDashesArgument := "3,6,8,4,2,1" +; +; Remarks This function sets the dash style for the pPen object to DashStyleCustom (6). +; Return status enumeration. + + Static Ptr := "UPtr" + Points := StrSplit(Dashes, ",") + PointsCount := Points.Length() + VarSetCapacity(PointsF, 8 * PointsCount, 0) + Loop %PointsCount% + NumPut(Points[A_Index], &PointsF, 4*(A_Index - 1), "float") + + Return DllCall("gdiplus\GdipSetPenDashArray", Ptr, pPen, Ptr, &PointsF, "int", PointsCount) +} + +Gdip_SetPenDashOffset(pPen, Offset) { +; Sets the distance from the start of the line to the start of the first space in a dashed line +; Offset - Real number that specifies the number of times to shift the spaces in a dashed line. Each shift is +; equal to the length of a space in the dashed line + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenDashOffset", Ptr, pPen, "float", Offset) +} + +Gdip_GetPenDashArray(pPen) { + iCount := Gdip_GetPenDashCount(pPen) + If (iCount=-1) + Return 0 + + VarSetCapacity(PointsF, 8 * iCount, 0) + Static Ptr := "UPtr" + DllCall("gdiplus\GdipGetPenDashArray", Ptr, pPen, "uPtr", &PointsF, "int", iCount) + + Loop %iCount% + { + A := NumGet(&PointsF, 4*(A_Index-1), "float") + printList .= A "," + } + + Return Trim(printList, ",") +} + +Gdip_GetPenCompoundArray(pPen) { + iCount := Gdip_GetPenCompoundCount(pPen) + VarSetCapacity(PointsF, 4 * iCount, 0) + Static Ptr := "UPtr" + DllCall("gdiplus\GdipGetPenCompoundArray", Ptr, pPen, "uPtr", &PointsF, "int", iCount) + + Loop %iCount% + { + A := NumGet(&PointsF, 4*(A_Index-1), "float") + printList .= A "|" + } + + Return Trim(printList, "|") +} + +Gdip_SetPenLineJoin(pPen, LineJoin) { +; LineJoin - Line join style: +; MITER = 0 - it produces a sharp corner or a clipped corner, depending on whether the length of the miter exceeds the miter limit. +; BEVEL = 1 - it produces a diagonal corner. +; ROUND = 2 - it produces a smooth, circular arc between the lines. +; MITERCLIPPED = 3 - it produces a sharp corner or a beveled corner, depending on whether the length of the miter exceeds the miter limit. + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenLineJoin", Ptr, pPen, "int", LineJoin) +} + +Gdip_SetPenMiterLimit(pPen, MiterLimit) { +; MiterLimit - Real number that specifies the miter limit of the Pen object. A real number value that is less +; than 1.0 will be replaced with 1.0, +; +; Remarks +; The miter length is the distance from the intersection of the line walls on the inside of the join to the +; intersection of the line walls outside of the join. The miter length can be large when the angle between two +; lines is small. The miter limit is the maximum allowed ratio of miter length to stroke width. The default +; value is 10.0. +; If the miter length of the join of the intersection exceeds the limit of the join, then the join will be +; beveled to keep it within the limit of the join of the intersection + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenMiterLimit", Ptr, pPen, "float", MiterLimit) +} + +Gdip_SetPenUnit(pPen, Unit) { +; Sets the unit of measurement for a pPen object. +; Unit - New unit of measurement for the pen: +; 0 - World coordinates, a non-physical unit +; 1 - Display units +; 2 - A unit is 1 pixel +; 3 - A unit is 1 point or 1/72 inch +; 4 - A unit is 1 inch +; 5 - A unit is 1/300 inch +; 6 - A unit is 1 millimeter + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetPenUnit", Ptr, pPen, "int", Unit) +} + +Gdip_GetPenDashCount(pPen) { + result := 0 + E := DllCall("gdiplus\GdipGetPenDashCount", Ptr, pPen, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetPenDashOffset(pPen) { + result := 0 + E := DllCall("gdiplus\GdipGetPenDashOffset", Ptr, pPen, "float*", result) + If E + Return -1 + Return result +} + +Gdip_GetPenLineJoin(pPen) { + result := 0 + E := DllCall("gdiplus\GdipGetPenLineJoin", Ptr, pPen, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetPenMiterLimit(pPen) { + result := 0 + E := DllCall("gdiplus\GdipGetPenMiterLimit", Ptr, pPen, "float*", result) + If E + Return -1 + Return result +} + +Gdip_GetPenUnit(pPen) { + result := 0 + E := DllCall("gdiplus\GdipGetPenUnit", Ptr, pPen, "int*", result) + If E + Return -1 + Return result +} + +Gdip_ClonePen(pPen) { + newPen := 0 + E := DllCall("gdiplus\GdipClonePen", "UPtr", pPen, "UPtr*", newPen) + Return newPen +} + +;##################################################################################### +; pBrush functions [types: SolidFill, Texture, Hatch patterns, PathGradient and LinearGradient] +; pBrush objects can be used by pPen objects via Gdip_SetPenBrushFill() +;##################################################################################### + +Gdip_BrushCreateSolid(ARGB:=0xff000000) { + pBrush := 0 + E := DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, "UPtr*", pBrush) + return pBrush +} + +Gdip_SetSolidFillColor(pBrush, ARGB) { + return DllCall("gdiplus\GdipSetSolidFillColor", "UPtr", pBrush, "UInt", ARGB) +} + +Gdip_GetSolidFillColor(pBrush) { + ARGB := 0 + E := DllCall("gdiplus\GdipGetSolidFillColor", "UPtr", pBrush, "UInt*", ARGB) + If E + return -1 + return Format("{1:#x}", ARGB) +} + +Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle:=0) { +; HatchStyle options: +; Horizontal = 0 +; Vertical = 1 +; ForwardDiagonal = 2 +; BackwardDiagonal = 3 +; Cross = 4 +; DiagonalCross = 5 +; 05Percent = 6 +; 10Percent = 7 +; 20Percent = 8 +; 25Percent = 9 +; 30Percent = 10 +; 40Percent = 11 +; 50Percent = 12 +; 60Percent = 13 +; 70Percent = 14 +; 75Percent = 15 +; 80Percent = 16 +; 90Percent = 17 +; LightDownwardDiagonal = 18 +; LightUpwardDiagonal = 19 +; DarkDownwardDiagonal = 20 +; DarkUpwardDiagonal = 21 +; WideDownwardDiagonal = 22 +; WideUpwardDiagonal = 23 +; LightVertical = 24 +; LightHorizontal = 25 +; NarrowVertical = 26 +; NarrowHorizontal = 27 +; DarkVertical = 28 +; DarkHorizontal = 29 +; DashedDownwardDiagonal = 30 +; DashedUpwardDiagonal = 31 +; DashedHorizontal = 32 +; DashedVertical = 33 +; SmallConfetti = 34 +; LargeConfetti = 35 +; ZigZag = 36 +; Wave = 37 +; DiagonalBrick = 38 +; HorizontalBrick = 39 +; Weave = 40 +; Plaid = 41 +; Divot = 42 +; DottedGrid = 43 +; DottedDiamond = 44 +; Shingle = 45 +; Trellis = 46 +; Sphere = 47 +; SmallGrid = 48 +; SmallCheckerBoard = 49 +; LargeCheckerBoard = 50 +; OutlinedDiamond = 51 +; SolidDiamond = 52 +; Total = 53 + pBrush := 0 + E := DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, "UPtr*", pBrush) + return pBrush +} + +Gdip_GetHatchBackgroundColor(pHatchBrush) { + ARGB := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipGetHatchBackgroundColor", Ptr, pHatchBrush, "uint*", ARGB) + If E + Return -1 + return Format("{1:#x}", ARGB) +} + +Gdip_GetHatchForegroundColor(pHatchBrush) { + ARGB := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipGetHatchForegroundColor", Ptr, pHatchBrush, "uint*", ARGB) + If E + Return -1 + return Format("{1:#x}", ARGB) +} + +Gdip_GetHatchStyle(pHatchBrush) { + result := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipGetHatchStyle", Ptr, pHatchBrush, "int*", result) + If E + Return -1 + Return result +} + +;##################################################################################### + +; Function: Gdip_CreateTextureBrush +; Description: Creates a TextureBrush object based on an image, a wrap mode and a defining rectangle. +; +; pBitmap Pointer to an Image object +; WrapMode Wrap mode that specifies how repeated copies of an image are used to tile an area when it is +; painted with the texture brush: +; 0 - Tile - Tiling without flipping +; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row +; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column +; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column +; 4 - Clamp - No tiling takes place +; x, y x, y coordinates of the image portion to be used by this brush +; w, h Width and height of the image portion +; matrix A color matrix to alter the colors of the given pBitmap +; ScaleX, ScaleY x, y scaling factor for the texture +; Angle Rotates the texture at given angle +; +; return If the function succeeds, the return value is nonzero +; notes If w and h are omitted, the entire pBitmap is used +; Matrix can be omitted to just draw with no alteration to the ARGB channels +; Matrix may be passed as a digit from 0.0 - 1.0 to change just transparency +; Matrix can be passed as a matrix with "|" as delimiter. +; Function modified by Marius Șucan, to allow use of color matrix and ImageAttributes object. + +Gdip_CreateTextureBrush(pBitmap, WrapMode:=1, x:=0, y:=0, w:="", h:="", matrix:="", ScaleX:="", ScaleY:="", Angle:=0, ImageAttr:=0) { + Static Ptr := "UPtr" + PtrA := "UPtr*" + pBrush := 0 + + if !(w && h) + { + DllCall("gdiplus\GdipCreateTexture", Ptr, pBitmap, "int", WrapMode, PtrA, pBrush) + } else + { + If !ImageAttr + { + if !IsNumber(Matrix) + 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") + } Else usrImageAttr := 1 + + If ImageAttr + { + DllCall("gdiplus\GdipCreateTextureIA", Ptr, pBitmap, Ptr, ImageAttr, "float", x, "float", y, "float", w, "float", h, PtrA, pBrush) + If pBrush + Gdip_SetTextureWrapMode(pBrush, WrapMode) + } Else + DllCall("gdiplus\GdipCreateTexture2", Ptr, pBitmap, "int", WrapMode, "float", x, "float", y, "float", w, "float", h, PtrA, pBrush) + } + + if (ImageAttr && usrImageAttr!=1) + Gdip_DisposeImageAttributes(ImageAttr) + + If (ScaleX && ScaleX && pBrush) + Gdip_ScaleTextureTransform(pBrush, ScaleX, ScaleY) + + If (Angle && pBrush) + Gdip_RotateTextureTransform(pBrush, Angle) + + return pBrush +} + +Gdip_RotateTextureTransform(pTexBrush, Angle, MatrixOrder:=0) { +; MatrixOrder options: +; Prepend = 0; The new operation is applied before the old operation. +; Append = 1; The new operation is applied after the old operation. +; Order of matrices multiplication:. + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipRotateTextureTransform", Ptr, pTexBrush, "float", Angle, "int", MatrixOrder) +} + +Gdip_ScaleTextureTransform(pTexBrush, ScaleX, ScaleY, MatrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipScaleTextureTransform", Ptr, pTexBrush, "float", ScaleX, "float", ScaleY, "int", MatrixOrder) +} + +Gdip_TranslateTextureTransform(pTexBrush, X, Y, MatrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipTranslateTextureTransform", Ptr, pTexBrush, "float", X, "float", Y, "int", MatrixOrder) +} + +Gdip_MultiplyTextureTransform(pTexBrush, hMatrix, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipMultiplyTextureTransform", Ptr, pTexBrush, Ptr, hMatrix, "int", matrixOrder) +} + +Gdip_SetTextureTransform(pTexBrush, hMatrix) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetTextureTransform", Ptr, pTexBrush, Ptr, hMatrix) +} + +Gdip_GetTextureTransform(pTexBrush) { + hMatrix := 0 + Static Ptr := "UPtr" + DllCall("gdiplus\GdipGetTextureTransform", Ptr, pTexBrush, "UPtr*", hMatrix) + Return hMatrix +} + +Gdip_ResetTextureTransform(pTexBrush) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipResetTextureTransform", Ptr, pTexBrush) +} + +Gdip_SetTextureWrapMode(pTexBrush, WrapMode) { +; WrapMode options: +; 0 - Tile - Tiling without flipping +; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row +; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column +; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column +; 4 - Clamp - No tiling takes place + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetTextureWrapMode", Ptr, pTexBrush, "int", WrapMode) +} + +Gdip_GetTextureWrapMode(pTexBrush) { + result := 0 + Static Ptr := "UPtr" + E := DllCall("gdiplus\GdipGetTextureWrapMode", Ptr, pTexBrush, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetTextureImage(pTexBrush) { + Static Ptr := "UPtr" + pBitmapDest := 0 + E := DllCall("gdiplus\GdipGetTextureImage", Ptr, pTexBrush + , "UPtr*", pBitmapDest) + Return pBitmapDest +} + +;##################################################################################### +; LinearGradientBrush functions +;##################################################################################### + +Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode:=1) { + return Gdip_CreateLinearGrBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode) +} + +Gdip_CreateLinearGrBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode:=1) { +; Linear gradient brush. +; WrapMode specifies how the pattern is repeated once it exceeds the defined space +; Tile [no flipping] = 0 +; TileFlipX = 1 +; TileFlipY = 2 +; TileFlipXY = 3 +; Clamp [no tiling] = 4 + Static Ptr := "UPtr" + CreatePointF(PointF1, x1, y1) + CreatePointF(PointF2, x2, y2) + pLinearGradientBrush := 0 + DllCall("gdiplus\GdipCreateLineBrush", Ptr, &PointF1, Ptr, &PointF2, "Uint", ARGB1, "Uint", ARGB2, "int", WrapMode, "UPtr*", pLinearGradientBrush) + return pLinearGradientBrush +} + +Gdip_SetLinearGrBrushColors(pLinearGradientBrush, ARGB1, ARGB2) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetLineColors", Ptr, pLinearGradientBrush, "UInt", ARGB1, "UInt", ARGB2) +} + +Gdip_GetLinearGrBrushColors(pLinearGradientBrush, ByRef ARGB1, ByRef ARGB2) { + Static Ptr := "UPtr" + VarSetCapacity(colors, 8, 0) + E := DllCall("gdiplus\GdipGetLineColors", Ptr, pLinearGradientBrush, "Ptr", &colors) + ARGB1 := NumGet(colors, 0, "UInt") + ARGB2 := NumGet(colors, 4, "UInt") + ARGB1 := Format("{1:#x}", ARGB1) + ARGB2 := Format("{1:#x}", ARGB2) + return E +} + +Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode:=1, WrapMode:=1) { + return Gdip_CreateLinearGrBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode, WrapMode) +} + +Gdip_CreateLinearGrBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode:=1, WrapMode:=1) { +; WrapMode options [LinearGradientMode]: +; Horizontal = 0 +; Vertical = 1 +; ForwardDiagonal = 2 +; BackwardDiagonal = 3 + CreateRectF(RectF, x, y, w, h) + pLinearGradientBrush := 0 + E := DllCall("gdiplus\GdipCreateLineBrushFromRect", "UPtr", &RectF, "int", ARGB1, "int", ARGB2, "int", LinearGradientMode, "int", WrapMode, "UPtr*", pLinearGradientBrush) + return pLinearGradientBrush +} + +Gdip_GetLinearGrBrushGammaCorrection(pLinearGradientBrush) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetLineGammaCorrection", Ptr, pLinearGradientBrush, "int*", result) + If E + Return -1 + Return result +} + +Gdip_SetLinearGrBrushGammaCorrection(pLinearGradientBrush, UseGammaCorrection) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetLineGammaCorrection", Ptr, pLinearGradientBrush, "int", UseGammaCorrection) +} + +Gdip_GetLinearGrBrushRect(pLinearGradientBrush) { + rData := {} + VarSetCapacity(RectF, 16, 0) + status := DllCall("gdiplus\GdipGetLineRect", "UPtr", pLinearGradientBrush, "UPtr", &RectF) + + If (!status) { + rData.x := NumGet(&RectF, 0, "float") + , rData.y := NumGet(&RectF, 4, "float") + , rData.w := NumGet(&RectF, 8, "float") + , rData.h := NumGet(&RectF, 12, "float") + } Else { + Return status + } + + return rData +} + +Gdip_ResetLinearGrBrushTransform(pLinearGradientBrush) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipResetLineTransform", Ptr, pLinearGradientBrush) +} + +Gdip_ScaleLinearGrBrushTransform(pLinearGradientBrush, ScaleX, ScaleY, matrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipScaleLineTransform", Ptr, pLinearGradientBrush, "float", ScaleX, "float", ScaleY, "int", matrixOrder) +} + +Gdip_MultiplyLinearGrBrushTransform(pLinearGradientBrush, hMatrix, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipMultiplyLineTransform", Ptr, pLinearGradientBrush, Ptr, hMatrix, "int", matrixOrder) +} + +Gdip_TranslateLinearGrBrushTransform(pLinearGradientBrush, X, Y, matrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipTranslateLineTransform", Ptr, pLinearGradientBrush, "float", X, "float", Y, "int", matrixOrder) +} + +Gdip_RotateLinearGrBrushTransform(pLinearGradientBrush, Angle, matrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipRotateLineTransform", Ptr, pLinearGradientBrush, "float", Angle, "int", matrixOrder) +} + +Gdip_SetLinearGrBrushTransform(pLinearGradientBrush, pMatrix) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetLineTransform", Ptr, pLinearGradientBrush, Ptr, pMatrix) +} + +Gdip_GetLinearGrBrushTransform(pLineGradientBrush) { + Static Ptr := "UPtr" + pMatrix := 0 + DllCall("gdiplus\GdipGetLineTransform", Ptr, pLineGradientBrush, "UPtr*", pMatrix) + Return pMatrix +} + +Gdip_RotateLinearGrBrushAtCenter(pLinearGradientBrush, Angle, MatrixOrder:=1) { +; function by Marius Șucan +; based on Gdip_RotatePathAtCenter() by RazorHalo + + Rect := Gdip_GetLinearGrBrushRect(pLinearGradientBrush) ; boundaries + cX := Rect.x + (Rect.w / 2) + cY := Rect.y + (Rect.h / 2) + pMatrix := Gdip_CreateMatrix() + Gdip_TranslateMatrix(pMatrix, -cX , -cY) + Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder) + Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder) + E := Gdip_SetLinearGrBrushTransform(pLinearGradientBrush, pMatrix) + Gdip_DeleteMatrix(pMatrix) + Return E +} + +Gdip_GetLinearGrBrushWrapMode(pLinearGradientBrush) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetLineWrapMode", Ptr, pLinearGradientBrush, "int*", result) + If E + return -1 + Return result +} + +Gdip_SetLinearGrBrushLinearBlend(pLinearGradientBrush, nFocus, nScale) { +; https://purebasic.developpez.com/tutoriels/gdi/documentation/GdiPlus/LinearGradientBrush/html/GdipSetLineLinearBlend.html + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetLineLinearBlend", Ptr, pLinearGradientBrush, "float", nFocus, "float", nScale) +} + +Gdip_SetLinearGrBrushSigmaBlend(pLinearGradientBrush, nFocus, nScale) { +; https://purebasic.developpez.com/tutoriels/gdi/documentation/GdiPlus/LinearGradientBrush/html/GdipSetLineSigmaBlend.html + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetLineSigmaBlend", Ptr, pLinearGradientBrush, "float", nFocus, "float", nScale) +} + +Gdip_SetLinearGrBrushWrapMode(pLinearGradientBrush, WrapMode) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetLineWrapMode", Ptr, pLinearGradientBrush, "int", WrapMode) +} + +Gdip_GetLinearGrBrushBlendCount(pLinearGradientBrush) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetLineBlendCount", Ptr, pLinearGradientBrush, "int*", result) + If E + return -1 + Return result +} + +Gdip_SetLinearGrBrushPresetBlend(pBrush, pA, pB, pC, pD, clr1, clr2, clr3, clr4) { + Static Ptr := "UPtr" + CreateRectF(POSITIONS, pA, pB, pC, pD) + CreateRect(COLORS, clr1, clr2, clr3, clr4) + E:= DllCall("gdiplus\GdipSetLinePresetBlend", Ptr, pBrush, "Ptr", &COLORS, "Ptr", &POSITIONS, "Int", 4) + Return E +} + +Gdip_CloneBrush(pBrush) { + pBrushClone := 0 + E := DllCall("gdiplus\GdipCloneBrush", "UPtr", pBrush, "UPtr*", pBrushClone) + return pBrushClone +} + +Gdip_GetBrushType(pBrush) { +; Possible brush types [return values]: +; 0 - Solid color +; 1 - Hatch pattern fill +; 2 - Texture fill +; 3 - Path gradient +; 4 - Linear gradient +; -1 - error + + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetBrushType", Ptr, pBrush, "int*", result) + If E + return -1 + Return result +} + +;##################################################################################### +; Delete resources +;##################################################################################### + +Gdip_DeleteRegion(Region) { + return DllCall("gdiplus\GdipDeleteRegion", "UPtr", Region) +} + +Gdip_DeletePen(pPen) { + return DllCall("gdiplus\GdipDeletePen", "UPtr", pPen) +} + +Gdip_DeleteBrush(pBrush) { + return DllCall("gdiplus\GdipDeleteBrush", "UPtr", pBrush) +} + +Gdip_DisposeImage(pBitmap, noErr:=0) { +; modified by Marius Șucan to help avoid crashes +; by disposing a non-existent pBitmap + + If (StrLen(pBitmap)<=2 && noErr=1) + Return 0 + + r := DllCall("gdiplus\GdipDisposeImage", "UPtr", pBitmap) + If (r=2 || r=1) && (noErr=1) + r := 0 + Return r +} + +Gdip_DeleteGraphics(pGraphics) { + return DllCall("gdiplus\GdipDeleteGraphics", "UPtr", pGraphics) +} + +Gdip_DisposeImageAttributes(ImageAttr) { + return DllCall("gdiplus\GdipDisposeImageAttributes", "UPtr", ImageAttr) +} + +Gdip_DeleteFont(hFont) { + return DllCall("gdiplus\GdipDeleteFont", "UPtr", hFont) +} + +Gdip_DeleteStringFormat(hStringFormat) { + return DllCall("gdiplus\GdipDeleteStringFormat", "UPtr", hStringFormat) +} + +Gdip_DeleteFontFamily(hFontFamily) { + return DllCall("gdiplus\GdipDeleteFontFamily", "UPtr", hFontFamily) +} + +Gdip_DeletePrivateFontCollection(hFontCollection) { + Return DllCall("gdiplus\GdipDeletePrivateFontCollection", "ptr*", hFontCollection) +} + +Gdip_DeleteMatrix(hMatrix) { + return DllCall("gdiplus\GdipDeleteMatrix", "UPtr", hMatrix) +} + +;##################################################################################### +; Text functions +; Easy to use functions: +; Gdip_DrawOrientedString() - allows to draw strings or string contours/outlines, +; or both, rotated at any angle. On success, its boundaries are returned. +; Gdip_DrawStringAlongPolygon() - allows you to draw a string along a pPath +; or multiple given coordinates. +; Gdip_TextToGraphics() - allows you to draw strings or measure their boundaries. +;##################################################################################### + +Gdip_DrawOrientedString(pGraphics, String, FontName, Size, Style, X, Y, Width, Height, Angle:=0, pBrush:=0, pPen:=0, Align:=0, ScaleX:=1) { +; FontName can be a name of an already installed font or it can point to a font file +; to be loaded and used to draw the string. + +; Size - in em, in world units [font size] +; Remarks: a high value might be required; over 60, 90... to see the text. +; X, Y - coordinates for the rectangle where the text will be drawn +; W, H - width and heigh for the rectangle where the text will be drawn +; Angle - the angle at which the text should be rotated + +; pBrush - a pointer to a pBrush object to fill the text with +; pPen - a pointer to a pPen object to draw the outline [contour] of the text +; Remarks: both are optional, but one at least must be given, otherwise +; the function fails, returns -3. +; For example, if you want only the contour of the text, pass only a pPen object. + +; Align options: +; Near/left = 0 +; Center = 1 +; Far/right = 2 + +; Style options: +; Regular = 0 +; Bold = 1 +; Italic = 2 +; BoldItalic = 3 +; Underline = 4 +; Strikeout = 8 + +; ScaleX - if you want to distort the text [make it wider or narrower] + +; On success, the function returns an array: +; PathBounds.x , PathBounds.y , PathBounds.w , PathBounds.h + + If (!pBrush && !pPen) + Return -3 + + If RegExMatch(FontName, "^(.\:\\.)") + { + hFontCollection := Gdip_NewPrivateFontCollection() + hFontFamily := Gdip_CreateFontFamilyFromFile(FontName, hFontCollection) + } Else hFontFamily := Gdip_FontFamilyCreate(FontName) + + If !hFontFamily + hFontFamily := Gdip_FontFamilyCreateGeneric(1) + + If !hFontFamily + { + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Return -1 + } + + FormatStyle := 0x4000 + hStringFormat := Gdip_StringFormatCreate(FormatStyle) + If !hStringFormat + hStringFormat := Gdip_StringFormatGetGeneric(1) + + If !hStringFormat + { + Gdip_DeleteFontFamily(hFontFamily) + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Return -2 + } + + Gdip_SetStringFormatTrimming(hStringFormat, 3) + Gdip_SetStringFormatAlign(hStringFormat, Align) + pPath := Gdip_CreatePath() + + E := Gdip_AddPathString(pPath, String, hFontFamily, Style, Size, hStringFormat, X, Y, Width, Height) + If (ScaleX>0 && ScaleX!=1) + { + hMatrix := Gdip_CreateMatrix() + Gdip_ScaleMatrix(hMatrix, ScaleX, 1) + Gdip_TransformPath(pPath, hMatrix) + Gdip_DeleteMatrix(hMatrix) + } + Gdip_RotatePathAtCenter(pPath, Angle) + + If (!E && pBrush) + E := Gdip_FillPath(pGraphics, pBrush, pPath) + If (!E && pPen) + E := Gdip_DrawPath(pGraphics, pPen, pPath) + PathBounds := Gdip_GetPathWorldBounds(pPath) + Gdip_DeleteStringFormat(hStringFormat) + Gdip_DeleteFontFamily(hFontFamily) + Gdip_DeletePath(pPath) + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Return E ? E : PathBounds +} + +Gdip_TextToGraphics(pGraphics, Text, Options, Font:="Arial", Width:="", Height:="", Measure:=0, userBrush:=0, Unit:=0) { +; Font parameter can be a name of an already installed font or it can point to a font file +; to be loaded and used to draw the string. +; +; Set Unit to 3 [Pts] to have the texts rendered at the same size +; with the texts rendered in GUIs with -DPIscale +; +; userBrush - if a pBrush object is passed, this will be used to draw the text +; Remarks: by changing the alignment, the text will be rendered at a different X +; coordinate position; the position of the text is set relative to +; the given X position coordinate and the text width.. +; See also Gdip_SetStringFormatAlign(). +; +; On success, the function returns a string in the following format: +; "x|y|width|height|chars|lines" +; The first four elements represent the boundaries of the text. +; The string is returned by Gdip_MeasureString() + + Static Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout" + , Alignments := "Near|Left|Centre|Center|Far|Right" + + IWidth := Width, IHeight:= Height + pattern_opts := (A_AhkVersion < "2") ? "iO)" : "i)" + RegExMatch(Options, pattern_opts "X([\-\d\.]+)(p*)", xpos) + RegExMatch(Options, pattern_opts "Y([\-\d\.]+)(p*)", ypos) + RegExMatch(Options, pattern_opts "W([\-\d\.]+)(p*)", Width) + RegExMatch(Options, pattern_opts "H([\-\d\.]+)(p*)", Height) + RegExMatch(Options, pattern_opts "C(?!(entre|enter))([a-f\d]+)", Colour) + RegExMatch(Options, pattern_opts "Top|Up|Bottom|Down|vCentre|vCenter", vPos) + RegExMatch(Options, pattern_opts "NoWrap", NoWrap) + RegExMatch(Options, pattern_opts "R(\d)", Rendering) + RegExMatch(Options, pattern_opts "S(\d+)(p*)", Size) + + if Colour && IsInteger(Colour[2]) && !Gdip_DeleteBrush(Gdip_CloneBrush(Colour[2])) + { + PassBrush := 1 + pBrush := Colour[2] + } + + if !(IWidth && IHeight) && ((xpos && xpos[2]) || (ypos && ypos[2]) || (Width && Width[2]) || (Height && Height[2]) || (Size && Size[2])) + return -1 + + Style := 0 + For eachStyle, valStyle in StrSplit(Styles, "|") + { + if RegExMatch(Options, "\b" valStyle) + Style |= (valStyle != "StrikeOut") ? (A_Index-1) : 8 + } + + Align := 0 + For eachAlignment, valAlignment in StrSplit(Alignments, "|") + { + if RegExMatch(Options, "\b" valAlignment) + Align |= A_Index//2.1 ; 0|0|1|1|2|2 + } + + xpos := (xpos && (xpos[1] != "")) ? xpos[2] ? IWidth*(xpos[1]/100) : xpos[1] : 0 + ypos := (ypos && (ypos[1] != "")) ? ypos[2] ? IHeight*(ypos[1]/100) : ypos[1] : 0 + Width := (Width && Width[1]) ? Width[2] ? IWidth*(Width[1]/100) : Width[1] : IWidth + Height := (Height && Height[1]) ? Height[2] ? IHeight*(Height[1]/100) : Height[1] : IHeight + If !PassBrush + Colour := "0x" (Colour && Colour[2] ? Colour[2] : "ff000000") + Rendering := (Rendering && (Rendering[1] >= 0) && (Rendering[1] <= 5)) ? Rendering[1] : 4 + Size := (Size && (Size[1] > 0)) ? Size[2] ? IHeight*(Size[1]/100) : Size[1] : 12 + If RegExMatch(Font, "^(.\:\\.)") + { + hFontCollection := Gdip_NewPrivateFontCollection() + hFontFamily := Gdip_CreateFontFamilyFromFile(Font, hFontCollection) + } Else hFontFamily := Gdip_FontFamilyCreate(Font) + + If !hFontFamily + hFontFamily := Gdip_FontFamilyCreateGeneric(1) + + hFont := Gdip_FontCreate(hFontFamily, Size, Style, Unit) + FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000 + hStringFormat := Gdip_StringFormatCreate(FormatStyle) + If !hStringFormat + hStringFormat := Gdip_StringFormatGetGeneric(1) + + pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour) + if !(hFontFamily && hFont && hStringFormat && pBrush && pGraphics) + { + E := !pGraphics ? -2 : !hFontFamily ? -3 : !hFont ? -4 : !hStringFormat ? -5 : !pBrush ? -6 : 0 + If pBrush + Gdip_DeleteBrush(pBrush) + If hStringFormat + Gdip_DeleteStringFormat(hStringFormat) + If hFont + Gdip_DeleteFont(hFont) + If hFontFamily + Gdip_DeleteFontFamily(hFontFamily) + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + return E + } + + CreateRectF(RC, xpos, ypos, Width, Height) + Gdip_SetStringFormatAlign(hStringFormat, Align) + If InStr(Options, "autotrim") + Gdip_SetStringFormatTrimming(hStringFormat, 3) + + Gdip_SetTextRenderingHint(pGraphics, Rendering) + ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hStringFormat, RC) + ReturnRCtest := StrSplit(ReturnRC, "|") + testX := Floor(ReturnRCtest[1]) - 2 + If (testX>xpos) ; error correction for different text alignments + { + nxpos := Floor(xpos - (testX - xpos)) + CreateRectF(RC, nxpos, ypos, Width, Height) + ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hStringFormat, RC) + ; MsgBox, % nxpos "--" xpos "--" ypos "`n" width "--" height "`n" ReturnRC + } + + If vPos + { + ReturnRC := StrSplit(ReturnRC, "|") + if (vPos[0] = "vCentre") || (vPos[0] = "vCenter") + ypos += (Height-ReturnRC[4])//2 + else if (vPos[0] = "Top") || (vPos[0] = "Up") + ypos += 0 + else if (vPos[0] = "Bottom") || (vPos[0] = "Down") + ypos += Height-ReturnRC[4] + + CreateRectF(RC, xpos, ypos, Width, ReturnRC[4]) + ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hStringFormat, RC) + } + + thisBrush := userBrush ? userBrush : pBrush + if !Measure + _E := Gdip_DrawString(pGraphics, Text, hFont, hStringFormat, thisBrush, RC) + + if !PassBrush + Gdip_DeleteBrush(pBrush) + Gdip_DeleteStringFormat(hStringFormat) + Gdip_DeleteFont(hFont) + Gdip_DeleteFontFamily(hFontFamily) + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + return _E ? _E : ReturnRC +} + +Gdip_DrawString(pGraphics, sString, hFont, hStringFormat, pBrush, ByRef RectF) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipDrawString" + , Ptr, pGraphics + , "WStr", sString + , "int", -1 + , Ptr, hFont + , Ptr, &RectF + , Ptr, hStringFormat + , Ptr, pBrush) +} + +Gdip_MeasureString(pGraphics, sString, hFont, hStringFormat, ByRef RectF) { +; The function returns a string in the following format: +; "x|y|width|height|chars|lines" +; The first four elements represent the boundaries of the text + + Static Ptr := "UPtr" + VarSetCapacity(RC, 16) + Chars := 0 + Lines := 0 + DllCall("gdiplus\GdipMeasureString" + , Ptr, pGraphics + , "WStr", sString + , "int", -1 + , Ptr, hFont + , Ptr, &RectF + , Ptr, hStringFormat + , Ptr, &RC + , "uint*", Chars + , "uint*", Lines) + + return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0 +} + +Gdip_DrawStringAlongPolygon(pGraphics, String, FontName, FontSize, Style, pBrush, DriverPoints:=0, pPath:=0, minDist:=0, flatness:=4, hMatrix:=0, Unit:=0) { +; The function allows you to draw a text string along a polygonal line. +; Each point on the line corresponds to a letter. +; If they are too close, the letters will overlap. If they are fewer than +; the string length, the text is going to be truncated. +; If given, a pPath object will be segmented according to the precision defined by «flatness». +; +; pGraphics - a pointer to a pGraphics object where to draw the text +; FontName can be the name of an already installed font or it can point to a font file +; to be loaded and used to draw the string. +; FontSize - in em, in world units +; a high value might be required; over 60, 90... to see the text. +; pBrush - a pointer to a pBrush object to fill the text with +; DriverPoints - a string with X, Y coordinates where the letters +; of the string will be drawn. Each X/Y pair corresponds to a letter. +; "x1,y1|x2,y2|x3,y3" [...and so on] +; pPath - A pointer to a pPath object. +; It will be used only if DriverPoints parameter is omitted. +; If both DriverPoints and pPath are omitted, the function will return -4. +; Intermmediate points will be generated if there are more glyphs / letters than defined points. +; +; flatness - from 0.1 to 5; the precision for arcs, beziers and curves segmentation; +; the lower the number is, the higher density of points is; +; it applies only for given pPath objects +; +; minDist - the minimum distance between letters; by default it is FontSize/4 +; does not apply for pPath objects; use the flatness parameter to control points density +; +; Style options: +; Regular = 0 +; Bold = 1 +; Italic = 2 +; BoldItalic = 3 +; Underline = 4 +; Strikeout = 8 +; +; Set Unit to 3 [Pts] to have the texts rendered at the same size +; with the texts rendered in GUIs with -DPIscale + + If (!minDist || minDist<1) + minDist := FontSize//4 + 1 + + If (pPath && !DriverPoints) + { + newPath := Gdip_ClonePath(pPath) + Gdip_PathOutline(newPath, flatness) + DriverPoints := Gdip_GetPathPoints(newPath) + Gdip_DeletePath(newPath) + If !DriverPoints + Return -5 + } + + If (!pPath && !DriverPoints) + Return -4 + + If RegExMatch(FontName, "^(.\:\\.)") + { + hFontCollection := Gdip_NewPrivateFontCollection() + hFontFamily := Gdip_CreateFontFamilyFromFile(FontName, hFontCollection) + } Else hFontFamily := Gdip_FontFamilyCreate(FontName) + + If !hFontFamily + hFontFamily := Gdip_FontFamilyCreateGeneric(1) + + If !hFontFamily + { + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Return -1 + } + + hFont := Gdip_FontCreate(hFontFamily, FontSize, Style, Unit) + If !hFont + { + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Gdip_DeleteFontFamily(hFontFamily) + Return -2 + } + + Points := StrSplit(DriverPoints, "|") + PointsCount := Points.Length() + If (PointsCount<2) + { + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Gdip_DeleteFont(hFont) + Gdip_DeleteFontFamily(hFontFamily) + Return -3 + } + + txtLen := StrLen(String) + If (PointsCount=txtLen) + Break + } + String := SubStr(String, 1, totalResult) + } Else newDriverPoints := DriverPoints + + E := Gdip_DrawDrivenString(pGraphics, String, hFont, pBrush, newDriverPoints, 1, hMatrix) + Gdip_DeleteFont(hFont) + Gdip_DeleteFontFamily(hFontFamily) + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + return E +} + +GenerateIntermediatePoints(PointsList, minDist, ByRef resultPointsCount) { +; function used by Gdip_DrawFreeFormString() + AllPoints := StrSplit(PointsList, "|") + PointsCount := AllPoints.Length() + thizIndex := 0.5 + resultPointsCount := 0 + loopsMax := PointsCount*2 + Loop %loopsMax% + { + thizIndex += 0.5 + thisIndex := InStr(thizIndex, ".5") ? thizIndex : Trim(Round(thizIndex)) + thisPoint := AllPoints[thisIndex] + theseCoords := StrSplit(thisPoint, ",") + If (theseCoords[1]!="" && theseCoords[2]!="") + { + resultPointsCount++ + newPointsList .= theseCoords[1] "," theseCoords[2] "|" + } Else + { + aIndex := Trim(Round(thizIndex - 0.5)) + bIndex := Trim(Round(thizIndex + 0.5)) + theseAcoords := StrSplit(AllPoints[aIndex], ",") + theseBcoords := StrSplit(AllPoints[bIndex], ",") + If (theseAcoords[1]!="" && theseAcoords[2]!="") + && (theseBcoords[1]!="" && theseBcoords[2]!="") + { + newPosX := (theseAcoords[1] + theseBcoords[1])//2 + newPosY := (theseAcoords[2] + theseBcoords[2])//2 + distPosX := newPosX - theseAcoords[1] + distPosY := newPosY - theseAcoords[2] + If (distPosX>minDist || distPosY>minDist) + { + newPointsList .= newPosX "," newPosY "|" + resultPointsCount++ + } + } + } + } + If !newPointsList + Return PointsList + Return Trim(newPointsList, "|") +} + +Gdip_DrawDrivenString(pGraphics, String, hFont, pBrush, DriverPoints, Flags:=1, hMatrix:=0) { +; Parameters: +; pBrush - pointer to a pBrush object used to draw the text into the given pGraphics +; hFont - pointer for a Font object used to draw the given text that determines font, size and style +; hMatrix - pointer to a transformation matrix object that specifies the transformation matrix to apply to each value in the DriverPoints +; DriverPoints - a list of points coordinates that determines where the glyphs [letters] will be drawn +; "x1,y1|x2,y2|x3,y3" [... and so on] +; Flags options: +; 1 - The string array contains Unicode character values. If this flag is not set, each value in $vText is +; interpreted as an index to a font glyph that defines a character to be displayed +; 2 - The string is displayed vertically +; 4 - The glyph positions are calculated from the position of the first glyph. If this flag is not set, the +; glyph positions are obtained from an array of coordinates ($aPoints) +; 8 - Less memory should be used for cache of antialiased glyphs. This also produces lower quality. If this +; flag is not set, more memory is used, but the quality is higher + + txtLen := -1 ; StrLen(String) + Static Ptr := "UPtr" + iCount := CreatePointsF(PointsF, DriverPoints) + return DllCall("gdiplus\GdipDrawDriverString", Ptr, pGraphics, "UPtr", &String, "int", txtLen, Ptr, hFont, Ptr, pBrush, Ptr, &PointsF, "int", Flags, Ptr, hMatrix) +} + +Gdip_StringFormatCreate(FormatFlags:=0, LangID:=0) { +; Format options [StringFormatFlags] +; DirectionRightToLeft = 0x00000001 +; - Activates is right to left reading order. For horizontal text, characters are read from right to left. For vertical text, columns are read from right to left. +; DirectionVertical = 0x00000002 +; - Individual lines of text are drawn vertically on the display device. +; NoFitBlackBox = 0x00000004 +; - Parts of characters are allowed to overhang the string's layout rectangle. +; DisplayFormatControl = 0x00000020 +; - Unicode layout control characters are displayed with a representative character. +; NoFontFallback = 0x00000400 +; - Prevent using an alternate font for characters that are not supported in the requested font. +; MeasureTrailingSpaces = 0x00000800 +; - The spaces at the end of each line are included in a string measurement. +; NoWrap = 0x00001000 +; - Disable text wrapping +; LineLimit = 0x00002000 +; - Only entire lines are laid out in the layout rectangle. +; NoClip = 0x00004000 +; - Characters overhanging the layout rectangle and text extending outside the layout rectangle are allowed to show. + + hStringFormat := 0 + E := DllCall("gdiplus\GdipCreateStringFormat", "int", FormatFlags, "int", LangID, "UPtr*", hStringFormat) + return hStringFormat +} + +Gdip_CloneStringFormat(hStringFormat) { + Static Ptr := "UPtr" + newHStringFormat := 0 + DllCall("gdiplus\GdipCloneStringFormat", Ptr, hStringFormat, "uint*", newHStringFormat) + Return newHStringFormat +} + +Gdip_StringFormatGetGeneric(whichFormat:=0) { +; Default = 0 +; Typographic := 1 + hStringFormat := 0 + If (whichFormat=1) + DllCall("gdiplus\GdipStringFormatGetGenericTypographic", "UPtr*", hStringFormat) + Else + DllCall("gdiplus\GdipStringFormatGetGenericDefault", "UPtr*", hStringFormat) + Return hStringFormat +} + +Gdip_SetStringFormatAlign(hStringFormat, Align) { +; Text alignments: +; 0 - [Near / Left] Alignment is towards the origin of the bounding rectangle +; 1 - [Center] Alignment is centered between origin and extent (width) of the formatting rectangle +; 2 - [Far / Right] Alignment is to the far extent (right side) of the formatting rectangle + + return DllCall("gdiplus\GdipSetStringFormatAlign", "UPtr", hStringFormat, "int", Align) +} + +Gdip_GetStringFormatAlign(hStringFormat) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetStringFormatAlign", Ptr, hStringFormat, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetStringFormatLineAlign(hStringFormat) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetStringFormatLineAlign", Ptr, hStringFormat, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetStringFormatDigitSubstitution(hStringFormat) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetStringFormatDigitSubstitution", Ptr, hStringFormat, "ushort*", 0, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetStringFormatHotkeyPrefix(hStringFormat) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetStringFormatHotkeyPrefix", Ptr, hStringFormat, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetStringFormatTrimming(hStringFormat) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetStringFormatTrimming", Ptr, hStringFormat, "int*", result) + If E + Return -1 + Return result +} + +Gdip_SetStringFormatLineAlign(hStringFormat, StringAlign) { +; The line alignment setting specifies how to align the string vertically in the layout rectangle. +; The layout rectangle is used to position the displayed string +; StringAlign - Type of vertical line alignment to use: +; 0 - Top +; 1 - Center +; 2 - Bottom + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipSetStringFormatLineAlign", Ptr, hStringFormat, "int", StringAlign) +} + +Gdip_SetStringFormatDigitSubstitution(hStringFormat, DigitSubstitute, LangID:=0) { +; Sets the language ID and the digit substitution method that is used by a StringFormat object +; DigitSubstitute - Digit substitution method that will be used by the StringFormat object: +; 0 - A user-defined substitution scheme +; 1 - Digit substitution is disabled +; 2 - Substitution digits that correspond with the official national language of the user's locale +; 3 - Substitution digits that correspond with the user's native script or language + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetStringFormatDigitSubstitution", Ptr, hStringFormat, "ushort", LangID, "int", DigitSubstitute) +} + +Gdip_SetStringFormatFlags(hStringFormat, Flags) { +; see Gdip_StringFormatCreate() for possible StringFormatFlags + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetStringFormatFlags", Ptr, hStringFormat, "int", Flags) +} + +Gdip_SetStringFormatHotkeyPrefix(hStringFormat, PrefixProcessMode) { +; Sets the type of processing that is performed on a string when a hot key prefix (&) is encountered +; PrefixProcessMode - Type of hot key prefix processing to use: +; 0 - No hot key processing occurs. +; 1 - Unicode text is scanned for ampersands (&). All pairs of ampersands are replaced by a single ampersand. +; All single ampersands are removed, the first character that follows a single ampersand is displayed underlined. +; 2 - Same as 1 but a character following a single ampersand is not displayed underlined. + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetStringFormatHotkeyPrefix", Ptr, hStringFormat, "int", PrefixProcessMode) +} + +Gdip_SetStringFormatTrimming(hStringFormat, TrimMode) { +; TrimMode - The trimming style to use: +; 0 - No trimming is done +; 1 - String is broken at the boundary of the last character that is inside the layout rectangle +; 2 - String is broken at the boundary of the last word that is inside the layout rectangle +; 3 - String is broken at the boundary of the last character that is inside the layout rectangle and an ellipsis (...) is inserted after the character +; 4 - String is broken at the boundary of the last word that is inside the layout rectangle and an ellipsis (...) is inserted after the word +; 5 - The center is removed from the string and replaced by an ellipsis. The algorithm keeps as much of the last portion of the string as possible + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetStringFormatTrimming", Ptr, hStringFormat, "int", TrimMode) +} + +Gdip_FontCreate(hFontFamily, Size, Style:=0, Unit:=0) { +; Font style options: +; Regular = 0 +; Bold = 1 +; Italic = 2 +; BoldItalic = 3 +; Underline = 4 +; Strikeout = 8 +; Unit options: see Gdip_SetPageUnit() + hFont := 0 + DllCall("gdiplus\GdipCreateFont", "UPtr", hFontFamily, "float", Size, "int", Style, "int", Unit, "UPtr*", hFont) + return hFont +} + +Gdip_FontFamilyCreate(FontName) { + hFontFamily := 0 + _E := DllCall("gdiplus\GdipCreateFontFamilyFromName" + , "WStr", FontName, "uint", 0 + , "UPtr*", hFontFamily) + + return hFontFamily +} + +Gdip_NewPrivateFontCollection() { + hFontCollection := 0 + DllCall("gdiplus\GdipNewPrivateFontCollection", "ptr*", hFontCollection) + Return hFontCollection +} + +Gdip_CreateFontFamilyFromFile(FontFile, hFontCollection, FontName:="") { +; hFontCollection - the collection to add the font to +; Pass the result of Gdip_NewPrivateFontCollection() to this parameter +; to create a private collection of fonts. +; After no longer needing the private fonts, use Gdip_DeletePrivateFontCollection() +; to free up resources. +; +; GDI+ does not support PostScript fonts or OpenType fonts which do not have TrueType outlines. +; +; function by tmplinshi +; source: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=813&p=298435#p297794 +; modified by Marius Șucan + If !hFontCollection + Return + + hFontFamily := 0 + E := DllCall("gdiplus\GdipPrivateAddFontFile", "ptr", hFontCollection, "str", FontFile) + if (FontName="" && !E) + { + VarSetCapacity(pFontFamily, 10, 0) + DllCall("gdiplus\GdipGetFontCollectionFamilyList", "ptr", hFontCollection, "int", 1, "ptr", &pFontFamily, "int*", found) + + VarSetCapacity(FontName, 100) + DllCall("gdiplus\GdipGetFamilyName", "ptr", NumGet(pFontFamily, 0, "ptr"), "str", FontName, "ushort", 1033) + } + + If !E + DllCall("gdiplus\GdipCreateFontFamilyFromName", "str", FontName, "ptr", hFontCollection, "uint*", hFontFamily) + Return hFontFamily +} + +Gdip_FontFamilyCreateGeneric(whichStyle) { +; This function returns a hFontFamily font object that uses a generic font. +; +; whichStyle options: +; 0 - monospace generic font +; 1 - sans-serif generic font +; 2 - serif generic font + + hFontFamily := 0 + If (whichStyle=0) + DllCall("gdiplus\GdipGetGenericFontFamilyMonospace", "UPtr*", hFontFamily) + Else If (whichStyle=1) + DllCall("gdiplus\GdipGetGenericFontFamilySansSerif", "UPtr*", hFontFamily) + Else If (whichStyle=2) + DllCall("gdiplus\GdipGetGenericFontFamilySerif", "UPtr*", hFontFamily) + Return hFontFamily +} + +Gdip_CreateFontFromDC(hDC) { +; a font must be selected in the hDC for this function to work +; function extracted from a class based wrapper around the GDI+ API made by nnnik + + pFont := 0 + r := DllCall("gdiplus\GdipCreateFontFromDC", "UPtr", hDC, "UPtr*", pFont) + Return pFont +} + +Gdip_CreateFontFromLogfontW(hDC, LogFont) { +; extracted from: https://github.com/flipeador/Library-AutoHotkey/tree/master/graphics +; by flipeador +; +; Creates a Font object directly from a GDI logical font. +; The GDI logical font is a LOGFONTW structure, which is the wide character version of a logical font. +; Parameters: +; hDC: +; A handle to a Windows device context that has a font selected. +; LogFont: +; A LOGFONTW structure that contains attributes of the font. +; The LOGFONTW structure is the wide character version of the logical font. +; +; https://docs.microsoft.com/en-us/windows/win32/api/gdiplusheaders/nf-gdiplusheaders-font-font(inhdc_inconstlogfontw) + + pFont := 0 + DllCall("Gdiplus\GdipCreateFontFromLogfontW", "Ptr", hDC, "Ptr", LogFont, "UPtrP", pFont) + return pFont +} + +Gdip_GetFontHeight(hFont, pGraphics:=0) { +; Gets the line spacing of a font in the current unit of a specified pGraphics object. +; The line spacing is the vertical distance between the base lines of two consecutive lines of text. +; Therefore, the line spacing includes the blank space between lines along with the height of +; the character itself. + + Static Ptr := "UPtr" + result := 0 + DllCall("gdiplus\GdipGetFontHeight", Ptr, hFont, Ptr, pGraphics, "float*", result) + Return result +} + +Gdip_GetFontHeightGivenDPI(hFont, DPI:=72) { +; Remarks: it seems to always yield the same value +; regardless of the given DPI. + + Static Ptr := "UPtr" + result := 0 + DllCall("gdiplus\GdipGetFontHeightGivenDPI", Ptr, hFont, "float", DPI, "float*", result) + Return result +} + +Gdip_GetFontSize(hFont) { + Static Ptr := "UPtr" + result := 0 + DllCall("gdiplus\GdipGetFontSize", Ptr, hFont, "float*", result) + Return result +} + +Gdip_GetFontStyle(hFont) { +; see also Gdip_FontCreate() + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetFontStyle", Ptr, hFont, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetFontUnit(hFont) { +; Gets the unit of measure of a Font object. + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetFontUnit", Ptr, hFont, "int*", result) + If E + Return -1 + Return result +} + +Gdip_CloneFont(hfont) { + Static Ptr := "UPtr" + newHFont := 0 + DllCall("gdiplus\GdipCloneFont", Ptr, hFont, "UPtr*", newHFont) + Return newHFont +} + +Gdip_GetFontFamily(hFont) { +; On success returns a handle to a hFontFamily object + Static Ptr := "UPtr" + hFontFamily := 0 + DllCall("gdiplus\GdipGetFamily", Ptr, hFont, "UPtr*", hFontFamily) + Return hFontFamily +} + + +Gdip_CloneFontFamily(hFontFamily) { + Static Ptr := "UPtr" + newHFontFamily := 0 + DllCall("gdiplus\GdipCloneFontFamily", Ptr, hFontFamily, "UPtr*", newHFontFamily) + Return newHFontFamily +} + +Gdip_IsFontStyleAvailable(hFontFamily, Style) { +; Remarks: given a proper hFontFamily object, it seems to be always +; returning 1 [true] regardless of Style... + + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsStyleAvailable", Ptr, hFontFamily, "int", Style, "Int*", result) + If E + Return -1 + Return result +} + +Gdip_GetFontFamilyCellScents(hFontFamily, ByRef Ascent, ByRef Descent, Style:=0) { +; Ascent and Descent values are given in «design units» + + Static Ptr := "UPtr" + Ascent := 0 + Descent := 0 + E := DllCall("gdiplus\GdipGetCellAscent", Ptr, hFontFamily, "int", Style, "ushort*", Ascent) + E := DllCall("gdiplus\GdipGetCellDescent", Ptr, hFontFamily, "int", Style, "ushort*", Descent) + Return E +} + +Gdip_GetFontFamilyEmHeight(hFontFamily, Style:=0) { +; EmHeight returned in «design units» + Static Ptr := "UPtr" + result := 0 + DllCall("gdiplus\GdipGetEmHeight", Ptr, hFontFamily, "int", Style, "ushort*", result) + Return result +} + +Gdip_GetFontFamilyLineSpacing(hFontFamily, Style:=0) { +; Line spacing returned in «design units» + Static Ptr := "UPtr" + result := 0 + DllCall("gdiplus\GdipGetLineSpacing", Ptr, hFontFamily, "int", Style, "ushort*", result) + Return result +} + +Gdip_GetFontFamilyName(hFontFamily) { + Static Ptr := "UPtr" + VarSetCapacity(FontName, 90) + DllCall("gdiplus\GdipGetFamilyName", Ptr, hFontFamily, "Ptr", &FontName, "ushort", 0) + Return FontName +} + + +;##################################################################################### +; Matrix functions +;##################################################################################### + +Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y) { + hMatrix := 0 + DllCall("gdiplus\GdipCreateMatrix2", "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y, "UPtr*", hMatrix) + return hMatrix +} + +Gdip_CreateMatrix() { + hMatrix := 0 + DllCall("gdiplus\GdipCreateMatrix", "UPtr*", hMatrix) + return hMatrix +} + +Gdip_InvertMatrix(hMatrix) { +; Replaces the elements of a matrix with the elements of its inverse + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipInvertMatrix", Ptr, hMatrix) +} + +Gdip_IsMatrixEqual(hMatrixA, hMatrixB) { +; compares two matrices; if identical, the function returns 1 + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsMatrixEqual", Ptr, hMatrixA, Ptr, hMatrixB, "int*", result) + If E + Return -1 + Return result +} + +Gdip_IsMatrixIdentity(hMatrix) { +; The identity matrix represents a transformation with no scaling, translation, rotation and conversion, and +; represents a transformation that does nothing. + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsMatrixIdentity", Ptr, hMatrix, "int*", result) + If E + Return -1 + Return result +} + +Gdip_IsMatrixInvertible(hMatrix) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsMatrixInvertible", Ptr, hMatrix, "int*", result) + If E + Return -1 + Return result +} + +Gdip_MultiplyMatrix(hMatrixA, hMatrixB, matrixOrder) { +; Updates hMatrixA with the product of itself and hMatrixB +; matrixOrder - Order of matrices multiplication: +; 0 - The second matrix is on the left +; 1 - The second matrix is on the right + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipMultiplyMatrix", Ptr, hMatrixA, Ptr, hMatrixB, "int", matrixOrder) +} + +Gdip_CloneMatrix(hMatrix) { + Static Ptr := "UPtr" + newHMatrix := 0 + DllCall("gdiplus\GdipCloneMatrix", Ptr, hMatrix, "UPtr*", newHMatrix) + return newHMatrix +} + +;##################################################################################### +; GraphicsPath functions +; pPath objects are rendered/drawn by pGraphics object using: +; - a) Gdip_FillPath() with an associated pBrush object created with any of the following functions: +; - Gdip_BrushCreateSolid() - SolidFill +; - Gdip_CreateTextureBrush() - Texture brush derived from a pBitmap +; - Gdip_CreateLinearGrBrush() - LinearGradient +; - Gdip_BrushCreateHatch() - Hatch pattern +; - Gdip_PathGradientCreateFromPath() +; - b) Gdip_DrawPath() with an associated pPen created with Gdip_CreatePen() +; +; A pPath object can be converted using: +; - a) Gdip_PathGradientCreateFromPath() to a PathGradient brush object +; - b) Gdip_CreateRegionPath() to a region object +;##################################################################################### + +Gdip_CreatePath(BrushMode:=0) { +; Alternate = 0 +; Winding = 1 + pPath := 0 + DllCall("gdiplus\GdipCreatePath", "int", BrushMode, "UPtr*", pPath) + return pPath +} + +Gdip_AddPathEllipse(pPath, x, y, w, h) { + return DllCall("gdiplus\GdipAddPathEllipse", "UPtr", pPath, "float", x, "float", y, "float", w, "float", h) +} + +Gdip_AddPathRectangle(pPath, x, y, w, h) { + return DllCall("gdiplus\GdipAddPathRectangle", "UPtr", pPath, "float", x, "float", y, "float", w, "float", h) +} + +Gdip_AddPathRoundedRectangle(pPath, x, y, w, h, r) { +; extracted from: https://github.com/tariqporter/Gdip2/blob/master/lib/Object.ahk +; and adapted by Marius Șucan + E := 0 + r := (w <= h) ? (r < w / 2) ? r : w / 2 : (r < h / 2) ? r : h / 2 + If (E := Gdip_AddPathRectangle(pPath, x+r, y, w-(2*r), r)) + Return E + If (E := Gdip_AddPathRectangle(pPath, x+r, y+h-r, w-(2*r), r)) + Return E + If (E := Gdip_AddPathRectangle(pPath, x, y+r, r, h-(2*r))) + Return E + If (E := Gdip_AddPathRectangle(pPath, x+w-r, y+r, r, h-(2*r))) + Return E + If (E := Gdip_AddPathRectangle(pPath, x+r, y+r, w-(2*r), h-(2*r))) + Return E + If (E := Gdip_AddPathPie(pPath, x, y, 2*r, 2*r, 180, 90)) + Return E + If (E := Gdip_AddPathPie(pPath, x+w-(2*r), y, 2*r, 2*r, 270, 90)) + Return E + If (E := Gdip_AddPathPie(pPath, x, y+h-(2*r), 2*r, 2*r, 90, 90)) + Return E + If (E := Gdip_AddPathPie(pPath, x+w-(2*r), y+h-(2*r), 2*r, 2*r, 0, 90)) + Return E + Return E +} + +Gdip_AddPathPolygon(pPath, Points) { +; Points: the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... [minimum three points must be given] + + Static Ptr := "UPtr" + iCount := CreatePointsF(PointsF, Points) + return DllCall("gdiplus\GdipAddPathPolygon", Ptr, pPath, Ptr, &PointsF, "int", iCount) +} + +Gdip_AddPathClosedCurve(pPath, Points, Tension:=1) { +; Adds a closed cardinal spline to a path. +; A cardinal spline is a curve that passes through each point in the array. +; +; Parameters: +; pPath: Pointer to the GraphicsPath +; Points: the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... [minimum three points must be given] +; Tension: Non-negative real number that controls the length of the curve and how the curve bends. A value of +; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller. + + iCount := CreatePointsF(PointsF, Points) + If Tension + return DllCall("gdiplus\GdipAddPathClosedCurve2", "UPtr", pPath, "UPtr", &PointsF, "int", iCount, "float", Tension) + Else + return DllCall("gdiplus\GdipAddPathClosedCurve", "UPtr", pPath, "UPtr", &PointsF, "int", iCount) +} + +Gdip_AddPathCurve(pPath, Points, Tension:="") { +; Adds a cardinal spline to the current figure of a path +; A cardinal spline is a curve that passes through each point in the array. +; +; Parameters: +; pPath: Pointer to the GraphicsPath +; Points: the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... [minimum three points must be given] +; Tension: Non-negative real number that controls the length of the curve and how the curve bends. A value of +; zero specifies that the spline is a sequence of straight lines. As the value increases, the curve becomes fuller. + + iCount := CreatePointsF(PointsF, Points) + If Tension + return DllCall("gdiplus\GdipAddPathCurve2", "UPtr", pPath, "UPtr", &PointsF, "int", iCount, "float", Tension) + Else + return DllCall("gdiplus\GdipAddPathCurve", "UPtr", pPath, "UPtr", &PointsF, "int", iCount) +} + +Gdip_AddPathToPath(pPathA, pPathB, fConnect) { +; Adds a path into another path. +; +; Parameters: +; pPathA and pPathB - Pointers to GraphicsPath objects +; fConnect - Specifies whether the first figure in the added path is part of the last figure in this path: +; 1 - The first figure in the added pPathB is part of the last figure in the pPathB path. +; 0 - The first figure in the added pPathB is separated from the last figure in the pPathA path. +; +; Remarks: Even if the value of the fConnect parameter is 1, this function might not be able to make the first figure +; of the added pPathB path part of the last figure of the pPathA path. If either of those figures is closed, +; then they must remain separated figures. + + return DllCall("gdiplus\GdipAddPathCurve2", "UPtr", pPathA, "UPtr", pPathB, "int", fConnect) +} + +Gdip_AddPathStringSimplified(pPath, String, FontName, Size, Style, X, Y, Width, Height, Align:=0, NoWrap:=0) { +; Adds the outline of a given string with the given font name, size and style +; to a Path object. + +; Size - in em, in world units [font size] +; Remarks: a high value might be required; over 60, 90... to see the text. + +; X, Y - coordinates for the rectangle where the text will be placed +; W, H - width and heigh for the rectangle where the text will be placed + +; Align options: +; Near/left = 0 +; Center = 1 +; Far/right = 2 + +; Style options: +; Regular = 0 +; Bold = 1 +; Italic = 2 +; BoldItalic = 3 +; Underline = 4 +; Strikeout = 8 + + FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000 + If RegExMatch(FontName, "^(.\:\\.)") + { + hFontCollection := Gdip_NewPrivateFontCollection() + hFontFamily := Gdip_CreateFontFamilyFromFile(FontName, hFontCollection) + } Else hFontFamily := Gdip_FontFamilyCreate(FontName) + + If !hFontFamily + hFontFamily := Gdip_FontFamilyCreateGeneric(1) + + If !hFontFamily + { + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Return -1 + } + + hStringFormat := Gdip_StringFormatCreate(FormatStyle) + If !hStringFormat + hStringFormat := Gdip_StringFormatGetGeneric(1) + + If !hStringFormat + { + Gdip_DeleteFontFamily(hFontFamily) + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Return -2 + } + + Gdip_SetStringFormatTrimming(hStringFormat, 3) + Gdip_SetStringFormatAlign(hStringFormat, Align) + E := Gdip_AddPathString(pPath, String, hFontFamily, Style, Size, hStringFormat, X, Y, Width, Height) + Gdip_DeleteStringFormat(hStringFormat) + Gdip_DeleteFontFamily(hFontFamily) + If hFontCollection + Gdip_DeletePrivateFontCollection(hFontCollection) + Return E +} + +Gdip_AddPathString(pPath, String, hFontFamily, Style, Size, hStringFormat, X, Y, W, H) { + Static Ptr := "UPtr" + CreateRectF(RectF, X, Y, W, H) + E := DllCall("gdiplus\GdipAddPathString", Ptr, pPath, "WStr", String, "int", -1, Ptr, hFontFamily, "int", Style, "float", Size, Ptr, &RectF, Ptr, hStringFormat) + Return E +} + +Gdip_SetPathFillMode(pPath, FillMode) { +; Parameters +; pPath - Pointer to a GraphicsPath object +; FillMode - Path fill mode: +; 0 - [Alternate] The areas are filled according to the even-odd parity rule +; 1 - [Winding] The areas are filled according to the non-zero winding rule + + return DllCall("gdiplus\GdipSetPathFillMode", "UPtr", pPath, "int", FillMode) +} + +Gdip_GetPathFillMode(pPath) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPathFillMode", Ptr, pPath, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetPathLastPoint(pPath, ByRef X, ByRef Y) { + Static Ptr := "UPtr" + VarSetCapacity(PointF, 8, 0) + E := DllCall("gdiplus\GdipGetPathLastPoint", Ptr, pPath, "UPtr", &PointF) + If !E + { + x := NumGet(PointF, 0, "float") + y := NumGet(PointF, 4, "float") + } + + Return E +} + +Gdip_GetPathPointsCount(pPath) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPointCount", Ptr, pPath, "int*", result) + If E + Return -1 + Return result +} + +Gdip_GetPathPoints(pPath) { + PointsCount := Gdip_GetPathPointsCount(pPath) + If (PointsCount=-1) + Return 0 + + Static Ptr := "UPtr" + VarSetCapacity(PointsF, 8 * PointsCount, 0) + DllCall("gdiplus\GdipGetPathPoints", Ptr, pPath, Ptr, &PointsF, "intP", PointsCount) + Loop %PointsCount% + { + A := NumGet(&PointsF, 8*(A_Index-1), "float") + B := NumGet(&PointsF, (8*(A_Index-1))+4, "float") + printList .= A "," B "|" + } + Return Trim(printList, "|") +} + +Gdip_FlattenPath(pPath, flatness, hMatrix:=0) { +; flatness - a precision value that specifies the maximum error between the path and +; its flattened [segmented] approximation. Reducing the flatness increases the number +; of line segments in the approximation. +; +; hMatrix - a pointer to a transformation matrix to apply. + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipFlattenPath", Ptr, pPath, Ptr, hMatrix, "float", flatness) +} + +Gdip_WidenPath(pPath, pPen, hMatrix:=0, Flatness:=1) { +; Replaces this path with curves that enclose the area that is filled when this path is drawn by a specified pen. +; This method also flattens the path. + + return DllCall("gdiplus\GdipWidenPath", "UPtr", pPath, "uint", pPen, "UPtr", hMatrix, "float", Flatness) +} + +Gdip_PathOutline(pPath, flatness:=1, hMatrix:=0) { +; Transforms and flattens [segmentates] a pPath object, and then converts the path's data points +; so that they represent only the outline of the given path. +; +; flatness - a precision value that specifies the maximum error between the path and +; its flattened [segmented] approximation. Reducing the flatness increases the number +; of line segments in the resulted approximation. +; +; hMatrix - a pointer to a transformation matrix to apply. + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipWindingModeOutline", Ptr, pPath, Ptr, hMatrix, "float", flatness) +} + +Gdip_ResetPath(pPath) { +; Empties a path and sets the fill mode to alternate (0) + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipResetPath", Ptr, pPath) +} + +Gdip_ReversePath(pPath) { +; Reverses the order of the points that define a path's lines and curves + + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipReversePath", Ptr, pPath) +} + +Gdip_IsOutlineVisiblePathPoint(pGraphics, pPath, pPen, X, Y) { + result := 0 + E := DllCall("gdiplus\GdipIsOutlineVisiblePathPoint", Ptr, pPath, "float", X, "float", Y, Ptr, pPen, Ptr, pGraphics, "int*", result) + If E + Return -1 + Return result +} + +Gdip_IsVisiblePathPoint(pPath, x, y, pGraphics) { +; Function by RazorHalo, modified by Marius Șucan + result := 0 + E := DllCall("gdiplus\GdipIsVisiblePathPoint", "UPtr", pPath, "float", x, "float", y, "UPtr", pGraphics, "UPtr*", result) + If E + return -1 + return result +} + +Gdip_DeletePath(pPath) { + return DllCall("gdiplus\GdipDeletePath", "UPtr", pPath) +} + +;##################################################################################### +; pGraphics rendering options functions +;##################################################################################### + +Gdip_SetTextRenderingHint(pGraphics, RenderingHint) { +; RenderingHint options: +; SystemDefault = 0 +; SingleBitPerPixelGridFit = 1 +; SingleBitPerPixel = 2 +; AntiAliasGridFit = 3 +; AntiAlias = 4 + return DllCall("gdiplus\GdipSetTextRenderingHint", "UPtr", pGraphics, "int", RenderingHint) +} + +Gdip_SetInterpolationMode(pGraphics, InterpolationMode) { +; InterpolationMode options: +; Default = 0 +; LowQuality = 1 +; HighQuality = 2 +; Bilinear = 3 +; Bicubic = 4 +; NearestNeighbor = 5 +; HighQualityBilinear = 6 +; HighQualityBicubic = 7 + return DllCall("gdiplus\GdipSetInterpolationMode", "UPtr", pGraphics, "int", InterpolationMode) +} + +Gdip_SetSmoothingMode(pGraphics, SmoothingMode) { +; SmoothingMode options: +; Default = 0 +; HighSpeed = 1 +; HighQuality = 2 +; None = 3 +; AntiAlias = 4 +; AntiAlias8x4 = 5 +; AntiAlias8x8 = 6 + return DllCall("gdiplus\GdipSetSmoothingMode", "UPtr", pGraphics, "int", SmoothingMode) +} + +Gdip_SetCompositingMode(pGraphics, CompositingMode) { +; CompositingMode_SourceOver = 0 (blended / default) +; CompositingMode_SourceCopy = 1 (overwrite) + + return DllCall("gdiplus\GdipSetCompositingMode", "UPtr", pGraphics, "int", CompositingMode) +} + +Gdip_SetCompositingQuality(pGraphics, CompositionQuality) { +; CompositionQuality options: +; 0 - Gamma correction is not applied. +; 1 - Gamma correction is not applied. High speed, low quality. +; 2 - Gamma correction is applied. Composition of high quality and speed. +; 3 - Gamma correction is applied. +; 4 - Gamma correction is not applied. Linear values are used. + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetCompositingQuality", Ptr, pGraphics, "int", CompositionQuality) +} + +Gdip_SetPageScale(pGraphics, Scale) { +; Sets the scaling factor for the page transformation of a pGraphics object. +; The page transformation converts page coordinates to device coordinates. + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetPageScale", Ptr, pGraphics, "float", Scale) +} + +Gdip_SetPageUnit(pGraphics, Unit) { +; Sets the unit of measurement for a pGraphics object. +; Unit of measuremnet options: +; 0 - World coordinates, a non-physical unit +; 1 - Display units +; 2 - A unit is 1 pixel +; 3 - A unit is 1 point or 1/72 inch +; 4 - A unit is 1 inch +; 5 - A unit is 1/300 inch +; 6 - A unit is 1 millimeter + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetPageUnit", Ptr, pGraphics, "int", Unit) +} + +Gdip_SetPixelOffsetMode(pGraphics, PixelOffsetMode) { +; Sets the pixel offset mode of a pGraphics object. +; PixelOffsetMode options: +; HighSpeed = QualityModeLow - Default +; 0, 1, 3 - Pixel centers have integer coordinates +; ModeHalf - ModeHighQuality +; 2, 4 - Pixel centers have coordinates that are half way between integer values (i.e. 0.5, 20, 105.5, etc...) + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetPixelOffsetMode", Ptr, pGraphics, "int", PixelOffsetMode) +} + +Gdip_SetRenderingOrigin(pGraphics, X, Y) { +; The rendering origin is used to set the dither origin for 8-bits-per-pixel and 16-bits-per-pixel dithering +; and is also used to set the origin for hatch brushes + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetRenderingOrigin", Ptr, pGraphics, "int", X, "int", Y) +} + +Gdip_SetTextContrast(pGraphics, Contrast) { +; Contrast - A number between 0 and 12, which defines the value of contrast used for antialiasing text + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetTextContrast", Ptr, pGraphics, "uint", Contrast) +} + +Gdip_RestoreGraphics(pGraphics, State) { + ; Sets the state of this Graphics object to the state stored by a previous call to the Save method of this Graphics object. + ; Parameters: + ; State: + ; A value returned by a previous call to the Save method that identifies a block of saved state. + ; Return value: + ; Returns TRUE if successful, or FALSE otherwise. To get extended error information, check «Gdiplus.LastStatus». + ; https://docs.microsoft.com/en-us/windows/win32/api/gdiplusgraphics/nf-gdiplusgraphics-graphics-restore + return DllCall("Gdiplus\GdipRestoreGraphics", "UPtr", pGraphics, "UInt", State) +} + +Gdip_SaveGraphics(pGraphics) { + ; Saves the current state (transformations, clipping region, and quality settings) of this Graphics object. + ; You can restore the state later by calling the Restore method. + ; Return value: + ; Returns a value that identifies the saved state. + ; Pass this value to the Restore method when you want to restore the state. + ; Remarks: + ; The identifier returned by a given call to the Save method can be passed only once to the Restore method. + ; https://docs.microsoft.com/en-us/windows/win32/api/gdiplusgraphics/nf-gdiplusgraphics-graphics-save + State := 0 + DllCall("Gdiplus\GdipSaveGraphics", "Ptr", pGraphics, "UIntP", State) + return State +} + +Gdip_GetTextContrast(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetTextContrast", Ptr, pGraphics, "uint*", result) + If E + return -1 + Return result +} + +Gdip_GetCompositingMode(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetCompositingMode", Ptr, pGraphics, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetCompositingQuality(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetCompositingQuality", Ptr, pGraphics, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetInterpolationMode(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetInterpolationMode", Ptr, pGraphics, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetSmoothingMode(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetSmoothingMode", Ptr, pGraphics, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetPageScale(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPageScale", Ptr, pGraphics, "float*", result) + If E + return -1 + Return result +} + +Gdip_GetPageUnit(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPageUnit", Ptr, pGraphics, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetPixelOffsetMode(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPixelOffsetMode", Ptr, pGraphics, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetRenderingOrigin(pGraphics, ByRef X, ByRef Y) { + Static Ptr := "UPtr" + x := 0 + y := 0 + return DllCall("gdiplus\GdipGetRenderingOrigin", Ptr, pGraphics, "uint*", X, "uint*", Y) +} + +Gdip_GetTextRenderingHint(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetTextRenderingHint", Ptr, pGraphics, "int*", result) + If E + return -1 + Return result +} + +;##################################################################################### +; More pGraphics functions +;##################################################################################### + +Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder:=0) { +; MatrixOrder options: +; Prepend = 0; The new operation is applied before the old operation. +; Append = 1; The new operation is applied after the old operation. +; Order of matrices multiplication:. + + return DllCall("gdiplus\GdipRotateWorldTransform", "UPtr", pGraphics, "float", Angle, "int", MatrixOrder) +} + +Gdip_ScaleWorldTransform(pGraphics, ScaleX, ScaleY, MatrixOrder:=0) { + return DllCall("gdiplus\GdipScaleWorldTransform", "UPtr", pGraphics, "float", ScaleX, "float", ScaleY, "int", MatrixOrder) +} + +Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder:=0) { + return DllCall("gdiplus\GdipTranslateWorldTransform", "UPtr", pGraphics, "float", x, "float", y, "int", MatrixOrder) +} + +Gdip_MultiplyWorldTransform(pGraphics, hMatrix, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipMultiplyWorldTransform", Ptr, pGraphics, Ptr, hMatrix, "int", matrixOrder) +} + +Gdip_ResetWorldTransform(pGraphics) { + return DllCall("gdiplus\GdipResetWorldTransform", "UPtr", pGraphics) +} + +Gdip_ResetPageTransform(pGraphics) { + return DllCall("gdiplus\GdipResetPageTransform", "UPtr", pGraphics) +} + +Gdip_SetWorldTransform(pGraphics, hMatrix) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetWorldTransform", Ptr, pGraphics, Ptr, hMatrix) +} + +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) { +; modified by Marius Șucan; removed Ceil() + Static pi := 3.14159 + if !(Width && Height) + return -1 + + TAngle := Angle*(pi/180) + RWidth := Abs(Width*Cos(TAngle))+Abs(Height*Sin(TAngle)) + RHeight := Abs(Width*Sin(TAngle))+Abs(Height*Cos(Tangle)) +} + +Gdip_GetRotatedEllipseDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight) { + if !(Width && Height) + return -1 + + pPath := Gdip_CreatePath() + Gdip_AddPathEllipse(pPath, 0, 0, Width, Height) + ; testAngle := Mod(Angle, 30) + pMatrix := Gdip_CreateMatrix() + Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder) + E := Gdip_TransformPath(pPath, pMatrix) + Gdip_DeleteMatrix(pMatrix) + pathBounds := Gdip_GetPathWorldBounds(pPath) + Gdip_DeletePath(pPath) + RWidth := pathBounds.w + RHeight := pathBounds.h + Return E +} + +Gdip_GetWorldTransform(pGraphics) { +; Returns the world transformation matrix of a pGraphics object. +; On error, it returns -1 + Static Ptr := "UPtr" + hMatrix := 0 + E := DllCall("gdiplus\GdipGetWorldTransform", Ptr, pGraphics, "UPtr*", hMatrix) + Return hMatrix +} + +Gdip_IsVisibleGraphPoint(pGraphics, X, Y) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsVisiblePoint", Ptr, pGraphics, "float", X, "float", Y, "int*", result) + If E + Return -1 + Return result +} + +Gdip_IsVisibleGraphRect(pGraphics, X, Y, Width, Height) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsVisibleRect", Ptr, pGraphics, "float", X, "float", Y, "float", Width, "float", Height, "int*", result) + If E + Return -1 + Return result +} + +Gdip_IsVisibleGraphRectEntirely(pGraphics, X, Y, Width, Height) { + a := Gdip_IsVisibleGraphPoint(pGraphics, X, Y) + b := Gdip_IsVisibleGraphPoint(pGraphics, X + Width, Y) + c := Gdip_IsVisibleGraphPoint(pGraphics, X + Width, Y + Height) + d := Gdip_IsVisibleGraphPoint(pGraphics, X, Y + Height) + If (a=1 && b=1 && c=1 && d=1) + Return 1 + Else If (a=-1 || b=-1 || c=-1 || d=-1) + Return -1 + Else + Return 0 +} + +;##################################################################################### +; Region and clip functions [pGraphics related] +; +; One of the properties of the pGraphics class is the clip region. +; All drawing done in a given pGraphics object can be restricted +; to the clip region of that pGraphics object. + +; The GDI+ Region class allows you to define a custom shape. +; The shape[s] can be made up of lines, polygons, and curves. +; +; Two common uses for regions are hit testing and clipping. +; Hit testing is determining whether the mouse was clicked +; in a certain region of the screen. +; +; Clipping is restricting drawing to a certain region in +; a given pGraphics object. +; +;##################################################################################### + +Gdip_IsClipEmpty(pGraphics) { +; Determines whether the clipping region of a pGraphics object is empty + + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsClipEmpty", Ptr, pGraphics, "int*", result) + If E + Return -1 + Return result +} + +Gdip_IsVisibleClipEmpty(pGraphics) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsVisibleClipEmpty", Ptr, pGraphics, "uint*", result) + If E + Return -1 + Return result +} + +;##################################################################################### + +; Name............. Gdip_SetClipFromGraphics +; +; Parameters: +; pGraphicsA Pointer to a pGraphics object +; pGrahpicsB Pointer to a pGraphics object that contains the clipping region to be combined with +; the clipping region of the pGraphicsA object +; CombineMode Regions combination mode: +; 0 - The existing region is replaced by the new region +; 1 - The existing region is replaced by the intersection of itself and the new region +; 2 - The existing region is replaced by the union of itself and the new region +; 3 - The existing region is replaced by the result of performing an XOR on the two regions +; 4 - The existing region is replaced by the portion of itself that is outside of the new region +; 5 - The existing region is replaced by the portion of the new region that is outside of the existing region +; return Status enumeration value + +Gdip_SetClipFromGraphics(pGraphics, pGraphicsSrc, CombineMode:=0) { + return DllCall("gdiplus\GdipSetClipGraphics", "UPtr", pGraphics, "UPtr", pGraphicsSrc, "int", CombineMode) +} + +Gdip_GetClipBounds(pGraphics) { + rData := {} + VarSetCapacity(RectF, 16, 0) + status := DllCall("gdiplus\GdipGetClipBounds", "UPtr", pGraphics, "UPtr", &RectF) + + If (!status) { + rData.x := NumGet(&RectF, 0, "float") + , rData.y := NumGet(&RectF, 4, "float") + , rData.w := NumGet(&RectF, 8, "float") + , rData.h := NumGet(&RectF, 12, "float") + } Else { + Return status + } + + return rData +} + +Gdip_GetVisibleClipBounds(pGraphics) { + rData := {} + VarSetCapacity(RectF, 16, 0) + status := DllCall("gdiplus\GdipGetVisibleClipBounds", "UPtr", pGraphics, "UPtr", &RectF) + + If (!status) { + rData.x := NumGet(&RectF, 0, "float") + , rData.y := NumGet(&RectF, 4, "float") + , rData.w := NumGet(&RectF, 8, "float") + , rData.h := NumGet(&RectF, 12, "float") + } Else { + Return status + } + + return rData +} + +Gdip_TranslateClip(pGraphics, dX, dY) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipTranslateClip", Ptr, pGraphics, "float", dX, "float", dY) +} + +Gdip_ResetClip(pGraphics) { + return DllCall("gdiplus\GdipResetClip", "UPtr", pGraphics) +} + +Gdip_GetClipRegion(pGraphics) { + Region := Gdip_CreateRegion() + E := DllCall("gdiplus\GdipGetClip", "UPtr", pGraphics, "UInt", Region) + If E + return -1 + return Region +} + +Gdip_SetClipRegion(pGraphics, Region, CombineMode:=0) { + ; see CombineMode options from Gdip_SetClipRect() + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetClipRegion", Ptr, pGraphics, Ptr, Region, "int", CombineMode) +} + +Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode:=0) { +; CombineMode options: +; Replace = 0 +; Intersect = 1 +; Union = 2 +; Xor = 3 +; Exclude = 4 +; Complement = 5 + + return DllCall("gdiplus\GdipSetClipRect", "UPtr", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode) +} + +Gdip_SetClipPath(pGraphics, pPath, CombineMode:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetClipPath", Ptr, pGraphics, Ptr, pPath, "int", CombineMode) +} + +Gdip_CreateRegion() { + Region := 0 + DllCall("gdiplus\GdipCreateRegion", "UInt*", Region) + return Region +} + +Gdip_CombineRegionRegion(Region, Region2, CombineMode) { +; Updates this region to the portion of itself that intersects another region. Added by Learning one +; see CombineMode options from Gdip_SetClipRect() + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipCombineRegionRegion", Ptr, Region, Ptr, Region2, "int", CombineMode) +} + +Gdip_CombineRegionRect(Region, x, y, w, h, CombineMode) { +; Updates this region to the portion of itself that intersects with the given rectangle. +; see CombineMode options from Gdip_SetClipRect() + + Static Ptr := "UPtr" + CreateRectF(RectF, x, y, w, h) + return DllCall("gdiplus\GdipCombineRegionRect", Ptr, Region, Ptr, &RectF, "int", CombineMode) +} + +Gdip_CombineRegionPath(Region, pPath, CombineMode) { +; see CombineMode options from Gdip_SetClipRect() + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipCombineRegionPath", Ptr, Region, Ptr, pPath, "int", CombineMode) +} + +Gdip_CreateRegionPath(pPath) { +; Creates a region that is defined by a GraphicsPath [pPath object]. Written by Learning one. + + Static Ptr := "UPtr" + Region := 0 + E := DllCall("gdiplus\GdipCreateRegionPath", Ptr, pPath, "UInt*", Region) + If E + return -1 + return Region +} + +Gdip_CreateRegionRect(x, y, w, h) { + CreateRectF(RectF, x, y, w, h) + E := DllCall("gdiplus\GdipCreateRegionRect", "UPtr", &RectF, "UInt*", Region) + If E + return -1 + return Region +} + +Gdip_IsEmptyRegion(pGraphics, Region) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsEmptyRegion", Ptr, Region, Ptr, pGraphics, "uInt*", result) + If E + return -1 + Return result +} + +Gdip_IsEqualRegion(pGraphics, Region1, Region2) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsEqualRegion", Ptr, Region1, Ptr, Region2, Ptr, pGraphics, "uInt*", result) + If E + return -1 + Return result +} + +Gdip_IsInfiniteRegion(pGraphics, Region) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsInfiniteRegion", Ptr, Region, Ptr, pGraphics, "uInt*", result) + If E + return -1 + Return result +} + +Gdip_IsVisibleRegionPoint(pGraphics, Region, x, y) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsVisibleRegionPoint", Ptr, Region, "float", X, "float", Y, Ptr, pGraphics, "uInt*", result) + If E + return -1 + Return result +} + +Gdip_IsVisibleRegionRect(pGraphics, Region, x, y, width, height) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipIsVisibleRegionRect", Ptr, Region, "float", X, "float", Y, "float", Width, "float", Height, Ptr, pGraphics, "uInt*", result) + If E + return -1 + Return result +} + +Gdip_IsVisibleRegionRectEntirely(pGraphics, Region, x, y, width, height) { + a := Gdip_IsVisibleRegionPoint(pGraphics, Region, X, Y) + b := Gdip_IsVisibleRegionPoint(pGraphics, Region, X + Width, Y) + c := Gdip_IsVisibleRegionPoint(pGraphics, Region, X + Width, Y + Height) + d := Gdip_IsVisibleRegionPoint(pGraphics, Region, X, Y + Height) + If (a=1 && b=1 && c=1 && d=1) + Return 1 + Else If (a=-1 || b=-1 || c=-1 || d=-1) + Return -1 + Else + Return 0 +} + +Gdip_SetEmptyRegion(Region) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetEmpty", Ptr, Region) +} + +Gdip_SetInfiniteRegion(Region) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetInfinite", Ptr, Region) +} + +Gdip_GetRegionBounds(pGraphics, Region) { + rData := {} + VarSetCapacity(RectF, 16, 0) + status := DllCall("gdiplus\GdipGetRegionBounds", "UPtr", Region, "UPtr", pGraphics, "UPtr", &RectF) + + If (!status) { + rData.x := NumGet(&RectF, 0, "float") + , rData.y := NumGet(&RectF, 4, "float") + , rData.w := NumGet(&RectF, 8, "float") + , rData.h := NumGet(&RectF, 12, "float") + } Else { + Return status + } + + return rData +} + +Gdip_TranslateRegion(Region, X, Y) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipTranslateRegion", Ptr, Region, "float", X, "float", Y) +} + +Gdip_RotateRegionAtCenter(pGraphics, Region, Angle, MatrixOrder:=1) { +; function by Marius Șucan +; based on Gdip_RotatePathAtCenter() by RazorHalo + + Rect := Gdip_GetRegionBounds(pGraphics, Region) + cX := Rect.x + (Rect.w / 2) + cY := Rect.y + (Rect.h / 2) + pMatrix := Gdip_CreateMatrix() + Gdip_TranslateMatrix(pMatrix, -cX , -cY) + Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder) + Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder) + E := Gdip_TransformRegion(Region, pMatrix) + Gdip_DeleteMatrix(pMatrix) + Return E +} + +Gdip_TransformRegion(Region, pMatrix) { + return DllCall("gdiplus\GdipTransformRegion", "UPtr", Region, "UPtr", pMatrix) +} + +Gdip_CloneRegion(Region) { + newRegion := 0 + DllCall("gdiplus\GdipCloneRegion", "UPtr", Region, "UInt*", newRegion) + return newRegion +} + +;##################################################################################### +; BitmapLockBits +;##################################################################################### + +Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode := 3, PixelFormat := 0x26200a) { + Static Ptr := "UPtr" + + CreateRect(_Rect, x, y, w, h) + VarSetCapacity(BitmapData, 16+2*A_PtrSize, 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) { + Static Ptr := "UPtr" + 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) { +/* +C/C++ Function by Tic and fixed by Fincs; +https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-55 + +int __stdcall Gdip_PixelateBitmap(unsigned char * sBitmap, unsigned char * dBitmap, int w, int h, int Stride, int Size) +{ + int sA, sR, sG, sB, rw, rh, o; + + for (int y1 = 0; y1 < h/Size; ++y1) + { + for (int x1 = 0; x1 < w/Size; ++x1) + { + sA = sR = sG = sB = 0; + for (int y2 = 0; y2 < Size; ++y2) + { + for (int x2 = 0; x2 < Size; ++x2) + { + o = 4*(x2+x1*Size)+Stride*(y2+y1*Size); + sA += sBitmap[3+o]; + sR += sBitmap[2+o]; + sG += sBitmap[1+o]; + sB += sBitmap[o]; + } + } + + sA /= Size*Size; + sR /= Size*Size; + sG /= Size*Size; + sB /= Size*Size; + for (int y2 = 0; y2 < Size; ++y2) + { + for (int x2 = 0; x2 < Size; ++x2) + { + o = 4*(x2+x1*Size)+Stride*(y2+y1*Size); + dBitmap[3+o] = sA; + dBitmap[2+o] = sR; + dBitmap[1+o] = sG; + dBitmap[o] = sB; + } + } + } + + if (w % Size != 0) + { + sA = sR = sG = sB = 0; + for (int y2 = 0; y2 < Size; ++y2) + { + for (int x2 = 0; x2 < w % Size; ++x2) + { + o = 4*(x2+(w/Size)*Size)+Stride*(y2+y1*Size); + sA += sBitmap[3+o]; + sR += sBitmap[2+o]; + sG += sBitmap[1+o]; + sB += sBitmap[o]; + } + } + + { + int tmp = (w % Size)*Size; + sA = tmp ? (sA / tmp) : 0; + sR = tmp ? (sR / tmp) : 0; + sG = tmp ? (sG / tmp) : 0; + sB = tmp ? (sB / tmp) : 0; + } + for (int y2 = 0; y2 < Size; ++y2) + { + for (int x2 = 0; x2 < w % Size; ++x2) + { + o = 4*(x2+(w/Size)*Size)+Stride*(y2+y1*Size); + dBitmap[3+o] = sA; + dBitmap[2+o] = sR; + dBitmap[1+o] = sG; + dBitmap[o] = sB; + } + } + } + } + + for (int x1 = 0; x1 < w/Size; ++x1) + { + sA = sR = sG = sB = 0; + for (int y2 = 0; y2 < h % Size; ++y2) + { + for (int x2 = 0; x2 < Size; ++x2) + { + o = 4*(x2+x1*Size)+Stride*(y2+(h/Size)*Size); + sA += sBitmap[3+o]; + sR += sBitmap[2+o]; + sG += sBitmap[1+o]; + sB += sBitmap[o]; + } + } + + { + int tmp = Size*(h % Size); + sA = tmp ? (sA / tmp) : 0; + sR = tmp ? (sR / tmp) : 0; + sG = tmp ? (sG / tmp) : 0; + sB = tmp ? (sB / tmp) : 0; + } + + for (int y2 = 0; y2 < h % Size; ++y2) + { + for (int x2 = 0; x2 < Size; ++x2) + { + o = 4*(x2+x1*Size)+Stride*(y2+(h/Size)*Size); + dBitmap[3+o] = sA; + dBitmap[2+o] = sR; + dBitmap[1+o] = sG; + dBitmap[o] = sB; + } + } + } + + sA = sR = sG = sB = 0; + for (int y2 = 0; y2 < h % Size; ++y2) + { + for (int x2 = 0; x2 < w % Size; ++x2) + { + o = 4*(x2+(w/Size)*Size)+Stride*(y2+(h/Size)*Size); + sA += sBitmap[3+o]; + sR += sBitmap[2+o]; + sG += sBitmap[1+o]; + sB += sBitmap[o]; + } + } + + { + int tmp = (w % Size)*(h % Size); + sA = tmp ? (sA / tmp) : 0; + sR = tmp ? (sR / tmp) : 0; + sG = tmp ? (sG / tmp) : 0; + sB = tmp ? (sB / tmp) : 0; + } + + for (int y2 = 0; y2 < h % Size; ++y2) + { + for (int x2 = 0; x2 < w % Size; ++x2) + { + o = 4*(x2+(w/Size)*Size)+Stride*(y2+(h/Size)*Size); + dBitmap[3+o] = sA; + dBitmap[2+o] = sR; + dBitmap[1+o] = sG; + dBitmap[o] = sB; + } + } + return 0; +} + +*/ + + static PixelateBitmap + Static Ptr := "UPtr" + 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) + nCount := StrLen(MCode_PixelateBitmap)//2 + N := (A_AhkVersion < 2) ? nCount : "nCount" + Loop %N% + NumPut("0x" SubStr(MCode_PixelateBitmap, (2*A_Index)-1, 2), PixelateBitmap, A_Index-1, "UChar") + DllCall("VirtualProtect", Ptr, &PixelateBitmap, Ptr, VarSetCapacity(PixelateBitmap), "uint", 0x40, "UPtr*", 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 := - unused exit code + 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 !IsInteger(Length) + 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 IsInteger(Encoding) + { + ; 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 +} + +Gdip_Startup(multipleInstances:=0) { + Static Ptr := "UPtr" + pToken := 0 + If (multipleInstances=0) + { + if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr) + DllCall("LoadLibrary", "str", "gdiplus") + } Else DllCall("LoadLibrary", "str", "gdiplus") + + VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1) + DllCall("gdiplus\GdiplusStartup", "UPtr*", pToken, Ptr, &si, Ptr, 0) + return pToken +} + +Gdip_Shutdown(pToken) { + Static Ptr := "UPtr" + + DllCall("gdiplus\GdiplusShutdown", Ptr, pToken) + hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr) + if hModule + DllCall("FreeLibrary", Ptr, hModule) + return 0 +} + +;##################################################################################### +; in AHK v1: uses normal 'if var is' command +; in AHK v2: all if's are expression-if, so the Integer variable is dereferenced to the string +;##################################################################################### +IsInteger(Var) { + Static Integer := "Integer" + If Var Is Integer + Return True + Return False +} + +IsNumber(Var) { + Static number := "number" + If Var Is number + Return True + Return False +} + +; ====================================================================================================================== +; Multiple Display Monitors Functions -> msdn.microsoft.com/en-us/library/dd145072(v=vs.85).aspx +; by 'just me' +; https://autohotkey.com/boards/viewtopic.php?f=6&t=4606 +; ====================================================================================================================== + +GetMonitorCount() { + Monitors := MDMF_Enum() + for k,v in Monitors + count := A_Index + return count +} + +GetMonitorInfo(MonitorNum) { + Monitors := MDMF_Enum() + for k,v in Monitors + if (v.Num = MonitorNum) + return v +} + +GetPrimaryMonitor() { + Monitors := MDMF_Enum() + for k,v in Monitors + If (v.Primary) + return v.Num +} + +; ---------------------------------------------------------------------------------------------------------------------- +; Name ..........: MDMF - Multiple Display Monitor Functions +; Description ...: Various functions for multiple display monitor environments +; Tested with ...: AHK 1.1.32.00 (A32/U32/U64) and 2.0-a108-a2fa0498 (U32/U64) +; Original Author: just me (https://www.autohotkey.com/boards/viewtopic.php?f=6&t=4606) +; Mod Authors ...: iPhilip, guest3456 +; Changes .......: Modified to work with v2.0-a108 and changed 'Count' key to 'TotalCount' to avoid conflicts +; ................ Modified MDMF_Enum() so that it works under both AHK v1 and v2. +; ................ Modified MDMF_EnumProc() to provide Count and Primary keys to the Monitors array. +; ................ Modified MDMF_FromHWND() to allow flag values that determine the function's return value if the +; ................ window does not intersect any display monitor. +; ................ Modified MDMF_FromPoint() to allow the cursor position to be returned ByRef if not specified and +; ................ allow flag values that determine the function's return value if the point is not contained within +; ................ any display monitor. +; ................ Modified MDMF_FromRect() to allow flag values that determine the function's return value if the +; ................ rectangle does not intersect any display monitor. +;................. Modified MDMF_GetInfo() with minor changes. +; ---------------------------------------------------------------------------------------------------------------------- +; +; ====================================================================================================================== +; Multiple Display Monitors Functions -> msdn.microsoft.com/en-us/library/dd145072(v=vs.85).aspx ======================= +; ====================================================================================================================== +; Enumerates display monitors and returns an object containing the properties of all monitors or the specified monitor. +; ====================================================================================================================== + +MDMF_Enum(HMON := "") { + Static CallbackFunc := Func(A_AhkVersion < "2" ? "RegisterCallback" : "CallbackCreate") + Static EnumProc := CallbackFunc.Call("MDMF_EnumProc") + Static Obj := (A_AhkVersion < "2") ? "Object" : "Map" + Static Monitors := {} + If (HMON = "") ; new enumeration + { + Monitors := %Obj%("TotalCount", 0) + If !DllCall("User32.dll\EnumDisplayMonitors", "Ptr", 0, "Ptr", 0, "Ptr", EnumProc, "Ptr", &Monitors, "Int") + Return False + } + Return (HMON = "") ? Monitors : Monitors.HasKey(HMON) ? Monitors[HMON] : False +} +; ====================================================================================================================== +; Callback function that is called by the MDMF_Enum function. +; ====================================================================================================================== +MDMF_EnumProc(HMON, HDC, PRECT, ObjectAddr) { + Monitors := Object(ObjectAddr) + Monitors[HMON] := MDMF_GetInfo(HMON) + Monitors["TotalCount"]++ + If (Monitors[HMON].Primary) + Monitors["Primary"] := HMON + Return True +} +; ====================================================================================================================== +; Retrieves the display monitor that has the largest area of intersection with a specified window. +; The following flag values determine the function's return value if the window does not intersect any display monitor: +; MONITOR_DEFAULTTONULL = 0 - Returns NULL. +; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor. +; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the window. +; ====================================================================================================================== +MDMF_FromHWND(HWND, Flag := 0) { + Return DllCall("User32.dll\MonitorFromWindow", "Ptr", HWND, "UInt", Flag, "Ptr") +} +; ====================================================================================================================== +; Retrieves the display monitor that contains a specified point. +; If either X or Y is empty, the function will use the current cursor position for this value and return it ByRef. +; The following flag values determine the function's return value if the point is not contained within any +; display monitor: +; MONITOR_DEFAULTTONULL = 0 - Returns NULL. +; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor. +; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the point. +; ====================================================================================================================== +MDMF_FromPoint(ByRef X := "", ByRef Y := "", Flag := 0) { + If (X = "") || (Y = "") { + VarSetCapacity(PT, 8, 0) + DllCall("User32.dll\GetCursorPos", "Ptr", &PT, "Int") + If (X = "") + X := NumGet(PT, 0, "Int") + If (Y = "") + Y := NumGet(PT, 4, "Int") + } + Return DllCall("User32.dll\MonitorFromPoint", "Int64", (X & 0xFFFFFFFF) | (Y << 32), "UInt", Flag, "Ptr") +} +; ====================================================================================================================== +; Retrieves the display monitor that has the largest area of intersection with a specified rectangle. +; Parameters are consistent with the common AHK definition of a rectangle, which is X, Y, W, H instead of +; Left, Top, Right, Bottom. +; The following flag values determine the function's return value if the rectangle does not intersect any +; display monitor: +; MONITOR_DEFAULTTONULL = 0 - Returns NULL. +; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor. +; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the rectangle. +; ====================================================================================================================== +MDMF_FromRect(X, Y, W, H, Flag := 0) { + VarSetCapacity(RC, 16, 0) + NumPut(X, RC, 0, "Int"), NumPut(Y, RC, 4, "Int"), NumPut(X + W, RC, 8, "Int"), NumPut(Y + H, RC, 12, "Int") + Return DllCall("User32.dll\MonitorFromRect", "Ptr", &RC, "UInt", Flag, "Ptr") +} +; ====================================================================================================================== +; Retrieves information about a display monitor. +; ====================================================================================================================== +MDMF_GetInfo(HMON) { + NumPut(VarSetCapacity(MIEX, 40 + (32 << !!A_IsUnicode)), MIEX, 0, "UInt") + If DllCall("User32.dll\GetMonitorInfo", "Ptr", HMON, "Ptr", &MIEX, "Int") + Return {Name: (Name := StrGet(&MIEX + 40, 32)) ; CCHDEVICENAME = 32 + , Num: RegExReplace(Name, ".*(\d+)$", "$1") + , Left: NumGet(MIEX, 4, "Int") ; display rectangle + , Top: NumGet(MIEX, 8, "Int") ; " + , Right: NumGet(MIEX, 12, "Int") ; " + , Bottom: NumGet(MIEX, 16, "Int") ; " + , WALeft: NumGet(MIEX, 20, "Int") ; work area + , WATop: NumGet(MIEX, 24, "Int") ; " + , WARight: NumGet(MIEX, 28, "Int") ; " + , WABottom: NumGet(MIEX, 32, "Int") ; " + , Primary: NumGet(MIEX, 36, "UInt")} ; contains a non-zero value for the primary monitor. + Return False +} + +;###################################################################################################################################### +; The following functions are written by Just Me +; Taken from https://autohotkey.com/board/topic/85238-get-image-metadata-using-gdi-ahk-l/ +; October 2013; minimal modifications by Marius Șucan in July 2019 + +Gdip_LoadImageFromFile(sFile, useICM:=0) { +; An Image object encapsulates a bitmap or a metafile and stores attributes that you can retrieve. + pImage := 0 + function2call := (useICM=1) ? "GdipLoadImageFromFileICM" : "GdipLoadImageFromFile" + R := DllCall("gdiplus\" function2call, "WStr", sFile, "UPtrP", pImage) + ErrorLevel := R + Return pImage +} + +;###################################################################################################################################### +; Gdip_GetPropertyCount() - Gets the number of properties (pieces of metadata) stored in this Image object. +; Parameters: +; pImage - Pointer to the Image object. +; Return values: +; On success - Number of properties. +; On failure - 0, ErrorLevel contains the GDIP status +;###################################################################################################################################### + +Gdip_GetPropertyCount(pImage) { + PropCount := 0 + Static Ptr := "UPtr" + R := DllCall("gdiplus\GdipGetPropertyCount", Ptr, pImage, "UIntP", PropCount) + ErrorLevel := R + Return PropCount +} + +;###################################################################################################################################### +; Gdip_GetPropertyIdList() - Gets an aray of the property identifiers used in the metadata of this Image object. +; Parameters: +; pImage - Pointer to the Image object. +; Return values: +; On success - Array containing the property identifiers as integer keys and the name retrieved from +; Gdip_GetPropertyTagName(PropID) as values. +; The total number of properties is stored in Array.Count. +; On failure - False, ErrorLevel contains the GDIP status +;###################################################################################################################################### + +Gdip_GetPropertyIdList(pImage) { + PropNum := Gdip_GetPropertyCount(pImage) + Static Ptr := "UPtr" + If (ErrorLevel) || (PropNum = 0) + Return False + VarSetCapacity(PropIDList, 4 * PropNum, 0) + R := DllCall("gdiplus\GdipGetPropertyIdList", Ptr, pImage, "UInt", PropNum, "Ptr", &PropIDList) + If (R) { + ErrorLevel := R + Return False + } + + PropArray := {Count: PropNum} + Loop %PropNum% + { + PropID := NumGet(PropIDList, (A_Index - 1) << 2, "UInt") + PropArray[PropID] := Gdip_GetPropertyTagName(PropID) + } + Return PropArray +} + +;###################################################################################################################################### +; Gdip_GetPropertyItem() - Gets a specified property item (piece of metadata) from this Image object. +; Parameters: +; pImage - Pointer to the Image object. +; PropID - Integer that identifies the property item to be retrieved (see Gdip_GetPropertyTagName()). +; Return values: +; On success - Property item object containing three keys: +; Length - Length of the value in bytes. +; Type - Type of the value (see Gdip_GetPropertyTagType()). +; Value - The value itself. +; On failure - False, ErrorLevel contains the GDIP status +;###################################################################################################################################### + +Gdip_GetPropertyItem(pImage, PropID) { + PropItem := {Length: 0, Type: 0, Value: ""} + ItemSize := 0 + R := DllCall("gdiplus\GdipGetPropertyItemSize", "Ptr", pImage, "UInt", PropID, "UIntP", ItemSize) + If (R) { + ErrorLevel := R + Return False + } + + Static Ptr := "UPtr" + VarSetCapacity(Item, ItemSize, 0) + R := DllCall("gdiplus\GdipGetPropertyItem", Ptr, pImage, "UInt", PropID, "UInt", ItemSize, "Ptr", &Item) + If (R) { + ErrorLevel := R + Return False + } + PropLen := NumGet(Item, 4, "UInt") + PropType := NumGet(Item, 8, "Short") + PropAddr := NumGet(Item, 8 + A_PtrSize, "UPtr") + PropItem.Length := PropLen + PropItem.Type := PropType + If (PropLen > 0) + { + PropVal := "" + Gdip_GetPropertyItemValue(PropVal, PropLen, PropType, PropAddr) + If (PropType = 1) || (PropType = 7) { + PropItem.SetCapacity("Value", PropLen) + ValAddr := PropItem.GetAddress("Value") + DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", ValAddr, "Ptr", &PropVal, "Ptr", PropLen) + } Else { + PropItem.Value := PropVal + } + } + ErrorLevel := 0 + Return PropItem +} + +;###################################################################################################################################### +; Gdip_GetAllPropertyItems() - Gets all the property items (metadata) stored in this Image object. +; Parameters: +; pImage - Pointer to the Image object. +; Return values: +; On success - Properties object containing one integer key for each property ID. Each value is an object +; containing three keys: +; Length - Length of the value in bytes. +; Type - Type of the value (see Gdip_GetPropertyTagType()). +; Value - The value itself. +; The total number of properties is stored in Properties.Count. +; On failure - False, ErrorLevel contains the GDIP status +;###################################################################################################################################### + +Gdip_GetAllPropertyItems(pImage) { + BufSize := PropNum := ErrorLevel := 0 + R := DllCall("gdiplus\GdipGetPropertySize", "Ptr", pImage, "UIntP", BufSize, "UIntP", PropNum) + If (R) || (PropNum = 0) { + ErrorLevel := R ? R : 19 ; 19 = PropertyNotFound + Return False + } + VarSetCapacity(Buffer, BufSize, 0) + Static Ptr := "UPtr" + R := DllCall("gdiplus\GdipGetAllPropertyItems", Ptr, pImage, "UInt", BufSize, "UInt", PropNum, "Ptr", &Buffer) + If (R) { + ErrorLevel := R + Return False + } + PropsObj := {Count: PropNum} + PropSize := 8 + (2 * A_PtrSize) + + Loop %PropNum% + { + OffSet := PropSize * (A_Index - 1) + PropID := NumGet(Buffer, OffSet, "UInt") + PropLen := NumGet(Buffer, OffSet + 4, "UInt") + PropType := NumGet(Buffer, OffSet + 8, "Short") + PropAddr := NumGet(Buffer, OffSet + 8 + A_PtrSize, "UPtr") + PropVal := "" + PropsObj[PropID] := {} + PropsObj[PropID, "Length"] := PropLen + PropsObj[PropID, "Type"] := PropType + PropsObj[PropID, "Value"] := PropVal + If (PropLen > 0) + { + Gdip_GetPropertyItemValue(PropVal, PropLen, PropType, PropAddr) + If (PropType = 1) || (PropType = 7) + { + PropsObj[PropID].SetCapacity("Value", PropLen) + ValAddr := PropsObj[PropID].GetAddress("Value") + DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", ValAddr, "Ptr", PropAddr, "Ptr", PropLen) + } Else { + PropsObj[PropID].Value := PropVal + } + } + } + ErrorLevel := 0 + Return PropsObj +} + +;###################################################################################################################################### +; Gdip_GetPropertyTagName() - Gets the name for the integer identifier of this property as defined in "Gdiplusimaging.h". +; Parameters: +; PropID - Integer that identifies the property item to be retrieved. +; Return values: +; On success - Corresponding name. +; On failure - "Unknown" +;###################################################################################################################################### + +Gdip_GetPropertyTagName(PropID) { +; All tags are taken from "Gdiplusimaging.h", probably there will be more. +; For most of them you'll find a description on http://msdn.microsoft.com/en-us/library/ms534418(VS.85).aspx +; +; modified by Marius Șucan in July/August 2019: +; I transformed the function to not yield errors on AHK v2 + + Static PropTagsA := {0x0001:"GPS LatitudeRef",0x0002:"GPS Latitude",0x0003:"GPS LongitudeRef",0x0004:"GPS Longitude",0x0005:"GPS AltitudeRef",0x0006:"GPS Altitude",0x0007:"GPS Time",0x0008:"GPS Satellites",0x0009:"GPS Status",0x000A:"GPS MeasureMode",0x001D:"GPS Date",0x001E:"GPS Differential",0x00FE:"NewSubfileType",0x00FF:"SubfileType",0x0102:"Bits Per Sample",0x0103:"Compression",0x0106:"Photometric Interpolation",0x0107:"ThreshHolding",0x010A:"Fill Order",0x010D:"Document Name",0x010E:"Image Description",0x010F:"Equipment Make",0x0110:"Equipment Model",0x0112:"Orientation",0x0115:"Samples Per Pixel",0x0118:"Min Sample Value",0x0119:"Max Sample Value",0x011D:"Page Name",0x0122:"GrayResponseUnit",0x0123:"GrayResponseCurve",0x0128:"Resolution Unit",0x012D:"Transfer Function",0x0131:"Software Used",0x0132:"Internal Date Time",0x013B:"Artist" + ,0x013C:"Host Computer",0x013D:"Predictor",0x013E:"White Point",0x013F:"Primary Chromaticities",0x0140:"Color Map",0x014C:"Ink Set",0x014D:"Ink Names",0x014E:"Number Of Inks",0x0150:"Dot Range",0x0151:"Target Printer",0x0152:"Extra Samples",0x0153:"Sample Format",0x0156:"Transfer Range",0x0200:"JPEGProc",0x0205:"JPEGLosslessPredictors",0x0301:"Gamma",0x0302:"ICC Profile Descriptor",0x0303:"SRGB Rendering Intent",0x0320:"Image Title",0x5010:"JPEG Quality",0x5011:"Grid Size",0x501A:"Color Transfer Function",0x5100:"Frame Delay",0x5101:"Loop Count",0x5110:"Pixel Unit",0x5111:"Pixel Per Unit X",0x5112:"Pixel Per Unit Y",0x8298:"Copyright",0x829A:"EXIF Exposure Time",0x829D:"EXIF F Number",0x8773:"ICC Profile",0x8822:"EXIF ExposureProg",0x8824:"EXIF SpectralSense",0x8827:"EXIF ISO Speed",0x9003:"EXIF Date Original",0x9004:"EXIF Date Digitized" + ,0x9102:"EXIF CompBPP",0x9201:"EXIF Shutter Speed",0x9202:"EXIF Aperture",0x9203:"EXIF Brightness",0x9204:"EXIF Exposure Bias",0x9205:"EXIF Max. Aperture",0x9206:"EXIF Subject Dist",0x9207:"EXIF Metering Mode",0x9208:"EXIF Light Source",0x9209:"EXIF Flash",0x920A:"EXIF Focal Length",0x9214:"EXIF Subject Area",0x927C:"EXIF Maker Note",0x9286:"EXIF Comments",0xA001:"EXIF Color Space",0xA002:"EXIF PixXDim",0xA003:"EXIF PixYDim",0xA004:"EXIF Related WAV",0xA005:"EXIF Interop",0xA20B:"EXIF Flash Energy",0xA20E:"EXIF Focal X Res",0xA20F:"EXIF Focal Y Res",0xA210:"EXIF FocalResUnit",0xA214:"EXIF Subject Loc",0xA215:"EXIF Exposure Index",0xA217:"EXIF Sensing Method",0xA300:"EXIF File Source",0xA301:"EXIF Scene Type",0xA401:"EXIF Custom Rendered",0xA402:"EXIF Exposure Mode",0xA403:"EXIF White Balance",0xA404:"EXIF Digital Zoom Ratio" + ,0xA405:"EXIF Focal Length In 35mm Film",0xA406:"EXIF Scene Capture Type",0xA407:"EXIF Gain Control",0xA408:"EXIF Contrast",0xA409:"EXIF Saturation",0xA40A:"EXIF Sharpness",0xA40B:"EXIF Device Setting Description",0xA40C:"EXIF Subject Distance Range",0xA420:"EXIF Unique Image ID"} + + Static PropTagsB := {0x0000:"GpsVer",0x000B:"GpsGpsDop",0x000C:"GpsSpeedRef",0x000D:"GpsSpeed",0x000E:"GpsTrackRef",0x000F:"GpsTrack",0x0010:"GpsImgDirRef",0x0011:"GpsImgDir",0x0012:"GpsMapDatum",0x0013:"GpsDestLatRef",0x0014:"GpsDestLat",0x0015:"GpsDestLongRef",0x0016:"GpsDestLong",0x0017:"GpsDestBearRef",0x0018:"GpsDestBear",0x0019:"GpsDestDistRef",0x001A:"GpsDestDist",0x001B:"GpsProcessingMethod",0x001C:"GpsAreaInformation",0x0100:"Original Image Width",0x0101:"Original Image Height",0x0108:"CellWidth",0x0109:"CellHeight",0x0111:"Strip Offsets",0x0116:"RowsPerStrip",0x0117:"StripBytesCount",0x011A:"XResolution",0x011B:"YResolution",0x011C:"Planar Config",0x011E:"XPosition",0x011F:"YPosition",0x0120:"FreeOffset",0x0121:"FreeByteCounts",0x0124:"T4Option",0x0125:"T6Option",0x0129:"PageNumber",0x0141:"Halftone Hints",0x0142:"TileWidth",0x0143:"TileLength",0x0144:"TileOffset" + ,0x0145:"TileByteCounts",0x0154:"SMin Sample Value",0x0155:"SMax Sample Value",0x0201:"JPEGInterFormat",0x0202:"JPEGInterLength",0x0203:"JPEGRestartInterval",0x0206:"JPEGPointTransforms",0x0207:"JPEGQTables",0x0208:"JPEGDCTables",0x0209:"JPEGACTables",0x0211:"YCbCrCoefficients",0x0212:"YCbCrSubsampling",0x0213:"YCbCrPositioning",0x0214:"REFBlackWhite",0x5001:"ResolutionXUnit",0x5002:"ResolutionYUnit",0x5003:"ResolutionXLengthUnit",0x5004:"ResolutionYLengthUnit",0x5005:"PrintFlags",0x5006:"PrintFlagsVersion",0x5007:"PrintFlagsCrop",0x5008:"PrintFlagsBleedWidth",0x5009:"PrintFlagsBleedWidthScale",0x500A:"HalftoneLPI",0x500B:"HalftoneLPIUnit",0x500C:"HalftoneDegree",0x500D:"HalftoneShape",0x500E:"HalftoneMisc",0x500F:"HalftoneScreen",0x5012:"ThumbnailFormat",0x5013:"ThumbnailWidth",0x5014:"ThumbnailHeight",0x5015:"ThumbnailColorDepth" + ,0x5016:"ThumbnailPlanes",0x5017:"ThumbnailRawBytes",0x5018:"ThumbnailSize",0x5019:"ThumbnailCompressedSize",0x501B:"ThumbnailData",0x5020:"ThumbnailImageWidth",0x5021:"ThumbnailImageHeight",0x5022:"ThumbnailBitsPerSample",0x5023:"ThumbnailCompression",0x5024:"ThumbnailPhotometricInterp",0x5025:"ThumbnailImageDescription",0x5026:"ThumbnailEquipMake",0x5027:"ThumbnailEquipModel",0x5028:"ThumbnailStripOffsets",0x5029:"ThumbnailOrientation",0x502A:"ThumbnailSamplesPerPixel",0x502B:"ThumbnailRowsPerStrip",0x502C:"ThumbnailStripBytesCount",0x502D:"ThumbnailResolutionX",0x502E:"ThumbnailResolutionY",0x502F:"ThumbnailPlanarConfig",0x5030:"ThumbnailResolutionUnit",0x5031:"ThumbnailTransferFunction",0x5032:"ThumbnailSoftwareUsed",0x5033:"ThumbnailDateTime",0x5034:"ThumbnailArtist",0x5035:"ThumbnailWhitePoint" + ,0x5036:"ThumbnailPrimaryChromaticities",0x5037:"ThumbnailYCbCrCoefficients",0x5038:"ThumbnailYCbCrSubsampling",0x5039:"ThumbnailYCbCrPositioning",0x503A:"ThumbnailRefBlackWhite",0x503B:"ThumbnailCopyRight",0x5090:"LuminanceTable",0x5091:"ChrominanceTable",0x5102:"Global Palette",0x5103:"Index Background",0x5104:"Index Transparent",0x5113:"Palette Histogram",0x8769:"ExifIFD",0x8825:"GpsIFD",0x8828:"ExifOECF",0x9000:"ExifVer",0x9101:"EXIF CompConfig",0x9290:"EXIF DTSubsec",0x9291:"EXIF DTOrigSS",0x9292:"EXIF DTDigSS",0xA000:"EXIF FPXVer",0xA20C:"EXIF Spatial FR",0xA302:"EXIF CfaPattern"} + + r := PropTagsA.HasKey(PropID) ? PropTagsA[PropID] : "Unknown" + If (r="Unknown") + r := PropTagsB.HasKey(PropID) ? PropTagsB[PropID] : "Unknown" + Return r +} + +;###################################################################################################################################### +; Gdip_GetPropertyTagType() - Gets the name for he type of this property's value as defined in "Gdiplusimaging.h". +; Parameters: +; PropType - Integer that identifies the type of the property item to be retrieved. +; Return values: +; On success - Corresponding type. +; On failure - "Unknown" +;###################################################################################################################################### + +Gdip_GetPropertyTagType(PropType) { + Static PropTypes := {1: "Byte", 2: "ASCII", 3: "Short", 4: "Long", 5: "Rational", 7: "Undefined", 9: "SLong", 10: "SRational"} + Return PropTypes.HasKey(PropType) ? PropTypes[PropType] : "Unknown" +} + +Gdip_GetPropertyItemValue(ByRef PropVal, PropLen, PropType, PropAddr) { +; Gdip_GetPropertyItemValue() - Reserved for internal use + PropVal := "" + If (PropType = 2) + { + PropVal := StrGet(PropAddr, PropLen, "CP0") + Return True + } + + If (PropType = 3) + { + PropyLen := PropLen // 2 + Loop %PropyLen% + PropVal .= (A_Index > 1 ? " " : "") . NumGet(PropAddr + 0, (A_Index - 1) << 1, "Short") + Return True + } + + If (PropType = 4) || (PropType = 9) + { + NumType := PropType = 4 ? "UInt" : "Int" + PropyLen := PropLen // 4 + Loop %PropyLen% + PropVal .= (A_Index > 1 ? " " : "") . NumGet(PropAddr + 0, (A_Index - 1) << 2, NumType) + Return True + } + + If (PropType = 5) || (PropType = 10) + { + NumType := PropType = 5 ? "UInt" : "Int" + PropyLen := PropLen // 8 + Loop %PropyLen% + PropVal .= (A_Index > 1 ? " " : "") . NumGet(PropAddr + 0, (A_Index - 1) << 2, NumType) + . "/" . NumGet(PropAddr + 4, (A_Index - 1) << 2, NumType) + Return True + } + + If (PropType = 1) || (PropType = 7) + { + VarSetCapacity(PropVal, PropLen, 0) + DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", &PropVal, "Ptr", PropAddr, "Ptr", PropLen) + Return True + } + Return False +} + +;##################################################################################### +; RotateAtCenter() and related Functions by RazorHalo +; from https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6517&start=260 +; in April 2019. +;##################################################################################### +; The Matrix order has to be "Append" for the transformations to be applied +; in the correct order - instead of the default "Prepend" + +Gdip_RotatePathAtCenter(pPath, Angle, MatrixOrder:=1, withinBounds:=0, withinBkeepRatio:=1) { +; modified by Marius Șucan - added withinBounds option + + ; Gets the bounding rectangle of the GraphicsPath + ; returns array x, y, w, h + Rect := Gdip_GetPathWorldBounds(pPath) + + ; Calculate center of bounding rectangle which will be the center of the graphics path + cX := Rect.x + (Rect.w / 2) + cY := Rect.y + (Rect.h / 2) + + ; Create a Matrix for the transformations + pMatrix := Gdip_CreateMatrix() + + ; Move the GraphicsPath center to the origin (0, 0) of the graphics object + Gdip_TranslateMatrix(pMatrix, -cX , -cY) + + ; Rotate matrix on graphics object origin + Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder) + + ; Move the GraphicsPath origin point back to its original position + Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder) + + ; Apply the transformations + E := Gdip_TransformPath(pPath, pMatrix) + + ; Delete Matrix + Gdip_DeleteMatrix(pMatrix) + + If (withinBounds=1 && !E && Angle!=0) + { + nRect := Gdip_GetPathWorldBounds(pPath) + ncX := nRect.x + (nRect.w / 2) + ncY := nRect.y + (nRect.h / 2) + pMatrix := Gdip_CreateMatrix() + Gdip_TranslateMatrix(pMatrix, -ncX , -ncY) + sX := Rect.w / nRect.w + sY := Rect.h / nRect.h + If (withinBkeepRatio=1) + { + sX := min(sX, sY) + sY := min(sX, sY) + } + Gdip_ScaleMatrix(pMatrix, sX, sY, MatrixOrder) + Gdip_TranslateMatrix(pMatrix, ncX, ncY, MatrixOrder) + If (sX!=0 && sY!=0) + E := Gdip_TransformPath(pPath, pMatrix) + Gdip_DeleteMatrix(pMatrix) + } + Return E +} + +;##################################################################################### +; Matrix transformations functions by RazorHalo +; +; NOTE: Be aware of the order that transformations are applied. You may need +; to pass MatrixOrder as 1 for "Append" +; the (default is 0 for "Prepend") to get the correct results. + +Gdip_ResetMatrix(hMatrix) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipResetMatrix", Ptr, hMatrix) +} + +Gdip_RotateMatrix(hMatrix, Angle, MatrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipRotateMatrix", Ptr, hMatrix, "float", Angle, "Int", MatrixOrder) +} + + +Gdip_GetPathWorldBounds(pPath, hMatrix:=0, pPen:=0) { +; hMatrix to use for calculating the boundaries +; pPen to use for calculating the boundaries +; Both will not affect the actual GraphicsPath. + + rData := {} + VarSetCapacity(RectF, 16, 0) + status := DllCall("gdiplus\GdipGetPathWorldBounds", "UPtr", pPath, "UPtr", &RectF, "UPtr", hMatrix, "UPtr", pPen) + + If (!status) { + rData.x := NumGet(&RectF, 0, "float") + , rData.y := NumGet(&RectF, 4, "float") + , rData.w := NumGet(&RectF, 8, "float") + , rData.h := NumGet(&RectF, 12, "float") + } Else { + Return status + } + + return rData +} + +Gdip_ScaleMatrix(hMatrix, ScaleX, ScaleY, MatrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipScaleMatrix", Ptr, hMatrix, "float", ScaleX, "float", ScaleY, "Int", MatrixOrder) +} + +Gdip_TranslateMatrix(hMatrix, offsetX, offsetY, MatrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipTranslateMatrix", Ptr, hMatrix, "float", offsetX, "float", offsetY, "Int", MatrixOrder) +} + +Gdip_TransformPath(pPath, hMatrix) { + return DllCall("gdiplus\GdipTransformPath", "UPtr", pPath, "UPtr", hMatrix) +} + +Gdip_SetMatrixElements(hMatrix, m11, m12, m21, m22, x, y) { + return DllCall("gdiplus\GdipSetMatrixElements", "UPtr", hMatrix, "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y) +} + +Gdip_GetMatrixLastStatus(pMatrix) { + return DllCall("gdiplus\GdipGetLastStatus", "UPtr", pMatrix) +} + +;##################################################################################### +; GraphicsPath functions written by Learning one +; found on https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-75 +; Updated on 14/08/2019 by Marius Șucan +;##################################################################################### +; +; Function: Gdip_AddPathBeziers +; Description: Adds a sequence of connected Bézier splines to the current figure of this path. +; A Bezier spline does not pass through its control points. The control points act as magnets, pulling the curve +; in certain directions to influence the way the spline bends. +; +; pPath: Pointer to the GraphicsPath. +; Points: The coordinates of all the points passed as x1,y1|x2,y2|x3,y3... +; +; Return: Status enumeration. 0 = success. +; +; Notes: The first spline is constructed from the first point through the fourth point in the array and uses the second and third points as control points. Each subsequent spline in the sequence needs exactly three more points: the ending point of the previous spline is used as the starting point, the next two points in the sequence are control points, and the third point is the ending point. + +Gdip_AddPathBeziers(pPath, Points) { + iCount := CreatePointsF(PointsF, Points) + return DllCall("gdiplus\GdipAddPathBeziers", "UPtr", pPath, "UPtr", &PointsF, "int", iCount) +} + +Gdip_AddPathBezier(pPath, x1, y1, x2, y2, x3, y3, x4, y4) { + ; Adds a Bézier spline to the current figure of this path + return DllCall("gdiplus\GdipAddPathBezier", "UPtr", pPath + , "float", x1, "float", y1, "float", x2, "float", y2 + , "float", x3, "float", y3, "float", x4, "float", y4) +} + +;##################################################################################### +; Function: Gdip_AddPathLines +; Description: Adds a sequence of connected lines to the current figure of this path. +; +; pPath: Pointer to the GraphicsPath +; Points: the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... +; +; Return: status enumeration. 0 = success. + +Gdip_AddPathLines(pPath, Points) { + iCount := CreatePointsF(PointsF, Points) + return DllCall("gdiplus\GdipAddPathLine2", "UPtr", pPath, "UPtr", &PointsF, "int", iCount) +} + +Gdip_AddPathLine(pPath, x1, y1, x2, y2) { + return DllCall("gdiplus\GdipAddPathLine", "UPtr", pPath, "float", x1, "float", y1, "float", x2, "float", y2) +} + +Gdip_AddPathArc(pPath, x, y, w, h, StartAngle, SweepAngle) { + return DllCall("gdiplus\GdipAddPathArc", "UPtr", pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle) +} + +Gdip_AddPathPie(pPath, x, y, w, h, StartAngle, SweepAngle) { + return DllCall("gdiplus\GdipAddPathPie", "UPtr", pPath, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle) +} + +Gdip_StartPathFigure(pPath) { +; Starts a new figure without closing the current figure. +; Subsequent points added to this path are added to the new figure. + return DllCall("gdiplus\GdipStartPathFigure", "UPtr", pPath) +} + +Gdip_ClosePathFigure(pPath) { +; Closes the current figure of this path. + return DllCall("gdiplus\GdipClosePathFigure", "UPtr", pPath) +} + +Gdip_ClosePathFigures(pPath) { +; Closes the current figure of this path. + return DllCall("gdiplus\GdipClosePathFigures", "UPtr", pPath) +} + +;##################################################################################### +; Function: Gdip_DrawPath +; Description: Draws a sequence of lines and curves defined by a GraphicsPath object +; +; pGraphics: Pointer to the Graphics of a bitmap +; pPen: Pointer to a pen object +; pPath: Pointer to a Path object +; +; Return: status enumeration. 0 = success. + +Gdip_DrawPath(pGraphics, pPen, pPath) { + return DllCall("gdiplus\GdipDrawPath", "UPtr", pGraphics, "UPtr", pPen, "UPtr", pPath) +} + +Gdip_ClonePath(pPath) { + pPathClone := 0 + DllCall("gdiplus\GdipClonePath", "UPtr", pPath, "UPtr*", pPathClone) + return pPathClone +} + +;###################################################################################################################################### +; The following PathGradient brush functions were written by 'Just Me' in March 2012 +; source: https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-65 +;###################################################################################################################################### + +Gdip_PathGradientCreateFromPath(pPath) { + ; Creates and returns a path gradient brush. + ; pPath path object returned from Gdip_CreatePath() + pBrush := 0 + DllCall("gdiplus\GdipCreatePathGradientFromPath", "Ptr", pPath, "PtrP", pBrush) + Return pBrush +} + +Gdip_PathGradientSetCenterPoint(pBrush, X, Y) { + ; Sets the center point of this path gradient brush. + ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath(). + ; X, Y X, y coordinates in pixels + VarSetCapacity(POINTF, 8) + NumPut(X, POINTF, 0, "Float") + NumPut(Y, POINTF, 4, "Float") + Return DllCall("gdiplus\GdipSetPathGradientCenterPoint", "Ptr", pBrush, "Ptr", &POINTF) +} + +Gdip_PathGradientSetCenterColor(pBrush, CenterColor) { + ; Sets the center color of this path gradient brush. + ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath(). + ; CenterColor ARGB color value: A(lpha)R(ed)G(reen)B(lue). + Return DllCall("gdiplus\GdipSetPathGradientCenterColor", "Ptr", pBrush, "UInt", CenterColor) +} + +Gdip_PathGradientSetSurroundColors(pBrush, SurroundColors) { + ; Sets the surround colors of this path gradient brush. + ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath(). + ; SurroundColours One or more ARGB color values seperated by pipe (|)). + ; updated by Marius Șucan + + Colors := StrSplit(SurroundColors, "|") + tColors := Colors.Length() + VarSetCapacity(ColorArray, 4 * tColors, 0) + + Loop %tColors% { + NumPut(Colors[A_Index], ColorArray, 4 * (A_Index - 1), "UInt") + } + + Return DllCall("gdiplus\GdipSetPathGradientSurroundColorsWithCount", "Ptr", pBrush, "Ptr", &ColorArray + , "IntP", tColors) +} + +Gdip_PathGradientSetSigmaBlend(pBrush, Focus, Scale:=1) { + ; Sets the blend shape of this path gradient brush to bell shape. + ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath(). + ; Focus Number that specifies where the center color will be at its highest intensity. + ; Values: 1.0 (center) - 0.0 (border) + ; Scale Number that specifies the maximum intensity of center color that gets blended with + ; the boundary color. + ; Values: 1.0 (100 %) - 0.0 (0 %) + Return DllCall("gdiplus\GdipSetPathGradientSigmaBlend", "Ptr", pBrush, "Float", Focus, "Float", Scale) +} + +Gdip_PathGradientSetLinearBlend(pBrush, Focus, Scale:=1) { + ; Sets the blend shape of this path gradient brush to triangular shape. + ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath() + ; Focus Number that specifies where the center color will be at its highest intensity. + ; Values: 1.0 (center) - 0.0 (border) + ; Scale Number that specifies the maximum intensity of center color that gets blended with + ; the boundary color. + ; Values: 1.0 (100 %) - 0.0 (0 %) + Return DllCall("gdiplus\GdipSetPathGradientLinearBlend", "Ptr", pBrush, "Float", Focus, "Float", Scale) +} + +Gdip_PathGradientSetFocusScales(pBrush, xScale, yScale) { + ; Sets the focus scales of this path gradient brush. + ; pBrush Brush object returned from Gdip_PathGradientCreateFromPath(). + ; xScale Number that specifies the x focus scale. + ; Values: 0.0 (0 %) - 1.0 (100 %) + ; yScale Number that specifies the y focus scale. + ; Values: 0.0 (0 %) - 1.0 (100 %) + Return DllCall("gdiplus\GdipSetPathGradientFocusScales", "Ptr", pBrush, "Float", xScale, "Float", yScale) +} + +Gdip_AddPathGradient(pGraphics, x, y, w, h, cX, cY, cClr, sClr, BlendFocus, ScaleX, ScaleY, Shape, Angle:=0) { +; Parameters: +; X, Y - coordinates where to add the gradient path object +; W, H - the width and height of the path gradient object +; cX, cY - the coordinates of the Center Point of the gradient within the wdith and height object boundaries +; cClr - the center color in 0xARGB +; sClr - the surrounding color in 0xARGB +; BlendFocus - 0.0 to 1.0; where the center color reaches the highest intensity +; Shape - 1 = rectangle ; 0 = ellipse +; Angle - Rotate the pPathGradientBrush at given angle +; +; function based on the example provided by Just Me for the path gradient functions +; adaptations/modifications by Marius Șucan + + pPath := Gdip_CreatePath() + If (Shape=1) + Gdip_AddPathRectangle(pPath, x, y, W, H) + Else + Gdip_AddPathEllipse(pPath, x, y, W, H) + zBrush := Gdip_PathGradientCreateFromPath(pPath) + If (Angle!=0) + Gdip_RotatePathGradientAtCenter(zBrush, Angle) + Gdip_PathGradientSetCenterPoint(zBrush, cX, cY) + Gdip_PathGradientSetCenterColor(zBrush, cClr) + Gdip_PathGradientSetSurroundColors(zBrush, sClr) + Gdip_PathGradientSetSigmaBlend(zBrush, BlendFocus) + Gdip_PathGradientSetLinearBlend(zBrush, BlendFocus) + Gdip_PathGradientSetFocusScales(zBrush, ScaleX, ScaleY) + E := Gdip_FillPath(pGraphics, zBrush, pPath) + Gdip_DeleteBrush(zBrush) + Gdip_DeletePath(pPath) + Return E +} + +;###################################################################################################################################### +; The following PathGradient brush functions were written by Marius Șucan +;###################################################################################################################################### + +Gdip_CreatePathGradient(Points, WrapMode) { +; Creates a PathGradientBrush object based on an array of points and initializes the wrap mode of the brush +; +; Points array format: +; Points := "x1,y1|x2,y2|x3,y3|x4,y4" [... and so on] +; +; WrapMode options: specifies how an area is tiled when it is painted with a brush: +; 0 - Tile - Tiling without flipping +; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row +; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column +; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column +; 4 - Clamp - No tiling + + Static Ptr := "UPtr" + iCount := CreatePointsF(PointsF, Points) + pPathGradientBrush := 0 + DllCall("gdiplus\GdipCreatePathGradient", Ptr, &PointsF, "int", iCount, "int", WrapMode, "int*", pPathGradientBrush) + Return pPathGradientBrush +} + +Gdip_PathGradientGetGammaCorrection(pPathGradientBrush) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPathGradientGammaCorrection", Ptr, pPathGradientBrush, "int*", result) + If E + return -1 + Return result +} + +Gdip_PathGradientGetPointCount(pPathGradientBrush) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPathGradientPointCount", Ptr, pPathGradientBrush, "int*", result) + If E + return -1 + Return result +} + +Gdip_PathGradientGetWrapMode(pPathGradientBrush) { + result := 0 + E := DllCall("gdiplus\GdipGetPathGradientWrapMode", "UPtr", pPathGradientBrush, "int*", result) + If E + return -1 + Return result +} + +Gdip_PathGradientGetRect(pPathGradientBrush) { + rData := {} + VarSetCapacity(RectF, 16, 0) + status := DllCall("gdiplus\GdipGetPathGradientRect", "UPtr", pPathGradientBrush, "UPtr", &RectF) + + If (!status) { + rData.x := NumGet(&RectF, 0, "float") + , rData.y := NumGet(&RectF, 4, "float") + , rData.w := NumGet(&RectF, 8, "float") + , rData.h := NumGet(&RectF, 12, "float") + } Else { + Return status + } + + return rData +} + +Gdip_PathGradientResetTransform(pPathGradientBrush) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipResetPathGradientTransform", Ptr, pPathGradientBrush) +} + +Gdip_PathGradientRotateTransform(pPathGradientBrush, Angle, matrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipRotatePathGradientTransform", Ptr, pPathGradientBrush, "float", Angle, "int", matrixOrder) +} + +Gdip_PathGradientScaleTransform(pPathGradientBrush, ScaleX, ScaleY, matrixOrder:=0) { + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipScalePathGradientTransform", Ptr, pPathGradientBrush, "float", ScaleX, "float", ScaleY, "int", matrixOrder) +} + +Gdip_PathGradientTranslateTransform(pPathGradientBrush, X, Y, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipTranslatePathGradientTransform", Ptr, pPathGradientBrush, "float", X, "float", Y, "int", matrixOrder) +} + +Gdip_PathGradientMultiplyTransform(pPathGradientBrush, hMatrix, matrixOrder:=0) { + Static Ptr := "UPtr" + Return DllCall("gdiplus\GdipMultiplyPathGradientTransform", Ptr, pPathGradientBrush, Ptr, hMatrix, "int", matrixOrder) +} + +Gdip_PathGradientSetTransform(pPathGradientBrush, pMatrix) { + return DllCall("gdiplus\GdipSetPathGradientTransform", "UPtr", pPathGradientBrush, "UPtr", pMatrix) +} + +Gdip_PathGradientGetTransform(pPathGradientBrush) { + pMatrix := 0 + DllCall("gdiplus\GdipGetPathGradientTransform", "UPtr", pPathGradientBrush, "UPtr*", pMatrix) + Return pMatrix +} + +Gdip_RotatePathGradientAtCenter(pPathGradientBrush, Angle, MatrixOrder:=1) { +; function by Marius Șucan +; based on Gdip_RotatePathAtCenter() by RazorHalo + + Rect := Gdip_PathGradientGetRect(pPathGradientBrush) + cX := Rect.x + (Rect.w / 2) + cY := Rect.y + (Rect.h / 2) + pMatrix := Gdip_CreateMatrix() + Gdip_TranslateMatrix(pMatrix, -cX , -cY) + Gdip_RotateMatrix(pMatrix, Angle, MatrixOrder) + Gdip_TranslateMatrix(pMatrix, cX, cY, MatrixOrder) + E := Gdip_PathGradientSetTransform(pPathGradientBrush, pMatrix) + Gdip_DeleteMatrix(pMatrix) + Return E +} + + +Gdip_PathGradientSetGammaCorrection(pPathGradientBrush, UseGammaCorrection) { +; Specifies whether gamma correction is enabled for a path gradient brush +; UseGammaCorrection: 1 or 0. + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetPathGradientGammaCorrection", Ptr, pPathGradientBrush, "int", UseGammaCorrection) +} + +Gdip_PathGradientSetWrapMode(pPathGradientBrush, WrapMode) { +; WrapMode options: specifies how an area is tiled when it is painted with a brush: +; 0 - Tile - Tiling without flipping +; 1 - TileFlipX - Tiles are flipped horizontally as you move from one tile to the next in a row +; 2 - TileFlipY - Tiles are flipped vertically as you move from one tile to the next in a column +; 3 - TileFlipXY - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column +; 4 - Clamp - No tiling + + Static Ptr := "UPtr" + return DllCall("gdiplus\GdipSetPathGradientWrapMode", Ptr, pPathGradientBrush, "int", WrapMode) +} + +Gdip_PathGradientGetCenterColor(pPathGradientBrush) { + Static Ptr := "UPtr" + ARGB := 0 + E := DllCall("gdiplus\GdipGetPathGradientCenterColor", Ptr, pPathGradientBrush, "uint*", ARGB) + If E + return -1 + Return Format("{1:#x}", ARGB) +} + +Gdip_PathGradientGetCenterPoint(pPathGradientBrush, ByRef X, ByRef Y) { + Static Ptr := "UPtr" + VarSetCapacity(PointF, 8, 0) + E := DllCall("gdiplus\GdipGetPathGradientCenterPoint", Ptr, pPathGradientBrush, "UPtr", &PointF) + If !E + { + x := NumGet(PointF, 0, "float") + y := NumGet(PointF, 4, "float") + } + Return E +} + +Gdip_PathGradientGetFocusScales(pPathGradientBrush, ByRef X, ByRef Y) { + Static Ptr := "UPtr" + x := 0 + y := 0 + Return DllCall("gdiplus\GdipGetPathGradientFocusScales", Ptr, pPathGradientBrush, "float*", X, "float*", Y) +} + +Gdip_PathGradientGetSurroundColorCount(pPathGradientBrush) { + Static Ptr := "UPtr" + result := 0 + E := DllCall("gdiplus\GdipGetPathGradientSurroundColorCount", Ptr, pPathGradientBrush, "int*", result) + If E + return -1 + Return result +} + +Gdip_GetPathGradientSurroundColors(pPathGradientBrush) { + iCount := Gdip_PathGradientGetSurroundColorCount(pPathGradientBrush) + If (iCount=-1) + Return 0 + + + Static Ptr := "UPtr" + VarSetCapacity(sColors, 8 * iCount, 0) + DllCall("gdiplus\GdipGetPathGradientSurroundColorsWithCount", Ptr, pPathGradientBrush, Ptr, &sColors, "intP", iCount) + Loop %iCount% + { + A := NumGet(&sColors, 8*(A_Index-1), "uint") + printList .= Format("{1:#x}", A) "," + } + + Return Trim(printList, ",") +} + +;#################################################################################### +; Function written by swagfag in July 2019 +; source https://www.autohotkey.com/boards/viewtopic.php?f=6&t=62550 +; modified by Marius Șucan +; whichFormat = 2; histogram for each channel: R, G, B +; whichFormat = 3; histogram of the luminance/brightness of the image +; Return: Status enumerated return type; 0 = OK/Success + +Gdip_GetHistogram(pBitmap, whichFormat, ByRef newArrayA, ByRef newArrayB, ByRef newArrayC) { + Static sizeofUInt := 4 + + ; HistogramFormats := {ARGB: 0, PARGB: 1, RGB: 2, Gray: 3, B: 4, G: 5, R: 6, A: 7} + z := DllCall("gdiplus\GdipBitmapGetHistogramSize", "UInt", whichFormat, "UInt*", numEntries) + + newArrayA := [], newArrayB := [], newArrayC := [] + VarSetCapacity(ch0, numEntries * sizeofUInt, 0) + VarSetCapacity(ch1, numEntries * sizeofUInt, 0) + VarSetCapacity(ch2, numEntries * sizeofUInt, 0) + If (whichFormat=2) + r := DllCall("gdiplus\GdipBitmapGetHistogram", "Ptr", pBitmap, "UInt", whichFormat, "UInt", numEntries, "Ptr", &ch0, "Ptr", &ch1, "Ptr", &ch2, "Ptr", 0) + Else If (whichFormat>2) + r := DllCall("gdiplus\GdipBitmapGetHistogram", "Ptr", pBitmap, "UInt", whichFormat, "UInt", numEntries, "Ptr", &ch0, "Ptr", 0, "Ptr", 0, "Ptr", 0) + + Loop % numEntries { + i := A_Index - 1 + r := NumGet(&ch0+0, i * sizeofUInt, "UInt") + newArrayA[i] := r + + If (whichFormat=2) { + g := NumGet(&ch1+0, i * sizeofUInt, "UInt") + b := NumGet(&ch2+0, i * sizeofUInt, "UInt") + newArrayB[i] := g + newArrayC[i] := b + } + } + + Return r +} + +Gdip_DrawRoundedLine(G, x1, y1, x2, y2, LineWidth, LineColor) { +; function by DevX and Rabiator found on: +; https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-11 + + pPen := Gdip_CreatePen(LineColor, LineWidth) + Gdip_DrawLine(G, pPen, x1, y1, x2, y2) + Gdip_DeletePen(pPen) + + pPen := Gdip_CreatePen(LineColor, LineWidth/2) + Gdip_DrawEllipse(G, pPen, x1-LineWidth/4, y1-LineWidth/4, LineWidth/2, LineWidth/2) + Gdip_DrawEllipse(G, pPen, x2-LineWidth/4, y2-LineWidth/4, LineWidth/2, LineWidth/2) + Gdip_DeletePen(pPen) +} + +Gdip_CreateBitmapFromGdiDib(BITMAPINFO, BitmapData) { + Static Ptr := "UPtr" + pBitmap := 0 + E := DllCall("gdiplus\GdipCreateBitmapFromGdiDib", Ptr, BITMAPINFO, Ptr, BitmapData, "UPtr*", pBitmap) + Return pBitmap +} + +Gdip_DrawImageFX(pGraphics, pBitmap, dX:="", dY:="", sX:="", sY:="", sW:="", sH:="", matrix:="", pEffect:="", ImageAttr:=0, hMatrix:=0, Unit:=2) { + + ;##################################################################################### + + ; Function Gdip_DrawImageFX + ; Description This function draws a bitmap into the pGraphics that can use an Effect. + ; + ; pGraphics Pointer to the Graphics of a bitmap + ; pBitmap Pointer to a bitmap to be drawn + ; dX, dY x, y coordinates of the destination upper-left corner where the image will be painted + ; sX, sY x, y coordinates of the source upper-left corner + ; sW, sH width and height of the source image + ; Matrix a color matrix used to alter image attributes when drawing + ; pEffect a pointer to an Effect object to apply when drawing the image + ; hMatrix a pointer to a transformation matrix + ; Unit Unit of measurement: + ; 0 - World coordinates, a nonphysical unit + ; 1 - Display units + ; 2 - A unit is 1 pixel + ; 3 - A unit is 1 point or 1/72 inch + ; 4 - A unit is 1 inch + ; 5 - A unit is 1/300 inch + ; 6 - A unit is 1 millimeter + ; + ; return status enumeration. 0 = success + ; + ; notes on the color matrix: + ; Matrix can be omitted to just draw with no alteration to ARGB + ; Matrix may be passed as a digit from 0.0 - 1.0 to change just transparency + ; Matrix can be passed as a matrix with "|" as 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 + ; ) + ; + ; example color matrix: + ; 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|1|1|1|0|1 + ; To generate a color matrix using user-friendly parameters, + ; use GenerateColorMatrix() + ; Function written by Marius Șucan. + + Static Ptr := "UPtr" + If !ImageAttr + { + if !IsNumber(Matrix) + 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") + } Else usrImageAttr := 1 + + if (sX="" && sY="") + sX := sY := 0 + + if (sW="" && sH="") + Gdip_GetImageDimensions(pBitmap, sW, sH) + + if (!hMatrix && dX!="" && dY!="") + { + hMatrix := dhMatrix := Gdip_CreateMatrix() + Gdip_TranslateMatrix(dhMatrix, dX, dY, 1) + } + + CreateRectF(sourceRect, sX, sY, sW, sH) + E := DllCall("gdiplus\GdipDrawImageFX" + , Ptr, pGraphics + , Ptr, pBitmap + , Ptr, &sourceRect + , Ptr, hMatrix ? hMatrix : 0 ; transformation matrix + , Ptr, pEffect ? pEffect : 0 + , Ptr, ImageAttr ? ImageAttr : 0 + , "Uint", Unit) ; srcUnit + ; r4 := GetStatus(A_LineNumber ":GdipDrawImageFX",r4) + + If dhMatrix + Gdip_DeleteMatrix(dhMatrix) + + If (ImageAttr && usrImageAttr!=1) + Gdip_DisposeImageAttributes(ImageAttr) + + Return E +} + +Gdip_BitmapApplyEffect(pBitmap, pEffect, x:="", y:="", w:="", h:="") { +; X, Y - coordinates for the rectangle where the effect is applied +; W, H - width and heigh for the rectangle where the effect is applied +; If X, Y, W or H are omitted , the effect is applied on the entire pBitmap +; +; written by Marius Șucan +; many thanks to Drugwash for the help provided + If InStr(pEffect, "err-") + Return pEffect + + If (!x && !y && !w && !h) + { + Gdip_GetImageDimensions(pBitmap, Width, Height) + CreateRectF(RectF, 0, 0, Width, Height) + } Else CreateRectF(RectF, X, Y, W, H) + + E := DllCall("gdiplus\GdipBitmapApplyEffect" + , "UPtr", pBitmap + , "UPtr", pEffect + , "UPtr", &RectF + , "UPtr", 0 ; useAuxData + , "UPtr", 0 ; auxData + , "UPtr", 0) ; auxDataSize + + Return E +} + +COM_CLSIDfromString(ByRef CLSID, String) { + VarSetCapacity(CLSID, 16, 0) + E := DllCall("ole32\CLSIDFromString", "WStr", String, "UPtr", &CLSID) + Return E +} + +Gdip_CreateEffect(whichFX, paramA, paramB, paramC:=0) { +/* + whichFX options: + 1 - Blur + paramA - radius [0, 255] + paramB - bool [0, 1] + 2 - Sharpen + paramA - radius [0, 255] + paramB - amount [0, 100] + 3 - ! ColorMatrix + 4 - ! ColorLUT + 5 - BrightnessContrast + paramA - brightness [-255, 255] + paramB - contrast [-100, 100] + 6 - HueSaturationLightness + paramA - hue [-180, 180] + paramB - saturation [-100, 100] + paramC - light [-100, 100] + 7 - LevelsAdjust + paramA - highlights [0, 100] + paramB - midtones [-100, 100] + paramC - shadows [0, 100] + 8 - Tint + paramA - hue [-180, 180] + paramB - amount [0, 100] + 9 - ColorBalance + paramA - Cyan / Red [-100, 100] + paramB - Magenta / Green [-100, 100] + paramC - Yellow / Blue [-100, 100] + 10 - ! RedEyeCorrection + 11 - ColorCurve + paramA - Type of adjustments [0, 7] + 0 - AdjustExposure [-255, 255] + 1 - AdjustDensity [-255, 255] + 2 - AdjustContrast [-100, 100] + 3 - AdjustHighlight [-100, 100] + 4 - AdjustShadow [-100, 100] + 5 - AdjustMidtone [-100, 100] + 6 - AdjustWhiteSaturation [0, 255] + 7 - AdjustBlackSaturation [0, 255] + + paramB - Apply ColorCurve on channels [1, 4] + 1 - Red + 2 - Green + 3 - Blue + 4 - All channels + + paramC - An adjust value within range according to paramA + + Effects marked with "!" are not yet implemented. + Through ParamA, ParamB and ParamC, the effects can be controlled. + Function written by Marius Șucan. Many thanks to Drugwash for the help provided, +*/ + + Static gdipImgFX := {1:"633C80A4-1843-482b-9EF2-BE2834C5FDD4", 2:"63CBF3EE-C526-402c-8F71-62C540BF5142", 3:"718F2615-7933-40e3-A511-5F68FE14DD74", 4:"A7CE72A9-0F7F-40d7-B3CC-D0C02D5C3212", 5:"D3A1DBE1-8EC4-4c17-9F4C-EA97AD1C343D", 6:"8B2DD6C3-EB07-4d87-A5F0-7108E26A9C5F", 7:"99C354EC-2A31-4f3a-8C34-17A803B33A25", 8:"1077AF00-2848-4441-9489-44AD4C2D7A2C", 9:"537E597D-251E-48da-9664-29CA496B70F8", 10:"74D29D05-69A4-4266-9549-3CC52836B632", 11:"DD6A0022-58E4-4a67-9D9B-D48EB881A53D"} + Ptr := A_PtrSize=8 ? "UPtr" : "UInt" + Ptr2 := A_PtrSize=8 ? "Ptr*" : "PtrP" + pEffect := 0 + r1 := COM_CLSIDfromString(eFXguid, "{" gdipImgFX[whichFX] "}" ) + If r1 + Return "err-" r1 + + If (A_PtrSize=4) ; 32 bits + { + r2 := DllCall("gdiplus\GdipCreateEffect" + , "UInt", NumGet(eFXguid, 0, "UInt") + , "UInt", NumGet(eFXguid, 4, "UInt") + , "UInt", NumGet(eFXguid, 8, "UInt") + , "UInt", NumGet(eFXguid, 12, "UInt") + , Ptr2, pEffect) + } Else + { + r2 := DllCall("gdiplus\GdipCreateEffect" + , Ptr, &eFXguid + , Ptr2, pEffect) + } + If r2 + Return "err-" r2 + + ; r2 := GetStatus(A_LineNumber ":GdipCreateEffect", r2) + + VarSetCapacity(FXparams, 16, 0) + If (whichFX=1) ; Blur FX + { + NumPut(paramA, FXparams, 0, "Float") ; radius [0, 255] + NumPut(paramB, FXparams, 4, "Uchar") ; bool 0, 1 + } Else If (whichFX=2) ; Sharpen FX + { + NumPut(paramA, FXparams, 0, "Float") ; radius [0, 255] + NumPut(paramB, FXparams, 4, "Float") ; amount [0, 100] + } Else If (whichFX=5) ; Brightness / Contrast + { + NumPut(paramA, FXparams, 0, "Int") ; brightness [-255, 255] + NumPut(paramB, FXparams, 4, "Int") ; contrast [-100, 100] + } Else If (whichFX=6) ; Hue / Saturation / Lightness + { + NumPut(paramA, FXparams, 0, "Int") ; hue [-180, 180] + NumPut(paramB, FXparams, 4, "Int") ; saturation [-100, 100] + NumPut(paramC, FXparams, 8, "Int") ; light [-100, 100] + } Else If (whichFX=7) ; Levels adjust + { + NumPut(paramA, FXparams, 0, "Int") ; highlights [0, 100] + NumPut(paramB, FXparams, 4, "Int") ; midtones [-100, 100] + NumPut(paramC, FXparams, 8, "Int") ; shadows [0, 100] + } Else If (whichFX=8) ; Tint adjust + { + NumPut(paramA, FXparams, 0, "Int") ; hue [180, 180] + NumPut(paramB, FXparams, 4, "Int") ; amount [0, 100] + } Else If (whichFX=9) ; Colors balance + { + NumPut(paramA, FXparams, 0, "Int") ; Cyan / Red [-100, 100] + NumPut(paramB, FXparams, 4, "Int") ; Magenta / Green [-100, 100] + NumPut(paramC, FXparams, 8, "Int") ; Yellow / Blue [-100, 100] + } Else If (whichFX=11) ; ColorCurve + { + NumPut(paramA, FXparams, 0, "Int") ; Type of adjustment [0, 7] + NumPut(paramB, FXparams, 4, "Int") ; Channels to affect [1, 4] + NumPut(paramC, FXparams, 8, "Int") ; Adjustment value [based on the type of adjustment] + } + + DllCall("gdiplus\GdipGetEffectParameterSize", Ptr, pEffect, "uint*", FXsize) + r3 := DllCall("gdiplus\GdipSetEffectParameters", Ptr, pEffect, Ptr, &FXparams, "UInt", FXsize) + If r3 + { + Gdip_DisposeEffect(pEffect) + Return "err-" r3 + } + ; r3 := GetStatus(A_LineNumber ":GdipSetEffectParameters", r3) + ; ToolTip, % r1 " -- " r2 " -- " r3 " -- " r4,,, 2 + Return pEffect +} + +Gdip_DisposeEffect(pEffect) { + Static Ptr := "UPtr" + r := DllCall("gdiplus\GdipDeleteEffect", Ptr, pEffect) + Return r +} + +GenerateColorMatrix(modus, bright:=1, contrast:=0, saturation:=1, alph:=1, chnRdec:=0, chnGdec:=0, chnBdec:=0) { +; parameters ranges / intervals: +; bright: [0.001 - 20.0] +; contrast: [-20.0 - 1.00] +; saturation: [0.001 - 5.00] +; alph: [0.001 - 5.00] +; +; modus options: +; 0 - personalized colors based on the bright, contrast [hue], saturation parameters +; 1 - personalized colors based on the bright, contrast, saturation parameters +; 2 - grayscale image +; 3 - grayscale R channel +; 4 - grayscale G channel +; 5 - grayscale B channel +; 6 - negative / invert image +; 7 - alpha channel as grayscale image +; +; chnRdec, chnGdec, chnBdec only apply in modus=1 +; these represent offsets for the RGB channels + +; in modus=0 the parameters have other ranges: +; bright: [-5.00 - 5.00] +; hue: [-1.57 - 1.57] ; pi/2 - contrast stands for hue in this mode +; saturation: [0.001 - 5.00] +; formulas for modus=0 were written by Smurth +; extracted from https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-86 +; +; function written by Marius Șucan +; infos from http://www.graficaobscura.com/matrix/index.html +; real NTSC values: r := 0.300, g := 0.587, b := 0.115 + + Static NTSCr := 0.308, NTSCg := 0.650, NTSCb := 0.095 ; personalized values + matrix := "" + + If (modus=2) ; grayscale + { + LGA := (bright<=1) ? bright/1.5 - 0.6666 : bright - 1 + Ra := NTSCr + LGA + If (Ra<0) + Ra := 0 + Ga := NTSCg + LGA + If (Ga<0) + Ga := 0 + Ba := NTSCb + LGA + If (Ba<0) + Ba := 0 + matrix := Ra "|" Ra "|" Ra "|0|0|" Ga "|" Ga "|" Ga "|0|0|" Ba "|" Ba "|" Ba "|0|0|0|0|0|" alph "|0|" contrast "|" contrast "|" contrast "|0|1" + } Else If (modus=3) ; grayscale R + { + Ga := 0, Ba := 0, GGA := 0 + Ra := bright + matrix := Ra "|" Ra "|" Ra "|0|0|" Ga "|" Ga "|" Ga "|0|0|" Ba "|" Ba "|" Ba "|0|0|0|0|0|25|0|" GGA+0.01 "|" GGA "|" GGA "|0|1" + } Else If (modus=4) ; grayscale G + { + Ra := 0, Ba := 0, GGA := 0 + Ga := bright + matrix := Ra "|" Ra "|" Ra "|0|0|" Ga "|" Ga "|" Ga "|0|0|" Ba "|" Ba "|" Ba "|0|0|0|0|0|25|0|" GGA "|" GGA+0.01 "|" GGA "|0|1" + } Else If (modus=5) ; grayscale B + { + Ra := 0, Ga := 0, GGA := 0 + Ba := bright + matrix := Ra "|" Ra "|" Ra "|0|0|" Ga "|" Ga "|" Ga "|0|0|" Ba "|" Ba "|" Ba "|0|0|0|0|0|25|0|" GGA "|" GGA "|" GGA+0.01 "|0|1" + } Else If (modus=6) ; negative / invert + { + matrix := "-1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|" alph "|0|1|1|1|0|1" + } Else If (modus=1) ; personalized saturation, contrast and brightness + { + bL := bright, aL := alph + G := contrast, sL := saturation + sLi := 1 - saturation + bLa := bright - 1 + If (sL>1) + { + z := (bL<1) ? bL : 1 + sL := sL*z + If (sL<0.98) + sL := 0.98 + + y := z*(1 - sL) + mA := z*(y*NTSCr + sL + bLa + chnRdec) + mB := z*(y*NTSCr) + mC := z*(y*NTSCr) + mD := z*(y*NTSCg) + mE := z*(y*NTSCg + sL + bLa + chnGdec) + mF := z*(y*NTSCg) + mG := z*(y*NTSCb) + mH := z*(y*NTSCb) + mI := z*(y*NTSCb + sL + bLa + chnBdec) + mtrx:= mA "|" mB "|" mC "| 0 |0" + . "|" mD "|" mE "|" mF "| 0 |0" + . "|" mG "|" mH "|" mI "| 0 |0" + . "| 0 | 0 | 0 |" aL "|0" + . "|" G "|" G "|" G "| 0 |1" + } Else + { + z := (bL<1) ? bL : 1 + tR := NTSCr - 0.5 + bL/2 + tG := NTSCg - 0.5 + bL/2 + tB := NTSCb - 0.5 + bL/2 + rB := z*(tR*sLi+bL*(1 - sLi) + chnRdec) + gB := z*(tG*sLi+bL*(1 - sLi) + chnGdec) + bB := z*(tB*sLi+bL*(1 - sLi) + chnBdec) ; Formula used: A*w + B*(1 – w) + rF := z*(NTSCr*sLi + (bL/2 - 0.5)*sLi) + gF := z*(NTSCg*sLi + (bL/2 - 0.5)*sLi) + bF := z*(NTSCb*sLi + (bL/2 - 0.5)*sLi) + + rB := rB*z+rF*(1 - z) + gB := gB*z+gF*(1 - z) + bB := bB*z+bF*(1 - z) ; Formula used: A*w + B*(1 – w) + If (rB<0) + rB := 0 + If (gB<0) + gB := 0 + If (bB<0) + bB := 0 + If (rF<0) + rF := 0 + + If (gF<0) + gF := 0 + + If (bF<0) + bF := 0 + + ; ToolTip, % rB " - " rF " --- " gB " - " gF + mtrx:= rB "|" rF "|" rF "| 0 |0" + . "|" gF "|" gB "|" gF "| 0 |0" + . "|" bF "|" bF "|" bB "| 0 |0" + . "| 0 | 0 | 0 |" aL "|0" + . "|" G "|" G "|" G "| 0 |1" + ; matrix adjusted for lisibility + } + matrix := StrReplace(mtrx, A_Space) + } Else If (modus=0) ; personalized hue, saturation and brightness + { + s1 := contrast ; in this mode, contrast stands for hue + s2 := saturation + s3 := bright + aL := alph + + s1 := s2*sin(s1) + sc := 1-s2 + r := NTSCr*sc-s1 + g := NTSCg*sc-s1 + b := NTSCb*sc-s1 + + rB := r+s2+3*s1 + gB := g+s2+3*s1 + bB := b+s2+3*s1 + mtrx := rB "|" r "|" r "| 0 |0" + . "|" g "|" gB "|" g "| 0 |0" + . "|" b "|" b "|" bB "| 0 |0" + . "| 0 | 0 | 0 |" aL "|0" + . "|" s3 "|" s3 "|" s3 "| 0 |1" + matrix := StrReplace(mtrx, A_Space) + } Else If (modus=7) + { + mtrx := "0|0|0|0|0" + . "|0|0|0|0|0" + . "|0|0|0|0|0" + . "|1|1|1|25|0" + . "|0|0|0|0|1" + matrix := StrReplace(mtrx, A_Space) + } + Return matrix +} + +Gdip_CompareBitmaps(pBitmapA, pBitmapB, accuracy:=25) { +; On success, it returns the percentage of similarity between the given pBitmaps. +; If the given pBitmaps do not have the same resolution, +; the return value is -1. +; +; Function by Tic, from June 2010 +; Source: https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-27 +; +; Warning: it can be very slow with really large images and high accuracy. +; +; Updated and modified by Marius Șucan in September 2019. +; Added accuracy factor. + + If (accuracy>99) + accuracy := 100 + Else If (accuracy<5) + accuracy := 5 + + Gdip_GetImageDimensions(pBitmapA, WidthA, HeightA) + Gdip_GetImageDimensions(pBitmapB, WidthB, HeightB) + If (accuracy!=100) + { + pBitmap1 := Gdip_ResizeBitmap(pBitmapA, Floor(WidthA*(accuracy/100)), Floor(HeightA*(accuracy/100)), 0, 5) + pBitmap2 := Gdip_ResizeBitmap(pBitmapB, Floor(WidthB*(accuracy/100)), Floor(HeightB*(accuracy/100)), 0, 5) + } Else + { + pBitmap1 := pBitmapA + pBitmap2 := pBitmapB + } + + Gdip_GetImageDimensions(pBitmap1, Width1, Height1) + Gdip_GetImageDimensions(pBitmap2, Width2, Height2) + if (!Width1 || !Height1 || !Width2 || !Height2 + || Width1 != Width2 || Height1 != Height2) + Return -1 + + E1 := Gdip_LockBits(pBitmap1, 0, 0, Width1, Height1, Stride1, Scan01, BitmapData1) + E2 := Gdip_LockBits(pBitmap2, 0, 0, Width2, Height2, Stride2, Scan02, BitmapData2) + z := 0 + Loop %Height1% + { + y++ + Loop %Width1% + { + Gdip_FromARGB(Gdip_GetLockBitPixel(Scan01, A_Index-1, y-1, Stride1), A1, R1, G1, B1) + Gdip_FromARGB(Gdip_GetLockBitPixel(Scan02, A_Index-1, y-1, Stride2), A2, R2, G2, B2) + z += Abs(A2-A1) + Abs(R2-R1) + Abs(G2-G1) + Abs(B2-B1) + } + } + + Gdip_UnlockBits(pBitmap1, BitmapData1), Gdip_UnlockBits(pBitmap2, BitmapData2) + If (accuracy!=100) + { + Gdip_DisposeImage(pBitmap1) + Gdip_DisposeImage(pBitmap2) + } + Return z/(Width1*Width2*3*255/100) +} + +Gdip_RetrieveBitmapChannel(pBitmap, channel) { + + ; Channel to retrive: + ; 1 - Red + ; 2 - Green + ; 3 - Blue + ; 4 - Alpha + ; On success, the function will return a pBitmap + ; in 32-ARGB PixelFormat containing a grayscale + ; rendition of the retrieved channel. + + + Gdip_GetImageDimensions(pBitmap, imgW, imgH) + If (!imgW || !imgH) + Return + + If (channel=1) + matrix := GenerateColorMatrix(3) + Else If (channel=2) + matrix := GenerateColorMatrix(4) + Else If (channel=3) + matrix := GenerateColorMatrix(5) + Else If (channel=4) + matrix := GenerateColorMatrix(7) + Else Return + + newBitmap := Gdip_CreateBitmap(imgW, imgH) + If !newBitmap + Return + + G := Gdip_GraphicsFromImage(newBitmap, 7) + Gdip_GraphicsClear(G, "0xff000000") + Gdip_DrawImage(G, pBitmap, 0, 0, imgW, imgH, 0, 0, imgW, imgH, matrix) + Gdip_DeleteGraphics(G) + Return newBitmap +} + +Gdip_RenderPixelsOpaque(pBitmap, pBrush:=0, alphaLevel:=0) { +; alphaLevel - from 0 [transparent] to 1 or beyond [opaque] +; +; This function is meant to make opaque partially transparent pixels. +; It returns a pointer to a new pBitmap. +; +; If pBrush is given, the background of the image is filled using it, +; otherwise, the pixels that are 100% transparent +; might remain transparent. + + Gdip_GetImageDimensions(pBitmap, imgW, imgH) + newBitmap := Gdip_CreateBitmap(imgW, imgH) + G := Gdip_GraphicsFromImage(newBitmap) + Gdip_SetInterpolationMode(G, 7) + If alphaLevel + matrix := GenerateColorMatrix(0, 0, 0, 1, alphaLevel) + Else + matrix := GenerateColorMatrix(0, 0, 0, 1, 25) + If pBrush + Gdip_FillRectangle(G, pBrush, 0, 0, imgW, imgH) + + Gdip_DrawImage(G, pBitmap, 0, 0, imgW, imgH, 0, 0, imgW, imgH, matrix) + Gdip_DeleteGraphics(G) + Return newBitmap +} + +Gdip_TestBitmapUniformity(pBitmap, HistogramFormat:=3, ByRef maxLevelIndex:=0, ByRef maxLevelPixels:=0) { +; This function tests whether the given pBitmap +; is in a single shade [color] or not. + +; If HistogramFormat parameter is set to 3, the function +; retrieves the intensity/gray histogram and checks +; how many pixels are for each level [0, 255]. +; +; If all pixels are found at a single level, +; the return value is 1, because the pBitmap is considered +; uniform, in a single shade. +; +; One can set the HistogramFormat to 4 [R], 5 [G], 6 [B] or 7 [A] +; to test for the uniformity of a specific channel. +; +; A threshold value of 0.0005% of all the pixels, is used. +; This is to ensure that a few pixels do not change the status. + + LevelsArray := [] + maxLevelIndex := maxLevelPixels := nrPixels := 9 + Gdip_GetImageDimensions(pBitmap, Width, Height) + Gdip_GetHistogram(pBitmap, HistogramFormat, LevelsArray, 0, 0) + Loop 256 + { + nrPixels := Round(LevelsArray[A_Index - 1]) + If (nrPixels>0) + histoList .= nrPixels "." A_Index - 1 "|" + } + Sort histoList, NURD| + histoList := Trim(histoList, "|") + histoListSortedArray := StrSplit(histoList, "|") + maxLevel := StrSplit(histoListSortedArray[1], ".") + maxLevelIndex := maxLevel[2] + maxLevelPixels := maxLevel[1] + ; ToolTip, % maxLevelIndex " -- " maxLevelPixels " | " histoListSortedArray[1] "`n" histoList, , , 3 + pixelsThreshold := Round((Width * Height) * 0.0005) + 1 + If (Floor(histoListSortedArray[2])> whichChannel; + int alpha2 = (invert==1) ? 255 - alpha : alpha; + imageData[px] = (alpha2 << 24) | (imageData[px] & 0x00ffffff); + } + } + } else { + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + px = x+y*w; + unsigned char a = imageData[px] >> 24; + unsigned char alpha = maskData[px] >> whichChannel; + int alpha2 = alpha - (255-a); // handles bitmaps that already have alpha + if (alpha2<0) { + alpha2 = 0; + } + + if (invert==1) { + alpha2 = 255 - alpha2; + } + imageData[px] = (alpha2 << 24) | (imageData[px] & 0x00ffffff); + } + } + } + return 1; +} +*/ + + static mCodeFunc := 0 + if (mCodeFunc=0) + { + if (A_PtrSize=8) + base64enc := " + (LTrim Join + 2,x64:QVdBVkFVQVRVV1ZTRItsJGhJicuLTCR4SInWg/kBD4TZAQAAg/kCD4SyAAAAg/kDD4TRAQAAg/kEuBgAAAAPRMiDfCRwAQ+EowAAAEWFwA+OZgEAAEWNcP9NY8Ax7UG8/wAAAEqNHIUAAAAAMf9mkEWFyX5YQYP9AQ+E2QAAAEyNB + K0AAAAAMdIPH4AAAAAAR4sUA0KLBAZFidfT+EHB7xgPtsBCjYQ4Af///4XAD0jHQYHi////AIPCAcHgGEQJ0EOJBANJAdhBOdF1w0iNRQFMOfUPhOEAAABIicXrkYN8JHABuQgAAAAPhV3///9FhcAPjsMAAABBjXj/TWPAMdtOjRSFAAAA + AA8fgAAAAABFhcl+MUGD/QEPhLEAAABIjQSdAAAAAEUxwGYPH0QAAIsUBkGDwAHT+kGIVAMDTAHQRTnBdepIjUMBSDnfdGxIicPrvA8fQABIjRStAAAAAEUxwA8fRAAARYsUE4sEFkWJ19P4QcHvGA+2wEKNhDgB////RYnnhcAPSMdBgeL + ///8AQYPAAUEpx0SJ+MHgGEQJ0EGJBBNIAdpFOcF1ukiNRQFMOfUPhR////+4AQAAAFteX11BXEFdQV5BX8MPHwBIjRSdAAAAAEUxwA8fRAAAiwQWQYPAAdP499BBiEQTA0wB0kU5wXXo6Un///+5EAAAAOk6/v//McnpM/7//w== + )" + else + base64enc := " + (LTrim Join + 2,x86:VVdWU4PsBIN8JDABD4T1AQAAg3wkMAIPhBwBAACDfCQwAw+E7AEAAIN8JDAEuBgAAAAPRUQkMIlEJDCDfCQsAQ+EBgEAAItUJCCF0g+OiQAAAItEJCDHBCQAAAAAjSyFAAAAAI10JgCLRCQkhcB+XosEJItcJBgx/400hQAAAAAB8wN0JByDfCQ + oAXRjjXYAixOLBg+2TCQw0/iJ0cHpGA+2wI2ECAH///+5AAAAAIXAD0jBgeL///8Ag8cBAe7B4BgJwokTAes5fCQkdcKDBCQBiwQkOUQkIHWNg8QEuAEAAABbXl9dw420JgAAAACQixOLBg+2TCQw0/iJ0cHpGA+2wI2ECAH///+5AAAAAIXAD0jBuf8A + AACB4v///wAB7oPHASnBicjB4BgJwokTAes5fCQkdbnrlYN8JCwBx0QkMAgAAAAPhfr+//+LTCQghcl+hzH/i0QkIItsJCSJPCSLTCQwjTSFAAAAAI10JgCF7X42g3wkKAGLBCR0Sot8JByNFIUAAAAAMdsB1wNUJBiNtCYAAAAAiweDwwEB99P4iEIDA + fI53XXugwQkAYsEJDlEJCB1uYPEBLgBAAAAW15fXcONdCYAi1wkHMHgAjHSAcMDRCQYiceNtCYAAAAAiwODwgEB89P499CIRwMB9znVdeyDBCQBiwQkOUQkIA+Fa////+uwx0QkMBAAAADpJ/7//8dEJDAAAAAA6Rr+//8= + )" + + ; FileRead, base64enc, E:\Sucan twins\_small-apps\AutoHotkey\other scripts\MCode4GCC-master\temp-mcode.txt + mCodeFunc := Gdip_RunMCode(base64enc) + } + + ; thisStartZeit := A_TickCount + Gdip_GetImageDimensions(pBitmap, w, h) + Gdip_GetImageDimensions(pBitmapMask, w2, h2) + If (w2!=w || h2!=h || !pBitmap || !pBitmapMask) + Return 0 + + Gdip_LockBits(pBitmap, 0, 0, w, h, stride, iScan, iData) + Gdip_LockBits(pBitmapMask, 0, 0, w, h, stride, mScan, mData) + r := DllCall(mCodeFunc, "UPtr", iScan, "UPtr", mScan, "Int", w, "Int", h, "Int", invertAlphaMask, "Int", replaceSourceAlphaChannel, "Int", whichChannel) + Gdip_UnlockBits(pBitmapMask, mData) + Gdip_UnlockBits(pBitmap, iData) + ; ToolTip, % A_TickCount - thisStartZeit, , , 2 + return r +} + +Gdip_BlendBitmaps(pBitmap, pBitmap2Blend, blendMode) { +/* +pBitmap and pBitmap2Blend must be the same width and height +and in 32-ARGB format: PXF32ARGB - 0x26200A. + +Original code: +int blendBitmaps(int *bgrImageData, int *otherData, int w, int h, int blendMode) { + float rT, gT, bT; // these must be INT for x32, to not crashes + int rO, gO, bO, rB, gB, bB; + unsigned char rF, gF, bF, aB, aO, aX; + for (int x = 0; x < w; x++) + { + for (int y = 0; y < h; y++) + { + unsigned int BGRcolor = bgrImageData[x+(y*w)]; + if (BGRcolor!=0x0) + { + unsigned int colorO = otherData[x+(y*w)]; + aO = (colorO >> 24) & 0xFF; + aB = (BGRcolor >> 24) & 0xFF; + aX = (aO> 16) & 0xFF; + gO = (colorO >> 8) & 0xFF; + bO = colorO & 0xFF; + + rB = (BGRcolor >> 16) & 0xFF; + gB = (BGRcolor >> 8) & 0xFF; + bB = BGRcolor & 0xFF; + + if (blendMode==1) { // darken + rT = (rO < rB) ? rO : rB; + gT = (gO < gB) ? gO : gB; + bT = (bO < bB) ? bO : bB; + } else if (blendMode==2) { // multiply + rT = (rO * rB)/255; + gT = (gO * gB)/255; + bT = (bO * bB)/255; + } else if (blendMode==3) { // linear burn + rT = ((rO + rB - 255) < 0) ? 0 : rO + rB - 255; + gT = ((gO + gB - 255) < 0) ? 0 : gO + gB - 255; + bT = ((bO + bB - 255) < 0) ? 0 : bO + bB - 255; + } else if (blendMode==4) { // color burn + rT = (255 - ((255 - rB) * 255) / (1 + rO) < 1) ? 0 : 255 - ((255 - rB) * 255) / (1 + rO); + gT = (255 - ((255 - gB) * 255) / (1 + gO) < 1) ? 0 : 255 - ((255 - gB) * 255) / (1 + gO); + bT = (255 - ((255 - bB) * 255) / (1 + bO) < 1) ? 0 : 255 - ((255 - bB) * 255) / (1 + bO); + } else if (blendMode==5) { // lighten + rT = (rO > rB) ? rO : rB; + gT = (gO > gB) ? gO : gB; + bT = (bO > bB) ? bO : bB; + } else if (blendMode==6) { // screen + rT = 255 - (((255 - rO) * (255 - rB))/255); + gT = 255 - (((255 - gO) * (255 - gB))/255); + bT = 255 - (((255 - bO) * (255 - bB))/255); + } else if (blendMode==7) { // linear dodge [add] + rT = ((rO + rB) > 255) ? 255 : rO + rB; + gT = ((gO + gB) > 255) ? 255 : gO + gB; + bT = ((bO + bB) > 255) ? 255 : bO + bB; + } else if (blendMode==8) { // hard light + rT = (rO < 127) ? (2 * rO * rB)/255 : 255 - ((2 * (255 - rO) * (255 - rB))/255); + gT = (gO < 127) ? (2 * gO * gB)/255 : 255 - ((2 * (255 - gO) * (255 - gB))/255); + bT = (bO < 127) ? (2 * bO * bB)/255 : 255 - ((2 * (255 - bO) * (255 - bB))/255); + } else if (blendMode==9) { // overlay + rT = (rB < 127) ? (2 * rO * rB)/255 : 255 - ((2 * (255 - rO) * (255 - rB))/255); + gT = (gB < 127) ? (2 * gO * gB)/255 : 255 - ((2 * (255 - gO) * (255 - gB))/255); + bT = (bB < 127) ? (2 * bO * bB)/255 : 255 - ((2 * (255 - bO) * (255 - bB))/255); + } else if (blendMode==10) { // hard mix + rT = (rO <= (255 - rB)) ? 0 : 255; + gT = (gO <= (255 - gB)) ? 0 : 255; + bT = (bO <= (255 - bB)) ? 0 : 255; + } else if (blendMode==11) { // linear light + rT = ((rB + (2*rO) - 255) > 254) ? 255 : rB + (2*rO) - 255; + gT = ((gB + (2*gO) - 255) > 254) ? 255 : gB + (2*gO) - 255; + bT = ((bB + (2*bO) - 255) > 254) ? 255 : bB + (2*bO) - 255; + } else if (blendMode==12) { // color dodge + rT = ((rB * 255) / (256 - rO) > 255) ? 255 : (rB * 255) / (256 - rO); + gT = ((gB * 255) / (256 - gO) > 255) ? 255 : (gB * 255) / (256 - gO); + bT = ((bB * 255) / (256 - bO) > 255) ? 255 : (bB * 255) / (256 - bO); + } else if (blendMode==13) { // vivid light + if (rO < 128) + rT = (255 - ((255 - rB) * 255) / (1 + 2*rO) < 1) ? 0 : 255 - ((255 - rB) * 255) / (1 + 2*rO); + else + rT = ((rB * 255) / (2*(256 - rO)) > 255) ? 255 : (rB * 255) / (2*(256 - rO)); + + if (gO < 128) + gT = (255 - ((255 - gB) * 255) / (1 + 2*gO) < 1) ? 0 : 255 - ((255 - gB) * 255) / (1 + 2*gO); + else + gT = ((gB * 255) / (2*(256 - gO)) > 255) ? 255 : (gB * 255) / (2*(256 - gO)); + + if (bO < 128) + bT = (255 - ((255 - bB) * 255) / (1 + 2*bO) < 1) ? 0 : 255 - ((255 - bB) * 255) / (1 + 2*bO); + else + bT = ((bB * 255) / (2*(256 - bO)) > 255) ? 255 : (bB * 255) / (2*(256 - bO)); + + } else if (blendMode==14) { // division + rT = ((rB * 255) / (1 + rO) > 255) ? 255 : (rB * 255) / (1 + rO); + gT = ((gB * 255) / (1 + gO) > 255) ? 255 : (gB * 255) / (1 + gO); + bT = ((bB * 255) / (1 + bO) > 255) ? 255 : (bB * 255) / (1 + bO); + } else if (blendMode==15) { // exclusion + rT = rO + rB - 2*((rO * rB)/255); + gT = gO + gB - 2*((gO * gB)/255); + bT = bO + bB - 2*((bO * bB)/255); + } else if (blendMode==16) { // difference + rT = (rO > rB) ? rO - rB : rB - rO; + gT = (gO > gB) ? gO - gB : gB - gO; + bT = (bO > bB) ? bO - bB : bB - bO; + } else if (blendMode==17) { // substract + rT = ((rB - rO) <= 0) ? 0 : rB - rO; + gT = ((gB - gO) <= 0) ? 0 : gB - gO; + bT = ((bB - bO) <= 0) ? 0 : bB - bO; + } else if (blendMode==18) { // inverted difference + rT = (rO > rB) ? 255 - rO - rB : 255 - rB - rO; + gT = (gO > gB) ? 255 - gO - gB : 255 - gB - gO; + bT = (bO > bB) ? 255 - bO - bB : 255 - bB - bO; + } + + if (blendMode!=10) { + if (rT<0) + rT += 255; + if (gT<0) + gT += 255; + if (bT<0) + bT += 255; + + if (rT<0) + rT = 0; + if (gT<0) + gT = 0; + if (bT<0) + bT = 0; + } + + rF = rT; + gF = gT; + bF = bT; + bgrImageData[x+(y*w)] = (aX << 24) | ((rF & 0xFF) << 16) | ((gF & 0xFF) << 8) | (bF & 0xFF); + } + } + } + return 1; +} +*/ + + static mCodeFunc := 0 + if (mCodeFunc=0) + { + if (A_PtrSize=8) + base64enc := " + (LTrim Join + 2,x64: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 + )" + else + base64enc := " + (LTrim Join + 2,x86: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 + QkDOkJ9/// + )" + ; FileRead, base64enc, E:\Sucan twins\_small-apps\AutoHotkey\other scripts\MCode4GCC-master\temp-mcode.txt + + mCodeFunc := Gdip_RunMCode(base64enc) + } + + Gdip_GetImageDimensions(pBitmap, w, h) + Gdip_GetImageDimensions(pBitmap2Blend, w2, h2) + If (w2!=w || h2!=h || !pBitmap || !pBitmap2Blend) + Return 0 + + Gdip_LockBits(pBitmap, 0, 0, w, h, stride, iScan, iData) + Gdip_LockBits(pBitmap2Blend, 0, 0, w, h, stride, mScan, mData) + ; thisStartZeit := A_TickCount + r := DllCall(mCodeFunc, "UPtr", iScan, "UPtr", mScan, "Int", w, "Int", h, "Int", blendMode) + ; ToolTip, % A_TickCount - thisStartZeit, , , 2 + ; ToolTip, % r " = r" , , , 2 + Gdip_UnlockBits(pBitmap2Blend, mData) + Gdip_UnlockBits(pBitmap, iData) + return r +} + +Gdip_BoxBlurBitmap(pBitmap, passes) { +; the blur will be applied on the provided pBitmap +/* +C/C++ function by Tic: +https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-30 + +void BoxBlurBitmap(unsigned char * Bitmap, int w, int h, int Stride, int Passes) +{ + int A1, R1, G1, B1, A2, R2, G2, B2, A3, R3, G3, B3; + for (int i = 0; i < Passes; ++i) + { + for (int y = 0; y < h*Stride; y += Stride) + { + A1 = R1 = G1 = B1 = A2 = R2 = G2 = B2 = 0; + for (int x = 0 ; x < w; ++x) + { + A3 = Bitmap[3+(4*x)+y]; + R3 = Bitmap[2+(4*x)+y]; + G3 = Bitmap[1+(4*x)+y]; + B3 = Bitmap[(4*x)+y]; + + Bitmap[3+(4*x)+y] = (A1+A2+A3)/3; + Bitmap[2+(4*x)+y] = (R1+R2+R3)/3; + Bitmap[1+(4*x)+y] = (G1+G2+G3)/3; + Bitmap[(4*x)+y] = (B1+B2+B3)/3; + + A1 = A2; R1 = R2; G1 = G2; B1 = B2; A2 = A3; R2 = R3; G2 = G3; B2 = B3; + } + + A1 = R1 = G1 = B1 = A2 = R2 = G2 = B2 = 0; + for (int x = w-1 ; x >= 0; --x) + { + A3 = Bitmap[3+(4*x)+y]; + R3 = Bitmap[2+(4*x)+y]; + G3 = Bitmap[1+(4*x)+y]; + B3 = Bitmap[(4*x)+y]; + + Bitmap[3+(4*x)+y] = (A1+A2+A3)/3; + Bitmap[2+(4*x)+y] = (R1+R2+R3)/3; + Bitmap[1+(4*x)+y] = (G1+G2+G3)/3; + Bitmap[(4*x)+y] = (B1+B2+B3)/3; + + A1 = A2; R1 = R2; G1 = G2; B1 = B2; A2 = A3; R2 = R3; G2 = G3; B2 = B3; + } + } + + for (int x = 0; x < w; ++x) + { + A1 = R1 = G1 = B1 = A2 = R2 = G2 = B2 = 0; + for (int y = 0; y < h*Stride; y += Stride) + { + A3 = Bitmap[3+(4*x)+y]; + R3 = Bitmap[2+(4*x)+y]; + G3 = Bitmap[1+(4*x)+y]; + B3 = Bitmap[(4*x)+y]; + + Bitmap[3+(4*x)+y] = (A1+A2+A3)/3; + Bitmap[2+(4*x)+y] = (R1+R2+R3)/3; + Bitmap[1+(4*x)+y] = (G1+G2+G3)/3; + Bitmap[(4*x)+y] = (B1+B2+B3)/3; + + A1 = A2; R1 = R2; G1 = G2; B1 = B2; A2 = A3; R2 = R3; G2 = G3; B2 = B3; + } + + A1 = R1 = G1 = B1 = A2 = R2 = G2 = B2 = 0; + for (int y = (h-1)*Stride; y >= 0; y -= Stride) + { + A3 = Bitmap[3+(4*x)+y]; + R3 = Bitmap[2+(4*x)+y]; + G3 = Bitmap[1+(4*x)+y]; + B3 = Bitmap[(4*x)+y]; + + Bitmap[3+(4*x)+y] = (A1+A2+A3)/3; + Bitmap[2+(4*x)+y] = (R1+R2+R3)/3; + Bitmap[1+(4*x)+y] = (G1+G2+G3)/3; + Bitmap[(4*x)+y] = (B1+B2+B3)/3; + + A1 = A2; R1 = R2; G1 = G2; B1 = B2; A2 = A3; R2 = R3; G2 = G3; B2 = B3; + } + } + } +} + +*/ + + static mCodeFunc := 0 + if (mCodeFunc=0) + { + + if (A_PtrSize=8) + base64enc := " + (LTrim Join + 2,x64:QVdBVkFVQVRVV1ZTSIPsWESLnCTAAAAASImMJKAAAABEicCJlCSoAAAARImMJLgAAABFhdsPjtoDAABEiceD6AHHRCQ8AAAAAEG+q6qqqkEPr/lBD6/BiXwkBInXg+8BiUQkJIn4iXwkOEiNdIEESPfYSIl0JEBIjTSFAAAAAI0EvQAAAABJY/lImEiJdCRISI1EBvxIiXwkCEiJRCQwRInI99hImEiJRCQQDx9EAABIi0QkQMdEJCAAAAAASIlEJBhIi0QkSEiD6ARIiUQkKItEJASFwA+OegEAAA8fQABEi4wkqAAAAEWFyQ+OPwMAAEiLRCQoTIt8JBgx9jHbRTHbRTHSRTHJRTHATAH4Mckx0mYPH0QAAEWJ1UQPtlADRYn + cRA+2WAJEAepEAeGJ3Q+2WAFEAdJBAeiJ9w+2MEkPr9ZBAflIg8AESMHqIYhQ/0KNFBlEieFJD6/WSMHqIYhQ/kGNFBhBiehJD6/WSMHqIYhQ/UGNFDFBiflJD6/WSMHqIYhQ/ESJ6kw5+HWJi3wkOEiLRCQwMfYx20gDRCQYRTHbRTHSRTHJRTHAMckx0g8fgAAAAABFiddED7ZQA0WJ3UQPtlgCRAH6RAHpQYncD7ZYAUQB0kUB4In1D7YwSQ+v1kEB6YPvAUiD6ARIweohiFAHQo0UGUSJ6UkPr9ZIweohiFAGQY0UGEWJ4EkPr9ZIweohiFAFQY0UMUGJ6UkPr9ZIweohiFAERIn6g///dYWLvCS4AAAASItcJAgBfCQgi0QkIEgB + XCQYO0QkBA+Miv7//0SLhCSoAAAAx0QkGAMAAADHRCQgAAAAAEWFwA+OiAEAAGYPH4QAAAAAAItUJASF0g+OpAAAAEhjRCQYMf8x9jHbSAOEJKAAAABFMdtFMdIxyUUxyUUxwDHSkEWJ10QPthBFid1ED7ZY/0QB+kQB6UGJ3A+2WP5EAdJFAeCJ9Q+2cP1JD6/WQQHpA7wkuAAAAEjB6iGIEEKNFBlEielJD6/WSMHqIYhQ/0GNFBhFieBJD6/WSMHqIYhQ/kGNFDFBielJD6/WSMHqIYhQ/UgDRCQIRIn6O3wkBHyAi0wkJIXJD4ioAAAATGNUJCRIY0QkGDH/MfYx20Ux20UxyUUxwEwB0DHJSAOEJKAAAAAx0g8fQABFid9ED7YYQ + YndD7ZY/0QB+kQB6UGJ9A+2cP5EAdpFAeCJ/Q+2eP1JD6/WQQHpSMHqIYgQjRQZSItMJBBJD6/WSQHKSMHqIYhQ/0GNFDBFieBJD6/WSMHqIYhQ/kGNFDlBielJD6/WSMHqIYhQ/UgByESJ+kSJ6UWF0nmEg0QkIAGLRCQgg0QkGAQ5hCSoAAAAD4WB/v//g0QkPAGLRCQ8OYQkwAAAAA+Fm/z//0iDxFhbXl9dQVxBXUFeQV/DZi4PH4QAAAAAAESLVCQ4RYXSD4j1/f//6Uz9//8= + )" + else + base64enc := " + (LTrim Join + 2,x86:VVdWU4PsPItsJGCLRCRYhe0PjncEAACLfCRcx0QkNAAAAAAPr/iD6AEPr0QkXIl8JCSLfCRUiUQkLItEJFCD7wGJfCQwi3wkVI0EuIlEJDiLRCQ4x0QkKAAAAACJRCQgi0QkJIXAD47pAQAAjXQmAIt0JFSF9g+OJAQAAMdEJAwAAAAAi0wkKDHtMf/HRCQYAAAAAANMJFAx9jHAx0QkFAAAAADHRCQQAAAAAI10JgCLVCQMD7ZZA4k0JIPBBA+2cf6JfCQEiVQkHAHCD7Z5/QHaiVwkDLurqqqqidCJbCQID7Zp/Pfji1wkEAMcJNHqiFH/idq7q6qqqgHyidD344tcJBQDXCQE0eqIUf6J2rurqqqqAfqJ0Pfj0eqIUf2LVCQ + YA1QkCAHqidD344scJItEJByJXCQQi1wkBNHqiVwkFItcJAiIUfyJXCQYO0wkIA+FWf///4tEJDDHBCQAAAAAMe0x/8dEJBwAAAAAi0wkIDH2x0QkGAAAAADHRCQUAAAAAIlEJAQxwI22AAAAAIscJA+2Uf+JdCQIg+kED7ZxAol8JAyJFCSNFBgDFCSJ0LqrqqqqD7Z5AYlsJBD34g+2KYNsJAQB0eqIUQOLVCQUA1QkCAHyidC6q6qqqvfi0eqIUQKLVCQYA1QkDAH6idC6q6qqqvfi0eqIUQGLVCQcA1QkEAHqidC6q6qqqvfiidiLXCQIiVwkFItcJAzR6ogRi1QkBIlcJBiLXCQQiVwkHIP6/w+FVf///4t8JFwBfCQoAXwkIItE + JCg7RCQkD4wb/v//i0QkUItcJFTHRCQoAAAAAPfYiUQkDIXbD44IAgAAjXQmAJCLVCQkhdIPjugAAAAx9otMJAzHRCQIAAAAADHtx0QkGAAAAAAx/zHAx0QkFAAAAAD32cdEJBAAAAAAiTQkjXYAi1QkCA+2cQOJfCQEixwkD7Z5AYlUJCABwgHyiXQkCL6rqqqqidCJXCQcD7ZZAvfmi3QkHItEJBCJHCSJ6w+2KQHwiXQkEIt0JAzR6ohRA4sUJAHCidC6q6qqqvfii0QkFANEJATR6ohRAonCAfqJ0Lqrqqqq9+KLRCQYiVwkGAHY0eqIUQGJwgHqidC6q6qqqvfii0QkINHqiBGLVCQEA0wkXIlUJBSNFDE5VCQkD49M////i0wkL + IXJD4jrAAAAMfbHRCQQAAAAAItMJCwx7cdEJBwAAAAAK0wkDDH/McDHRCQYAAAAAMdEJBQAAAAAiTQkjXQmAJCLHCSLVCQQiXwkBA+2cQMPtnkBiWwkCIlcJCAPtlkCiXQkEA+2KYkcJInTAcIB8r6rqqqqidD35ot0JCCLRCQUAfCJdCQUi3QkDNHqiFEDixQkAcKJ0Lqrqqqq9+KLRCQYA0QkBNHqiFECicIB+onQuquqqqr34otEJBwDRCQI0eqIUQGJwgHqidC6q6qqqvfiidjR6ogRi1QkBCtMJFyJVCQYi1QkCAHOiVQkHA+JTf///4NEJCgBi0QkKINsJAwEOUQkVA+F/f3//4NEJDQBi0QkNDlEJGAPhcL7//+DxDxbXl9dw4 + 20JgAAAACNdgCLfCQwhf8PiI/9///ppvz//w== + )" + + mCodeFunc := Gdip_RunMCode(base64enc) + } + + Gdip_GetImageDimensions(pBitmap,w,h) + Gdip_LockBits(pBitmap,0,0,w,h,stride,iScan,iData) + r := DllCall(mCodeFunc, "UPtr",iScan, "Int",w, "Int",h, "Int",stride, "Int",passes) + Gdip_UnlockBits(pBitmap,iData) + ; DllCall("GlobalFree", "ptr", mCodeFunc) + return r +} + +Gdip_RunMCode(mcode) { + static e := {1:4, 2:1} + , c := (A_PtrSize=8) ? "x64" : "x86" + + if (!regexmatch(mcode, "^([0-9]+),(" c ":|.*?," c ":)([^,]+)", m)) + return + + if (!DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", StrLen(m3), "uint", e[m1], "ptr", 0, "uintp", s, "ptr", 0, "ptr", 0)) + return + + p := DllCall("GlobalAlloc", "uint", 0, "ptr", s, "ptr") + ; if (c="x64") + DllCall("VirtualProtect", "ptr", p, "ptr", s, "uint", 0x40, "uint*", op) + + if (DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", StrLen(m3), "uint", e[m1], "ptr", p, "uint*", s, "ptr", 0, "ptr", 0)) + return p + + DllCall("GlobalFree", "ptr", p) +} + +calcIMGdimensions(imgW, imgH, givenW, givenH, ByRef ResizedW, ByRef ResizedH) { +; This function calculates from original imgW and imgH +; new image dimensions that maintain the aspect ratio +; and are within the boundaries of givenW and givenH. +; +; imgW, imgH - original image width and height [in pixels] +; givenW, givenH - the width and height to adapt to [in pixels] +; ResizedW, ResizedH - the width and height resulted from adapting imgW, imgH to givenW, givenH +; by keeping the aspect ratio + + PicRatio := Round(imgW/imgH, 5) + givenRatio := Round(givenW/givenH, 5) + If (imgW <= givenW) && (imgH <= givenH) + { + ResizedW := givenW + ResizedH := Round(ResizedW / PicRatio) + If (ResizedH>givenH) + { + ResizedH := (imgH <= givenH) ? givenH : imgH + ResizedW := Round(ResizedH * PicRatio) + } + } Else If (PicRatio > givenRatio) + { + ResizedW := givenW + ResizedH := Round(ResizedW / PicRatio) + } Else + { + ResizedH := (imgH >= givenH) ? givenH : imgH ;set the maximum picture height to the original height + ResizedW := Round(ResizedH * PicRatio) + } +} + +GetWindowRect(hwnd, ByRef W, ByRef H) { + ; function by GeekDude: https://gist.github.com/G33kDude/5b7ba418e685e52c3e6507e5c6972959 + ; W10 compatible function to find a window's visible boundaries + ; modified by Marius Șucanto return an array + size := VarSetCapacity(rect, 16, 0) + er := DllCall("dwmapi\DwmGetWindowAttribute" + , "UPtr", hWnd ; HWND hwnd + , "UInt", 9 ; DWORD dwAttribute (DWMWA_EXTENDED_FRAME_BOUNDS) + , "UPtr", &rect ; PVOID pvAttribute + , "UInt", size ; DWORD cbAttribute + , "UInt") ; HRESULT + + If er + DllCall("GetWindowRect", "UPtr", hwnd, "UPtr", &rect, "UInt") + + r := [] + r.x1 := NumGet(rect, 0, "Int"), r.y1 := NumGet(rect, 4, "Int") + r.x2 := NumGet(rect, 8, "Int"), r.y2 := NumGet(rect, 12, "Int") + r.w := Abs(max(r.x1, r.x2) - min(r.x1, r.x2)) + r.h := Abs(max(r.y1, r.y2) - min(r.y1, r.y2)) + W := r.w + H := r.h + ; ToolTip, % r.w " --- " r.h , , , 2 + Return r +} + +Gdip_BitmapConvertGray(pBitmap, hue:=0, vibrance:=-40, brightness:=1, contrast:=0, KeepPixelFormat:=0) { +; hue, vibrance, contrast and brightness parameters +; influence the resulted new grayscale pBitmap. +; +; KeepPixelFormat can receive a specific PixelFormat. +; The function returns a pointer to a new pBitmap. + + Gdip_GetImageDimensions(pBitmap, Width, Height) + If (KeepPixelFormat=1) + PixelFormat := Gdip_GetImagePixelFormat(pBitmap, 1) + If StrLen(KeepPixelFormat)>3 + PixelFormat := KeepPixelFormat + + newBitmap := Gdip_CreateBitmap(Width, Height, PixelFormat) + G := Gdip_GraphicsFromImage(newBitmap, InterpolationMode) + If (hue!=0 || vibrance!=0) + pEffect := Gdip_CreateEffect(6, hue, vibrance, 0) + + matrix := GenerateColorMatrix(2, brightness, contrast) + If pEffect + { + E := Gdip_DrawImageFX(G, pBitmap, 0, 0, 0, 0, Width, Height, matrix, pEffect) + Gdip_DisposeEffect(pEffect) + } Else + E := Gdip_DrawImage(G, pBitmap, 0, 0, Width, Height, 0, 0, Width, Height, matrix) + + Gdip_DeleteGraphics(G) + Return newBitmap +} + +Gdip_BitmapSetColorDepth(pBitmap, bitsDepth, useDithering:=1) { +; Return 0 = OK - Success + + ditheringMode := (useDithering=1) ? 9 : 1 + If (useDithering=1 && bitsDepth=16) + ditheringMode := 2 + + Colors := 2**bitsDepth + If bitsDepth Between 2 and 4 + bitsDepth := "40s" + If bitsDepth Between 5 and 8 + bitsDepth := "80s" + + If (bitsDepth="BW") + E := Gdip_BitmapConvertFormat(pBitmap, 0x30101, ditheringMode, 2, 2, 2, 2, 0, 0) + Else If (bitsDepth=1) + E := Gdip_BitmapConvertFormat(pBitmap, 0x30101, ditheringMode, 1, 2, 1, 2, 0, 0) + Else If (bitsDepth="40s") + E := Gdip_BitmapConvertFormat(pBitmap, 0x30402, ditheringMode, 1, Colors, 1, Colors, 0, 0) + Else If (bitsDepth="80s") + E := Gdip_BitmapConvertFormat(pBitmap, 0x30803, ditheringMode, 1, Colors, 1, Colors, 0, 0) + Else If (bitsDepth=16) + E := Gdip_BitmapConvertFormat(pBitmap, 0x21005, ditheringMode, 1, Colors, 1, Colors, 0, 0) + Else If (bitsDepth=24) + E := Gdip_BitmapConvertFormat(pBitmap, 0x21808, 2, 1, 0, 0, 0, 0, 0) + Else If (bitsDepth=32) + E := Gdip_BitmapConvertFormat(pBitmap, 0x26200A, 2, 1, 0, 0, 0, 0, 0) + Else + E := -1 + Return E +} + +Gdip_BitmapConvertFormat(pBitmap, PixelFormat, DitherType, DitherPaletteType, PaletteEntries, PaletteType, OptimalColors, UseTransparentColor:=0, AlphaThresholdPercent:=0) { + + ; pBitmap - Handle to a pBitmap object on which the color conversion is applied. + + ; PixelFormat options: see Gdip_GetImagePixelFormat() + ; Pixel format constant that specifies the new pixel format. + + ; PaletteEntries Number of Entries. + ; OptimalColors - Integer that specifies the number of colors you want to have in an optimal palette based on a specified pBitmap. + ; This parameter is relevant if PaletteType parameter is set to PaletteTypeOptimal [1]. + ; UseTransparentColor Boolean value that specifies whether to include the transparent color in the palette. + ; AlphaThresholdPercent - Real number in the range 0.0 through 100.0 that specifies which pixels in the source bitmap will map to the transparent color in the converted bitmap. + ; + ; PaletteType options: + ; Custom = 0 ; Arbitrary custom palette provided by caller. + ; Optimal = 1 ; Optimal palette generated using a median-cut algorithm. + ; FixedBW = 2 ; Black and white palette. + ; + ; Symmetric halftone palettes. Each of these halftone palettes will be a superset of the system palette. + ; e.g. Halftone8 will have its 8-color on-off primaries and the 16 system colors added. With duplicates removed, that leaves 16 colors. + ; FixedHalftone8 = 3 ; 8-color, on-off primaries + ; FixedHalftone27 = 4 ; 3 intensity levels of each color + ; FixedHalftone64 = 5 ; 4 intensity levels of each color + ; FixedHalftone125 = 6 ; 5 intensity levels of each color + ; FixedHalftone216 = 7 ; 6 intensity levels of each color + ; + ; Assymetric halftone palettes. These are somewhat less useful than the symmetric ones, but are included for completeness. + ; These do not include all of the system colors. + ; FixedHalftone252 = 8 ; 6-red, 7-green, 6-blue intensities + ; FixedHalftone256 = 9 ; 8-red, 8-green, 4-blue intensities + ; + ; DitherType options: + ; None = 0 + ; Solid = 1 + ; - it picks the nearest matching color with no attempt to halftone or dither. May be used on an arbitrary palette. + ; + ; Ordered dithers and spiral dithers must be used with a fixed palette. + ; NOTE: DitherOrdered4x4 is unique in that it may apply to 16bpp conversions also. + ; Ordered4x4 = 2 + ; Ordered8x8 = 3 + ; Ordered16x16 = 4 + ; Ordered91x91 = 5 + ; Spiral4x4 = 6 + ; Spiral8x8 = 7 + ; DualSpiral4x4 = 8 + ; DualSpiral8x8 = 9 + ; ErrorDiffusion = 10 ; may be used with any palette + ; Return 0 = OK - Success + + VarSetCapacity(hPalette, 4 * PaletteEntries + 8, 0) + + ; tPalette := DllStructCreate("uint Flags; uint Count; uint ARGB[" & $iEntries & "];") + NumPut(PaletteType, &hPalette, 0, "uint") + NumPut(PaletteEntries, &hPalette, 4, "uint") + NumPut(0, &hPalette, 8, "uint") + + Static Ptr := "UPtr" + E1 := DllCall("gdiplus\GdipInitializePalette", "UPtr", &hPalette, "uint", PaletteType, "uint", OptimalColors, "Int", UseTransparentColor, Ptr, pBitmap) + E2 := DllCall("gdiplus\GdipBitmapConvertFormat", Ptr, pBitmap, "uint", PixelFormat, "uint", DitherType, "uint", DitherPaletteType, "uPtr", &hPalette, "float", AlphaThresholdPercent) + E := E1 ? E1 : E2 + Return E +} + +Gdip_GetImageThumbnail(pBitmap, W, H) { +; by jballi, source +; https://www.autohotkey.com/boards/viewtopic.php?style=7&t=70508 + + DllCall("gdiplus\GdipGetImageThumbnail" + ,"UPtr",pBitmap ;-- *image + ,"UInt",W ;-- thumbWidth + ,"UInt",H ;-- thumbHeight + ,"UPtr*",pThumbnail ;-- **thumbImage + ,"UPtr",0 ;-- callback + ,"UPtr",0) ;-- callbackData + + Return pThumbnail +} + +; ================================================= +; The following functions were written by Tidbit +; handed to me by himself to be included here. +; ================================================= + +ConvertRGBtoHSL(R, G, B) { +; http://www.easyrgb.com/index.php?X=MATH&H=18#text18 + SetFormat, float, 0.5 ; for some reason I need this for some colors to work. + + R := (R / 255) + G := (G / 255) + B := (B / 255) + + Min := min(R, G, B) + Max := max(R, G, B) + del_Max := Max - Min + + L := (Max + Min) / 2 + + if (del_Max = 0) + { + H := S := 0 + } else + { + if (L < 0.5) + S := del_Max / (Max + Min) + else + S := del_Max / (2 - Max - Min) + + del_R := (((Max - R) / 6) + (del_Max / 2)) / del_Max + del_G := (((Max - G) / 6) + (del_Max / 2)) / del_Max + del_B := (((Max - B) / 6) + (del_Max / 2)) / del_Max + + if (R = Max) + { + H := del_B - del_G + } else + { + if (G = Max) + H := (1 / 3) + del_R - del_B + else if (B = Max) + H := (2 / 3) + del_G - del_R + } + if (H < 0) + H += 1 + if (H > 1) + H -= 1 + } + ; return round(h*360) "," s "," l + ; return (h*360) "," s "," l + return [abs(round(h*360)), abs(s), abs(l)] +} + +ConvertHSLtoRGB(H, S, L) { +; http://www.had2know.com/technology/hsl-rgb-color-converter.html + + H := H/360 + if (S == 0) + { + R := L*255 + G := L*255 + B := L*255 + } else + { + if (L < 0.5) + var_2 := L * (1 + S) + else + var_2 := (L + S) - (S * L) + var_1 := 2 * L - var_2 + + R := 255 * ConvertHueToRGB(var_1, var_2, H + (1 / 3)) + G := 255 * ConvertHueToRGB(var_1, var_2, H) + B := 255 * ConvertHueToRGB(var_1, var_2, H - (1 / 3)) + } + ; Return round(R) "," round(G) "," round(B) + ; Return (R) "," (G) "," (B) + Return [round(R), round(G), round(B)] +} + +ConvertHueToRGB(v1, v2, vH) { + vH := ((vH<0) ? ++vH : vH) + vH := ((vH>1) ? --vH : vH) + return ((6 * vH) < 1) ? (v1 + (v2 - v1) * 6 * vH) + : ((2 * vH) < 1) ? (v2) + : ((3 * vH) < 2) ? (v1 + (v2 - v1) * ((2 / 3) - vH) * 6) + : v1 +} + +Gdip_ErrrorHandler(errCode, throwErrorMsg, additionalInfo:="") { + Static errList := {1:"Generic_Error", 2:"Invalid_Parameter" + , 3:"Out_Of_Memory", 4:"Object_Busy" + , 5:"Insufficient_Buffer", 6:"Not_Implemented" + , 7:"Win32_Error", 8:"Wrong_State" + , 9:"Aborted", 10:"File_Not_Found" + , 11:"Value_Overflow", 12:"Access_Denied" + , 13:"Unknown_Image_Format", 14:"Font_Family_Not_Found" + , 15:"Font_Style_Not_Found", 16:"Not_TrueType_Font" + , 17:"Unsupported_GdiPlus_Version", 18:"Not_Initialized" + , 19:"Property_Not_Found", 20:"Property_Not_Supported" + , 21:"Profile_Not_Found", 100:"Unknown_Wrapper_Error"} + + If !errCode + Return + + aerrCode := (errCode<0) ? 100 : errCode + If errList.HasKey(aerrCode) + GdipErrMsg := "GDI+ ERROR: " errList[aerrCode] " [CODE: " aerrCode "]" additionalInfo + Else + GdipErrMsg := "GDI+ UNKNOWN ERROR: " aerrCode additionalInfo + + If (throwErrorMsg=1) + MsgBox, % GdipErrMsg + + Return GdipErrMsg +} \ No newline at end of file diff --git a/src/lib/SysC.ahk b/src/lib/SysC.ahk new file mode 100644 index 0000000..e0af773 --- /dev/null +++ b/src/lib/SysC.ahk @@ -0,0 +1,73 @@ +class SySC { + static COLOR_SCROLLBAR := 0 ; Scroll bar gray area.Windows 10 or greater: This value is not supported. + static COLOR_DESKTOP := 1 ; Desktop.Windows 10 or greater: This value is not supported. + static COLOR_BACKGROUND := 1 ; Desktop.Windows 10 or greater: This value is not supported. + static COLOR_ACTIVECAPTION := 2 ; Active window title bar.The associated foreground color is COLOR_CAPTIONTEXT. + ;Specifies the left side color in the color gradient of an active window's title bar if the gradient effect is enabled. + ;Windows 10 or greater: This value is not supported. + static COLOR_INACTIVECAPTION := 3 ; Inactive window caption.The associated foreground color is COLOR_INACTIVECAPTIONTEXT. + ;Specifies the left side color in the color gradient of an inactive window's title bar if the gradient effect is enabled. + ;Windows 10 or greater: This value is not supported. + static COLOR_MENU := 4 ; Menu background. The associated foreground color is COLOR_MENUTEXT.Windows 10 or greater: This value is not supported. + static COLOR_WINDOW := 5 ; Window background. The associated foreground colors are COLOR_WINDOWTEXT and COLOR_HOTLITE. + static COLOR_WINDOWFRAME := 6 ; Window frame.Windows 10 or greater: This value is not supported. + static COLOR_MENUTEXT := 7 ; Text in menus. The associated background color is COLOR_MENU.Windows 10 or greater: This value is not supported. + static COLOR_WINDOWTEXT := 8 ; Text in windows. The associated background color is COLOR_WINDOW. + static COLOR_CAPTIONTEXT := 9 ; Text in caption, size box, and scroll bar arrow box. The associated background color is COLOR_ACTIVECAPTION.Windows 10 or greater: This value is not supported. + static COLOR_ACTIVEBORDER := 10 ; Active window border.Windows 10 or greater: This value is not supported. + static COLOR_INACTIVEBORDER := 11 ; Inactive window border.Windows 10 or greater: This value is not supported. + static COLOR_APPWORKSPACE := 12 ; Background color of multiple document interface (MDI) applications.Windows 10 or greater: This value is not supported. + static COLOR_HIGHLIGHT := 13 ; Item(s) selected in a control. The associated foreground color is COLOR_HIGHLIGHTTEXT. + static COLOR_HIGHLIGHTTEXT := 14 ; Text of item(s) selected in a control. The associated background color is COLOR_HIGHLIGHT. + static COLOR_BTNFACE := 15 ; Face color for three-dimensional display elements and for dialog box backgrounds. The associated foreground color is COLOR_BTNTEXT.Windows 10 or greater: This value is not supported. + static COLOR_3DFACE := 15 ; Face color for three-dimensional display elements and for dialog box backgrounds. + static COLOR_BTNSHADOW := 16 ; Shadow color for three-dimensional display elements (for edges facing away from the light source).Windows 10 or greater: This value is not supported. + static COLOR_3DSHADOW := 16 ; Shadow color for three-dimensional display elements (for edges facing away from the light source).Windows 10 or greater: This value is not supported. + static COLOR_GRAYTEXT := 17 ; Grayed (disabled) text. This color is set to 0 if the current display driver does not support a solid gray color. + static COLOR_BTNTEXT := 18 ; Text on push buttons. The associated background color is COLOR_BTNFACE. + static COLOR_3DHIGHLIGHT := 20 ; Highlight color for three-dimensional display elements (for edges facing the light source.)Windows 10 or greater: This value is not supported. + static COLOR_BTNHIGHLIGHT := 20 ; Highlight color for three-dimensional display elements (for edges facing the light source.)Windows 10 or greater: This value is not supported. + static COLOR_BTNHILIGHT := 20 ; Highlight color for three-dimensional display elements (for edges facing the light source.)Windows 10 or greater: This value is not supported. + static COLOR_INACTIVECAPTIONTEXT := 19 ; Color of text in an inactive caption. The associated background color is COLOR_INACTIVECAPTION.Windows 10 or greater: This value is not supported. + static COLOR_3DHILIGHT := 20 ; Highlight color for three-dimensional display elements (for edges facing the light source.)Windows 10 or greater: This value is not supported. + static COLOR_3DDKSHADOW := 21 ; Dark shadow for three-dimensional display elements.Windows 10 or greater: This value is not supported. + static COLOR_3DLIGHT := 22 ; Light color for three-dimensional display elements (for edges facing the light source.)Windows 10 or greater: This value is not supported. + static COLOR_INFOTEXT := 23 ; Text color for tooltip controls. The associated background color is COLOR_INFOBK.Windows 10 or greater: This value is not supported. + static COLOR_INFOBK := 24 ; Background color for tooltip controls. The associated foreground color is COLOR_INFOTEXT.Windows 10 or greater: This value is not supported. + static COLOR_HOTLIGHT := 26 ; Color for a hyperlink or hot-tracked item. The associated background color is COLOR_WINDOW. + static COLOR_GRADIENTACTIVECAPTION := 27 ; Right side color in the color gradient of an active window's title bar. COLOR_ACTIVECAPTION specifies the left side color. Use SPI_GETGRADIENTCAPTIONS with the SystemParametersInfo function to determine whether the gradient effect is enabled.Windows 10 or greater: This value is not supported. + static COLOR_GRADIENTINACTIVECAPTION := 28 ; Right side color in the color gradient of an inactive window's title bar. COLOR_INACTIVECAPTION specifies the left side color.Windows 10 or greater: This value is not supported. + static COLOR_MENUHILIGHT := 29 ; The color used to highlight menu items when the menu appears as a flat menu (see SystemParametersInfo). The highlighted menu item is outlined with COLOR_HIGHLIGHT.Windows 2000, Windows 10 or greater: This value is not supported. + static COLOR_MENUBAR := 30 ; The background color for the menu bar when menus appear as flat menus (see SystemParametersInfo). However, COLOR_MENU continues to specify the background color of the menu popup.Windows 2000, Windows 10 or greater: This value is not supported. + ; + GetColor(n){ + Return this.BGRtoRGB(DllCall("User32.dll\GetSysColor", "Int", n, "UInt")) + } + BGRtoRGB(BGR){ + return Format("0x{:06X}", (BGR & 255) << 16 | (BGR & 65280) | (BGR >> 16)) + } + Invert(SX = 0x0011aa){ + lastformat:= A_FormatInteger + SetFormat, Integer, Hex + SX ^= 0xffffff + SetFormat, Integer, % lastformat + return SX + } + list(){ + for i,o in this + ((IsFunc(o)=0 and not i == "__Class")?info.=((IsFunc(o)=3) ? (" func: "): prop:=" property: ") i (IsFunc(o)=0?" = "o:"") IsFunc(o) "`n":"") + return info + } + demo(){ + Gui, -Caption +LastFound + Gui, Color, 0x808080 + Gui, Font, s6 + props:=[] + for i,o in this + ((i ~="^COLOR_")?(props.push(i)):) + loop, % count:=props.count() + Gui, Add, text, % "x" (((count/2) >= A_Index)?0:250) " y" (((count/2) >= A_Index)?0+((A_Index-1)*20):100+(((A_Index-count/2)-6)*20)) " c" (color:=this.GetColor(this[props[A_Index]]) ), % props[A_Index] "=" this[props[A_Index]] "=" color "`n" + Gui, show, autosize + } +} +outputdebug, % SySC.demo() diff --git a/src/lib/colorpicker.ahk b/src/lib/colorpicker.ahk deleted file mode 100644 index 6df1e9f..0000000 --- a/src/lib/colorpicker.ahk +++ /dev/null @@ -1,162 +0,0 @@ -colorpicker(){ - global - Gui, ColorPicker:Default - Gui, -MinimizeBox - local progressX:=0 - local progressY:=5 - local progressS:=50 - glable:="gColorPickerUpdate" - Gui, Add, Progress, % "x" progressX " y"progressY " w" progressS " h" progressS " +C0xFF0000 vProg", 100 - Gui, Add, Edit, % "x" (progressX+=progressS) " y" (progressY) " w" 70 " h20 vHex " glable, 0xFFFF0000 - Gui, Font, s9 - local buttony:=progressY - Gui, Add, Button, % "x" progressX " y" (buttony+=20) " w" 70 " h" 15, CopyRGB - Gui, Add, Button, % "x" progressX " y" (buttony+=15 )" w" 70 " h" 15, CopyAlpha - ;Gui, Add, Button, % "x" 165 " y" buttony " w75 h23", Close - rgbtX:=13 , rgbty:=buttony+25 - Gui, Font, s12 - Gui, Add, Text, % "x" rgbtX " y" rgbty " w20 h20 Center", R - Gui, Font, s9 - Gui, Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vR " glable, 255 - Gui, Font, s12 - Gui, Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", G - Gui, Font, s9 - Gui, Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vG " glable, 0 - Gui, Font, s12 - Gui, Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", B - Gui, Font, s9 - Gui, Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vB " glable, 0 - Gui, Font, s12 - Gui, Add, Text, % "x" (rgbtX+=25) " y"rgbty " w25 h25 Center", A - Gui, Font, s9 - Gui, Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vA " glable, 255 - local sliderh:=150 - local sliderw:=25 - local sliderx:=10 - local slidery:=rgbty+50 - options:=" TickInterval1 +Vertical +0x20 +0x200 +Vertical +Invert +Center +Range0-255 -Tabstop AltSubmit " glable - Gui, Add, Slider, % "x" sliderx " y" slidery " w" sliderw " h" sliderh options " vRS", 255 - Gui, Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vGS", 0 - Gui, Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vBS", 0 - Gui, Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vAS", 255 - Gui, Show,, % "Color Picker" - -} - -ColorPickerGuiEscape(){ - ColorPickerGuiClose() -} -ColorPickerGuiClose(){ - Gui, ColorPicker:Destroy -} -ColorPickerButtonClose(){ - ColorPickerGuiClose() -} -ColorPickerUpdate(){ - GuiControlGet, RS - GuiControlGet, GS - GuiControlGet, BS - GuiControlGet, AS - - GuiControlGet, R - GuiControlGet, G - GuiControlGet, B - GuiControlGet, A - GuiControlGet, Hex - GuiControlGet, Prog - - ColorPickerSet("R", RS) - ColorPickerSet("G", GS) - ColorPickerSet("B", BS) - ColorPickerSet("A", AS) - ColorPickerSet("RS", R, "+Range0-255") - ColorPickerSet("GS", G, "+Range0-255") - ColorPickerSet("BS", B, "+Range0-255") - ColorPickerSet("AS", A, "+Range1-255") - ColorPickerSet("Hex", ARGB(R, G, B, A)) - ColorPickerSet("Prog",, "+C" ARGB(R, G, B)) -} - -ColorPickerButtonCopyRGB(){ - GuiControlGet, Hex - return Clipboard:=SubStr(Hex, 5) -} -ColorPickerButtonCopyAlpha(){ - GuiControlGet, R - GuiControlGet, G - GuiControlGet, B - GuiControlGet, A - return clipboard:=SubStr(ARGB(R, G, B, A), 1 , 4) -} - -ARGB(R, G, B, A := 00) { - lastformat:=A_FormatInteger - SetFormat, Integer, Hex - ARGB:=(A << 24) | (R << 16) | (G << 8) | B - setformat, integer, % lastformat - Return ARGB -} - -ColorPickerSet(Control, Data := "", AddOpt := "") { - GuiControl, %AddOpt%, %Control%, % Data - return !ErrorLevel -} -RGB300(Val_0_300){ - ; aa 0-300 for full hue - Max := 255 - a2 := 0 - a3 := 0 - n := Round(max/50,0) - if (aa:=Val_0_300) between 1 and 50 - { - a1 := Color300(max) - ab := aa*n - a2 := Color300(ab) - a3 := Color300(0) - } - if aa between 51 and 100 - { - a2 := Color300(max) - ab := (max-aa)*n - a1 := Color300(ab) - a3 := Color300(0) - } - if aa between 101 and 150 - { - a2 := Color300(max) - ab := (aa-100)*n - a3 := Color300(ab) - a1 := Color300(0) - } - if aa between 151 and 200 - { - a3 := Color300(max) - ab := (max-(aa-150))*n - a2 := Color300(ab) - a1 := Color300(0) - } - if aa between 201 and 250 - { - a3 := Color300(max) - ab := (aa-200)*n - a1 := Color300(ab) - a2 := Color300(0) - } - if aa between 251 and 300 - { - a1 := Color300(max) - ab := (max-(aa-250))*n - a3 := Color300(ab) - a2 := Color300(0) - } - return a1 a2 a3 -} -Color300(N) { ; Function borrowed from Wicked (http://www.autohotkey.com/forum/viewtopic.php?t=57368&postdays=0&postorder=asc&start=0) - SetFormat, Integer, Hex - N += 0 - SetFormat, Integer, D - StringTrimLeft, N, N, 2 - If(StrLen(N) < 2) - N = 0%N% - Return N -} \ No newline at end of file diff --git a/src/localization.ahk b/src/localization.ahk index 6cc8d5f..fab703d 100644 --- a/src/localization.ahk +++ b/src/localization.ahk @@ -20,7 +20,7 @@ LoadLocalization(ByRef settings) { if (settings["locale"] == "") { locale := GetLocale() settings["locale"] := locale - writeIniVar("locale") + writeIniVar("locale", settings, defaultsettings) } else { locale := settings["locale"] } diff --git a/src/ui/gdip/BuffBarLayer.ahk b/src/ui/gdip/BuffBarLayer.ahk index 9a7803a..5c16290 100644 --- a/src/ui/gdip/BuffBarLayer.ahk +++ b/src/ui/gdip/BuffBarLayer.ahk @@ -67,8 +67,8 @@ class BuffBarLayer { this.locked := 1 settings["buffBarX"] := this.leftMargin settings["buffBarY"] := this.topMargin - writeIniVar("buffBarX") - writeIniVar("buffBarX") + writeIniVar("buffBarX", settings, 0) + writeIniVar("buffBarY", settings, 0) } checkHover(mouseX, mouseY) { diff --git a/src/ui/gdip/ItemCounterLayer.ahk b/src/ui/gdip/ItemCounterLayer.ahk index 2f20023..1dfae27 100644 --- a/src/ui/gdip/ItemCounterLayer.ahk +++ b/src/ui/gdip/ItemCounterLayer.ahk @@ -58,8 +58,8 @@ class ItemCounterLayer { this.locked := 1 settings["itemCounterX"] := this.leftMargin settings["itemCounterY"] := this.topMargin - writeIniVar("itemCounterX") - writeIniVar("itemCounterX") + writeIniVar("itemCounterX", settings, 0) + writeIniVar("itemCounterY", settings, 0) } drawItemCounter(ByRef HUDItems) { diff --git a/src/ui/helper.ahk b/src/ui/helper.ahk index 9280fb1..b7bc940 100644 --- a/src/ui/helper.ahk +++ b/src/ui/helper.ahk @@ -128,4 +128,102 @@ b64Decode(string) if !(DllCall("crypt32\CryptStringToBinary", "ptr", &string, "uint", 0, "uint", 0x1, "ptr", &buf, "uint*", size, "ptr", 0, "ptr", 0)) throw Exception("CryptStringToBinary failed", -1) return StrGet(&buf, size, "UTF-8") -} \ No newline at end of file +} + + + +ConvertD2H(var=255){ + lastformat:=A_FormatInteger + SetFormat, IntegerFast, hex + var:=((Var += 0) += 0) "" + SetFormat, IntegerFast, % lastformat + return var +} + +Strip0x(covered){ + return RegExReplace(covered, "0x(.*)","$1") +} + +ARGB(R, G, B, A=00){ + lastformat:=A_FormatInteger + SetFormat, Integer, Hex + ARGB:=(A << 24) | (R << 16) | (G << 8) | B + setformat, integer, % lastformat + Return ARGB +} + +RGB300(Val_0_300){ + ; aa 0-300 for full hue + Max := 255 + a2 := 0 + a3 := 0 + n := Round(max/50,0) + if (aa:=Val_0_300) between 1 and 50 + { + a1 := Color300(max) + ab := aa*n + a2 := Color300(ab) + a3 := Color300(0) + } + if aa between 51 and 100 + { + a2 := Color300(max) + ab := (max-aa)*n + a1 := Color300(ab) + a3 := Color300(0) + } + if aa between 101 and 150 + { + a2 := Color300(max) + ab := (aa-100)*n + a3 := Color300(ab) + a1 := Color300(0) + } + if aa between 151 and 200 + { + a3 := Color300(max) + ab := (max-(aa-150))*n + a2 := Color300(ab) + a1 := Color300(0) + } + if aa between 201 and 250 + { + a3 := Color300(max) + ab := (aa-200)*n + a1 := Color300(ab) + a2 := Color300(0) + } + if aa between 251 and 300 + { + a1 := Color300(max) + ab := (max-(aa-250))*n + a3 := Color300(ab) + a2 := Color300(0) + } + return a1 a2 a3 +} + +Color300(N){ ; Function borrowed from Wicked (http://www.autohotkey.com/forum/viewtopic.php?t=57368&postdays=0&postorder=asc&start=0) + SetFormat, Integer, Hex + N += 0 + SetFormat, Integer, D + StringTrimLeft, N, N, 2 + If (StrLen(N) < 2) + N = 0%N% + Return N +} + +Gdip_SizeObj(array,offsetratio=4){ + TextSA:=StrSplit(array, "|") + x:=TextSA.1 + y:=TextSA.2 + width:=TextSA.3 + height:=TextSA.4 + chars:=TextSA.5 + lines:=TextSA.6 + center:=TextSA.3/2 + charwidth:=width/chars + centeroffset:=((co:=((charwidth/offsetratio) * chars))?co:0) + obj:= {"x":x,"y":y,"width":width,"height":height,"chars":chars,"lines":lines,"center":center,"charwidth":charwidth,"centeroffset":centeroffset} + return obj +} diff --git a/src/ui/image/clearCache.ahk b/src/ui/image/clearCache.ahk index 4183d15..e075317 100644 --- a/src/ui/image/clearCache.ahk +++ b/src/ui/image/clearCache.ahk @@ -1,3 +1,7 @@ +#SingleInstance, Force +SendMode Input +SetWorkingDir, %A_ScriptDir% + ClearCache(folder) { files := 0 Loop Files, %folder%\*.png diff --git a/src/ui/map/Drawing.ahk b/src/ui/map/Drawing.ahk index 11d42bf..bca31f4 100644 --- a/src/ui/map/Drawing.ahk +++ b/src/ui/map/Drawing.ahk @@ -37,8 +37,8 @@ class Brushes { ; missiles missileOpacity := settings["missileOpacity"] - , physicalMajorColor := missileOpacity . settings["missilePhysicalMajorColor"] - , physicalMinorColor := missileOpacity . settings["missilePhysicalMinorColor"] + , physicalMajorColor := missileOpacity . settings["missileColorPhysicalMajor"] + , physicalMinorColor := missileOpacity . settings["missileColorPhysicalMinor"] , fireMajorColor := missileOpacity . settings["missileFireMajorColor"] , fireMinorColor := missileOpacity . settings["missileFireMinorColor"] , iceMajorColor := missileOpacity . settings["missileIceMajorColor"] diff --git a/src/ui/settingsPanel.ahk b/src/ui/settingsPanel.ahk index b3adebf081337209102131f60acb4854600f51c7..b695c85c64f2a16ba842b0971bbe1d1565305528 100644 GIT binary patch literal 111830 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 literal 87336 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 Date: Tue, 11 Oct 2022 20:33:32 -0700 Subject: [PATCH 05/12] Default settings display and revert --- src/d2r-map.ahk | 3 ++- src/ui/settingsPanel.ahk | Bin 111830 -> 112934 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/d2r-map.ahk b/src/d2r-map.ahk index e55c8cf..4910b2d 100644 --- a/src/d2r-map.ahk +++ b/src/d2r-map.ahk @@ -126,6 +126,7 @@ global redrawMap := 1 global offsets := [] global hudBitmaps := loadBitmaps() global buffBitmaps := loadBuffIcons() +global SettingsShow:=False CreateSettingsGUI() @@ -283,7 +284,7 @@ While 1 { mapGuis.downloadMapImages(mapList, gameMemoryData) mapLoading := 0 - Gui, LoadingText: Destroy ; remove loading text + SplashClose() redrawMap := 1 } diff --git a/src/ui/settingsPanel.ahk b/src/ui/settingsPanel.ahk index b695c85c64f2a16ba842b0971bbe1d1565305528..c3fd91f63d13732f4c1ce5ebdee9e6bad323f9e9 100644 GIT binary patch delta 836 zcmZva-%C?r7{{N-b9Q#BIp;P{y2_oYt>q>Re_#m8A`uFdS*t54C!5X~bF-tUge;0K zBEs>2?@bNtqRSw>7=(xvM0n*z?5c~=RY7$j{Q*7aU^5~Phxd8k_j$k1_x(I?^_%kQ zP}zuzt|Dq-1Lh$QAuwPVI{1sgN&rA=uNPVGP343I7^4~{IArb)q0ep$(vzO z%U~;g=+kI=Ko|L|sEF7)x=ZDgb{&$CgA^6)9*W9plg`@1tYyF=EJ0dqJ;qKEUq&y* zn&i@#N92-S^cJT|dn#!SRde{>FlG+DQo`E&Ec@&MOQVCfB)`-Fy5+TIxJe&(lnz{{ z(p)kLGmwQey^uPo_TEcJ+aflHnixu9i1wukDqeOCT!97t79j=WJf{daJCa8^uX<*c(cRS1HBLx0SyDDX>v9y;>j#J#n^px zHXfVo;m&Op&X_r(cn8~$kY%Vi;^P}yhm1MHtOkzabPN9OM^g{~Q*P9}Y zW1j8*59Z#cO8rth9S(M}o&~{X`JjT@c3i)x@T;hLDX*wB67n*cFEhKGswTHvlpGgbI-Sj&c#m9hKHZoQ8&8-H~wL4 zFk@4o-U$j^Yk9a9tgHnwKV&^QzV;67S6jtS67P!j8BA0@&0rj<=FuwU6!v4~YZ`w} F{06zn;K~31 delta 350 zcmXYrze@sf7{>4Q=U0>ntLwUs(0&nG;b0(25e^MPM}$L@Afa|vBxMFoK@D;=-0=?Y zA`uNii;KZEMMH>#L^MdFjWtC02S}GTJlp5_JkM>%(fV{~A>^YHh4w+BstR)$2Z1^& zOp=xY0qbyqtBnEr$pEv*IEBmN$IJ+w<$%%K28g(2N#UcVg%#@>ep!=$EeU0NiMpr2 zupS=lvCd_#$Q^RW1UmS!ZDqR3W10Ez*&*URllru56S3=*`;G$J!8W_;t%r1&!1tgB z;|(vq4n5Fb(Uhm$vk;{_6{c!e?s@hP@U_d~rUwH{A}&sQ>1hmjDB*$4UwiSdxX#N# zqa1`n6q_duBlajovY=5r3wcV!KyV+KN7H5$ZX44uPS*;El*mESsN`T1NZSP-tFC~v b$YnSaMtyx0eG8IdQy>f|0B=O{@GbuWd;E9J From 19c609943b3c465a9c39a6574c83df2036b8f75b Mon Sep 17 00:00:00 2001 From: Teo <106943092+t3ohm@users.noreply.github.com> Date: Wed, 12 Oct 2022 17:05:03 -0700 Subject: [PATCH 06/12] Settings Reset Added Default Color and Font color assigned for pop! Fixed Settings window show/hide so it show and hides correctly regardless of how it was accessed. --- src/init/readSettings.ahk | 6 ++++-- src/ui/settingsPanel.ahk | Bin 112934 -> 111784 bytes 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/init/readSettings.ahk b/src/init/readSettings.ahk index 22a0026..e5d6fe1 100644 --- a/src/init/readSettings.ahk +++ b/src/init/readSettings.ahk @@ -161,8 +161,10 @@ readSettings(settingsFile, ByRef settings) { settings["CustomSettings"] := 0 settings["InvertedColors"] := 0 - settings["WindowColor"] := SySC.GetColor(SySC.COLOR_WINDOW) - settings["FontColor"] := SySC.GetColor(SySC.COLOR_WINDOWTEXT) + ;settings["WindowColor"] := SySC.GetColor(SySC.COLOR_WINDOW) + settings["WindowColor"] := "2e2f30" + ;settings["FontColor"] := SySC.GetColor(SySC.COLOR_WINDOWTEXT) + settings["FontColor"] := "d1c18c" diff --git a/src/ui/settingsPanel.ahk b/src/ui/settingsPanel.ahk index c3fd91f63d13732f4c1ce5ebdee9e6bad323f9e9..1d91e25f43b43bf3aa516192209aba19a383d47a 100644 GIT binary patch delta 2264 zcma)7drXs86u+lHMOsSf3n&#zd8939YEfitDq}eDg@8=OG2|r*qA*~JaT+v43^4{c z3nwG71K+xh;l5=xaWT3q#y>O?w;4i=k;H%IAC4KbKg_o5d|x3H$2N0wzkAQ?cOLiN z^PPXLzW9r}$5WLrc8EGrB|Z|3qD_>FdeJPLyjw2bWp1NrWqF2Ze}z8q3f;zbdswrH zab#Ps@F>G24$`5c5Tj`qb{4kqH;HaWKs-JU2~XXi=*u2f^K27EOt-Q(J7aB~TFVHI zLgIpUk;AYu+r?s8#VHO<@yhT@WDMrs*7bH?xI}3>%!HTPzfdITjiDko+ZR1Q(t6ffYw?YpMGv z#9|R_rk)Dk+=4}cjY*Y-KZUKQ!-b$WCy5eHd#6~%<=w!=ZWA?P7f#HJ&&=S^OJs`W zHDb4%2**$*_KI3L_J6aBlI=F}q1ChA4$*>1;mN6UW##0293n`9>q3%493lsM!^|{! z6b$%-+JNX_?#j__26~yG3BGobi^Mxz&L%GW4&lU`?sYio zRw@wU6fSD&ldpOkZcmQ`7amNH$9_|P;ub#p z?P9&i6Yp`TrDCHfoxRKNX||<3P#~-V zBUK&&tsJ;Cxwte0Tb5phOpatJR%T_OE;|kO;Y8Lc$eQL!x@?CE2g~l`$UrEK+95&8 z&e@ho-CG!@!flaywi&{x(#Ut^#;028>GnPq7A?19d977?Qtehxiz2YHVTp9SJ~RRc z4?398Nsn7^sqoGk6F#mfr0b2~z_VBQAv7B#&;HKjfUgGwgI)#Cb5DmI;|A&BU2nia zfZ>o1k6MEn27Gu|Cx!lK31+59Cw`u#l_FWjW*Ab(ctsYZ;zXIb?_MYk8^H?c_+fDz zHkWIu%?M7vI~qDQMklw<>6h;cbV#~pgO&3F4bw?~+8{1|rhCq47btzyi%rGx465^Q zUI4$VFyEu6<^+iF*V&`*bLFiX__4NaT0W?3QVg(chTGG-YkJ4vAQLM!u z$aJt%dl*&}FrZ?mUi=czcHukpHNpz{6Oz>cAG3r0;1c%|Bg zjaCOLNhOK-14&ib?NTM$+re5`A363o+d{_HlG#pL^-A*^^RoH)mNFY#6-}r-JC8j` zxCjL!-uJS0)=IO-DWJHEzDfI!(Am9g(WEoOq*p^J&~Ay;2o)x87P2*LiS%v}exRg7 z7~fR<$#NIZ%qv3ey5esq&o|Mz^C@Zn5)YoMF3A1YUD6|Md|Pqh`RY8G8a%G#6j1`m zRo|2#%4O*5$kY~6jEHckZeB`}9gpXmDdYCsc5=Oi($hgn66u+ohH~uL<0pK!fp_rm z3Q$%|0ZlQZCGz}VaR_%c)<$L%4&u3a1)_d9kklZI@{8NR1`&Kwaq;Jxz>%_!YSc?X z996tY8s*`0Wf6@*?9nKw8U-)Sbl`x;mR!zCSrI?93JQ2*FW5$A*!bcdU`vk^T!cA? zC_FP`7S=VXG9C64PBA7jnmKJg@sMp6wkaN|63<{fBYdCsrXY9 zQasn6D>U!#lC+GIQzT$2IhT^GkAA}4PNHo*Rf%(qb%b?M0t#-j+9Y?vl5WP0lJ&at z|JKVlxstLT@q_H%Hgcx#|4`+Y?0x9&d`g2VtD7uK!gn--OC~j52Nh}L-7d($aJh=7 z({r%-HY;j2gt5ORS^GNDSIae&%iL(_; zSjf262WH%82}!_v7IJ!?ich6E(Uw*$Wz}i-$nmMPrN%lNucpCA#> zY;WiTGltUmpY5RHxWj^ti!FH2U5oCyRU1~vPNuWg|{@u*7HbQKj z+L9)7l)A`2+m=S3B;k$d{Oibf5ov@8pAI>)@c4`MBSk)aX!fAWt2Tp&H?IJ*_m+2r zuL(j{=8Zt(M;o1$_gG;T|EwQudLZuz@CB7ng`vPW_MUgZUHXiI1Hhx%u=Hfn51`iu z>yoglumrcyeUAVc*jW~m>r-V~%2rlOIb47{3TNR&=^*Y3R^f12Q0(ic%6ujq@T<5z z*Uqn2fal~L!CaiExFRpfL9bH}Eq5g2u2BvDSXqY+tBbL7Rkr@^W7Q^fzpmllrh1)( zW{DVYtIECyJZ^Fj0Jn1Ud%{S}K-6MWpd>2^xunU~JZBMkE_s^v7 z_V7oABcHo5^oc|N`NMKkT!pls1^J8^M^M5@~2KiI&sk#SM=!%F1ih2 z!xsYT)5j)mNQOUBaQtiS2Gsd=ZB;coE};3qP{ zH9OvT`>5U<er?Oy9jp|4!v2`m34fR{a^B8|$G{TvxM1);JUggP`o7J%B^QWW zK4O&MeguE*_Gc|4mbJ3YWHmy2f{`I&U_C$60{OA`o8g*C_J9$ag>PR2)|ADPlYLm$ z>c#LL2S42cmAv^F1n@EyS3uGY2pJK?eQ=LofUN1yh$WlLip9tmc0iH*Z}lB@Lvz56 zb*2oLFh7TtNnjjaObP^#&25FFZXSIBl-Q+yxMaoC6=pvC9A$!JdsF2OFX3=DW_}42 z5EqsQ_rX^*abt5(IB?hJE1X1N*_rFTVnze~33? zNlt(l9)PGk#%;>b9-Y$Z@@K~9`y9M`8#jI%Q9F`kB1M9!r0A=U3 Date: Wed, 12 Oct 2022 17:20:24 -0700 Subject: [PATCH 07/12] RGB picker Added --- src/ui/settingsPanel.ahk | Bin 111784 -> 112462 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/ui/settingsPanel.ahk b/src/ui/settingsPanel.ahk index 1d91e25f43b43bf3aa516192209aba19a383d47a..5f76118b05e7632ab2140b76013725fe771a6fde 100644 GIT binary patch delta 437 zcmZ4SlI`3(whc;Blh+AxO%8D5nmkX&X0nXF(d1=PdhEpv84URh<5M{?cbW2;7c-PFBm!|JLo$N`Loh@qLjahc&5+7a1QfMmumzH7Ky^6` z#XvD$2Cm5)O~p-7^&;zWVkiZgkOMRqL-)jq!jg&%8You4l}}D&krYh^Iz9)8ix>(J z&Y0d9$0(_Y-42lZLV(Ik8B(WT%x09H{wt2LL>n9iDAs_~DPr>@$lA#pRJo=LtY*|< z4PtO-aGIW<$Y?wL!8}HZ>H88Hr6zAMVPUMDo;aOx@8k|4waM#5c($9(V7ws23=E9v qfhmlV(;uv66q??$nsE)g2hiCmK)0-4!>BlY!A3^D?Kx{0Z8!j(esPHa delta 131 zcmX^2j%~$Dwhc;B({IgZ Date: Wed, 12 Oct 2022 18:46:18 -0700 Subject: [PATCH 08/12] removed Sys demo from outputdebug removing leftovers --- src/lib/SysC.ahk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/SysC.ahk b/src/lib/SysC.ahk index e0af773..a6b1ed6 100644 --- a/src/lib/SysC.ahk +++ b/src/lib/SysC.ahk @@ -69,5 +69,4 @@ Gui, Add, text, % "x" (((count/2) >= A_Index)?0:250) " y" (((count/2) >= A_Index)?0+((A_Index-1)*20):100+(((A_Index-count/2)-6)*20)) " c" (color:=this.GetColor(this[props[A_Index]]) ), % props[A_Index] "=" this[props[A_Index]] "=" color "`n" Gui, show, autosize } -} -outputdebug, % SySC.demo() +} From 4328eb6d5fcd17da1a4bf67a5f8635fb3e277072 Mon Sep 17 00:00:00 2001 From: Teo <106943092+t3ohm@users.noreply.github.com> Date: Wed, 12 Oct 2022 19:24:32 -0700 Subject: [PATCH 09/12] Split Settings up Seperated Settings panel file into panel and tabs --- src/ui/settingsPanel.ahk | Bin 112462 -> 22372 bytes src/ui/settingsTabs.ahk | 632 +++++++++++++++++++++++++++++++++++++++ src/ui/splash/splash.ahk | 7 + 3 files changed, 639 insertions(+) create mode 100644 src/ui/settingsTabs.ahk diff --git a/src/ui/settingsPanel.ahk b/src/ui/settingsPanel.ahk index 5f76118b05e7632ab2140b76013725fe771a6fde..a8815fc3ac91ae3abcc05c00f29ed40d8ac092ba 100644 GIT binary patch delta 132 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 diff --git a/src/ui/settingsTabs.ahk b/src/ui/settingsTabs.ahk new file mode 100644 index 0000000..d8520e8 --- /dev/null +++ b/src/ui/settingsTabs.ahk @@ -0,0 +1,632 @@ + +OpacitySlide(){ + GuiControlGet, Opac + GuiControl, , missileOpacity, % Format("0x{:X}", Opac) + SettingsUpdateFlag() +} + +PathSlide(){ + GuiControlGet, PathcolorSlide + GuiControl, , pathFindingColour, % RGB300(PathcolorSlide) + SettingsUpdateFlag() +} + +Colorslide(){ + Gui, Settings:Default + lastformat:=A_FormatInteger + SetFormat, IntegerFast, Hex + GuiControlGet, SliderRed + GuiControlGet, SliderGreen + GuiControlGet, SliderBlue + + if StrLen(R:=Strip0x(ConvertD2H(SliderRed))) < 2 + R:=0 R + if StrLen(G:=Strip0x(ConvertD2H(SliderGreen))) < 2 + G:=0 G + if StrLen(B:=Strip0x(ConvertD2H(SliderBlue))) < 2 + B:=0 B + StringUpper, R, R + StringUpper, G, G + StringUpper, B, B + SetFormat, IntegerFast, hex + if selected:=RadioSelect(Projectilelist()){ + GuiControl % "+Background" R G B , % selected "preview" + + misslecontrol:="missile" selected "Color" + OutputDebug, % rcheck:=selected "Rcheck" + colorRGB:="+c" R G B + GuiControl % colorRGB , % rcheck + GuiControl,, % rcheck , % selected + + GuiControl % colorRGB , % misslecontrol + GuiControl, , % misslecontrol, % R G B + } + SetFormat, IntegerFast, % lastformat + SettingsUpdateFlag() +} + +RadioToSliders(){ + GuiControlGet, RBG,, % "missile" RadioSelect(Projectilelist()) "Color" + GuiControl,, SliderRed , % R:=(R:="0x" SubStr(RBG, 1, 2))+0 + GuiControl,, SliderGreen , % G:=(G:="0x" SubStr(RBG, 3, 2))+0 + GuiControl,, SliderBlue , % B:=(B:="0x" SubStr(RBG, 5, 2))+0 + SettingsUpdateFlag() +} + + + +RadioSelect(Rlist){ + lastformat:=A_FormatInteger + for each,Radio in (Rlist) + { + Selected = %Radio%Rcheck + GuiControlGet,controlvar,, %Selected% + if (controlvar) + { + SetFormat, integer, D + Selected:=RegExReplace(Selected,"(.*)Rcheck$","$1") + SetFormat, integer, % lastformat + return Selected + } + } +} + +DiscordLink(){ + run, % "https://discord.com/invite/qEgqyVW3uj" +} +ReadMeLink(){ + run, % "https://github.com/joffreybesos/d2r-mapview#readme" +} + +Projectilelist(){ + return ["PhysicalMajor","PhysicalMinor","FireMajor","FireMinor","IceMajor","IceMinor" + ,"LightMajor","LightMinor","PoisonMajor","PoisonMinor","MagicMajor","MagicMinor"] +} + +TabTitles(){ + return "Info|General|Map Items|Game Data|NPCs|Immunities|Item Filter|Hotkeys|Other|Projectiles|Advanced" +} + +SettingDefault(setting){ + return (settings[setting]?settings[setting]:defaultSettings[setting]) +} + +SettingsTabInfo(x,y){ + global + Gui, Settings:+labelSettings + Gui, Settings:Default + Gui, Tab, Info + local (InfoX:=x) , (InfoY:=y) + + Gui, Add, Picture, % "x" (InfoX-20) " y" 59 " w" 370 " h" 320, % settings.SplashImg + ;Gui, Add, Text, % "c" 0xff0000 " x" (SettingsAnchorX+20) " y" (InfoY+=20) " w" 300 " h" 250 " +Center Backgroundtrans", d2r-mapview %version% + + ;Gui, Add, Text, % "c" UniqueColor " x" (SettingsAnchorX+15) " y" (InfoY+=56) " w" 300 " h" 120 " +Center Backgroundtrans", % localizedStrings["uitext"] ;what is this? + local locale := settings["locale"] + local choiceIdx := LocaleToChoice(locale) + Gui, Add, Button, % "x" (SettingsAnchorX+90) " y" (SettingsAnchorY+311) " h" 23 "Backgroundtrans AltSubmit vRevertDefaults gRevertToDefaults", Default All Settings + Gui, Add, DropDownList, % "x" (SettingsAnchorX+220) " y" (SettingsAnchorY+311) " h" 180 (" Choose" choiceIdx) "Backgroundtrans AltSubmit vlocaleIdx gSettingsUpdateFlag", English|中文|Deutsch|español|français|italiano|한국어|polski|español mexicano|日本語|português|Русский|福佬話 + Gui, Font, % "s" SettingsD2RFontSize + Gui, Add, Link, % " c" 0x00FF00 " x" (SettingsAnchorX) " y" (SettingsAnchorY+339) " w" 100 " h" 30 " gReadMeLink", Github + Gui, Add, Link, % "c" 0xff0000 " x" (SettingsAnchorX+130) " y" (SettingsAnchorY+339) " w"100 " h" 30 " gDiscordLink", v%version% + Gui, Add, Link, % " c" 0x00FF00 " x" (SettingsAnchorX+260) " y" (SettingsAnchorY+339) " w"100 " h" 30 " gDiscordLink", Discord + Gui, Font, % "s" SettingFontsize1 +} + +SettingsTabGeneral(x,y){ + global + Gui, Settings:Default + Gui, Tab, General + local (mapserverX:=x),(mapserverY:=y),(mapserverW:=),(mapserverH:=),(mapserverW:=20),(mapserverH:=20) + Gui, Add, GroupBox, % "c" UniqueColor " x" mapserverX " y" mapserverY " w" 340 " h" 80 , % localizedStrings["s3"] ;mapserver + Gui, Add, Edit, % "c" EditColor " x" (mapserverX+=18) " y" (mapserverY+=20) " w300 vBaseUrl gSettingsUpdateFlag" , settings.baseUrl + Gui, Add, Text, % "c" disabledfont " x" (mapserverX+=1) " y" (mapserverY+=25) " w180" , % "Ex: http://localhost:3002`nhttp://192.168.1.123:3002" + + local (MapPosX:=SettingsAnchorX), (MapPosY:=mapserverY+71), (MapPosW:=0), (MapPosH:=0) + Gui, Add, GroupBox, % "c" UniqueColor " x" MapPosX " y" MapPosY " w340 h80", % MapPos:="Map Position" + Gui, Add, DropDownList, % "x" (MapPosX+10) " y" (MapPosY+20) " w" 140 " h" 80 " vmapPosition gSettingsUpdateFlag", + Gui, Add, Checkbox, % "c" UniqueColor " x" (MapPosX+180) " y" (MapPosY+25) " w" 135 " h" 20 " vAlwaysShowMap gSettingsUpdateFlag", % "Always show map" + Gui, Add, Checkbox, % "c" UniqueColor " x" (MapPosX+10) " y" (MapPosY+45) " w" 135 " h" 20 " vHideTown gSettingsUpdateFlag", % "Hide town maps" + + local (CenPosX:=SettingsAnchorX), (CenPosY:=MapPosY+85), (CenPosW:=), (CenPosH:=) + Gui, Add, GroupBox, % "c" UniqueColor " x" CenPosX " y" CenPosY " w" 340 " h" 80, % "Centered position settings" + local (CenCol4:=(CenCol3:=(CenCol2:=(CenCol1:=CenPosX+10)+50)+115)+50) + local (CenRow4:=(CenRow3:=(CenRow2:=(CenRow1:=CenPosY+20)+5)+15)+5) + Gui, Add, Edit, % "c" EditColor " x" CenCol1 " y" CenRow1 " w" 44 " h" 20 " vcenterModeScale gSettingsUpdateFlag" + Gui, Add, Edit, % "c" EditColor " x" CenCol1 " y" CenRow3 " w" 44 " h" 20 " vcenterModeOpacity gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CenCol2 " y" CenRow2 " w" 80 " h" 15, % "Centered Scale" + Gui, Add, Text, % "c" UniqueColor " x" CenCol2 " y" CenRow4 " w" 80 " h" 15, % "Center Opacity (0-1)" + Gui, Add, Edit, % "c" EditColor " x" CenCol3 " y" CenRow1 " w" 44 " h" 20 " vcenterModeOffsetX gSettingsUpdateFlag" + Gui, Add, Edit, % "c" EditColor " x" CenCol3 " y" CenRow3 " w" 44 " h" 20 " vcenterModeOffsetY gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CenCol4 " y" CenRow2 " w" 80 " h" 15, % "X offset" + Gui, Add, Text, % "c" UniqueColor " x" CenCol4 " y" CenRow4 " w" 80 " h" 15, % "Y offset" + + local (CorPosX:=SettingsAnchorX), (CorPosY:=CenRow4) + Gui, Add, GroupBox, % "c" UniqueColor " x" CorPosX " y" (CorPosY+40) " w" 340 " h" 80, % "Corner position settings" + local (CorCol4:=(CorCol3:=(CorCol2:=(CorCol1:=CorPosX+10)+50)+115)+50) + local (CorRow4:=(CorRow3:=(CorRow2:=(CorRow1:=CorPosY+60)+5)+15)+5) + Gui, Add, Edit, % "c" EditColor " x" CorCol1 " y" CorRow1 " w" 44 " h" 20 " vcornerModeScale gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CorCol2 " y" CorRow2 " w" 80 " h" 15, % "Corner Scale" + Gui, Add, Edit, % "c" EditColor " x" CorCol1 " y" CorRow3 " w" 44 " h20 vcornerModeOpacity gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CorCol2 " y" CorRow4 " w" 80 " h" 15, % "Corner Opacity (0-1)" + Gui, Add, Edit, % "c" EditColor " x" CorCol3 " y" CorRow1 " w" 44 " h" 20 " vcornerModeOffsetX gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CorCol4 " y" CorRow2 " w" 80 " h" 15, % "X offset" + Gui, Add, Edit, % "c" EditColor " x" CorCol3 " y" CorRow3 " w" 44 " h" 20 " vcornerModeOffsetY gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CorCol4 " y" CorRow4 " w" 80 " h" 15, % "Y offset" +} + +SettingsTabMapItems(x,y){ + global + Gui, Settings:Default + Gui, Tab, Map Items + local (MapItemX:=x),(MapItemY:=y) + local (MapItemCol4:=(MapItemCol3:=(MapItemCol2:=(MapItemCol1:=MapItemX+12)+140)+53)+50) + local (PortalRow4:=(PortalRow3:=(PortalRow2:=(PortalRow1:=y+20)+5)+15)+5) + Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" MapItemY " w" 340 " h" (PortalsGroupH:=70), % localizedStrings["s25"] + Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" PortalRow1 " w" 140 " h" 20 " vShowPortals gSettingsUpdateFlag", % localizedStrings["s26"] ;True + Gui, Add, Edit, % " c" EditColor " x" (PortalColorx:=MapItemCol2) " y" (PortalColory:=PortalRow1) " w" (PortalColorwidth:=50) " h" 20 " vPortalColor gSettingsUpdateFlag", 00AAFF + Gui, Add, Text, % "c" SettingDefault("PortalColor") " x" (PortalColorx+PortalColorwidth+5) " y" (PortalColory+3) " h" 20, % localizedStrings["s27"] + Gui, Add, Edit, % "c" EditColor " x" (RPortalColorx:=MapItemCol2) " y" (RedPortalColory:=PortalRow1+20) " w" 50 " h" 20 " vRedPortalColor gSettingsUpdateFlag", FF0000 + Gui, Add, Text, % "c" SettingDefault("RedPortalColor") " x" (RPortalColorx+PortalColorwidth+5) " y" (RedPortalColory+3) " h" 20, % localizedStrings["s28"] + local ShrinesY:=(PortalRow1+PortalsGroupH+5) + + + Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" ShrinesY " w" 340 " h" PortalsGroupH , % localizedStrings["s29"] + Gui, Font, % "s" SettingFontsize1 " C" UniqueColor, + local shrinerow2:=(shrinerow1:=ShrinesY+20)+20 + Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (shrinerow1) " w" 140 " h" 20 " vShowShrines gSettingsUpdateFlag", % localizedStrings["s30"] ;True + Gui, Add, Edit, % " c" EditColor " x" MapItemCol2 " y" shrinerow1 " w" 50 " h" 20 " vShrineColor gSettingsUpdateFlag", FFD700 + Gui, Add, Edit, % "c" EditColor " x" MapItemCol2 " y" shrinerow2 " w" 50 " h" 20 " vShrineTextSize gSettingsUpdateFlag", 14 + Gui, Add, Text, % "c" SettingDefault("ShrineColor") " x" MapItemCol3 " y" (shrinerow2-17) " h" 20 , % localizedStrings["s31"] + Gui, Add, Text, % "c" UniqueColor " x" MapItemCol3 " y" (shrinerow2+3) " h" 20 , % localizedStrings["s32"] + + local ChestY:=(ShrinesY+PortalsGroupH+20) + Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" ChestY " w" 168 " h" (ChestH:=PortalsGroupH-20) , % localizedStrings["gb1"] + Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (ChestY+20) " w" 120 " h" 20 " vShowChests gSettingsUpdateFlag", % localizedStrings["cb1"] + + Gui, Add, GroupBox, % "c" UniqueColor " x" (MapItemCol2+20)" y" ChestY " w" 168 " h" 50 " ", % localizedStrings["gb18"] + Gui, Add, Edit, % "c" EditColor " x" (MapItemCol2+25) " y" (ChestY+20) " w" 25 " h" 20 " vexitTextSize gSettingsUpdateFlag", 12 + Gui, Add, Text, % "c" UniqueColor " x" (MapItemCol3) " y" (ChestY+23) " w" 90 " h" 20 " ", % localizedStrings["gb19"] + + local PathfindY:=(ChestY+ChestH+20) + Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" PathfindY " w" 340 " h" 70 " ", % "Pathfinding" + Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (PathfindY+20) " w" 120 " h" 20 " vshowPathFinding gSettingsUpdateFlag", % "Show pathfinding" + + Gui, Add, Edit, % "c" EditColor " x" MapItemCol2 " y" (PathfindY+18) " w" 60 " h" 20 " vpathFindingColour gSettingsUpdateFlag" + Gui, Add, Text, % "c" SettingDefault("pathFindingColour") " x" (MapItemCol3+10) " y" (PathfindY+20) " w" 90 " h" 20 " ", % "Pathfinding color" + ;Gui, Add, Slider, % "x" (MapItemCol3+5) " y" (PathfindY+40) " h" 20 " w" 84 " vPathcolorSlide gPathSlide range0-300", 0 +} + +SettingsTabGameData(x,y){ + global + Gui, Settings:Default + Gui, Tab, Game Data + { ; Game History + local (HistoryX:=x) , (HistoryY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" (HistoryX) " y" (HistoryY) " w" 340 " h" 115 " ", % localizedStrings["gb2"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (HistoryX+12) " y" (HistoryY+20) " w" 270 " h" 20 " vshowGameHistory gSettingsUpdateFlag", % localizedStrings["cb2"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (HistoryX+12) " y" (HistoryY+40) " w" 270 " h" 20 " vshowAllHistory gSettingsUpdateFlag", % localizedStrings["cb3"] + Gui, Add, Text, % "c" UniqueColor " x" (HistoryX+75) " y" (HistoryY+63) " w" 150 " h" 20 " ", % localizedStrings["t1"] + Gui, Add, DropDownList, % "x" (HistoryX+12) " y" (HistoryY+60) " w" 60 " h" 80 " vhistoryTextAlignment gSettingsUpdateFlag", LEFT||RIGHT + Gui, Add, Text, % "c" UniqueColor " x" (HistoryX+55) " y" (HistoryY+90) " w" 250 " h" 20 " ", % localizedStrings["t4"] + Gui, Add, Edit, % "c" EditColor " x" (HistoryX+12) " y" (HistoryY+86) " w" 40 " h" 20 " vhistoryTextSize gSettingsUpdateFlag", 20 + } + { ; Game info + local (gameinfoX:=x) , (gameinfoY:=179) + Gui, Add, GroupBox, % "c" UniqueColor " x" (gameinfoX) " y" (gameinfoY) " w" 340 " h" 95 " ", % localizedStrings["gb20"] ;y179 + Gui, Add, Checkbox, % "c" UniqueColor " x" (gameinfoX+=12) " y" (gameinfoY+22) " w" 200 " h" 20 " vshowGameInfo gSettingsUpdateFlag", % localizedStrings["cb4"] + + + Gui, Add, DropDownList, % "x" gameinfoX " y" (gameinfoY+43) " w" 60 " h" 80 " vgameInfoAlignment gSettingsUpdateFlag", RIGHT||LEFT ;y219 + Gui, Add, Text, % "c" UniqueColor " x" (gameinfoX+63) " y" (gameinfoY+45) " w" 150 " h" 20 " ", % localizedStrings["t2"] + + Gui, Add, Checkbox, % "c" UniqueColor " x" (gameinfoX+215) " y" (gameinfoY+43) " w" 84 " h" 20 " vshowNumPlayers gSettingsUpdateFlag", % "Player count" + + + Gui, Add, Edit, % "c" EditColor " x" gameinfoX " y" (gameinfoY+69) " w" 40 " h" 20 " vgameInfoFontSize gSettingsUpdateFlag", 18 + Gui, Add, Text, % "c" UniqueColor " x" (gameinfoX+43) " y" (gameinfoY+72) " w" 250 " h" 20 " ", % localizedStrings["t5"] + + } + { ; PLayer Location + local (PLayersLocX:=x) , (PLayersLocY:=279) + Gui, Add, GroupBox, % "c" UniqueColor " x" (PLayersLocX) " y" PLayersLocY " w" 340 " h" 55 " ", % localizedStrings["gb21"] ; PLayer Location + Gui, Add, Checkbox, % "c" UniqueColor " x" (PLayersLocX+12) " y" (PLayersLocY+20) " w" 190 " h" 20 " vshowPartyLocations gSettingsUpdateFlag", % localizedStrings["gb22"] + Gui, Add, Edit, % "c" EditColor " x" (PLayersLocX+212) " y" (PLayersLocY+20) " w" 40 " h" 20 " vpartyInfoFontSize gSettingsUpdateFlag", 0 + Gui, Add, Text, % "c" UniqueColor " x" (PLayersLocX+255) " y" (PLayersLocY+23) " w" 70 " h" 20 " ", % localizedStrings["gb27"] ; font size + } + { ; Mouse over resist and health + local ( MouseoverX:=x) , (MouseoverY:=340) + Gui, Add, GroupBox, % "c" UniqueColor " x" MouseoverX " y" (MouseoverY) " w" 340 " h" 80 " ", % localizedStrings["gb26"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MouseoverX+12) " y" (MouseoverY+20) " w" 190 " h" 20 " vshowResists gSettingsUpdateFlag", % localizedStrings["gb25"] + Gui, Add, Text, % "c" UniqueColor " x" (MouseoverX+255) " y" (MouseoverY+23) " w" 50 " h" 20 " ", % localizedStrings["gb27"] + Gui, Add, Edit, % "c" EditColor " x" (MouseoverX+212) " y" (MouseoverY+20) " w" 40 " h" 20 " vresistFontSize gSettingsUpdateFlag", 0 + Gui, Add, Checkbox, % "c" UniqueColor " x" (MouseoverX+12) " y" (MouseoverY+40) " w" 190 " h" 20 " vshowHealthPc gSettingsUpdateFlag", % localizedStrings["gb24"] + Gui, Add, Text, % "c" UniqueColor " x" (MouseoverX+255) " y" (MouseoverY+43) " w" 50 " h" 20 " ", % localizedStrings["gb27"] + Gui, Add, Edit, % "c" EditColor " x" (MouseoverX+212) " y" (MouseoverY+40) " w" 40 " h" 20 " vhealthFontSize gSettingsUpdateFlag", 0 + } +} + +SettingsTabNPCs(x,y){ + global + Gui, Settings:Default + Gui, Tab, NPCs + { ; Monster dots + local ( MonDotX:=x) , (MonDotY:=y) ;; GroupboxX:=10, GroupboxY:=59 + Gui, Add, GroupBox, % "c" UniqueColor " x" MonDotX " y" MonDotY " w" 340 " h" 165 " ", % localizedStrings["gb3"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+20) " w" 150 " h" 20 " vshowNormalMobs gSettingsUpdateFlag", % localizedStrings["cb5"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+40) " w" 150 " h" 20 " vshowUniqueMobs gSettingsUpdateFlag", % localizedStrings["cb6"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+60) " w" 150 " h" 20 " vshowBosses gSettingsUpdateFlag", % localizedStrings["cb7"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+80) " w" 150 " h" 20 " vshowDeadMobs gSettingsUpdateFlag", % localizedStrings["cb8"] + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+23) " w" 30 " h" 20 " ", % "Size" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+20) " w" 30 " h" 20 " vnormalDotSize gSettingsUpdateFlag", 2.5 + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+43) " w" 30 " h" 20 " ", % "Size" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+40) " w" 30 " h" 20 " vuniqueDotSize gSettingsUpdateFlag", 5 + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+63) " w" 30 " h" 20 " ", % "Size" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+60) " w" 30 " h" 20 " vbossDotSize gSettingsUpdateFlag", 5 + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY-59)+142 " w" 30 " h" 20 " ", % "Size" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+80) " w" 30 " h" 20 " vdeadDotSize gSettingsUpdateFlag", 2 + + Gui, Add, Text, % "c" SettingDefault("normalMobColor") " x" (MonDotX+287) " y" (MonDotY+23) " w" 50 " h" 20 " ", % "Colour" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+20) " w" 50 " h" 20 " vnormalMobColor gSettingsUpdateFlag", FFFFFF + Gui, Add, Text, % "c" SettingDefault("uniqueMobColor") " x" (MonDotX+287) " y" (MonDotY+43) " w" 50 " h" 20 " ", % "Colour" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+40) " w" 50 " h" 20 " vuniqueMobColor gSettingsUpdateFlag", D4AF37 + Gui, Add, Text, % "c" SettingDefault("bossColor") " x" (MonDotX+287) " y" (MonDotY+63) " w" 50 " h" 20 " ", % "Colour" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+60) " w" 50 " h" 20 " vbossColor gSettingsUpdateFlag", FF0000 + Gui, Add, Text, % "c" SettingDefault("deadColor") " x" (MonDotX+287) " y" (MonDotY+83) " w" 50 " h" 20 " backgroundFFFFFF", % "Colour" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+80) " w" 50 " h" 20 " vdeadColor gSettingsUpdateFlag", 000000 + + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+45) " y" (MonDotY+113) " w" 190 " h" 20 " ", % localizedStrings["t14"] + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+12) " y" (MonDotY+110) " w" 30 " h" 20 " vnormalImmunitySize gSettingsUpdateFlag", 4 + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+45) " y" (MonDotY+133) " w" 190 " h" 20 " ", % localizedStrings["t15"] + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+12) " y" (MonDotY+130) " w" 30 " h" 20 " vuniqueImmunitySize gSettingsUpdateFlag", 11 + } + { ; Friendly NPCs + local (FriendlyNPCsX:=x), (FriendlyNPCsY:=209) + Gui, Add, GroupBox, % "c" UniqueColor " x" FriendlyNPCsX " y" (FriendlyNPCsY+20) " w" 340 " h" 130 " ", % localizedStrings["gb12"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+40) " w" 250 " h" 20 " vShowOtherPlayers gSettingsUpdateFlag", % localizedStrings["s34"] ;True + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+60) " w" 270 " h" 20 " vShowOtherPlayerNames gSettingsUpdateFlag", % localizedStrings["s35"] ;False + + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+80) " w" 160 " h" 20 " vshowMerc gSettingsUpdateFlag", % localizedStrings["gb13"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+100) " w" 160 " h" 20 " vshowTownNPCs gSettingsUpdateFlag", % localizedStrings["gb14"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+120) " w" 160 " h" 20 " vNPCsAsCross gSettingsUpdateFlag", % localizedStrings["gb15"] + + Gui, Add, Text, % "c" SettingDefault("mercColor") " x" (FriendlyNPCsX+245) " y" (FriendlyNPCsY+82) " w" 90 " h" 20 " ", % localizedStrings["gb16"] + Gui, Add, Edit, % "c" EditColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+79) " w" 70 " h" 20 " vmercColor gSettingsUpdateFlag", % SettingDefault("mercColor") + + Gui, Add, Text, % "c" SettingDefault("townNPCColor") " x" (FriendlyNPCsX+245) " y" (FriendlyNPCsY+102) " w" 90 " h" 20 " ", % localizedStrings["gb17"] + Gui, Add, Edit, % "c" EditColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+100) " w" 70 " h" 20 " vtownNPCColor gSettingsUpdateFlag", % SettingDefault("townNPCColor") ;250 settings["townNPCColor"] + + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+120) " w" 160 " h" 20 " vshowTownNPCNames gSettingsUpdateFlag", % localizedStrings["gb23"] + } +} + +SettingsTabImmunes(x,y){ + global + Gui, Settings:Default + Gui, Tab, Immunities + { ; Monster Immunities + local (ImmunX:=x) , (ImmunY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" ImmunX " y" y " w" 340 " h" 170 " ", % localizedStrings["gb4"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (ImmunX+10) " y" (ImmunY+20) " w" 210 " h" 20 " vshowImmunities gSettingsUpdateFlag", % localizedStrings["cb9"] + Gui, Add, Text, % "c" settings.physicalImmuneColor " x" (ImmunX+85) " y" (ImmunY+43) " w" 140 " h" 20 " ", % localizedStrings["t16"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" ImmunY+40 " w" 70 " h" 20 " vphysicalImmuneColor gSettingsUpdateFlag", % settings.physicalImmuneColor + Gui, Add, Text, % "c" settings.magicImmuneColor " x" (ImmunX+85) " y" (ImmunY+63) " w" 140 " h" 20 " ", % localizedStrings["t17"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+60) " w" 70 " h" 20 " vmagicImmuneColor gSettingsUpdateFlag", % settings.magicImmuneColor + Gui, Add, Text, % "c" settings.fireImmuneColor " x" (ImmunX+85) " y" (ImmunY+83) " w" 140 " h" 20 " ", % localizedStrings["t18"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" ImmunY+80 " w" 70 " h" 20 " vfireImmuneColor gSettingsUpdateFlag", % settings.fireImmuneColor + Gui, Add, Text, % "c" settings.lightImmuneColor " x" (ImmunX+85) " y" (ImmunY+103) " w" 140 " h" 20 " ", % localizedStrings["t19"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+100) " w" 70 " h" 20 " vlightImmuneColor gSettingsUpdateFlag", % settings.lightImmuneColor + Gui, Add, Text, % "c" settings.coldImmuneColor " x" (ImmunX+85) " y" (ImmunY+123) " w" 140 " h" 20 " ", % localizedStrings["t20"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+120) " w" 70 " h" 20 " vcoldImmuneColor gSettingsUpdateFlag", % settings.coldImmuneColor + Gui, Add, Text, % "c" settings.poisonImmuneColor " x" (ImmunX+85) " y" (ImmunY+143) " w" 140 " h" 20 " ", % localizedStrings["t21"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+140) " w" 70 " h" 20 " vpoisonImmuneColor gSettingsUpdateFlag", % settings.poisonImmuneColor + } +} + +SettingsTabItemFilter(x,y){ + global + Gui, Settings:Default + Gui, Tab, Item Filter + local (ItemFilterX:=x) , (ItemFilterY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" x " y" y " w" 340 " h" 180 " ", % localizedStrings["gb5"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+20) " w" 200 " h" 20 " vEnableItemFilter gSettingsUpdateFlag", % localizedStrings["cb10"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+40) " w" 200 " h" 20 " vallowItemDropSounds gSettingsUpdateFlag", % localizedStrings["cb11"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+60) " w" 200 " h" 20 " vshowItemStats gSettingsUpdateFlag", % "Show item stats" + + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+80) " w" 200 " h" 20 " vitemLogEnabled gSettingsUpdateFlag", % "Show item log" + + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+100) " w" 200 " h" 20 " vincludeVendorItems gSettingsUpdateFlag", % "Include vendor items" + + Gui, Add, Edit, % "c" EditColor " x" (ItemFilterX+12) " y" (ItemFilterY+123) " w" 20 " h" 20 " vitemFontSize gSettingsUpdateFlag", 12 + Gui, Add, Text, % "c" UniqueColor " x" (ItemFilterX+35) " y" 185 " w" 80 " h" 20, % localizedStrings["cb23"] + Gui, Add, Edit, % "c" EditColor " x" (ItemFilterX+12) " y" (ItemFilterY+147) " w" 20 " h" 20 " vitemLogFontSize gSettingsUpdateFlag", % 18 + Gui, Add, Text, % "c" UniqueColor " x" (ItemFilterX+35) " y" (ItemFilterY+150) " w" 80 " h" 20, % "Log font size" + + local (TTSX:=x) , (TTSY:=ItemFilterY+200) + Gui, Add, GroupBox, % "c" UniqueColor " x" (TTSX) " y" (TTSY) " w" 340 " h" 135 " ", % localizedStrings["gb6"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (TTSX+12) " y" (TTSY+18) " w" 200 " h" 20 " vallowTextToSpeech gSettingsUpdateFlag", % localizedStrings["cb12"] + Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+41) " w" 200 " h" 20, % localizedStrings["t23"] + Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+38) " w" 30 " h" 20 " vtextToSpeechVolume gSettingsUpdateFlag", 50 + Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+61) " w" 200 " h" 20, % localizedStrings["t22"] + Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+58) " w" 30 " h" 20 " vtextToSpeechPitch gSettingsUpdateFlag", 1 + Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+81) " w" 200 " h" 20, % localizedStrings["t24"] + Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+78) " w" 30 " h" 20 " vtextToSpeechSpeed gSettingsUpdateFlag", 1 + + voiceList := GetVoiceList() + chosenVoice := settings["chosenVoice"] + oSPVoice.Voice := oSPVoice.GetVoices().Item(chosenVoice-1) + Gui, Add, DropDownList, % "x" (TTSX+12) " y" (ItemFilterY+304) " w" 200 " h" 90 " vChosenVoice Choose" chosenVoice " ReadOnly AltSubmit gSettingsUpdateFlag", % voiceList + + Gui, Add, Link, % "x" (ItemFilterY+85) " y" (ItemFilterY+359) " w" 200 " h" 20 " ", Click here for the wiki on item filter +} + +SettingsTabHotkeys(x,y){ + global + Gui, Settings:Default + Gui, Tab, Hotkeys + local (hotkeyX:=x) , (hotkeyY:=y) , hotkeytexty:=95 , checkboxy:=hotkeytexty-3 + Gui, Add, GroupBox, % "c" UniqueColor " x" hotkeyX " y" hotkeyY " w" 340 " h" 220 " ", % localizedStrings["gb11"] + local ishotkey:="Edit" + local hotkeycheckboxoptions:="gSettingsUpdateFlag " (ishotkey~="hotkey"?"enabled":"disabled") " c" UniqueColor " x" (hotkeyX+10) " w" 20 " h" 20 " y" + local hotkeyinputoptions:="gSettingsUpdateFlag" " c" 0x000000 " x" (hotkeyx+30) " w" 90 " h" 20 " y" + local hotkeytextoptions:="x" (hotkeyx+130) " w" 200 " h" 20 " y" + + + Gui, Add, Text, % "c" UniqueColor " x" (hotkeyX+10) " w200 h20 y" hotkeytexty-20, % (ishotkey == "Hotkey")?"checkbox to use Windows key as modifier":"" + Gui, Add, Text, % hotkeytextoptions hotkeytexty, % localizedStrings["t34"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions checkboxy " vWinincreaseMapSizeKey", + Gui, Add, % ishotkey, % hotkeyinputoptions checkboxy " vincreaseMapSizeKey", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+20), % localizedStrings["t35"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+20) " vWdecreaseMapSizeKey", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+20) " vdecreaseMapSizeKey", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+40), % localizedStrings["t36"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+40) " vWinmoveMapLeft", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+40) " vmoveMapLeft", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+60), % localizedStrings["t37"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+60) " vWinmoveMapRight", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+60) " vmoveMapRight", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+80), % localizedStrings["t38"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+80) " vWinmoveMapUp", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+80) " vmoveMapUp", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+100), % localizedStrings["t39"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+100) " vWinmoveMapDown", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+100) " vmoveMapDown", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+120), % localizedStrings["t40"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+120) " vWinhistoryToggleKey", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+120) " vhistoryToggleKey", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+140), % localizedStrings["t41"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+140) " vWinalwaysShowKey", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+140) " valwaysShowKey", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+160), % localizedStrings["t42"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+160) " vWinswitchMapMode", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+160) " vswitchMapMode", + + + Gui, Add, Link, % "x" (hotkeyx+85) " y" (hotkeyY+359) " w" 200 " h" 20 " ", Click here for possible key combos +} + +SettingsTabOther(x,y){ + global + Gui, Settings:Default + Gui, Tab, Other + local (otherX:=x) , (otherY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" otherX " y" otherY " w" 340 " h" 110 " ", % localizedStrings["gb7"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+20) " w" 270 " h" 20 " vshowWaypointLine gSettingsUpdateFlag", % localizedStrings["cb13"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+40) " w" 270 " h" 20 " vshowNextExitLine gSettingsUpdateFlag", % localizedStrings["cb14"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+60) " w" 270 " h" 20 " vshowBossLine gSettingsUpdateFlag", % localizedStrings["cb15"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+80) " w" 270 " h" 20 " vshowQuestLine gSettingsUpdateFlag", % localizedStrings["cb16"] + + local (HudX:=x) , (HudY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" x " y" (HudY+=120) " w" 340 " h" 130 " ", % "HUD" + Gui, Add, Checkbox, % "c" UniqueColor " x" (HudX+12) " y" (HudY+20) " w" 270 " h" 20 " vitemCounterEnabled gSettingsUpdateFlag", % localizedStrings["gb29"] + Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+46) " w" 200 " h" 20, % localizedStrings["gb30"] + Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+43) " w" 30 " h" 20 " vitemCounterSize gSettingsUpdateFlag", 75 + Gui, Add, Checkbox, % "c" UniqueColor " x" (HudX+12) " y" (HudY+63) " w" 270 " h" 20 " vbuffBarEnabled gSettingsUpdateFlag", % localizedStrings["gb31"] + Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+86) " w" 200 " h" 20, % localizedStrings["gb32"] + Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+83) " w" 30 " h" 20 " vbuffBarIconSize gSettingsUpdateFlag", 75 + Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+106) " w" 200 " h" 20, % localizedStrings["gb33"] + Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+103) " w" 30 " h" 20 " vbuffBarVerticalOffset gSettingsUpdateFlag", 0 + + local (SplashConfgiX:=x) , (SplashConfgiY:=HudY+120) + Gui, Add, GroupBox, % "c" UniqueColor " x" (SplashConfgiX) " y" (HudY+=130) " w" 340 " h" 120 " ", % "Splash" + Gui, Add, Checkbox, % "c" UniqueColor " x" (SplashConfgiX+=10) " y" (HudY+20) " w" 270 " h" 20 " vStartSplash gSettingsUpdateFlag", % "Start Splash" + Gui, Add, Checkbox, % "c" UniqueColor " x" (SplashConfgiX) " y" (HudY+40) " w" 270 " h" 20 " vLoadingSplash gSettingsUpdateFlag", % "Loading Splash" +} + +SettingsTabProjectiles(x,y){ + global + Gui, Settings:Default + Gui, Tab, Projectiles + local (mY4 := (mY3:=(mY2:=(mY1:=y)+(rowh:=20))+rowh)+rowh) , (mX4 := (mX3:=(mX2:=(mX1:=x+10)+cboxW:=40)+(tW:=100))+cboxW) + local fontwidth:=140 , eboxwidth:=32 + Gui, Add, GroupBox, % "c" UniqueColor " x" (mX1-10) " y" (mY1-16) " w" 340 " h" 400, % localizedStrings["gb8"] + Gui, Add, Checkbox, % "c" UniqueColor " x" mX1 " y" mY1 " w110 h" rowh " vshowPlayerMissiles gSettingsUpdateFlag", % localizedStrings["cb18"] + Gui, Add, Checkbox, % "c" UniqueColor " x" mX1 " y" mY2 " w110 h" rowh " vshowEnemyMissiles gSettingsUpdateFlag", % localizedStrings["cb17"] + Gui, Add, Slider, % "x" mX1 " y" mY3 " h" rowh " vOpac tooltip gOpacitySlide range1-255", % (settings.missileOpacity+0) + local projectileEditOption:=" gSettingsUpdateFlag center x" mX3 " w" eboxwidth " h" rowh " y" + Gui, Add, Edit, % " c" EditColor projectileEditOption mY1 " vmissileMajorDotSize" + Gui, Add, Edit, % " c" EditColor projectileEditOption mY2 " vmissileMinorDotSize" + Gui, Add, Edit, % " c" EditColor projectileEditOption mY3 " vmissileOpacity" + + Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY1 " w" fontwidth " h" rowh, % localizedStrings["t25"] + Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY2 " w" fontwidth " h" rowh, % localizedStrings["t26"] + Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY3 " w" fontwidth " h" rowh, % localizedStrings["t27"] + + local each, mtype + for each,mtype in (Projectilelist()) + { + local mY:=(mY4+each*rowh+5) + Gui, Add, Progress, % "x" 20 " y" mY " w20 h20 cWhite v" mtype "preview Background" settings["missile" mtype "Color"] + Gui, Add,Edit, % "c" settings["missile" mtype "Color"] " x" mX2-30 " y" mY " w" (eboxwidth+50) " h" rowh " vmissile" mtype "Color gSettingsUpdateFlag center" + } + ; we do this seperately and consecutively to force the radio to be "together" without additional code + for each,mtype in (Projectilelist()) + Gui, Add, radio, % " c" settings["missile" mtype "Color"] " x" mX3-47 " y" (mY4+7+(each*20)) " v" mtype "Rcheck gRadioToSliders", % mtype + ;RGB sliders + local (slide), (sliders:=["Red","Green","Blue"]) ,( slidex:=mX3) , (slideH:=250) + local (slidey:=mY4+10), slidetexty:=slidey+250 + for each,slide in sliders + { + Gui, Add, Slider, % "x" (slidex+=30) " y" slidey " h" slideH " w" 50 " vSlider" slide " gColorslide c0x000000 vertical Invert AltSubmit Range0-255 TickInterval" 1, 119 + local Channel:=SubStr(slide, 1 , 1) + Gui, Add, Text, % "c" UniqueColor " x" (slidex+=15) " y" slidetexty " vch" Channel, % Channel + } +} + +SettingsTabAdvanced(x,y){ + global + Gui, Settings:Default + Gui, Tab, Advanced + local (AdvancedX:=x) , (AdvancedY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" AdvancedY " w" 340 " h" 220 " ", % localizedStrings["gb9"] + Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+20) " w" 100 " h" 20 " r2", % localizedStrings["t28"] + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+40) " w" 40 " h" 20 " vperformanceMode gSettingsUpdateFlag", 50ms + Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+60) " y" (AdvancedY+40) " w" 250 " h" 40 " ", % localizedStrings["t29"] + + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+109) " w" 250 " h" 20 " ", % localizedStrings["t30"] ;168 + + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+69) " w" 150 " h" 20 " vshowFPS gSettingsUpdateFlag", % localizedStrings["cb22"] ;128 + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+240) " y" (AdvancedY+71) " w" 75 " h" 18 " ", % localizedStrings["gb28"] ;fpscap + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+197) " y" (AdvancedY+68) " w" 40 " h" 20 " vfpscap gSettingsUpdateFlag", 60 ;FPSedit + + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+130) " w" 150 " h" 20 " venableD2ML gSettingsUpdateFlag", % localizedStrings["cb20"] ;189 + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+135) " y" (AdvancedY+153) " w" 200 " h" 18 " ", % localizedStrings["t31"] + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+150) " w" 120 " h" 20 " vwindowTitle gSettingsUpdateFlag", D2R:main + Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+170) " w" 300 " h" 30, % localizedStrings["t32"] + + Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" (AdvancedY+230) " w" 340 " h" 80, % localizedStrings["gb10"] ;289 + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+250) " w" 200 " h" 20 " vdebug gSettingsUpdateFlag", % localizedStrings["cb21"] + Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+270) " w" 320 " h" 30, % localizedStrings["t33"] + + Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" (AdvancedY+310) " w" 340 " h" 60, % "Settings" + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+325) " w" 150 " h" 20 " vCustomSettings gSettingsUpdateFlag", Custom Settings colors + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+160) " y" (AdvancedY+325) " w" 175 " h" 20 " vInvertedColors gSettingsUpdateFlag", Invert Colors (requires restart) + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+345) " w" 60 " h" 20 " vWindowColor gSettingsUpdateFlag", % settings["WindowColor"] + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+70) " y" (AdvancedY+348) " w" 75 " h" 18 " ", Window Color + + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+140) " y" (AdvancedY+345) " w" 60 " h" 20 " vFontColor gSettingsUpdateFlag", % settings["FontColor"] + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+200) " y" (AdvancedY+348) " w" 75 " h" 18 " ", Font Color + +} + +;colorpicker +showColorPicker(){ + local static ShowPicker := false + local static PickerBuilt := false + if !(PickerBuilt){ + colorpicker() + PickerBuilt:=True + } + ; open the settings window and a given position + if (ShowPicker:=!ShowPicker){ + Gui, ColorPicker:Show,, % "RGB" + } else { + Gui, ColorPicker:hide + } + +} + +colorpicker(){ + global + Gui, ColorPicker:Default + Gui, ColorPicker:-MinimizeBox +AlwaysOnTop + local progressX:=0 + local progressY:=5 + local progressS:=50 + glable:="gColorPickerUpdate" + Gui, ColorPicker:Add, Progress, % "x" progressX " y"progressY " w" progressS " h" progressS " +C0xFF0000 vProg", 100 + Gui, ColorPicker:Add, Edit, % "x" (progressX+=progressS) " y" (progressY) " w" 70 " h20 vHex " glable, 0xFFFF0000 + Gui, ColorPicker:Font, s9 + local buttony:=progressY + Gui, ColorPicker:Add, Button, % "x" progressX " y" (buttony+=20) " w" 70 " h" 15, CopyRGB + Gui, ColorPicker:Add, Button, % "x" progressX " y" (buttony+=15 )" w" 70 " h" 15, CopyAlpha + ;Gui, ColorPicker:Add, Button, % "x" 165 " y" buttony " w75 h23", Close + rgbtX:=13 , rgbty:=buttony+25 + Gui, ColorPicker:Font, s12 + Gui, ColorPicker:Add, Text, % "x" rgbtX " y" rgbty " w20 h20 Center", R + Gui, ColorPicker:Font, s9 + Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vR " glable, 255 + Gui, ColorPicker:Font, s12 + Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", G + Gui, ColorPicker:Font, s9 + Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vG " glable, 0 + Gui, ColorPicker:Font, s12 + Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", B + Gui, ColorPicker:Font, s9 + Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vB " glable, 0 + Gui, ColorPicker:Font, s12 + Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y"rgbty " w25 h25 Center", A + Gui, ColorPicker:Font, s9 + Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vA " glable, 255 + local sliderh:=150 + local sliderw:=25 + local sliderx:=10 + local slidery:=rgbty+50 + options:=" TickInterval1 +Vertical +0x20 +0x200 +Vertical +Invert +Center +Range0-255 -Tabstop AltSubmit " glable + Gui, ColorPicker:Add, Slider, % "x" sliderx " y" slidery " w" sliderw " h" sliderh options " vRS", 255 + Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vGS", 0 + Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vBS", 0 + Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vAS", 255 + + +} + +ColorPickerGuiEscape(){ + ColorPickerGuiClose() +} + +ColorPickerGuiClose(){ + showColorPicker() +} + +ColorPickerUpdate(){ + GuiControlGet, RS + GuiControlGet, GS + GuiControlGet, BS + GuiControlGet, AS + + GuiControlGet, R + GuiControlGet, G + GuiControlGet, B + GuiControlGet, A + GuiControlGet, Hex + GuiControlGet, Prog + + ColorPickerSet("R", RS) + ColorPickerSet("G", GS) + ColorPickerSet("B", BS) + ColorPickerSet("A", AS) + ColorPickerSet("RS", R, "+Range0-255") + ColorPickerSet("GS", G, "+Range0-255") + ColorPickerSet("BS", B, "+Range0-255") + ColorPickerSet("AS", A, "+Range1-255") + ColorPickerSet("Hex", ARGB(R, G, B, A)) + ColorPickerSet("Prog",, "+C" ARGB(R, G, B)) +} + +ColorPickerButtonCopyRGB(){ + GuiControlGet, Hex + return Clipboard:=SubStr(Hex, 5) +} + +ColorPickerButtonCopyAlpha(){ + GuiControlGet, R + GuiControlGet, G + GuiControlGet, B + GuiControlGet, A + return clipboard:=SubStr(ARGB(R, G, B, A), 1 , 4) +} + +ColorPickerSet(Control, Data := "", AddOpt := "") { + GuiControl, %AddOpt%, %Control%, % Data + return !ErrorLevel +} diff --git a/src/ui/splash/splash.ahk b/src/ui/splash/splash.ahk index e0d3e24..d111e9b 100644 --- a/src/ui/splash/splash.ahk +++ b/src/ui/splash/splash.ahk @@ -2,10 +2,16 @@ StartSplash(){ if settings.StartSplash Splash(version,3000,"StartSettings") } + LoadingSplash(){ Splash("loading",0,,0.25) } +StartSettings(){ + SetTimer, ShowSettings, -1000 + OnMessage(0x201, "WM_LBUTTONDOWN") +} + Splash(text="",time=1000,onclickcmd=False,opacity=1){ global if !FileExist(settings.SplashImg) @@ -63,6 +69,7 @@ Splash(text="",time=1000,onclickcmd=False,opacity=1){ if (time !=0) SetTimer, SplashClose, % time } + SplashClose(){ Gui, Splash:Destroy OnMessage(0x201, "WM_LBUTTONDOWN") From 8e97e30267c08579538afd7ab444106f38c8ef2c Mon Sep 17 00:00:00 2001 From: Teo <106943092+t3ohm@users.noreply.github.com> Date: Wed, 12 Oct 2022 19:44:31 -0700 Subject: [PATCH 10/12] Revert "Split Settings up" This reverts commit 4328eb6d5fcd17da1a4bf67a5f8635fb3e277072. --- src/ui/settingsPanel.ahk | Bin 22372 -> 112462 bytes src/ui/settingsTabs.ahk | 632 --------------------------------------- src/ui/splash/splash.ahk | 7 - 3 files changed, 639 deletions(-) delete mode 100644 src/ui/settingsTabs.ahk diff --git a/src/ui/settingsPanel.ahk b/src/ui/settingsPanel.ahk index a8815fc3ac91ae3abcc05c00f29ed40d8ac092ba..5f76118b05e7632ab2140b76013725fe771a6fde 100644 GIT binary patch literal 112462 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 delta 132 zcmX^2j_t`h#t8Github - Gui, Add, Link, % "c" 0xff0000 " x" (SettingsAnchorX+130) " y" (SettingsAnchorY+339) " w"100 " h" 30 " gDiscordLink", v%version% - Gui, Add, Link, % " c" 0x00FF00 " x" (SettingsAnchorX+260) " y" (SettingsAnchorY+339) " w"100 " h" 30 " gDiscordLink", Discord - Gui, Font, % "s" SettingFontsize1 -} - -SettingsTabGeneral(x,y){ - global - Gui, Settings:Default - Gui, Tab, General - local (mapserverX:=x),(mapserverY:=y),(mapserverW:=),(mapserverH:=),(mapserverW:=20),(mapserverH:=20) - Gui, Add, GroupBox, % "c" UniqueColor " x" mapserverX " y" mapserverY " w" 340 " h" 80 , % localizedStrings["s3"] ;mapserver - Gui, Add, Edit, % "c" EditColor " x" (mapserverX+=18) " y" (mapserverY+=20) " w300 vBaseUrl gSettingsUpdateFlag" , settings.baseUrl - Gui, Add, Text, % "c" disabledfont " x" (mapserverX+=1) " y" (mapserverY+=25) " w180" , % "Ex: http://localhost:3002`nhttp://192.168.1.123:3002" - - local (MapPosX:=SettingsAnchorX), (MapPosY:=mapserverY+71), (MapPosW:=0), (MapPosH:=0) - Gui, Add, GroupBox, % "c" UniqueColor " x" MapPosX " y" MapPosY " w340 h80", % MapPos:="Map Position" - Gui, Add, DropDownList, % "x" (MapPosX+10) " y" (MapPosY+20) " w" 140 " h" 80 " vmapPosition gSettingsUpdateFlag", - Gui, Add, Checkbox, % "c" UniqueColor " x" (MapPosX+180) " y" (MapPosY+25) " w" 135 " h" 20 " vAlwaysShowMap gSettingsUpdateFlag", % "Always show map" - Gui, Add, Checkbox, % "c" UniqueColor " x" (MapPosX+10) " y" (MapPosY+45) " w" 135 " h" 20 " vHideTown gSettingsUpdateFlag", % "Hide town maps" - - local (CenPosX:=SettingsAnchorX), (CenPosY:=MapPosY+85), (CenPosW:=), (CenPosH:=) - Gui, Add, GroupBox, % "c" UniqueColor " x" CenPosX " y" CenPosY " w" 340 " h" 80, % "Centered position settings" - local (CenCol4:=(CenCol3:=(CenCol2:=(CenCol1:=CenPosX+10)+50)+115)+50) - local (CenRow4:=(CenRow3:=(CenRow2:=(CenRow1:=CenPosY+20)+5)+15)+5) - Gui, Add, Edit, % "c" EditColor " x" CenCol1 " y" CenRow1 " w" 44 " h" 20 " vcenterModeScale gSettingsUpdateFlag" - Gui, Add, Edit, % "c" EditColor " x" CenCol1 " y" CenRow3 " w" 44 " h" 20 " vcenterModeOpacity gSettingsUpdateFlag" - Gui, Add, Text, % "c" UniqueColor " x" CenCol2 " y" CenRow2 " w" 80 " h" 15, % "Centered Scale" - Gui, Add, Text, % "c" UniqueColor " x" CenCol2 " y" CenRow4 " w" 80 " h" 15, % "Center Opacity (0-1)" - Gui, Add, Edit, % "c" EditColor " x" CenCol3 " y" CenRow1 " w" 44 " h" 20 " vcenterModeOffsetX gSettingsUpdateFlag" - Gui, Add, Edit, % "c" EditColor " x" CenCol3 " y" CenRow3 " w" 44 " h" 20 " vcenterModeOffsetY gSettingsUpdateFlag" - Gui, Add, Text, % "c" UniqueColor " x" CenCol4 " y" CenRow2 " w" 80 " h" 15, % "X offset" - Gui, Add, Text, % "c" UniqueColor " x" CenCol4 " y" CenRow4 " w" 80 " h" 15, % "Y offset" - - local (CorPosX:=SettingsAnchorX), (CorPosY:=CenRow4) - Gui, Add, GroupBox, % "c" UniqueColor " x" CorPosX " y" (CorPosY+40) " w" 340 " h" 80, % "Corner position settings" - local (CorCol4:=(CorCol3:=(CorCol2:=(CorCol1:=CorPosX+10)+50)+115)+50) - local (CorRow4:=(CorRow3:=(CorRow2:=(CorRow1:=CorPosY+60)+5)+15)+5) - Gui, Add, Edit, % "c" EditColor " x" CorCol1 " y" CorRow1 " w" 44 " h" 20 " vcornerModeScale gSettingsUpdateFlag" - Gui, Add, Text, % "c" UniqueColor " x" CorCol2 " y" CorRow2 " w" 80 " h" 15, % "Corner Scale" - Gui, Add, Edit, % "c" EditColor " x" CorCol1 " y" CorRow3 " w" 44 " h20 vcornerModeOpacity gSettingsUpdateFlag" - Gui, Add, Text, % "c" UniqueColor " x" CorCol2 " y" CorRow4 " w" 80 " h" 15, % "Corner Opacity (0-1)" - Gui, Add, Edit, % "c" EditColor " x" CorCol3 " y" CorRow1 " w" 44 " h" 20 " vcornerModeOffsetX gSettingsUpdateFlag" - Gui, Add, Text, % "c" UniqueColor " x" CorCol4 " y" CorRow2 " w" 80 " h" 15, % "X offset" - Gui, Add, Edit, % "c" EditColor " x" CorCol3 " y" CorRow3 " w" 44 " h" 20 " vcornerModeOffsetY gSettingsUpdateFlag" - Gui, Add, Text, % "c" UniqueColor " x" CorCol4 " y" CorRow4 " w" 80 " h" 15, % "Y offset" -} - -SettingsTabMapItems(x,y){ - global - Gui, Settings:Default - Gui, Tab, Map Items - local (MapItemX:=x),(MapItemY:=y) - local (MapItemCol4:=(MapItemCol3:=(MapItemCol2:=(MapItemCol1:=MapItemX+12)+140)+53)+50) - local (PortalRow4:=(PortalRow3:=(PortalRow2:=(PortalRow1:=y+20)+5)+15)+5) - Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" MapItemY " w" 340 " h" (PortalsGroupH:=70), % localizedStrings["s25"] - Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" PortalRow1 " w" 140 " h" 20 " vShowPortals gSettingsUpdateFlag", % localizedStrings["s26"] ;True - Gui, Add, Edit, % " c" EditColor " x" (PortalColorx:=MapItemCol2) " y" (PortalColory:=PortalRow1) " w" (PortalColorwidth:=50) " h" 20 " vPortalColor gSettingsUpdateFlag", 00AAFF - Gui, Add, Text, % "c" SettingDefault("PortalColor") " x" (PortalColorx+PortalColorwidth+5) " y" (PortalColory+3) " h" 20, % localizedStrings["s27"] - Gui, Add, Edit, % "c" EditColor " x" (RPortalColorx:=MapItemCol2) " y" (RedPortalColory:=PortalRow1+20) " w" 50 " h" 20 " vRedPortalColor gSettingsUpdateFlag", FF0000 - Gui, Add, Text, % "c" SettingDefault("RedPortalColor") " x" (RPortalColorx+PortalColorwidth+5) " y" (RedPortalColory+3) " h" 20, % localizedStrings["s28"] - local ShrinesY:=(PortalRow1+PortalsGroupH+5) - - - Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" ShrinesY " w" 340 " h" PortalsGroupH , % localizedStrings["s29"] - Gui, Font, % "s" SettingFontsize1 " C" UniqueColor, - local shrinerow2:=(shrinerow1:=ShrinesY+20)+20 - Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (shrinerow1) " w" 140 " h" 20 " vShowShrines gSettingsUpdateFlag", % localizedStrings["s30"] ;True - Gui, Add, Edit, % " c" EditColor " x" MapItemCol2 " y" shrinerow1 " w" 50 " h" 20 " vShrineColor gSettingsUpdateFlag", FFD700 - Gui, Add, Edit, % "c" EditColor " x" MapItemCol2 " y" shrinerow2 " w" 50 " h" 20 " vShrineTextSize gSettingsUpdateFlag", 14 - Gui, Add, Text, % "c" SettingDefault("ShrineColor") " x" MapItemCol3 " y" (shrinerow2-17) " h" 20 , % localizedStrings["s31"] - Gui, Add, Text, % "c" UniqueColor " x" MapItemCol3 " y" (shrinerow2+3) " h" 20 , % localizedStrings["s32"] - - local ChestY:=(ShrinesY+PortalsGroupH+20) - Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" ChestY " w" 168 " h" (ChestH:=PortalsGroupH-20) , % localizedStrings["gb1"] - Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (ChestY+20) " w" 120 " h" 20 " vShowChests gSettingsUpdateFlag", % localizedStrings["cb1"] - - Gui, Add, GroupBox, % "c" UniqueColor " x" (MapItemCol2+20)" y" ChestY " w" 168 " h" 50 " ", % localizedStrings["gb18"] - Gui, Add, Edit, % "c" EditColor " x" (MapItemCol2+25) " y" (ChestY+20) " w" 25 " h" 20 " vexitTextSize gSettingsUpdateFlag", 12 - Gui, Add, Text, % "c" UniqueColor " x" (MapItemCol3) " y" (ChestY+23) " w" 90 " h" 20 " ", % localizedStrings["gb19"] - - local PathfindY:=(ChestY+ChestH+20) - Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" PathfindY " w" 340 " h" 70 " ", % "Pathfinding" - Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (PathfindY+20) " w" 120 " h" 20 " vshowPathFinding gSettingsUpdateFlag", % "Show pathfinding" - - Gui, Add, Edit, % "c" EditColor " x" MapItemCol2 " y" (PathfindY+18) " w" 60 " h" 20 " vpathFindingColour gSettingsUpdateFlag" - Gui, Add, Text, % "c" SettingDefault("pathFindingColour") " x" (MapItemCol3+10) " y" (PathfindY+20) " w" 90 " h" 20 " ", % "Pathfinding color" - ;Gui, Add, Slider, % "x" (MapItemCol3+5) " y" (PathfindY+40) " h" 20 " w" 84 " vPathcolorSlide gPathSlide range0-300", 0 -} - -SettingsTabGameData(x,y){ - global - Gui, Settings:Default - Gui, Tab, Game Data - { ; Game History - local (HistoryX:=x) , (HistoryY:=y) - Gui, Add, GroupBox, % "c" UniqueColor " x" (HistoryX) " y" (HistoryY) " w" 340 " h" 115 " ", % localizedStrings["gb2"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (HistoryX+12) " y" (HistoryY+20) " w" 270 " h" 20 " vshowGameHistory gSettingsUpdateFlag", % localizedStrings["cb2"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (HistoryX+12) " y" (HistoryY+40) " w" 270 " h" 20 " vshowAllHistory gSettingsUpdateFlag", % localizedStrings["cb3"] - Gui, Add, Text, % "c" UniqueColor " x" (HistoryX+75) " y" (HistoryY+63) " w" 150 " h" 20 " ", % localizedStrings["t1"] - Gui, Add, DropDownList, % "x" (HistoryX+12) " y" (HistoryY+60) " w" 60 " h" 80 " vhistoryTextAlignment gSettingsUpdateFlag", LEFT||RIGHT - Gui, Add, Text, % "c" UniqueColor " x" (HistoryX+55) " y" (HistoryY+90) " w" 250 " h" 20 " ", % localizedStrings["t4"] - Gui, Add, Edit, % "c" EditColor " x" (HistoryX+12) " y" (HistoryY+86) " w" 40 " h" 20 " vhistoryTextSize gSettingsUpdateFlag", 20 - } - { ; Game info - local (gameinfoX:=x) , (gameinfoY:=179) - Gui, Add, GroupBox, % "c" UniqueColor " x" (gameinfoX) " y" (gameinfoY) " w" 340 " h" 95 " ", % localizedStrings["gb20"] ;y179 - Gui, Add, Checkbox, % "c" UniqueColor " x" (gameinfoX+=12) " y" (gameinfoY+22) " w" 200 " h" 20 " vshowGameInfo gSettingsUpdateFlag", % localizedStrings["cb4"] - - - Gui, Add, DropDownList, % "x" gameinfoX " y" (gameinfoY+43) " w" 60 " h" 80 " vgameInfoAlignment gSettingsUpdateFlag", RIGHT||LEFT ;y219 - Gui, Add, Text, % "c" UniqueColor " x" (gameinfoX+63) " y" (gameinfoY+45) " w" 150 " h" 20 " ", % localizedStrings["t2"] - - Gui, Add, Checkbox, % "c" UniqueColor " x" (gameinfoX+215) " y" (gameinfoY+43) " w" 84 " h" 20 " vshowNumPlayers gSettingsUpdateFlag", % "Player count" - - - Gui, Add, Edit, % "c" EditColor " x" gameinfoX " y" (gameinfoY+69) " w" 40 " h" 20 " vgameInfoFontSize gSettingsUpdateFlag", 18 - Gui, Add, Text, % "c" UniqueColor " x" (gameinfoX+43) " y" (gameinfoY+72) " w" 250 " h" 20 " ", % localizedStrings["t5"] - - } - { ; PLayer Location - local (PLayersLocX:=x) , (PLayersLocY:=279) - Gui, Add, GroupBox, % "c" UniqueColor " x" (PLayersLocX) " y" PLayersLocY " w" 340 " h" 55 " ", % localizedStrings["gb21"] ; PLayer Location - Gui, Add, Checkbox, % "c" UniqueColor " x" (PLayersLocX+12) " y" (PLayersLocY+20) " w" 190 " h" 20 " vshowPartyLocations gSettingsUpdateFlag", % localizedStrings["gb22"] - Gui, Add, Edit, % "c" EditColor " x" (PLayersLocX+212) " y" (PLayersLocY+20) " w" 40 " h" 20 " vpartyInfoFontSize gSettingsUpdateFlag", 0 - Gui, Add, Text, % "c" UniqueColor " x" (PLayersLocX+255) " y" (PLayersLocY+23) " w" 70 " h" 20 " ", % localizedStrings["gb27"] ; font size - } - { ; Mouse over resist and health - local ( MouseoverX:=x) , (MouseoverY:=340) - Gui, Add, GroupBox, % "c" UniqueColor " x" MouseoverX " y" (MouseoverY) " w" 340 " h" 80 " ", % localizedStrings["gb26"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (MouseoverX+12) " y" (MouseoverY+20) " w" 190 " h" 20 " vshowResists gSettingsUpdateFlag", % localizedStrings["gb25"] - Gui, Add, Text, % "c" UniqueColor " x" (MouseoverX+255) " y" (MouseoverY+23) " w" 50 " h" 20 " ", % localizedStrings["gb27"] - Gui, Add, Edit, % "c" EditColor " x" (MouseoverX+212) " y" (MouseoverY+20) " w" 40 " h" 20 " vresistFontSize gSettingsUpdateFlag", 0 - Gui, Add, Checkbox, % "c" UniqueColor " x" (MouseoverX+12) " y" (MouseoverY+40) " w" 190 " h" 20 " vshowHealthPc gSettingsUpdateFlag", % localizedStrings["gb24"] - Gui, Add, Text, % "c" UniqueColor " x" (MouseoverX+255) " y" (MouseoverY+43) " w" 50 " h" 20 " ", % localizedStrings["gb27"] - Gui, Add, Edit, % "c" EditColor " x" (MouseoverX+212) " y" (MouseoverY+40) " w" 40 " h" 20 " vhealthFontSize gSettingsUpdateFlag", 0 - } -} - -SettingsTabNPCs(x,y){ - global - Gui, Settings:Default - Gui, Tab, NPCs - { ; Monster dots - local ( MonDotX:=x) , (MonDotY:=y) ;; GroupboxX:=10, GroupboxY:=59 - Gui, Add, GroupBox, % "c" UniqueColor " x" MonDotX " y" MonDotY " w" 340 " h" 165 " ", % localizedStrings["gb3"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+20) " w" 150 " h" 20 " vshowNormalMobs gSettingsUpdateFlag", % localizedStrings["cb5"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+40) " w" 150 " h" 20 " vshowUniqueMobs gSettingsUpdateFlag", % localizedStrings["cb6"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+60) " w" 150 " h" 20 " vshowBosses gSettingsUpdateFlag", % localizedStrings["cb7"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+80) " w" 150 " h" 20 " vshowDeadMobs gSettingsUpdateFlag", % localizedStrings["cb8"] - Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+23) " w" 30 " h" 20 " ", % "Size" - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+20) " w" 30 " h" 20 " vnormalDotSize gSettingsUpdateFlag", 2.5 - Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+43) " w" 30 " h" 20 " ", % "Size" - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+40) " w" 30 " h" 20 " vuniqueDotSize gSettingsUpdateFlag", 5 - Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+63) " w" 30 " h" 20 " ", % "Size" - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+60) " w" 30 " h" 20 " vbossDotSize gSettingsUpdateFlag", 5 - Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY-59)+142 " w" 30 " h" 20 " ", % "Size" - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+80) " w" 30 " h" 20 " vdeadDotSize gSettingsUpdateFlag", 2 - - Gui, Add, Text, % "c" SettingDefault("normalMobColor") " x" (MonDotX+287) " y" (MonDotY+23) " w" 50 " h" 20 " ", % "Colour" - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+20) " w" 50 " h" 20 " vnormalMobColor gSettingsUpdateFlag", FFFFFF - Gui, Add, Text, % "c" SettingDefault("uniqueMobColor") " x" (MonDotX+287) " y" (MonDotY+43) " w" 50 " h" 20 " ", % "Colour" - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+40) " w" 50 " h" 20 " vuniqueMobColor gSettingsUpdateFlag", D4AF37 - Gui, Add, Text, % "c" SettingDefault("bossColor") " x" (MonDotX+287) " y" (MonDotY+63) " w" 50 " h" 20 " ", % "Colour" - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+60) " w" 50 " h" 20 " vbossColor gSettingsUpdateFlag", FF0000 - Gui, Add, Text, % "c" SettingDefault("deadColor") " x" (MonDotX+287) " y" (MonDotY+83) " w" 50 " h" 20 " backgroundFFFFFF", % "Colour" - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+80) " w" 50 " h" 20 " vdeadColor gSettingsUpdateFlag", 000000 - - Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+45) " y" (MonDotY+113) " w" 190 " h" 20 " ", % localizedStrings["t14"] - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+12) " y" (MonDotY+110) " w" 30 " h" 20 " vnormalImmunitySize gSettingsUpdateFlag", 4 - Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+45) " y" (MonDotY+133) " w" 190 " h" 20 " ", % localizedStrings["t15"] - Gui, Add, Edit, % "c" EditColor " x" (MonDotX+12) " y" (MonDotY+130) " w" 30 " h" 20 " vuniqueImmunitySize gSettingsUpdateFlag", 11 - } - { ; Friendly NPCs - local (FriendlyNPCsX:=x), (FriendlyNPCsY:=209) - Gui, Add, GroupBox, % "c" UniqueColor " x" FriendlyNPCsX " y" (FriendlyNPCsY+20) " w" 340 " h" 130 " ", % localizedStrings["gb12"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+40) " w" 250 " h" 20 " vShowOtherPlayers gSettingsUpdateFlag", % localizedStrings["s34"] ;True - Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+60) " w" 270 " h" 20 " vShowOtherPlayerNames gSettingsUpdateFlag", % localizedStrings["s35"] ;False - - Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+80) " w" 160 " h" 20 " vshowMerc gSettingsUpdateFlag", % localizedStrings["gb13"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+100) " w" 160 " h" 20 " vshowTownNPCs gSettingsUpdateFlag", % localizedStrings["gb14"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+120) " w" 160 " h" 20 " vNPCsAsCross gSettingsUpdateFlag", % localizedStrings["gb15"] - - Gui, Add, Text, % "c" SettingDefault("mercColor") " x" (FriendlyNPCsX+245) " y" (FriendlyNPCsY+82) " w" 90 " h" 20 " ", % localizedStrings["gb16"] - Gui, Add, Edit, % "c" EditColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+79) " w" 70 " h" 20 " vmercColor gSettingsUpdateFlag", % SettingDefault("mercColor") - - Gui, Add, Text, % "c" SettingDefault("townNPCColor") " x" (FriendlyNPCsX+245) " y" (FriendlyNPCsY+102) " w" 90 " h" 20 " ", % localizedStrings["gb17"] - Gui, Add, Edit, % "c" EditColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+100) " w" 70 " h" 20 " vtownNPCColor gSettingsUpdateFlag", % SettingDefault("townNPCColor") ;250 settings["townNPCColor"] - - Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+120) " w" 160 " h" 20 " vshowTownNPCNames gSettingsUpdateFlag", % localizedStrings["gb23"] - } -} - -SettingsTabImmunes(x,y){ - global - Gui, Settings:Default - Gui, Tab, Immunities - { ; Monster Immunities - local (ImmunX:=x) , (ImmunY:=y) - Gui, Add, GroupBox, % "c" UniqueColor " x" ImmunX " y" y " w" 340 " h" 170 " ", % localizedStrings["gb4"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (ImmunX+10) " y" (ImmunY+20) " w" 210 " h" 20 " vshowImmunities gSettingsUpdateFlag", % localizedStrings["cb9"] - Gui, Add, Text, % "c" settings.physicalImmuneColor " x" (ImmunX+85) " y" (ImmunY+43) " w" 140 " h" 20 " ", % localizedStrings["t16"] - Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" ImmunY+40 " w" 70 " h" 20 " vphysicalImmuneColor gSettingsUpdateFlag", % settings.physicalImmuneColor - Gui, Add, Text, % "c" settings.magicImmuneColor " x" (ImmunX+85) " y" (ImmunY+63) " w" 140 " h" 20 " ", % localizedStrings["t17"] - Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+60) " w" 70 " h" 20 " vmagicImmuneColor gSettingsUpdateFlag", % settings.magicImmuneColor - Gui, Add, Text, % "c" settings.fireImmuneColor " x" (ImmunX+85) " y" (ImmunY+83) " w" 140 " h" 20 " ", % localizedStrings["t18"] - Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" ImmunY+80 " w" 70 " h" 20 " vfireImmuneColor gSettingsUpdateFlag", % settings.fireImmuneColor - Gui, Add, Text, % "c" settings.lightImmuneColor " x" (ImmunX+85) " y" (ImmunY+103) " w" 140 " h" 20 " ", % localizedStrings["t19"] - Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+100) " w" 70 " h" 20 " vlightImmuneColor gSettingsUpdateFlag", % settings.lightImmuneColor - Gui, Add, Text, % "c" settings.coldImmuneColor " x" (ImmunX+85) " y" (ImmunY+123) " w" 140 " h" 20 " ", % localizedStrings["t20"] - Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+120) " w" 70 " h" 20 " vcoldImmuneColor gSettingsUpdateFlag", % settings.coldImmuneColor - Gui, Add, Text, % "c" settings.poisonImmuneColor " x" (ImmunX+85) " y" (ImmunY+143) " w" 140 " h" 20 " ", % localizedStrings["t21"] - Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+140) " w" 70 " h" 20 " vpoisonImmuneColor gSettingsUpdateFlag", % settings.poisonImmuneColor - } -} - -SettingsTabItemFilter(x,y){ - global - Gui, Settings:Default - Gui, Tab, Item Filter - local (ItemFilterX:=x) , (ItemFilterY:=y) - Gui, Add, GroupBox, % "c" UniqueColor " x" x " y" y " w" 340 " h" 180 " ", % localizedStrings["gb5"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+20) " w" 200 " h" 20 " vEnableItemFilter gSettingsUpdateFlag", % localizedStrings["cb10"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+40) " w" 200 " h" 20 " vallowItemDropSounds gSettingsUpdateFlag", % localizedStrings["cb11"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+60) " w" 200 " h" 20 " vshowItemStats gSettingsUpdateFlag", % "Show item stats" - - Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+80) " w" 200 " h" 20 " vitemLogEnabled gSettingsUpdateFlag", % "Show item log" - - Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+100) " w" 200 " h" 20 " vincludeVendorItems gSettingsUpdateFlag", % "Include vendor items" - - Gui, Add, Edit, % "c" EditColor " x" (ItemFilterX+12) " y" (ItemFilterY+123) " w" 20 " h" 20 " vitemFontSize gSettingsUpdateFlag", 12 - Gui, Add, Text, % "c" UniqueColor " x" (ItemFilterX+35) " y" 185 " w" 80 " h" 20, % localizedStrings["cb23"] - Gui, Add, Edit, % "c" EditColor " x" (ItemFilterX+12) " y" (ItemFilterY+147) " w" 20 " h" 20 " vitemLogFontSize gSettingsUpdateFlag", % 18 - Gui, Add, Text, % "c" UniqueColor " x" (ItemFilterX+35) " y" (ItemFilterY+150) " w" 80 " h" 20, % "Log font size" - - local (TTSX:=x) , (TTSY:=ItemFilterY+200) - Gui, Add, GroupBox, % "c" UniqueColor " x" (TTSX) " y" (TTSY) " w" 340 " h" 135 " ", % localizedStrings["gb6"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (TTSX+12) " y" (TTSY+18) " w" 200 " h" 20 " vallowTextToSpeech gSettingsUpdateFlag", % localizedStrings["cb12"] - Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+41) " w" 200 " h" 20, % localizedStrings["t23"] - Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+38) " w" 30 " h" 20 " vtextToSpeechVolume gSettingsUpdateFlag", 50 - Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+61) " w" 200 " h" 20, % localizedStrings["t22"] - Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+58) " w" 30 " h" 20 " vtextToSpeechPitch gSettingsUpdateFlag", 1 - Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+81) " w" 200 " h" 20, % localizedStrings["t24"] - Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+78) " w" 30 " h" 20 " vtextToSpeechSpeed gSettingsUpdateFlag", 1 - - voiceList := GetVoiceList() - chosenVoice := settings["chosenVoice"] - oSPVoice.Voice := oSPVoice.GetVoices().Item(chosenVoice-1) - Gui, Add, DropDownList, % "x" (TTSX+12) " y" (ItemFilterY+304) " w" 200 " h" 90 " vChosenVoice Choose" chosenVoice " ReadOnly AltSubmit gSettingsUpdateFlag", % voiceList - - Gui, Add, Link, % "x" (ItemFilterY+85) " y" (ItemFilterY+359) " w" 200 " h" 20 " ", Click here for the wiki on item filter -} - -SettingsTabHotkeys(x,y){ - global - Gui, Settings:Default - Gui, Tab, Hotkeys - local (hotkeyX:=x) , (hotkeyY:=y) , hotkeytexty:=95 , checkboxy:=hotkeytexty-3 - Gui, Add, GroupBox, % "c" UniqueColor " x" hotkeyX " y" hotkeyY " w" 340 " h" 220 " ", % localizedStrings["gb11"] - local ishotkey:="Edit" - local hotkeycheckboxoptions:="gSettingsUpdateFlag " (ishotkey~="hotkey"?"enabled":"disabled") " c" UniqueColor " x" (hotkeyX+10) " w" 20 " h" 20 " y" - local hotkeyinputoptions:="gSettingsUpdateFlag" " c" 0x000000 " x" (hotkeyx+30) " w" 90 " h" 20 " y" - local hotkeytextoptions:="x" (hotkeyx+130) " w" 200 " h" 20 " y" - - - Gui, Add, Text, % "c" UniqueColor " x" (hotkeyX+10) " w200 h20 y" hotkeytexty-20, % (ishotkey == "Hotkey")?"checkbox to use Windows key as modifier":"" - Gui, Add, Text, % hotkeytextoptions hotkeytexty, % localizedStrings["t34"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions checkboxy " vWinincreaseMapSizeKey", - Gui, Add, % ishotkey, % hotkeyinputoptions checkboxy " vincreaseMapSizeKey", - Gui, Add, Text, % hotkeytextoptions (hotkeytexty+20), % localizedStrings["t35"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+20) " vWdecreaseMapSizeKey", - Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+20) " vdecreaseMapSizeKey", - Gui, Add, Text, % hotkeytextoptions (hotkeytexty+40), % localizedStrings["t36"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+40) " vWinmoveMapLeft", - Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+40) " vmoveMapLeft", - Gui, Add, Text, % hotkeytextoptions (hotkeytexty+60), % localizedStrings["t37"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+60) " vWinmoveMapRight", - Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+60) " vmoveMapRight", - Gui, Add, Text, % hotkeytextoptions (hotkeytexty+80), % localizedStrings["t38"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+80) " vWinmoveMapUp", - Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+80) " vmoveMapUp", - Gui, Add, Text, % hotkeytextoptions (hotkeytexty+100), % localizedStrings["t39"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+100) " vWinmoveMapDown", - Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+100) " vmoveMapDown", - Gui, Add, Text, % hotkeytextoptions (hotkeytexty+120), % localizedStrings["t40"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+120) " vWinhistoryToggleKey", - Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+120) " vhistoryToggleKey", - Gui, Add, Text, % hotkeytextoptions (hotkeytexty+140), % localizedStrings["t41"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+140) " vWinalwaysShowKey", - Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+140) " valwaysShowKey", - Gui, Add, Text, % hotkeytextoptions (hotkeytexty+160), % localizedStrings["t42"] - if ishotkey~="hotkey" - Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+160) " vWinswitchMapMode", - Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+160) " vswitchMapMode", - - - Gui, Add, Link, % "x" (hotkeyx+85) " y" (hotkeyY+359) " w" 200 " h" 20 " ", Click here for possible key combos -} - -SettingsTabOther(x,y){ - global - Gui, Settings:Default - Gui, Tab, Other - local (otherX:=x) , (otherY:=y) - Gui, Add, GroupBox, % "c" UniqueColor " x" otherX " y" otherY " w" 340 " h" 110 " ", % localizedStrings["gb7"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+20) " w" 270 " h" 20 " vshowWaypointLine gSettingsUpdateFlag", % localizedStrings["cb13"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+40) " w" 270 " h" 20 " vshowNextExitLine gSettingsUpdateFlag", % localizedStrings["cb14"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+60) " w" 270 " h" 20 " vshowBossLine gSettingsUpdateFlag", % localizedStrings["cb15"] - Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+80) " w" 270 " h" 20 " vshowQuestLine gSettingsUpdateFlag", % localizedStrings["cb16"] - - local (HudX:=x) , (HudY:=y) - Gui, Add, GroupBox, % "c" UniqueColor " x" x " y" (HudY+=120) " w" 340 " h" 130 " ", % "HUD" - Gui, Add, Checkbox, % "c" UniqueColor " x" (HudX+12) " y" (HudY+20) " w" 270 " h" 20 " vitemCounterEnabled gSettingsUpdateFlag", % localizedStrings["gb29"] - Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+46) " w" 200 " h" 20, % localizedStrings["gb30"] - Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+43) " w" 30 " h" 20 " vitemCounterSize gSettingsUpdateFlag", 75 - Gui, Add, Checkbox, % "c" UniqueColor " x" (HudX+12) " y" (HudY+63) " w" 270 " h" 20 " vbuffBarEnabled gSettingsUpdateFlag", % localizedStrings["gb31"] - Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+86) " w" 200 " h" 20, % localizedStrings["gb32"] - Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+83) " w" 30 " h" 20 " vbuffBarIconSize gSettingsUpdateFlag", 75 - Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+106) " w" 200 " h" 20, % localizedStrings["gb33"] - Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+103) " w" 30 " h" 20 " vbuffBarVerticalOffset gSettingsUpdateFlag", 0 - - local (SplashConfgiX:=x) , (SplashConfgiY:=HudY+120) - Gui, Add, GroupBox, % "c" UniqueColor " x" (SplashConfgiX) " y" (HudY+=130) " w" 340 " h" 120 " ", % "Splash" - Gui, Add, Checkbox, % "c" UniqueColor " x" (SplashConfgiX+=10) " y" (HudY+20) " w" 270 " h" 20 " vStartSplash gSettingsUpdateFlag", % "Start Splash" - Gui, Add, Checkbox, % "c" UniqueColor " x" (SplashConfgiX) " y" (HudY+40) " w" 270 " h" 20 " vLoadingSplash gSettingsUpdateFlag", % "Loading Splash" -} - -SettingsTabProjectiles(x,y){ - global - Gui, Settings:Default - Gui, Tab, Projectiles - local (mY4 := (mY3:=(mY2:=(mY1:=y)+(rowh:=20))+rowh)+rowh) , (mX4 := (mX3:=(mX2:=(mX1:=x+10)+cboxW:=40)+(tW:=100))+cboxW) - local fontwidth:=140 , eboxwidth:=32 - Gui, Add, GroupBox, % "c" UniqueColor " x" (mX1-10) " y" (mY1-16) " w" 340 " h" 400, % localizedStrings["gb8"] - Gui, Add, Checkbox, % "c" UniqueColor " x" mX1 " y" mY1 " w110 h" rowh " vshowPlayerMissiles gSettingsUpdateFlag", % localizedStrings["cb18"] - Gui, Add, Checkbox, % "c" UniqueColor " x" mX1 " y" mY2 " w110 h" rowh " vshowEnemyMissiles gSettingsUpdateFlag", % localizedStrings["cb17"] - Gui, Add, Slider, % "x" mX1 " y" mY3 " h" rowh " vOpac tooltip gOpacitySlide range1-255", % (settings.missileOpacity+0) - local projectileEditOption:=" gSettingsUpdateFlag center x" mX3 " w" eboxwidth " h" rowh " y" - Gui, Add, Edit, % " c" EditColor projectileEditOption mY1 " vmissileMajorDotSize" - Gui, Add, Edit, % " c" EditColor projectileEditOption mY2 " vmissileMinorDotSize" - Gui, Add, Edit, % " c" EditColor projectileEditOption mY3 " vmissileOpacity" - - Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY1 " w" fontwidth " h" rowh, % localizedStrings["t25"] - Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY2 " w" fontwidth " h" rowh, % localizedStrings["t26"] - Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY3 " w" fontwidth " h" rowh, % localizedStrings["t27"] - - local each, mtype - for each,mtype in (Projectilelist()) - { - local mY:=(mY4+each*rowh+5) - Gui, Add, Progress, % "x" 20 " y" mY " w20 h20 cWhite v" mtype "preview Background" settings["missile" mtype "Color"] - Gui, Add,Edit, % "c" settings["missile" mtype "Color"] " x" mX2-30 " y" mY " w" (eboxwidth+50) " h" rowh " vmissile" mtype "Color gSettingsUpdateFlag center" - } - ; we do this seperately and consecutively to force the radio to be "together" without additional code - for each,mtype in (Projectilelist()) - Gui, Add, radio, % " c" settings["missile" mtype "Color"] " x" mX3-47 " y" (mY4+7+(each*20)) " v" mtype "Rcheck gRadioToSliders", % mtype - ;RGB sliders - local (slide), (sliders:=["Red","Green","Blue"]) ,( slidex:=mX3) , (slideH:=250) - local (slidey:=mY4+10), slidetexty:=slidey+250 - for each,slide in sliders - { - Gui, Add, Slider, % "x" (slidex+=30) " y" slidey " h" slideH " w" 50 " vSlider" slide " gColorslide c0x000000 vertical Invert AltSubmit Range0-255 TickInterval" 1, 119 - local Channel:=SubStr(slide, 1 , 1) - Gui, Add, Text, % "c" UniqueColor " x" (slidex+=15) " y" slidetexty " vch" Channel, % Channel - } -} - -SettingsTabAdvanced(x,y){ - global - Gui, Settings:Default - Gui, Tab, Advanced - local (AdvancedX:=x) , (AdvancedY:=y) - Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" AdvancedY " w" 340 " h" 220 " ", % localizedStrings["gb9"] - Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+20) " w" 100 " h" 20 " r2", % localizedStrings["t28"] - Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+40) " w" 40 " h" 20 " vperformanceMode gSettingsUpdateFlag", 50ms - Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+60) " y" (AdvancedY+40) " w" 250 " h" 40 " ", % localizedStrings["t29"] - - Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+109) " w" 250 " h" 20 " ", % localizedStrings["t30"] ;168 - - Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+69) " w" 150 " h" 20 " vshowFPS gSettingsUpdateFlag", % localizedStrings["cb22"] ;128 - Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+240) " y" (AdvancedY+71) " w" 75 " h" 18 " ", % localizedStrings["gb28"] ;fpscap - Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+197) " y" (AdvancedY+68) " w" 40 " h" 20 " vfpscap gSettingsUpdateFlag", 60 ;FPSedit - - Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+130) " w" 150 " h" 20 " venableD2ML gSettingsUpdateFlag", % localizedStrings["cb20"] ;189 - Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+135) " y" (AdvancedY+153) " w" 200 " h" 18 " ", % localizedStrings["t31"] - Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+150) " w" 120 " h" 20 " vwindowTitle gSettingsUpdateFlag", D2R:main - Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+170) " w" 300 " h" 30, % localizedStrings["t32"] - - Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" (AdvancedY+230) " w" 340 " h" 80, % localizedStrings["gb10"] ;289 - Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+250) " w" 200 " h" 20 " vdebug gSettingsUpdateFlag", % localizedStrings["cb21"] - Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+270) " w" 320 " h" 30, % localizedStrings["t33"] - - Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" (AdvancedY+310) " w" 340 " h" 60, % "Settings" - Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+325) " w" 150 " h" 20 " vCustomSettings gSettingsUpdateFlag", Custom Settings colors - Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+160) " y" (AdvancedY+325) " w" 175 " h" 20 " vInvertedColors gSettingsUpdateFlag", Invert Colors (requires restart) - Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+345) " w" 60 " h" 20 " vWindowColor gSettingsUpdateFlag", % settings["WindowColor"] - Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+70) " y" (AdvancedY+348) " w" 75 " h" 18 " ", Window Color - - Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+140) " y" (AdvancedY+345) " w" 60 " h" 20 " vFontColor gSettingsUpdateFlag", % settings["FontColor"] - Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+200) " y" (AdvancedY+348) " w" 75 " h" 18 " ", Font Color - -} - -;colorpicker -showColorPicker(){ - local static ShowPicker := false - local static PickerBuilt := false - if !(PickerBuilt){ - colorpicker() - PickerBuilt:=True - } - ; open the settings window and a given position - if (ShowPicker:=!ShowPicker){ - Gui, ColorPicker:Show,, % "RGB" - } else { - Gui, ColorPicker:hide - } - -} - -colorpicker(){ - global - Gui, ColorPicker:Default - Gui, ColorPicker:-MinimizeBox +AlwaysOnTop - local progressX:=0 - local progressY:=5 - local progressS:=50 - glable:="gColorPickerUpdate" - Gui, ColorPicker:Add, Progress, % "x" progressX " y"progressY " w" progressS " h" progressS " +C0xFF0000 vProg", 100 - Gui, ColorPicker:Add, Edit, % "x" (progressX+=progressS) " y" (progressY) " w" 70 " h20 vHex " glable, 0xFFFF0000 - Gui, ColorPicker:Font, s9 - local buttony:=progressY - Gui, ColorPicker:Add, Button, % "x" progressX " y" (buttony+=20) " w" 70 " h" 15, CopyRGB - Gui, ColorPicker:Add, Button, % "x" progressX " y" (buttony+=15 )" w" 70 " h" 15, CopyAlpha - ;Gui, ColorPicker:Add, Button, % "x" 165 " y" buttony " w75 h23", Close - rgbtX:=13 , rgbty:=buttony+25 - Gui, ColorPicker:Font, s12 - Gui, ColorPicker:Add, Text, % "x" rgbtX " y" rgbty " w20 h20 Center", R - Gui, ColorPicker:Font, s9 - Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vR " glable, 255 - Gui, ColorPicker:Font, s12 - Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", G - Gui, ColorPicker:Font, s9 - Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vG " glable, 0 - Gui, ColorPicker:Font, s12 - Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", B - Gui, ColorPicker:Font, s9 - Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vB " glable, 0 - Gui, ColorPicker:Font, s12 - Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y"rgbty " w25 h25 Center", A - Gui, ColorPicker:Font, s9 - Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vA " glable, 255 - local sliderh:=150 - local sliderw:=25 - local sliderx:=10 - local slidery:=rgbty+50 - options:=" TickInterval1 +Vertical +0x20 +0x200 +Vertical +Invert +Center +Range0-255 -Tabstop AltSubmit " glable - Gui, ColorPicker:Add, Slider, % "x" sliderx " y" slidery " w" sliderw " h" sliderh options " vRS", 255 - Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vGS", 0 - Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vBS", 0 - Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vAS", 255 - - -} - -ColorPickerGuiEscape(){ - ColorPickerGuiClose() -} - -ColorPickerGuiClose(){ - showColorPicker() -} - -ColorPickerUpdate(){ - GuiControlGet, RS - GuiControlGet, GS - GuiControlGet, BS - GuiControlGet, AS - - GuiControlGet, R - GuiControlGet, G - GuiControlGet, B - GuiControlGet, A - GuiControlGet, Hex - GuiControlGet, Prog - - ColorPickerSet("R", RS) - ColorPickerSet("G", GS) - ColorPickerSet("B", BS) - ColorPickerSet("A", AS) - ColorPickerSet("RS", R, "+Range0-255") - ColorPickerSet("GS", G, "+Range0-255") - ColorPickerSet("BS", B, "+Range0-255") - ColorPickerSet("AS", A, "+Range1-255") - ColorPickerSet("Hex", ARGB(R, G, B, A)) - ColorPickerSet("Prog",, "+C" ARGB(R, G, B)) -} - -ColorPickerButtonCopyRGB(){ - GuiControlGet, Hex - return Clipboard:=SubStr(Hex, 5) -} - -ColorPickerButtonCopyAlpha(){ - GuiControlGet, R - GuiControlGet, G - GuiControlGet, B - GuiControlGet, A - return clipboard:=SubStr(ARGB(R, G, B, A), 1 , 4) -} - -ColorPickerSet(Control, Data := "", AddOpt := "") { - GuiControl, %AddOpt%, %Control%, % Data - return !ErrorLevel -} diff --git a/src/ui/splash/splash.ahk b/src/ui/splash/splash.ahk index d111e9b..e0d3e24 100644 --- a/src/ui/splash/splash.ahk +++ b/src/ui/splash/splash.ahk @@ -2,16 +2,10 @@ StartSplash(){ if settings.StartSplash Splash(version,3000,"StartSettings") } - LoadingSplash(){ Splash("loading",0,,0.25) } -StartSettings(){ - SetTimer, ShowSettings, -1000 - OnMessage(0x201, "WM_LBUTTONDOWN") -} - Splash(text="",time=1000,onclickcmd=False,opacity=1){ global if !FileExist(settings.SplashImg) @@ -69,7 +63,6 @@ Splash(text="",time=1000,onclickcmd=False,opacity=1){ if (time !=0) SetTimer, SplashClose, % time } - SplashClose(){ Gui, Splash:Destroy OnMessage(0x201, "WM_LBUTTONDOWN") From a38093f358ed6ae9f9221a2c8329975c1eee9f0a Mon Sep 17 00:00:00 2001 From: Teo <106943092+t3ohm@users.noreply.github.com> Date: Wed, 12 Oct 2022 19:47:10 -0700 Subject: [PATCH 11/12] Revert "Revert "Split Settings up"" This reverts commit 8e97e30267c08579538afd7ab444106f38c8ef2c. --- src/ui/settingsPanel.ahk | Bin 112462 -> 22372 bytes src/ui/settingsTabs.ahk | 632 +++++++++++++++++++++++++++++++++++++++ src/ui/splash/splash.ahk | 7 + 3 files changed, 639 insertions(+) create mode 100644 src/ui/settingsTabs.ahk diff --git a/src/ui/settingsPanel.ahk b/src/ui/settingsPanel.ahk index 5f76118b05e7632ab2140b76013725fe771a6fde..a8815fc3ac91ae3abcc05c00f29ed40d8ac092ba 100644 GIT binary patch delta 132 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 diff --git a/src/ui/settingsTabs.ahk b/src/ui/settingsTabs.ahk new file mode 100644 index 0000000..d8520e8 --- /dev/null +++ b/src/ui/settingsTabs.ahk @@ -0,0 +1,632 @@ + +OpacitySlide(){ + GuiControlGet, Opac + GuiControl, , missileOpacity, % Format("0x{:X}", Opac) + SettingsUpdateFlag() +} + +PathSlide(){ + GuiControlGet, PathcolorSlide + GuiControl, , pathFindingColour, % RGB300(PathcolorSlide) + SettingsUpdateFlag() +} + +Colorslide(){ + Gui, Settings:Default + lastformat:=A_FormatInteger + SetFormat, IntegerFast, Hex + GuiControlGet, SliderRed + GuiControlGet, SliderGreen + GuiControlGet, SliderBlue + + if StrLen(R:=Strip0x(ConvertD2H(SliderRed))) < 2 + R:=0 R + if StrLen(G:=Strip0x(ConvertD2H(SliderGreen))) < 2 + G:=0 G + if StrLen(B:=Strip0x(ConvertD2H(SliderBlue))) < 2 + B:=0 B + StringUpper, R, R + StringUpper, G, G + StringUpper, B, B + SetFormat, IntegerFast, hex + if selected:=RadioSelect(Projectilelist()){ + GuiControl % "+Background" R G B , % selected "preview" + + misslecontrol:="missile" selected "Color" + OutputDebug, % rcheck:=selected "Rcheck" + colorRGB:="+c" R G B + GuiControl % colorRGB , % rcheck + GuiControl,, % rcheck , % selected + + GuiControl % colorRGB , % misslecontrol + GuiControl, , % misslecontrol, % R G B + } + SetFormat, IntegerFast, % lastformat + SettingsUpdateFlag() +} + +RadioToSliders(){ + GuiControlGet, RBG,, % "missile" RadioSelect(Projectilelist()) "Color" + GuiControl,, SliderRed , % R:=(R:="0x" SubStr(RBG, 1, 2))+0 + GuiControl,, SliderGreen , % G:=(G:="0x" SubStr(RBG, 3, 2))+0 + GuiControl,, SliderBlue , % B:=(B:="0x" SubStr(RBG, 5, 2))+0 + SettingsUpdateFlag() +} + + + +RadioSelect(Rlist){ + lastformat:=A_FormatInteger + for each,Radio in (Rlist) + { + Selected = %Radio%Rcheck + GuiControlGet,controlvar,, %Selected% + if (controlvar) + { + SetFormat, integer, D + Selected:=RegExReplace(Selected,"(.*)Rcheck$","$1") + SetFormat, integer, % lastformat + return Selected + } + } +} + +DiscordLink(){ + run, % "https://discord.com/invite/qEgqyVW3uj" +} +ReadMeLink(){ + run, % "https://github.com/joffreybesos/d2r-mapview#readme" +} + +Projectilelist(){ + return ["PhysicalMajor","PhysicalMinor","FireMajor","FireMinor","IceMajor","IceMinor" + ,"LightMajor","LightMinor","PoisonMajor","PoisonMinor","MagicMajor","MagicMinor"] +} + +TabTitles(){ + return "Info|General|Map Items|Game Data|NPCs|Immunities|Item Filter|Hotkeys|Other|Projectiles|Advanced" +} + +SettingDefault(setting){ + return (settings[setting]?settings[setting]:defaultSettings[setting]) +} + +SettingsTabInfo(x,y){ + global + Gui, Settings:+labelSettings + Gui, Settings:Default + Gui, Tab, Info + local (InfoX:=x) , (InfoY:=y) + + Gui, Add, Picture, % "x" (InfoX-20) " y" 59 " w" 370 " h" 320, % settings.SplashImg + ;Gui, Add, Text, % "c" 0xff0000 " x" (SettingsAnchorX+20) " y" (InfoY+=20) " w" 300 " h" 250 " +Center Backgroundtrans", d2r-mapview %version% + + ;Gui, Add, Text, % "c" UniqueColor " x" (SettingsAnchorX+15) " y" (InfoY+=56) " w" 300 " h" 120 " +Center Backgroundtrans", % localizedStrings["uitext"] ;what is this? + local locale := settings["locale"] + local choiceIdx := LocaleToChoice(locale) + Gui, Add, Button, % "x" (SettingsAnchorX+90) " y" (SettingsAnchorY+311) " h" 23 "Backgroundtrans AltSubmit vRevertDefaults gRevertToDefaults", Default All Settings + Gui, Add, DropDownList, % "x" (SettingsAnchorX+220) " y" (SettingsAnchorY+311) " h" 180 (" Choose" choiceIdx) "Backgroundtrans AltSubmit vlocaleIdx gSettingsUpdateFlag", English|中文|Deutsch|español|français|italiano|한국어|polski|español mexicano|日本語|português|Русский|福佬話 + Gui, Font, % "s" SettingsD2RFontSize + Gui, Add, Link, % " c" 0x00FF00 " x" (SettingsAnchorX) " y" (SettingsAnchorY+339) " w" 100 " h" 30 " gReadMeLink", Github + Gui, Add, Link, % "c" 0xff0000 " x" (SettingsAnchorX+130) " y" (SettingsAnchorY+339) " w"100 " h" 30 " gDiscordLink", v%version% + Gui, Add, Link, % " c" 0x00FF00 " x" (SettingsAnchorX+260) " y" (SettingsAnchorY+339) " w"100 " h" 30 " gDiscordLink", Discord + Gui, Font, % "s" SettingFontsize1 +} + +SettingsTabGeneral(x,y){ + global + Gui, Settings:Default + Gui, Tab, General + local (mapserverX:=x),(mapserverY:=y),(mapserverW:=),(mapserverH:=),(mapserverW:=20),(mapserverH:=20) + Gui, Add, GroupBox, % "c" UniqueColor " x" mapserverX " y" mapserverY " w" 340 " h" 80 , % localizedStrings["s3"] ;mapserver + Gui, Add, Edit, % "c" EditColor " x" (mapserverX+=18) " y" (mapserverY+=20) " w300 vBaseUrl gSettingsUpdateFlag" , settings.baseUrl + Gui, Add, Text, % "c" disabledfont " x" (mapserverX+=1) " y" (mapserverY+=25) " w180" , % "Ex: http://localhost:3002`nhttp://192.168.1.123:3002" + + local (MapPosX:=SettingsAnchorX), (MapPosY:=mapserverY+71), (MapPosW:=0), (MapPosH:=0) + Gui, Add, GroupBox, % "c" UniqueColor " x" MapPosX " y" MapPosY " w340 h80", % MapPos:="Map Position" + Gui, Add, DropDownList, % "x" (MapPosX+10) " y" (MapPosY+20) " w" 140 " h" 80 " vmapPosition gSettingsUpdateFlag", + Gui, Add, Checkbox, % "c" UniqueColor " x" (MapPosX+180) " y" (MapPosY+25) " w" 135 " h" 20 " vAlwaysShowMap gSettingsUpdateFlag", % "Always show map" + Gui, Add, Checkbox, % "c" UniqueColor " x" (MapPosX+10) " y" (MapPosY+45) " w" 135 " h" 20 " vHideTown gSettingsUpdateFlag", % "Hide town maps" + + local (CenPosX:=SettingsAnchorX), (CenPosY:=MapPosY+85), (CenPosW:=), (CenPosH:=) + Gui, Add, GroupBox, % "c" UniqueColor " x" CenPosX " y" CenPosY " w" 340 " h" 80, % "Centered position settings" + local (CenCol4:=(CenCol3:=(CenCol2:=(CenCol1:=CenPosX+10)+50)+115)+50) + local (CenRow4:=(CenRow3:=(CenRow2:=(CenRow1:=CenPosY+20)+5)+15)+5) + Gui, Add, Edit, % "c" EditColor " x" CenCol1 " y" CenRow1 " w" 44 " h" 20 " vcenterModeScale gSettingsUpdateFlag" + Gui, Add, Edit, % "c" EditColor " x" CenCol1 " y" CenRow3 " w" 44 " h" 20 " vcenterModeOpacity gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CenCol2 " y" CenRow2 " w" 80 " h" 15, % "Centered Scale" + Gui, Add, Text, % "c" UniqueColor " x" CenCol2 " y" CenRow4 " w" 80 " h" 15, % "Center Opacity (0-1)" + Gui, Add, Edit, % "c" EditColor " x" CenCol3 " y" CenRow1 " w" 44 " h" 20 " vcenterModeOffsetX gSettingsUpdateFlag" + Gui, Add, Edit, % "c" EditColor " x" CenCol3 " y" CenRow3 " w" 44 " h" 20 " vcenterModeOffsetY gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CenCol4 " y" CenRow2 " w" 80 " h" 15, % "X offset" + Gui, Add, Text, % "c" UniqueColor " x" CenCol4 " y" CenRow4 " w" 80 " h" 15, % "Y offset" + + local (CorPosX:=SettingsAnchorX), (CorPosY:=CenRow4) + Gui, Add, GroupBox, % "c" UniqueColor " x" CorPosX " y" (CorPosY+40) " w" 340 " h" 80, % "Corner position settings" + local (CorCol4:=(CorCol3:=(CorCol2:=(CorCol1:=CorPosX+10)+50)+115)+50) + local (CorRow4:=(CorRow3:=(CorRow2:=(CorRow1:=CorPosY+60)+5)+15)+5) + Gui, Add, Edit, % "c" EditColor " x" CorCol1 " y" CorRow1 " w" 44 " h" 20 " vcornerModeScale gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CorCol2 " y" CorRow2 " w" 80 " h" 15, % "Corner Scale" + Gui, Add, Edit, % "c" EditColor " x" CorCol1 " y" CorRow3 " w" 44 " h20 vcornerModeOpacity gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CorCol2 " y" CorRow4 " w" 80 " h" 15, % "Corner Opacity (0-1)" + Gui, Add, Edit, % "c" EditColor " x" CorCol3 " y" CorRow1 " w" 44 " h" 20 " vcornerModeOffsetX gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CorCol4 " y" CorRow2 " w" 80 " h" 15, % "X offset" + Gui, Add, Edit, % "c" EditColor " x" CorCol3 " y" CorRow3 " w" 44 " h" 20 " vcornerModeOffsetY gSettingsUpdateFlag" + Gui, Add, Text, % "c" UniqueColor " x" CorCol4 " y" CorRow4 " w" 80 " h" 15, % "Y offset" +} + +SettingsTabMapItems(x,y){ + global + Gui, Settings:Default + Gui, Tab, Map Items + local (MapItemX:=x),(MapItemY:=y) + local (MapItemCol4:=(MapItemCol3:=(MapItemCol2:=(MapItemCol1:=MapItemX+12)+140)+53)+50) + local (PortalRow4:=(PortalRow3:=(PortalRow2:=(PortalRow1:=y+20)+5)+15)+5) + Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" MapItemY " w" 340 " h" (PortalsGroupH:=70), % localizedStrings["s25"] + Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" PortalRow1 " w" 140 " h" 20 " vShowPortals gSettingsUpdateFlag", % localizedStrings["s26"] ;True + Gui, Add, Edit, % " c" EditColor " x" (PortalColorx:=MapItemCol2) " y" (PortalColory:=PortalRow1) " w" (PortalColorwidth:=50) " h" 20 " vPortalColor gSettingsUpdateFlag", 00AAFF + Gui, Add, Text, % "c" SettingDefault("PortalColor") " x" (PortalColorx+PortalColorwidth+5) " y" (PortalColory+3) " h" 20, % localizedStrings["s27"] + Gui, Add, Edit, % "c" EditColor " x" (RPortalColorx:=MapItemCol2) " y" (RedPortalColory:=PortalRow1+20) " w" 50 " h" 20 " vRedPortalColor gSettingsUpdateFlag", FF0000 + Gui, Add, Text, % "c" SettingDefault("RedPortalColor") " x" (RPortalColorx+PortalColorwidth+5) " y" (RedPortalColory+3) " h" 20, % localizedStrings["s28"] + local ShrinesY:=(PortalRow1+PortalsGroupH+5) + + + Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" ShrinesY " w" 340 " h" PortalsGroupH , % localizedStrings["s29"] + Gui, Font, % "s" SettingFontsize1 " C" UniqueColor, + local shrinerow2:=(shrinerow1:=ShrinesY+20)+20 + Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (shrinerow1) " w" 140 " h" 20 " vShowShrines gSettingsUpdateFlag", % localizedStrings["s30"] ;True + Gui, Add, Edit, % " c" EditColor " x" MapItemCol2 " y" shrinerow1 " w" 50 " h" 20 " vShrineColor gSettingsUpdateFlag", FFD700 + Gui, Add, Edit, % "c" EditColor " x" MapItemCol2 " y" shrinerow2 " w" 50 " h" 20 " vShrineTextSize gSettingsUpdateFlag", 14 + Gui, Add, Text, % "c" SettingDefault("ShrineColor") " x" MapItemCol3 " y" (shrinerow2-17) " h" 20 , % localizedStrings["s31"] + Gui, Add, Text, % "c" UniqueColor " x" MapItemCol3 " y" (shrinerow2+3) " h" 20 , % localizedStrings["s32"] + + local ChestY:=(ShrinesY+PortalsGroupH+20) + Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" ChestY " w" 168 " h" (ChestH:=PortalsGroupH-20) , % localizedStrings["gb1"] + Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (ChestY+20) " w" 120 " h" 20 " vShowChests gSettingsUpdateFlag", % localizedStrings["cb1"] + + Gui, Add, GroupBox, % "c" UniqueColor " x" (MapItemCol2+20)" y" ChestY " w" 168 " h" 50 " ", % localizedStrings["gb18"] + Gui, Add, Edit, % "c" EditColor " x" (MapItemCol2+25) " y" (ChestY+20) " w" 25 " h" 20 " vexitTextSize gSettingsUpdateFlag", 12 + Gui, Add, Text, % "c" UniqueColor " x" (MapItemCol3) " y" (ChestY+23) " w" 90 " h" 20 " ", % localizedStrings["gb19"] + + local PathfindY:=(ChestY+ChestH+20) + Gui, Add, GroupBox, % "c" UniqueColor " x" MapItemX " y" PathfindY " w" 340 " h" 70 " ", % "Pathfinding" + Gui, Add, Checkbox, % "c" UniqueColor " x" MapItemCol1 " y" (PathfindY+20) " w" 120 " h" 20 " vshowPathFinding gSettingsUpdateFlag", % "Show pathfinding" + + Gui, Add, Edit, % "c" EditColor " x" MapItemCol2 " y" (PathfindY+18) " w" 60 " h" 20 " vpathFindingColour gSettingsUpdateFlag" + Gui, Add, Text, % "c" SettingDefault("pathFindingColour") " x" (MapItemCol3+10) " y" (PathfindY+20) " w" 90 " h" 20 " ", % "Pathfinding color" + ;Gui, Add, Slider, % "x" (MapItemCol3+5) " y" (PathfindY+40) " h" 20 " w" 84 " vPathcolorSlide gPathSlide range0-300", 0 +} + +SettingsTabGameData(x,y){ + global + Gui, Settings:Default + Gui, Tab, Game Data + { ; Game History + local (HistoryX:=x) , (HistoryY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" (HistoryX) " y" (HistoryY) " w" 340 " h" 115 " ", % localizedStrings["gb2"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (HistoryX+12) " y" (HistoryY+20) " w" 270 " h" 20 " vshowGameHistory gSettingsUpdateFlag", % localizedStrings["cb2"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (HistoryX+12) " y" (HistoryY+40) " w" 270 " h" 20 " vshowAllHistory gSettingsUpdateFlag", % localizedStrings["cb3"] + Gui, Add, Text, % "c" UniqueColor " x" (HistoryX+75) " y" (HistoryY+63) " w" 150 " h" 20 " ", % localizedStrings["t1"] + Gui, Add, DropDownList, % "x" (HistoryX+12) " y" (HistoryY+60) " w" 60 " h" 80 " vhistoryTextAlignment gSettingsUpdateFlag", LEFT||RIGHT + Gui, Add, Text, % "c" UniqueColor " x" (HistoryX+55) " y" (HistoryY+90) " w" 250 " h" 20 " ", % localizedStrings["t4"] + Gui, Add, Edit, % "c" EditColor " x" (HistoryX+12) " y" (HistoryY+86) " w" 40 " h" 20 " vhistoryTextSize gSettingsUpdateFlag", 20 + } + { ; Game info + local (gameinfoX:=x) , (gameinfoY:=179) + Gui, Add, GroupBox, % "c" UniqueColor " x" (gameinfoX) " y" (gameinfoY) " w" 340 " h" 95 " ", % localizedStrings["gb20"] ;y179 + Gui, Add, Checkbox, % "c" UniqueColor " x" (gameinfoX+=12) " y" (gameinfoY+22) " w" 200 " h" 20 " vshowGameInfo gSettingsUpdateFlag", % localizedStrings["cb4"] + + + Gui, Add, DropDownList, % "x" gameinfoX " y" (gameinfoY+43) " w" 60 " h" 80 " vgameInfoAlignment gSettingsUpdateFlag", RIGHT||LEFT ;y219 + Gui, Add, Text, % "c" UniqueColor " x" (gameinfoX+63) " y" (gameinfoY+45) " w" 150 " h" 20 " ", % localizedStrings["t2"] + + Gui, Add, Checkbox, % "c" UniqueColor " x" (gameinfoX+215) " y" (gameinfoY+43) " w" 84 " h" 20 " vshowNumPlayers gSettingsUpdateFlag", % "Player count" + + + Gui, Add, Edit, % "c" EditColor " x" gameinfoX " y" (gameinfoY+69) " w" 40 " h" 20 " vgameInfoFontSize gSettingsUpdateFlag", 18 + Gui, Add, Text, % "c" UniqueColor " x" (gameinfoX+43) " y" (gameinfoY+72) " w" 250 " h" 20 " ", % localizedStrings["t5"] + + } + { ; PLayer Location + local (PLayersLocX:=x) , (PLayersLocY:=279) + Gui, Add, GroupBox, % "c" UniqueColor " x" (PLayersLocX) " y" PLayersLocY " w" 340 " h" 55 " ", % localizedStrings["gb21"] ; PLayer Location + Gui, Add, Checkbox, % "c" UniqueColor " x" (PLayersLocX+12) " y" (PLayersLocY+20) " w" 190 " h" 20 " vshowPartyLocations gSettingsUpdateFlag", % localizedStrings["gb22"] + Gui, Add, Edit, % "c" EditColor " x" (PLayersLocX+212) " y" (PLayersLocY+20) " w" 40 " h" 20 " vpartyInfoFontSize gSettingsUpdateFlag", 0 + Gui, Add, Text, % "c" UniqueColor " x" (PLayersLocX+255) " y" (PLayersLocY+23) " w" 70 " h" 20 " ", % localizedStrings["gb27"] ; font size + } + { ; Mouse over resist and health + local ( MouseoverX:=x) , (MouseoverY:=340) + Gui, Add, GroupBox, % "c" UniqueColor " x" MouseoverX " y" (MouseoverY) " w" 340 " h" 80 " ", % localizedStrings["gb26"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MouseoverX+12) " y" (MouseoverY+20) " w" 190 " h" 20 " vshowResists gSettingsUpdateFlag", % localizedStrings["gb25"] + Gui, Add, Text, % "c" UniqueColor " x" (MouseoverX+255) " y" (MouseoverY+23) " w" 50 " h" 20 " ", % localizedStrings["gb27"] + Gui, Add, Edit, % "c" EditColor " x" (MouseoverX+212) " y" (MouseoverY+20) " w" 40 " h" 20 " vresistFontSize gSettingsUpdateFlag", 0 + Gui, Add, Checkbox, % "c" UniqueColor " x" (MouseoverX+12) " y" (MouseoverY+40) " w" 190 " h" 20 " vshowHealthPc gSettingsUpdateFlag", % localizedStrings["gb24"] + Gui, Add, Text, % "c" UniqueColor " x" (MouseoverX+255) " y" (MouseoverY+43) " w" 50 " h" 20 " ", % localizedStrings["gb27"] + Gui, Add, Edit, % "c" EditColor " x" (MouseoverX+212) " y" (MouseoverY+40) " w" 40 " h" 20 " vhealthFontSize gSettingsUpdateFlag", 0 + } +} + +SettingsTabNPCs(x,y){ + global + Gui, Settings:Default + Gui, Tab, NPCs + { ; Monster dots + local ( MonDotX:=x) , (MonDotY:=y) ;; GroupboxX:=10, GroupboxY:=59 + Gui, Add, GroupBox, % "c" UniqueColor " x" MonDotX " y" MonDotY " w" 340 " h" 165 " ", % localizedStrings["gb3"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+20) " w" 150 " h" 20 " vshowNormalMobs gSettingsUpdateFlag", % localizedStrings["cb5"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+40) " w" 150 " h" 20 " vshowUniqueMobs gSettingsUpdateFlag", % localizedStrings["cb6"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+60) " w" 150 " h" 20 " vshowBosses gSettingsUpdateFlag", % localizedStrings["cb7"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (MonDotX+12) " y" (MonDotY+80) " w" 150 " h" 20 " vshowDeadMobs gSettingsUpdateFlag", % localizedStrings["cb8"] + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+23) " w" 30 " h" 20 " ", % "Size" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+20) " w" 30 " h" 20 " vnormalDotSize gSettingsUpdateFlag", 2.5 + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+43) " w" 30 " h" 20 " ", % "Size" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+40) " w" 30 " h" 20 " vuniqueDotSize gSettingsUpdateFlag", 5 + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY+63) " w" 30 " h" 20 " ", % "Size" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+60) " w" 30 " h" 20 " vbossDotSize gSettingsUpdateFlag", 5 + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+195) " y" (MonDotY-59)+142 " w" 30 " h" 20 " ", % "Size" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+162) " y" (MonDotY+80) " w" 30 " h" 20 " vdeadDotSize gSettingsUpdateFlag", 2 + + Gui, Add, Text, % "c" SettingDefault("normalMobColor") " x" (MonDotX+287) " y" (MonDotY+23) " w" 50 " h" 20 " ", % "Colour" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+20) " w" 50 " h" 20 " vnormalMobColor gSettingsUpdateFlag", FFFFFF + Gui, Add, Text, % "c" SettingDefault("uniqueMobColor") " x" (MonDotX+287) " y" (MonDotY+43) " w" 50 " h" 20 " ", % "Colour" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+40) " w" 50 " h" 20 " vuniqueMobColor gSettingsUpdateFlag", D4AF37 + Gui, Add, Text, % "c" SettingDefault("bossColor") " x" (MonDotX+287) " y" (MonDotY+63) " w" 50 " h" 20 " ", % "Colour" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+60) " w" 50 " h" 20 " vbossColor gSettingsUpdateFlag", FF0000 + Gui, Add, Text, % "c" SettingDefault("deadColor") " x" (MonDotX+287) " y" (MonDotY+83) " w" 50 " h" 20 " backgroundFFFFFF", % "Colour" + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+235) " y" (MonDotY+80) " w" 50 " h" 20 " vdeadColor gSettingsUpdateFlag", 000000 + + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+45) " y" (MonDotY+113) " w" 190 " h" 20 " ", % localizedStrings["t14"] + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+12) " y" (MonDotY+110) " w" 30 " h" 20 " vnormalImmunitySize gSettingsUpdateFlag", 4 + Gui, Add, Text, % "c" UniqueColor " x" (MonDotX+45) " y" (MonDotY+133) " w" 190 " h" 20 " ", % localizedStrings["t15"] + Gui, Add, Edit, % "c" EditColor " x" (MonDotX+12) " y" (MonDotY+130) " w" 30 " h" 20 " vuniqueImmunitySize gSettingsUpdateFlag", 11 + } + { ; Friendly NPCs + local (FriendlyNPCsX:=x), (FriendlyNPCsY:=209) + Gui, Add, GroupBox, % "c" UniqueColor " x" FriendlyNPCsX " y" (FriendlyNPCsY+20) " w" 340 " h" 130 " ", % localizedStrings["gb12"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+40) " w" 250 " h" 20 " vShowOtherPlayers gSettingsUpdateFlag", % localizedStrings["s34"] ;True + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+60) " w" 270 " h" 20 " vShowOtherPlayerNames gSettingsUpdateFlag", % localizedStrings["s35"] ;False + + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+80) " w" 160 " h" 20 " vshowMerc gSettingsUpdateFlag", % localizedStrings["gb13"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+100) " w" 160 " h" 20 " vshowTownNPCs gSettingsUpdateFlag", % localizedStrings["gb14"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+12) " y" (FriendlyNPCsY+120) " w" 160 " h" 20 " vNPCsAsCross gSettingsUpdateFlag", % localizedStrings["gb15"] + + Gui, Add, Text, % "c" SettingDefault("mercColor") " x" (FriendlyNPCsX+245) " y" (FriendlyNPCsY+82) " w" 90 " h" 20 " ", % localizedStrings["gb16"] + Gui, Add, Edit, % "c" EditColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+79) " w" 70 " h" 20 " vmercColor gSettingsUpdateFlag", % SettingDefault("mercColor") + + Gui, Add, Text, % "c" SettingDefault("townNPCColor") " x" (FriendlyNPCsX+245) " y" (FriendlyNPCsY+102) " w" 90 " h" 20 " ", % localizedStrings["gb17"] + Gui, Add, Edit, % "c" EditColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+100) " w" 70 " h" 20 " vtownNPCColor gSettingsUpdateFlag", % SettingDefault("townNPCColor") ;250 settings["townNPCColor"] + + Gui, Add, Checkbox, % "c" UniqueColor " x" (FriendlyNPCsX+172) " y" (FriendlyNPCsY+120) " w" 160 " h" 20 " vshowTownNPCNames gSettingsUpdateFlag", % localizedStrings["gb23"] + } +} + +SettingsTabImmunes(x,y){ + global + Gui, Settings:Default + Gui, Tab, Immunities + { ; Monster Immunities + local (ImmunX:=x) , (ImmunY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" ImmunX " y" y " w" 340 " h" 170 " ", % localizedStrings["gb4"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (ImmunX+10) " y" (ImmunY+20) " w" 210 " h" 20 " vshowImmunities gSettingsUpdateFlag", % localizedStrings["cb9"] + Gui, Add, Text, % "c" settings.physicalImmuneColor " x" (ImmunX+85) " y" (ImmunY+43) " w" 140 " h" 20 " ", % localizedStrings["t16"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" ImmunY+40 " w" 70 " h" 20 " vphysicalImmuneColor gSettingsUpdateFlag", % settings.physicalImmuneColor + Gui, Add, Text, % "c" settings.magicImmuneColor " x" (ImmunX+85) " y" (ImmunY+63) " w" 140 " h" 20 " ", % localizedStrings["t17"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+60) " w" 70 " h" 20 " vmagicImmuneColor gSettingsUpdateFlag", % settings.magicImmuneColor + Gui, Add, Text, % "c" settings.fireImmuneColor " x" (ImmunX+85) " y" (ImmunY+83) " w" 140 " h" 20 " ", % localizedStrings["t18"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" ImmunY+80 " w" 70 " h" 20 " vfireImmuneColor gSettingsUpdateFlag", % settings.fireImmuneColor + Gui, Add, Text, % "c" settings.lightImmuneColor " x" (ImmunX+85) " y" (ImmunY+103) " w" 140 " h" 20 " ", % localizedStrings["t19"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+100) " w" 70 " h" 20 " vlightImmuneColor gSettingsUpdateFlag", % settings.lightImmuneColor + Gui, Add, Text, % "c" settings.coldImmuneColor " x" (ImmunX+85) " y" (ImmunY+123) " w" 140 " h" 20 " ", % localizedStrings["t20"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+120) " w" 70 " h" 20 " vcoldImmuneColor gSettingsUpdateFlag", % settings.coldImmuneColor + Gui, Add, Text, % "c" settings.poisonImmuneColor " x" (ImmunX+85) " y" (ImmunY+143) " w" 140 " h" 20 " ", % localizedStrings["t21"] + Gui, Add, Edit, % "c" EditColor " x" (ImmunX+12) " y" (ImmunY+140) " w" 70 " h" 20 " vpoisonImmuneColor gSettingsUpdateFlag", % settings.poisonImmuneColor + } +} + +SettingsTabItemFilter(x,y){ + global + Gui, Settings:Default + Gui, Tab, Item Filter + local (ItemFilterX:=x) , (ItemFilterY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" x " y" y " w" 340 " h" 180 " ", % localizedStrings["gb5"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+20) " w" 200 " h" 20 " vEnableItemFilter gSettingsUpdateFlag", % localizedStrings["cb10"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+40) " w" 200 " h" 20 " vallowItemDropSounds gSettingsUpdateFlag", % localizedStrings["cb11"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+60) " w" 200 " h" 20 " vshowItemStats gSettingsUpdateFlag", % "Show item stats" + + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+80) " w" 200 " h" 20 " vitemLogEnabled gSettingsUpdateFlag", % "Show item log" + + Gui, Add, Checkbox, % "c" UniqueColor " x" (ItemFilterX+12) " y" (ItemFilterY+100) " w" 200 " h" 20 " vincludeVendorItems gSettingsUpdateFlag", % "Include vendor items" + + Gui, Add, Edit, % "c" EditColor " x" (ItemFilterX+12) " y" (ItemFilterY+123) " w" 20 " h" 20 " vitemFontSize gSettingsUpdateFlag", 12 + Gui, Add, Text, % "c" UniqueColor " x" (ItemFilterX+35) " y" 185 " w" 80 " h" 20, % localizedStrings["cb23"] + Gui, Add, Edit, % "c" EditColor " x" (ItemFilterX+12) " y" (ItemFilterY+147) " w" 20 " h" 20 " vitemLogFontSize gSettingsUpdateFlag", % 18 + Gui, Add, Text, % "c" UniqueColor " x" (ItemFilterX+35) " y" (ItemFilterY+150) " w" 80 " h" 20, % "Log font size" + + local (TTSX:=x) , (TTSY:=ItemFilterY+200) + Gui, Add, GroupBox, % "c" UniqueColor " x" (TTSX) " y" (TTSY) " w" 340 " h" 135 " ", % localizedStrings["gb6"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (TTSX+12) " y" (TTSY+18) " w" 200 " h" 20 " vallowTextToSpeech gSettingsUpdateFlag", % localizedStrings["cb12"] + Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+41) " w" 200 " h" 20, % localizedStrings["t23"] + Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+38) " w" 30 " h" 20 " vtextToSpeechVolume gSettingsUpdateFlag", 50 + Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+61) " w" 200 " h" 20, % localizedStrings["t22"] + Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+58) " w" 30 " h" 20 " vtextToSpeechPitch gSettingsUpdateFlag", 1 + Gui, Add, Text, % "c" UniqueColor " x" (TTSX+43) " y" (TTSY+81) " w" 200 " h" 20, % localizedStrings["t24"] + Gui, Add, Edit, % "c" EditColor " x" (TTSX+12) " y" (TTSY+78) " w" 30 " h" 20 " vtextToSpeechSpeed gSettingsUpdateFlag", 1 + + voiceList := GetVoiceList() + chosenVoice := settings["chosenVoice"] + oSPVoice.Voice := oSPVoice.GetVoices().Item(chosenVoice-1) + Gui, Add, DropDownList, % "x" (TTSX+12) " y" (ItemFilterY+304) " w" 200 " h" 90 " vChosenVoice Choose" chosenVoice " ReadOnly AltSubmit gSettingsUpdateFlag", % voiceList + + Gui, Add, Link, % "x" (ItemFilterY+85) " y" (ItemFilterY+359) " w" 200 " h" 20 " ", Click here for the wiki on item filter +} + +SettingsTabHotkeys(x,y){ + global + Gui, Settings:Default + Gui, Tab, Hotkeys + local (hotkeyX:=x) , (hotkeyY:=y) , hotkeytexty:=95 , checkboxy:=hotkeytexty-3 + Gui, Add, GroupBox, % "c" UniqueColor " x" hotkeyX " y" hotkeyY " w" 340 " h" 220 " ", % localizedStrings["gb11"] + local ishotkey:="Edit" + local hotkeycheckboxoptions:="gSettingsUpdateFlag " (ishotkey~="hotkey"?"enabled":"disabled") " c" UniqueColor " x" (hotkeyX+10) " w" 20 " h" 20 " y" + local hotkeyinputoptions:="gSettingsUpdateFlag" " c" 0x000000 " x" (hotkeyx+30) " w" 90 " h" 20 " y" + local hotkeytextoptions:="x" (hotkeyx+130) " w" 200 " h" 20 " y" + + + Gui, Add, Text, % "c" UniqueColor " x" (hotkeyX+10) " w200 h20 y" hotkeytexty-20, % (ishotkey == "Hotkey")?"checkbox to use Windows key as modifier":"" + Gui, Add, Text, % hotkeytextoptions hotkeytexty, % localizedStrings["t34"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions checkboxy " vWinincreaseMapSizeKey", + Gui, Add, % ishotkey, % hotkeyinputoptions checkboxy " vincreaseMapSizeKey", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+20), % localizedStrings["t35"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+20) " vWdecreaseMapSizeKey", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+20) " vdecreaseMapSizeKey", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+40), % localizedStrings["t36"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+40) " vWinmoveMapLeft", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+40) " vmoveMapLeft", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+60), % localizedStrings["t37"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+60) " vWinmoveMapRight", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+60) " vmoveMapRight", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+80), % localizedStrings["t38"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+80) " vWinmoveMapUp", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+80) " vmoveMapUp", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+100), % localizedStrings["t39"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+100) " vWinmoveMapDown", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+100) " vmoveMapDown", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+120), % localizedStrings["t40"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+120) " vWinhistoryToggleKey", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+120) " vhistoryToggleKey", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+140), % localizedStrings["t41"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+140) " vWinalwaysShowKey", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+140) " valwaysShowKey", + Gui, Add, Text, % hotkeytextoptions (hotkeytexty+160), % localizedStrings["t42"] + if ishotkey~="hotkey" + Gui, Add, checkbox, % hotkeycheckboxoptions (checkboxy+160) " vWinswitchMapMode", + Gui, Add, % ishotkey, % hotkeyinputoptions (checkboxy+160) " vswitchMapMode", + + + Gui, Add, Link, % "x" (hotkeyx+85) " y" (hotkeyY+359) " w" 200 " h" 20 " ", Click here for possible key combos +} + +SettingsTabOther(x,y){ + global + Gui, Settings:Default + Gui, Tab, Other + local (otherX:=x) , (otherY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" otherX " y" otherY " w" 340 " h" 110 " ", % localizedStrings["gb7"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+20) " w" 270 " h" 20 " vshowWaypointLine gSettingsUpdateFlag", % localizedStrings["cb13"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+40) " w" 270 " h" 20 " vshowNextExitLine gSettingsUpdateFlag", % localizedStrings["cb14"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+60) " w" 270 " h" 20 " vshowBossLine gSettingsUpdateFlag", % localizedStrings["cb15"] + Gui, Add, Checkbox, % "c" UniqueColor " x" (otherX+12) " y" (otherY+80) " w" 270 " h" 20 " vshowQuestLine gSettingsUpdateFlag", % localizedStrings["cb16"] + + local (HudX:=x) , (HudY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" x " y" (HudY+=120) " w" 340 " h" 130 " ", % "HUD" + Gui, Add, Checkbox, % "c" UniqueColor " x" (HudX+12) " y" (HudY+20) " w" 270 " h" 20 " vitemCounterEnabled gSettingsUpdateFlag", % localizedStrings["gb29"] + Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+46) " w" 200 " h" 20, % localizedStrings["gb30"] + Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+43) " w" 30 " h" 20 " vitemCounterSize gSettingsUpdateFlag", 75 + Gui, Add, Checkbox, % "c" UniqueColor " x" (HudX+12) " y" (HudY+63) " w" 270 " h" 20 " vbuffBarEnabled gSettingsUpdateFlag", % localizedStrings["gb31"] + Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+86) " w" 200 " h" 20, % localizedStrings["gb32"] + Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+83) " w" 30 " h" 20 " vbuffBarIconSize gSettingsUpdateFlag", 75 + Gui, Add, Text, % "c" UniqueColor " x" (HudX+45) " y" (HudY+106) " w" 200 " h" 20, % localizedStrings["gb33"] + Gui, Add, Edit, % "c" EditColor " x" (HudX+12) " y" (HudY+103) " w" 30 " h" 20 " vbuffBarVerticalOffset gSettingsUpdateFlag", 0 + + local (SplashConfgiX:=x) , (SplashConfgiY:=HudY+120) + Gui, Add, GroupBox, % "c" UniqueColor " x" (SplashConfgiX) " y" (HudY+=130) " w" 340 " h" 120 " ", % "Splash" + Gui, Add, Checkbox, % "c" UniqueColor " x" (SplashConfgiX+=10) " y" (HudY+20) " w" 270 " h" 20 " vStartSplash gSettingsUpdateFlag", % "Start Splash" + Gui, Add, Checkbox, % "c" UniqueColor " x" (SplashConfgiX) " y" (HudY+40) " w" 270 " h" 20 " vLoadingSplash gSettingsUpdateFlag", % "Loading Splash" +} + +SettingsTabProjectiles(x,y){ + global + Gui, Settings:Default + Gui, Tab, Projectiles + local (mY4 := (mY3:=(mY2:=(mY1:=y)+(rowh:=20))+rowh)+rowh) , (mX4 := (mX3:=(mX2:=(mX1:=x+10)+cboxW:=40)+(tW:=100))+cboxW) + local fontwidth:=140 , eboxwidth:=32 + Gui, Add, GroupBox, % "c" UniqueColor " x" (mX1-10) " y" (mY1-16) " w" 340 " h" 400, % localizedStrings["gb8"] + Gui, Add, Checkbox, % "c" UniqueColor " x" mX1 " y" mY1 " w110 h" rowh " vshowPlayerMissiles gSettingsUpdateFlag", % localizedStrings["cb18"] + Gui, Add, Checkbox, % "c" UniqueColor " x" mX1 " y" mY2 " w110 h" rowh " vshowEnemyMissiles gSettingsUpdateFlag", % localizedStrings["cb17"] + Gui, Add, Slider, % "x" mX1 " y" mY3 " h" rowh " vOpac tooltip gOpacitySlide range1-255", % (settings.missileOpacity+0) + local projectileEditOption:=" gSettingsUpdateFlag center x" mX3 " w" eboxwidth " h" rowh " y" + Gui, Add, Edit, % " c" EditColor projectileEditOption mY1 " vmissileMajorDotSize" + Gui, Add, Edit, % " c" EditColor projectileEditOption mY2 " vmissileMinorDotSize" + Gui, Add, Edit, % " c" EditColor projectileEditOption mY3 " vmissileOpacity" + + Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY1 " w" fontwidth " h" rowh, % localizedStrings["t25"] + Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY2 " w" fontwidth " h" rowh, % localizedStrings["t26"] + Gui, Add, Text, % "c" UniqueColor " x" mX4 " y" mY3 " w" fontwidth " h" rowh, % localizedStrings["t27"] + + local each, mtype + for each,mtype in (Projectilelist()) + { + local mY:=(mY4+each*rowh+5) + Gui, Add, Progress, % "x" 20 " y" mY " w20 h20 cWhite v" mtype "preview Background" settings["missile" mtype "Color"] + Gui, Add,Edit, % "c" settings["missile" mtype "Color"] " x" mX2-30 " y" mY " w" (eboxwidth+50) " h" rowh " vmissile" mtype "Color gSettingsUpdateFlag center" + } + ; we do this seperately and consecutively to force the radio to be "together" without additional code + for each,mtype in (Projectilelist()) + Gui, Add, radio, % " c" settings["missile" mtype "Color"] " x" mX3-47 " y" (mY4+7+(each*20)) " v" mtype "Rcheck gRadioToSliders", % mtype + ;RGB sliders + local (slide), (sliders:=["Red","Green","Blue"]) ,( slidex:=mX3) , (slideH:=250) + local (slidey:=mY4+10), slidetexty:=slidey+250 + for each,slide in sliders + { + Gui, Add, Slider, % "x" (slidex+=30) " y" slidey " h" slideH " w" 50 " vSlider" slide " gColorslide c0x000000 vertical Invert AltSubmit Range0-255 TickInterval" 1, 119 + local Channel:=SubStr(slide, 1 , 1) + Gui, Add, Text, % "c" UniqueColor " x" (slidex+=15) " y" slidetexty " vch" Channel, % Channel + } +} + +SettingsTabAdvanced(x,y){ + global + Gui, Settings:Default + Gui, Tab, Advanced + local (AdvancedX:=x) , (AdvancedY:=y) + Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" AdvancedY " w" 340 " h" 220 " ", % localizedStrings["gb9"] + Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+20) " w" 100 " h" 20 " r2", % localizedStrings["t28"] + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+40) " w" 40 " h" 20 " vperformanceMode gSettingsUpdateFlag", 50ms + Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+60) " y" (AdvancedY+40) " w" 250 " h" 40 " ", % localizedStrings["t29"] + + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+109) " w" 250 " h" 20 " ", % localizedStrings["t30"] ;168 + + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+69) " w" 150 " h" 20 " vshowFPS gSettingsUpdateFlag", % localizedStrings["cb22"] ;128 + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+240) " y" (AdvancedY+71) " w" 75 " h" 18 " ", % localizedStrings["gb28"] ;fpscap + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+197) " y" (AdvancedY+68) " w" 40 " h" 20 " vfpscap gSettingsUpdateFlag", 60 ;FPSedit + + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+130) " w" 150 " h" 20 " venableD2ML gSettingsUpdateFlag", % localizedStrings["cb20"] ;189 + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+135) " y" (AdvancedY+153) " w" 200 " h" 18 " ", % localizedStrings["t31"] + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+150) " w" 120 " h" 20 " vwindowTitle gSettingsUpdateFlag", D2R:main + Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+170) " w" 300 " h" 30, % localizedStrings["t32"] + + Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" (AdvancedY+230) " w" 340 " h" 80, % localizedStrings["gb10"] ;289 + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+250) " w" 200 " h" 20 " vdebug gSettingsUpdateFlag", % localizedStrings["cb21"] + Gui, Add, Text, % "c" DetailFontColor " x" (AdvancedX+10) " y" (AdvancedY+270) " w" 320 " h" 30, % localizedStrings["t33"] + + Gui, Add, GroupBox, % "c" UniqueColor " x" AdvancedX " y" (AdvancedY+310) " w" 340 " h" 60, % "Settings" + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+10) " y" (AdvancedY+325) " w" 150 " h" 20 " vCustomSettings gSettingsUpdateFlag", Custom Settings colors + Gui, Add, Checkbox, % "c" UniqueColor " x" (AdvancedX+160) " y" (AdvancedY+325) " w" 175 " h" 20 " vInvertedColors gSettingsUpdateFlag", Invert Colors (requires restart) + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+10) " y" (AdvancedY+345) " w" 60 " h" 20 " vWindowColor gSettingsUpdateFlag", % settings["WindowColor"] + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+70) " y" (AdvancedY+348) " w" 75 " h" 18 " ", Window Color + + Gui, Add, Edit, % "c" EditColor " x" (AdvancedX+140) " y" (AdvancedY+345) " w" 60 " h" 20 " vFontColor gSettingsUpdateFlag", % settings["FontColor"] + Gui, Add, Text, % "c" UniqueColor " x" (AdvancedX+200) " y" (AdvancedY+348) " w" 75 " h" 18 " ", Font Color + +} + +;colorpicker +showColorPicker(){ + local static ShowPicker := false + local static PickerBuilt := false + if !(PickerBuilt){ + colorpicker() + PickerBuilt:=True + } + ; open the settings window and a given position + if (ShowPicker:=!ShowPicker){ + Gui, ColorPicker:Show,, % "RGB" + } else { + Gui, ColorPicker:hide + } + +} + +colorpicker(){ + global + Gui, ColorPicker:Default + Gui, ColorPicker:-MinimizeBox +AlwaysOnTop + local progressX:=0 + local progressY:=5 + local progressS:=50 + glable:="gColorPickerUpdate" + Gui, ColorPicker:Add, Progress, % "x" progressX " y"progressY " w" progressS " h" progressS " +C0xFF0000 vProg", 100 + Gui, ColorPicker:Add, Edit, % "x" (progressX+=progressS) " y" (progressY) " w" 70 " h20 vHex " glable, 0xFFFF0000 + Gui, ColorPicker:Font, s9 + local buttony:=progressY + Gui, ColorPicker:Add, Button, % "x" progressX " y" (buttony+=20) " w" 70 " h" 15, CopyRGB + Gui, ColorPicker:Add, Button, % "x" progressX " y" (buttony+=15 )" w" 70 " h" 15, CopyAlpha + ;Gui, ColorPicker:Add, Button, % "x" 165 " y" buttony " w75 h23", Close + rgbtX:=13 , rgbty:=buttony+25 + Gui, ColorPicker:Font, s12 + Gui, ColorPicker:Add, Text, % "x" rgbtX " y" rgbty " w20 h20 Center", R + Gui, ColorPicker:Font, s9 + Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vR " glable, 255 + Gui, ColorPicker:Font, s12 + Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", G + Gui, ColorPicker:Font, s9 + Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vG " glable, 0 + Gui, ColorPicker:Font, s12 + Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y" rgbty " w25 h25 Center", B + Gui, ColorPicker:Font, s9 + Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vB " glable, 0 + Gui, ColorPicker:Font, s12 + Gui, ColorPicker:Add, Text, % "x" (rgbtX+=25) " y"rgbty " w25 h25 Center", A + Gui, ColorPicker:Font, s9 + Gui, ColorPicker:Add, Edit, % "x" rgbtX " y" (rgbty+25) " w25 h20 +Number Center ReadOnly vA " glable, 255 + local sliderh:=150 + local sliderw:=25 + local sliderx:=10 + local slidery:=rgbty+50 + options:=" TickInterval1 +Vertical +0x20 +0x200 +Vertical +Invert +Center +Range0-255 -Tabstop AltSubmit " glable + Gui, ColorPicker:Add, Slider, % "x" sliderx " y" slidery " w" sliderw " h" sliderh options " vRS", 255 + Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vGS", 0 + Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vBS", 0 + Gui, ColorPicker:Add, Slider, % "x" (sliderx+=sliderw) " y" slidery " w" sliderw " h" sliderh options " vAS", 255 + + +} + +ColorPickerGuiEscape(){ + ColorPickerGuiClose() +} + +ColorPickerGuiClose(){ + showColorPicker() +} + +ColorPickerUpdate(){ + GuiControlGet, RS + GuiControlGet, GS + GuiControlGet, BS + GuiControlGet, AS + + GuiControlGet, R + GuiControlGet, G + GuiControlGet, B + GuiControlGet, A + GuiControlGet, Hex + GuiControlGet, Prog + + ColorPickerSet("R", RS) + ColorPickerSet("G", GS) + ColorPickerSet("B", BS) + ColorPickerSet("A", AS) + ColorPickerSet("RS", R, "+Range0-255") + ColorPickerSet("GS", G, "+Range0-255") + ColorPickerSet("BS", B, "+Range0-255") + ColorPickerSet("AS", A, "+Range1-255") + ColorPickerSet("Hex", ARGB(R, G, B, A)) + ColorPickerSet("Prog",, "+C" ARGB(R, G, B)) +} + +ColorPickerButtonCopyRGB(){ + GuiControlGet, Hex + return Clipboard:=SubStr(Hex, 5) +} + +ColorPickerButtonCopyAlpha(){ + GuiControlGet, R + GuiControlGet, G + GuiControlGet, B + GuiControlGet, A + return clipboard:=SubStr(ARGB(R, G, B, A), 1 , 4) +} + +ColorPickerSet(Control, Data := "", AddOpt := "") { + GuiControl, %AddOpt%, %Control%, % Data + return !ErrorLevel +} diff --git a/src/ui/splash/splash.ahk b/src/ui/splash/splash.ahk index e0d3e24..d111e9b 100644 --- a/src/ui/splash/splash.ahk +++ b/src/ui/splash/splash.ahk @@ -2,10 +2,16 @@ StartSplash(){ if settings.StartSplash Splash(version,3000,"StartSettings") } + LoadingSplash(){ Splash("loading",0,,0.25) } +StartSettings(){ + SetTimer, ShowSettings, -1000 + OnMessage(0x201, "WM_LBUTTONDOWN") +} + Splash(text="",time=1000,onclickcmd=False,opacity=1){ global if !FileExist(settings.SplashImg) @@ -63,6 +69,7 @@ Splash(text="",time=1000,onclickcmd=False,opacity=1){ if (time !=0) SetTimer, SplashClose, % time } + SplashClose(){ Gui, Splash:Destroy OnMessage(0x201, "WM_LBUTTONDOWN") From 518de1abc049bcc86b113f832f8ce44a5dd789ac Mon Sep 17 00:00:00 2001 From: Teo <106943092+t3ohm@users.noreply.github.com> Date: Wed, 12 Oct 2022 19:48:40 -0700 Subject: [PATCH 12/12] Update Drawing.ahk --- src/ui/map/Drawing.ahk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/map/Drawing.ahk b/src/ui/map/Drawing.ahk index bca31f4..11d42bf 100644 --- a/src/ui/map/Drawing.ahk +++ b/src/ui/map/Drawing.ahk @@ -37,8 +37,8 @@ class Brushes { ; missiles missileOpacity := settings["missileOpacity"] - , physicalMajorColor := missileOpacity . settings["missileColorPhysicalMajor"] - , physicalMinorColor := missileOpacity . settings["missileColorPhysicalMinor"] + , physicalMajorColor := missileOpacity . settings["missilePhysicalMajorColor"] + , physicalMinorColor := missileOpacity . settings["missilePhysicalMinorColor"] , fireMajorColor := missileOpacity . settings["missileFireMajorColor"] , fireMinorColor := missileOpacity . settings["missileFireMinorColor"] , iceMajorColor := missileOpacity . settings["missileIceMajorColor"]