监控脚本源码
V1
#NoEnv
#Persistent
#SingleInstance Force
SendMode Input
SetWorkingDir %A_ScriptDir%
SetBatchLines -1; 包含 GDI+ 库
#Include Gdip_all.ahk
if (pToken := Gdip_Startup()) = 0 {MsgBox, Gdip 启动失败,请确认 Gdip_all.ahk 在脚本目录下!ExitApp
}; 设置坐标模式
CoordMode, Mouse, Screen
CoordMode, ToolTip, Screen
CoordMode, Gui, Screen
CoordMode, Pixel, Screen; 配置文件
global ConfigFile := A_ScriptDir "\monitor_config.ini"
global CurrentFileConfig := "current_file.ini"
global RemainingFilesConfig := "remaining_files.ini"
global SignalFile := A_ScriptDir "\signal.ini"
global LogFile := A_ScriptDir "\monitor_log.txt"; 全局变量
global IsMonitoring := False
global TriggerKey, ToggleGuiKey, StartTriggerKey, PauseMonitorKey
global GuiVisible, AutoStartMonitor, StartTriggerMode, NextTriggerMode
global MonitorX1, MonitorY1, MonitorX2, MonitorY2
global CaptureX1, CaptureY1, CaptureX2, CaptureY2
global ArrowWhiteImage := A_ScriptDir "\arrow_white.png"
global ArrowBlackImage := A_ScriptDir "\arrow_black.png"
global BlockBlackImage := A_ScriptDir "\block_black.png"
global LastState := ""
global TimerInterval := 1000
global DetectionStatus := "未启动"
global RemainingSec := 20
global Countdown := 5
global DebugFolder := A_ScriptDir "\debug"
global DebugImages := []
global TempFolder := A_ScriptDir "\temp"
global LastChangeTime := A_TickCount
global ScriptPaused := False
global RecordedFileName := ""
global RemainingFiles := 0
global MainGuiHwnd, FloatGuiHwnd
global SignalMonitorName := "TriggerMonitor"
global SignalNextName := "TriggerTypora"
global SignalValue := 0
global FloatVisible := 1; 初始化目录
if !FileExist(DebugFolder)FileCreateDir, %DebugFolder%
if !FileExist(TempFolder)FileCreateDir, %TempFolder%; 初始化配置文件
if !FileExist(ConfigFile) {IniWrite, ^!t, %ConfigFile%, Hotkeys, TriggerKeyIniWrite, #s, %ConfigFile%, Hotkeys, ToggleGuiKeyIniWrite, ^!m, %ConfigFile%, Hotkeys, StartTriggerKeyIniWrite, ^!p, %ConfigFile%, Hotkeys, PauseMonitorKeyIniWrite, 1, %ConfigFile%, Settings, GuiVisibleIniWrite, 0, %ConfigFile%, Monitoring, AutoStartMonitorIniWrite, 0, %ConfigFile%, Settings, StartTriggerModeIniWrite, 0, %ConfigFile%, Settings, NextTriggerMode
}
if !FileExist(SignalFile) {IniWrite, 0, %SignalFile%, Signals, TriggerSenderIniWrite, 0, %SignalFile%, Signals, TriggerMonitorIniWrite, 0, %SignalFile%, Signals, TriggerTyporaIniWrite, 0, %SignalFile%, Signals, ReadyForNote
}; 重置所有信号量为 0
IniWrite, 0, %SignalFile%, Signals, TriggerSender
IniWrite, 0, %SignalFile%, Signals, TriggerMonitor
IniWrite, 0, %SignalFile%, Signals, TriggerTypora
IniWrite, 0, %SignalFile%, Signals, ReadyForNote; 读取设置
IniRead, TriggerKey, %ConfigFile%, Hotkeys, TriggerKey, ^!t
IniRead, ToggleGuiKey, %ConfigFile%, Hotkeys, ToggleGuiKey, #s
IniRead, StartTriggerKey, %ConfigFile%, Hotkeys, StartTriggerKey, ^!m
IniRead, PauseMonitorKey, %ConfigFile%, Hotkeys, PauseMonitorKey, ^!p
IniRead, GuiVisible, %ConfigFile%, Settings, GuiVisible, 1
IniRead, AutoStartMonitor, %ConfigFile%, Monitoring, AutoStartMonitor, 0
IniRead, StartTriggerMode, %ConfigFile%, Settings, StartTriggerMode, 0
IniRead, NextTriggerMode, %ConfigFile%, Settings, NextTriggerMode, 0
IniRead, MonitorX1, %ConfigFile%, Monitoring, X1, %A_Space%
IniRead, MonitorY1, %ConfigFile%, Monitoring, Y1, %A_Space%
IniRead, MonitorX2, %ConfigFile%, Monitoring, X2, %A_Space%
IniRead, MonitorY2, %ConfigFile%, Monitoring, Y2, %A_Space%; 检查监控区域设置
if (MonitorX1 = "" || MonitorY1 = "" || MonitorX2 = "" || MonitorY2 = "" || !FileExist(ArrowWhiteImage) || !FileExist(ArrowBlackImage) || !FileExist(BlockBlackImage)) {ToolTip, 监控设置未配置,请在区域监控中定义区域并采集参考图片, , , , 16SetTimer, RemoveTooltip, -2000
} else {borderThickness := 5CaptureX1 := MonitorX1 + borderThicknessCaptureY1 := MonitorY1 + borderThicknessCaptureX2 := MonitorX2 - borderThicknessCaptureY2 := MonitorY2 - borderThicknessGosub, CreateOverlay
}; 检查并加载 RemainingFiles 配置文件
IfNotExist, %RemainingFilesConfig%
{IniWrite, 0, %RemainingFilesConfig%, Settings, RemainingFiles
}
IniRead, RemainingFiles, %RemainingFilesConfig%, Settings, RemainingFiles, 0; 读取当前文件名
IniRead, RecordedFileName, %CurrentFileConfig%, CurrentFile, Name, %A_Space%; 主 GUI
Gui, Main: +LastFound +Resize
MainGuiHwnd := WinExist(); 初始化单选按钮状态
StartTriggerModeKey := !StartTriggerMode
StartTriggerModeSignal := StartTriggerMode
NextTriggerModeKey := !NextTriggerMode
NextTriggerModeSignal := NextTriggerModeGui, Main: Add, Tab2, x10 y10 w500 h450 vMyTab, 区域监控
Gui, Main: Tab, 区域监控
Gui, Main: Add, Button, x20 y50 w120 h30 gRedefineArea, 重新定义区域
Gui, Main: Add, Button, x150 y50 w120 h30 gRecaptureImages, 重新采集图片
Gui, Main: Add, Button, x280 y50 w120 h30 gSetTriggerKey, 设置触发信号
Gui, Main: Add, Button, x20 y90 w120 h30 gStartMonitoring, 开启监控
Gui, Main: Add, Button, x150 y90 w120 h30 gPauseMonitoring, 暂停监控
Gui, Main: Add, Button, x280 y90 w120 h30 gSimulateTrigger, 模拟触发
Gui, Main: Add, Button, x410 y90 w120 h30 gShowMonitorGUI, 显示监控窗口
Gui, Main: Add, Button, x20 y130 w120 h30 gShowHotkeyMenu, 快捷键设置
Gui, Main: Add, CheckBox, x150 y130 w300 h20 vAutoStartMonitor gSaveSettings Checked%AutoStartMonitor%, 脚本启动时自动开启监控
Gui, Main: Add, Text, x20 y160 w150 h20, 被触发方式:
Gui, Main: Add, Radio, x20 y180 w150 h20 vStartTriggerModeKey gSaveStartTriggerMode Checked%StartTriggerModeKey%, 快捷键触发
Gui, Main: Add, Radio, x180 y180 w150 h20 vStartTriggerModeSignal gSaveStartTriggerMode Checked%StartTriggerModeSignal%, 信号量触发
Gui, Main: Add, Text, x20 y210 w150 h20, 触发下一脚本方式:
Gui, Main: Add, Radio, x20 y230 w150 h20 vNextTriggerModeKey gSaveNextTriggerMode Checked%NextTriggerModeKey%, 快捷键触发
Gui, Main: Add, Radio, x180 y230 w150 h20 vNextTriggerModeSignal gSaveNextTriggerMode Checked%NextTriggerModeSignal%, 信号量触发
Gui, Main: Add, Text, x20 y260 w460 h20 vMonitorStatus, 监控状态: %DetectionStatus%
Gui, Main: Add, Text, x20 y290 w460 h20 vTriggerKeyDisplay, 状态完成后触发的信号快捷键: %TriggerKey%
Gui, Main: Add, Text, x20 y320 w460 h20 vRemainingFilesDisplay, 剩余文件数量: %RemainingFiles%
Gui, Main: Add, Text, x20 y350 w460 h20 vToggleGuiKeyDisplay, 显示/隐藏 GUI 快捷键: %ToggleGuiKey%
Gui, Main: Add, Text, x20 y380 w460 h20 vStartTriggerKeyDisplay, 被触发快捷键: %StartTriggerKey%
Gui, Main: Add, Text, x20 y410 w460 h20 vPauseMonitorKeyDisplay, 暂停监控快捷键: %PauseMonitorKey%
Gui, Main: Tab
Gui, Main: Add, StatusBar, vStatusBar, 状态: 就绪; 创建悬浮窗
Gosub, CreateFloatWindowif (GuiVisible = 1) {Gui, Main:Show, w520 h480, 区域监控器
} else {Gui, Main:Hide
}; 绑定快捷键和信号量监控
BindHotkeys()
SetTimer, MonitorSignal, 500
if (StartTriggerMode = 1) {SetTimer, UpdateCountdown, 1000DetectionStatus := "监控中(信号量模式)"GuiControl, Main:, MonitorStatus, 监控状态: %DetectionStatus%
}; 自动启动监控(如果启用)
if (AutoStartMonitor) {Gosub, StartMonitoring
}return; --- 日志记录函数 ---
LogMessage(message) {FormatTime, CurrentTime,, yyyy-MM-dd HH:mm:ssFileAppend, [%CurrentTime%] %message%`n, %LogFile%
}; --- 调试日志函数 ---
LogDebug(message) {FormatTime, CurrentTime,, yyyy-MM-dd HH:mm:ssFileAppend, [DEBUG %CurrentTime%] %message%`n, %LogFile%
}; --- 创建悬浮窗 ---
CreateFloatWindow:
Gui, Float:+LastFound +AlwaysOnTop +Border
FloatGuiHwnd := WinExist()
Gui, Float:Add, Text, w300 vFloatSignalDisplay, 信号量 %SignalMonitorName%: %SignalValue% (倒计时: %Countdown% 秒)
Gui, Float:Show, x10 y30 w320 h30
FloatVisible := 1
LogMessage("悬浮窗创建成功,句柄: " FloatGuiHwnd)
return; --- 更新悬浮窗和倒计时 ---
UpdateFloatWindow:
IniRead, SignalValue, %SignalFile%, Signals, %SignalMonitorName%, 0
GuiControl, Float:, FloatSignalDisplay, 信号量 %SignalMonitorName%: %SignalValue% (倒计时: %Countdown% 秒)
GuiControl, Main:, MonitorStatus, 监控状态: %DetectionStatus%
returnUpdateCountdown:
if (StartTriggerMode != 1) {return
}
Countdown -= 1
if (Countdown <= 0) {Countdown := 5Gosub, MonitorSignal
}
Gosub, UpdateFloatWindow
return; --- 动态绑定快捷键 ---
BindHotkeys() {try {Hotkey, %ToggleGuiKey%, ToggleGuiLogMessage("绑定快捷键 ToggleGuiKey: " ToggleGuiKey " 成功")} catch e {LogMessage("绑定快捷键 ToggleGuiKey: " ToggleGuiKey " 失败: " e)}try {Hotkey, %PauseMonitorKey%, PauseMonitoringLogMessage("绑定快捷键 PauseMonitorKey: " PauseMonitorKey " 成功")} catch e {LogMessage("绑定快捷键 PauseMonitorKey: " PauseMonitorKey " 失败: " e)}if (StartTriggerMode = 0) {try {Hotkey, %StartTriggerKey%, StartMonitoringLogMessage("绑定被触发快捷键 StartTriggerKey: " StartTriggerKey " 成功")} catch e {LogMessage("绑定被触发快捷键 StartTriggerKey: " StartTriggerKey " 失败: " e)}}
}; --- 信号量监控 ---
MonitorSignal:
if (StartTriggerMode = 1) {IniRead, SignalValue, %SignalFile%, Signals, %SignalMonitorName%, 0if (SignalValue = 1) {LogDebug("检测到信号量 " SignalMonitorName "=1,触发监控")Gosub, StartMonitoringIniWrite, 0, %SignalFile%, Signals, %SignalMonitorName%LogDebug("重置信号量 " SignalMonitorName "=0")}
}
return; --- 切换 GUI 显示 ---
ToggleGui:
GuiVisible := !GuiVisible
if (GuiVisible = 1) {Gui, Main:Show
} else {Gui, Main:Hide
}
IniWrite, %GuiVisible%, %ConfigFile%, Settings, GuiVisible
LogMessage("切换 GUI 显示状态: " (GuiVisible ? "显示" : "隐藏"))
return; --- 显示快捷键菜单 ---
ShowHotkeyMenu:
Menu, HotkeyMenu, Add
Menu, HotkeyMenu, DeleteAll
Menu, HotkeyMenu, Add, 显示/隐藏 GUI (%ToggleGuiKey%), SetToggleGuiKey
Menu, HotkeyMenu, Add, 暂停监控 (%PauseMonitorKey%), SetPauseMonitorKey
Menu, HotkeyMenu, Add, 被触发快捷键 (%StartTriggerKey%), SetStartTriggerKey
Menu, HotkeyMenu, Add, 状态完成后触发的信号快捷键 (%TriggerKey%), SetTriggerKey
Menu, HotkeyMenu, Show
return; --- 设置快捷键 ---
SetToggleGuiKey:
Gosub, ShowHotkeyInput
global CurrentHotkeyField := "ToggleGuiKey"
global CurrentLabel := "ToggleGui"
returnSetPauseMonitorKey:
Gosub, ShowHotkeyInput
global CurrentHotkeyField := "PauseMonitorKey"
global CurrentLabel := "PauseMonitoring"
returnSetStartTriggerKey:
Gosub, ShowHotkeyInput
global CurrentHotkeyField := "StartTriggerKey"
global CurrentLabel := "StartMonitoring"
returnSetTriggerKey:
Gosub, ShowHotkeyInput
global CurrentHotkeyField := "TriggerKey"
global CurrentLabel := ""
returnShowHotkeyInput:
Gui, KeyInput:New, +AlwaysOnTop
Gui, KeyInput:Add, CheckBox, vUseCtrl gUpdateHotkeyPreview, 使用 Ctrl
Gui, KeyInput:Add, CheckBox, vUseAlt gUpdateHotkeyPreview xm, 使用 Alt
Gui, KeyInput:Add, CheckBox, vUseWin gUpdateHotkeyPreview xm, 使用 Win
Gui, KeyInput:Add, CheckBox, vUseXButton1 gUpdateHotkeyPreview xm, 使用 XButton1
Gui, KeyInput:Add, CheckBox, vUseXButton2 gUpdateHotkeyPreview xm, 使用 XButton2
Gui, KeyInput:Add, Text, xm, 选择按键(如果未选择 XButton1/XButton2):
Gui, KeyInput:Add, DropDownList, vHotkeyChoice gUpdateHotkeyPreview, A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|F1|F2|F3|F4|F5|F6|F7|F8|F9|F10|F11|F12
Gui, KeyInput:Add, Text, xm vHotkeyPreview, 快捷键预览:
Gui, KeyInput:Add, Button, default w80 gSaveHotkey, 确定
Gui, KeyInput:Show
returnUpdateHotkeyPreview:
Gui, KeyInput:Submit, NoHide
newKey := ""
if (UseCtrl)newKey .= "^"
if (UseAlt)newKey .= "!"
if (UseWin)newKey .= "#"
if (UseXButton1)newKey .= (UseXButton2 ? "" : "XButton1")
else if (UseXButton2)newKey .= "XButton2"
else if (HotkeyChoice != "")newKey .= HotkeyChoice
GuiControl, KeyInput:, HotkeyPreview, 快捷键预览: %newKey%
returnSaveHotkey:
Gui, KeyInput:Submit
newKey := ""
if (UseCtrl)newKey .= "^"
if (UseAlt)newKey .= "!"
if (UseWin)newKey .= "#"
if (UseXButton1) {if (UseXButton2) {MsgBox, 不能同时选择 XButton1 和 XButton2!Gui, KeyInput:Showreturn}newKey .= "XButton1"
} else if (UseXButton2)newKey .= "XButton2"
else if (HotkeyChoice != "")newKey .= HotkeyChoice
else {MsgBox, 请选择一个按键或勾选 XButton1/XButton2!Gui, KeyInput:Showreturn
}
if (newKey = "") {MsgBox, 请至少选择一个修饰键或按键!Gui, KeyInput:Showreturn
}
if (newKey = ToggleGuiKey || newKey = PauseMonitorKey || newKey = StartTriggerKey || newKey = TriggerKey) && (newKey != %CurrentHotkeyField%) {MsgBox, 快捷键 %newKey% 已与其他功能冲突,请选择其他组合!Gui, KeyInput:Showreturn
}
if (%CurrentHotkeyField% != "") {try {Hotkey, % %CurrentHotkeyField%, OffLogMessage("释放旧快捷键 " CurrentHotkeyField ": " %CurrentHotkeyField% " 成功")} catch e {LogMessage("释放旧快捷键 " CurrentHotkeyField ": " %CurrentHotkeyField% " 失败: " e)}
}
%CurrentHotkeyField% := newKey
IniWrite, %newKey%, %ConfigFile%, Hotkeys, %CurrentHotkeyField%
if (CurrentLabel != "") {try {Hotkey, %newKey%, %CurrentLabel%LogMessage("绑定新快捷键 " CurrentHotkeyField ": " newKey " 成功")} catch e {LogMessage("绑定新快捷键 " CurrentHotkeyField ": " newKey " 失败: " e)defaultKey := (CurrentHotkeyField = "ToggleGuiKey" ? "#s" : CurrentHotkeyField = "StartTriggerKey" ? "^!m" : CurrentHotkeyField = "PauseMonitorKey" ? "^!p" : "^!t")%CurrentHotkeyField% := defaultKeyIniWrite, %defaultKey%, %ConfigFile%, Hotkeys, %CurrentHotkeyField%try {Hotkey, %defaultKey%, %CurrentLabel%LogMessage("恢复默认快捷键 " CurrentHotkeyField ": " defaultKey " 成功")} catch e {LogMessage("恢复默认快捷键 " CurrentHotkeyField ": " defaultKey " 失败: " e)}}
}
GuiControl, Main:, %CurrentHotkeyField%Display, % (CurrentHotkeyField = "TriggerKey" ? "状态完成后触发的信号快捷键" : CurrentHotkeyField) "快捷键: " newKey
Gui, KeyInput:Destroy
ToolTip, %CurrentHotkeyField% 已设置为:%newKey%, , , , 16
SetTimer, RemoveTooltip, -2000
LogMessage(CurrentHotkeyField " 设置为: " newKey)
returnStartMonitoring:
if (MonitorX1 = "" || MonitorY1 = "" || MonitorX2 = "" || MonitorY2 = "") {ToolTip, 请先定义监控区域, , , , 16SetTimer, RemoveTooltip, -2000return
}
if (!FileExist(ArrowWhiteImage) || !FileExist(ArrowBlackImage) || !FileExist(BlockBlackImage)) {ToolTip, 请先采集参考图片, , , , 16SetTimer, RemoveTooltip, -2000return
}
IsMonitoring := True
ScriptPaused := False
SetTimer, MonitorArea, %TimerInterval%
DetectionStatus := "运行中"
Gui, Monitor:New, +AlwaysOnTop -Resize
Gui, Monitor:Add, Text, x10 y10 w300 h20 vStatusText, 监控状态: %DetectionStatus%
Gui, Monitor:Add, Text, x10 y40 w300 h20 vCurrentFile, 当前文件: %RecordedFileName%
Gui, Monitor:Show, w320 h100, 监控状态
Gosub, UpdateMonitoringStatus
ToolTip, 监控已开启, , , , 16
SetTimer, RemoveTooltip, -2000
LogMessage("监控已开启")
returnPauseMonitoring:
ScriptPaused := True
SetTimer, MonitorArea, Off
DetectionStatus := "已暂停"
Gosub, UpdateMonitoringStatus
ToolTip, 监控已暂停, , , , 16
SetTimer, RemoveTooltip, -2000
LogMessage("监控已暂停")
returnSimulateTrigger:
if (NextTriggerMode = 0) {SendInput, %TriggerKey%ToolTip, 模拟触发 - 发送快捷键 %TriggerKey% 成功, , , , 16Sleep, 100
} else {IniWrite, 1, %SignalFile%, Signals, %SignalNextName%Sleep, 100ToolTip, 模拟触发 - 写入信号量 %SignalNextName% 成功, , , , 16LogDebug("模拟触发 - 写入信号量 " SignalNextName "=1")
}
SetTimer, RemoveTooltip, -2000
LogMessage("模拟触发完成: " (NextTriggerMode = 0 ? "快捷键 " TriggerKey : "信号量 " SignalNextName))
returnMonitorArea:
if (ScriptPaused || !IsMonitoring)return
CaptureScreen("temp.png", CaptureX1, CaptureY1, CaptureX2, CaptureY2)
currentState := ""
whiteArrowSimilarity := CompareImages("temp.png", ArrowWhiteImage)
blackArrowSimilarity := CompareImages("temp.png", ArrowBlackImage)
blackBlockSimilarity := CompareImages("temp.png", BlockBlackImage)
if (whiteArrowSimilarity >= 99)currentState := "等待输入信息 (白色箭头)"
else if (blackArrowSimilarity >= 99)currentState := "正在输入信息 (黑色箭头)"
else if (blackBlockSimilarity >= 99)currentState := "正在 AI 处理 (黑色方块)"
elsecurrentState := "未知"
DetectionStatus := currentState
if (LastState = "正在 AI 处理 (黑色方块)" && currentState = "等待输入信息 (白色箭头)") {DetectionStatus := "触发中"Gosub, UpdateMonitoringStatusSleep, 3000; 检查 HasSupplement 信号量以判断任务类型IniRead, HasSupplement, %SignalFile%, Signals, HasSupplement, 0if (HasSupplement = 1) {; 主文件(输入 "ww"),触发发送补充文件LogDebug("检测到主文件(HasSupplement=1),触发发送补充文件")if (NextTriggerMode = 0) {SendInput, %TriggerKey%ToolTip, 主文件触发 - 发送快捷键 %TriggerKey% 成功, , , , 16LogDebug("主文件 - 发送快捷键 " TriggerKey)} else {IniWrite, 1, %SignalFile%, Signals, TriggerNextSendToolTip, 主文件触发 - 写入信号量 TriggerNextSend 成功, , , , 16LogDebug("主文件 - 写入信号量 TriggerNextSend=1")}; 继续监控,不暂停DetectionStatus := "等待补充文件处理"} else {; 补充文件(输入 "aa"),触发新建 TyporaLogDebug("检测到补充文件(HasSupplement=0),触发新建 Typora")IniWrite, 1, %SignalFile%, Signals, ReadyForNoteLogDebug("设置 ReadyForNote=1")if (NextTriggerMode = 0) {SendInput, %TriggerKey%ToolTip, 补充文件触发 - 发送快捷键 %TriggerKey% 成功, , , , 16LogDebug("补充文件 - 发送快捷键 " TriggerKey)} else {IniWrite, 1, %SignalFile%, Signals, %SignalNextName%ToolTip, 补充文件触发 - 写入信号量 %SignalNextName% 成功, , , , 16LogDebug("补充文件 - 写入信号量 " SignalNextName "=1")}; 补充文件处理完成后暂停监控IsMonitoring := FalseScriptPaused := TrueSetTimer, MonitorArea, OffDetectionStatus := "已暂停(触发完成)"Gui, Monitor:Hide}SetTimer, RemoveTooltip, -2000LogMessage("触发完成: " (HasSupplement = 1 ? "主文件 - 信号量 TriggerNextSend" : "补充文件 - 信号量 " SignalNextName))Gosub, UpdateMonitoringStatus
}
LastState := currentState
debugFile := DebugFolder "\detect_" A_Now "_" currentState ".png"
FileCopy, temp.png, %debugFile%
FileDelete, temp.png
ManageDebugImages(debugFile)
Gosub, UpdateMonitoringStatus
returnShowMonitorGUI:
Gui, Monitor:Show
returnUpdateMonitoringStatus:
IniRead, RemainingFiles, %RemainingFilesConfig%, Settings, RemainingFiles, 0
IniRead, RecordedFileName, %CurrentFileConfig%, CurrentFile, Name, %A_Space%
GuiControl, Main:, MonitorStatus, % "监控状态: " DetectionStatus
GuiControl, Main:, RemainingFilesDisplay, 剩余文件数量: %RemainingFiles%
GuiControl, Monitor:, StatusText, % "监控状态: " DetectionStatus
GuiControl, Monitor:, CurrentFile, % "当前文件: " (RecordedFileName ? RecordedFileName : "无")
GuiControl, Main:, StatusBar, % "状态: " DetectionStatus
returnSaveSettings:
Gui, Main:Submit, NoHide
IniWrite, %AutoStartMonitor%, %ConfigFile%, Monitoring, AutoStartMonitor
LogMessage("保存设置: AutoStartMonitor=" AutoStartMonitor)
returnSaveStartTriggerMode:
Gui, Main:Submit, NoHide
StartTriggerMode := (StartTriggerModeKey = 1) ? 0 : 1
IniWrite, %StartTriggerMode%, %ConfigFile%, Settings, StartTriggerMode
if (StartTriggerMode = 0) {try {Hotkey, %StartTriggerKey%, StartMonitoringLogMessage("绑定被触发快捷键 StartTriggerKey: " StartTriggerKey " 成功")} catch e {LogMessage("绑定被触发快捷键 StartTriggerKey: " StartTriggerKey " 失败: " e)}SetTimer, UpdateCountdown, OffDetectionStatus := "就绪(快捷键模式)"
} else {try {Hotkey, %StartTriggerKey%, OffLogMessage("解除被触发快捷键绑定 StartTriggerKey: " StartTriggerKey)} catch e {}SetTimer, UpdateCountdown, 1000DetectionStatus := "监控中(信号量模式)"
}
GuiControl, Main:, MonitorStatus, 监控状态: %DetectionStatus%
LogDebug("保存被触发模式: " (StartTriggerMode = 0 ? "快捷键" : "信号量"))
returnSaveNextTriggerMode:
Gui, Main:Submit, NoHide
NextTriggerMode := (NextTriggerModeKey = 1) ? 0 : 1
IniWrite, %NextTriggerMode%, %ConfigFile%, Settings, NextTriggerMode
LogDebug("保存触发下一脚本模式: " (NextTriggerMode = 0 ? "快捷键" : "信号量"))
returnRedefineArea:
SetTimer, MonitorArea, Off
ToolTip, 请按住左键拖动选择监控区域,然后松开, , , , 16
KeyWait, LButton, D
MouseGetPos, StartX, StartY
Gui, Selection: +AlwaysOnTop -Caption +ToolWindow
Gui, Selection: Color, Red
WinSet, Transparent, 100, Selection
Loop {if GetKeyState("LButton", "P") {MouseGetPos, EndX, EndYWidth := Abs(EndX - StartX)Height := Abs(EndY - StartY)X := Min(StartX, EndX)Y := Min(StartY, EndY)Gui, Selection: Show, x%X% y%Y% w%Width% h%Height% NoActivate} else {break}Sleep, 10
}
MouseGetPos, MonitorX2, MonitorY2
MonitorX1 := StartX
MonitorY1 := StartY
Gui, Selection: Destroy
borderThickness := 5
CaptureX1 := MonitorX1 + borderThickness
CaptureY1 := MonitorY1 + borderThickness
CaptureX2 := MonitorX2 - borderThickness
CaptureY2 := MonitorY2 - borderThickness
Gosub, CreateOverlay
IniWrite, %MonitorX1%, %ConfigFile%, Monitoring, X1
IniWrite, %MonitorY1%, %ConfigFile%, Monitoring, Y1
IniWrite, %MonitorX2%, %ConfigFile%, Monitoring, X2
IniWrite, %MonitorY2%, %ConfigFile%, Monitoring, Y2
ToolTip, 监控区域已定义, , , , 16
SetTimer, RemoveTooltip, -2000
Gosub, UpdateMonitoringStatus
LogMessage("监控区域已定义: X1=" MonitorX1 " Y1=" MonitorY1 " X2=" MonitorX2 " Y2=" MonitorY2)
returnRecaptureImages:
SetTimer, MonitorArea, Off
ToolTip, 接下来将在 10 秒内持续截图监控区域,请依次切换区域内容:`n1. 等待输入信息(白色箭头)`n2. 正在输入信息(黑色箭头)`n3. 正在 AI 处理(黑色方块)`n倒计时结束后,将逐次打开文件夹选择图片, , , , 16
FileCreateDir, %TempFolder%
FileDelete, %TempFolder%\*.png
endTime := A_TickCount + 10000
while (A_TickCount < endTime) {FormatTime, dt, , yyyyMMdd_HHmmsstempFile := TempFolder "\sample_" dt "_" A_Msec ".png"CaptureScreen(tempFile, CaptureX1, CaptureY1, CaptureX2, CaptureY2)Sleep, 500
}
ToolTip, 截图完成!, , , , 16
SetTimer, RemoveTooltip, -3000; 逐次选择图片并存储
; 选择白色箭头
Run, %TempFolder%
MsgBox, 64, 提示, 请在打开的文件夹中选择一张白色箭头的图片,然后点击确定。
FileSelectFile, selectedFile, 1, %TempFolder%, 请选择白色箭头的图片, 图片文件 (*.png)
if (selectedFile = "") {MsgBox, 未选择白色箭头的图片,请重新采集!return
}
FileCopy, %selectedFile%, %A_ScriptDir%\arrow_white.png, 1
ToolTip, 白色箭头图片已保存, , , , 16
SetTimer, RemoveTooltip, -2000; 选择黑色箭头
Run, %TempFolder%
MsgBox, 64, 提示, 请在打开的文件夹中选择一张黑色箭头的图片,然后点击确定。
FileSelectFile, selectedFile, 1, %TempFolder%, 请选择黑色箭头的图片, 图片文件 (*.png)
if (selectedFile = "") {MsgBox, 未选择黑色箭头的图片,请重新采集!return
}
FileCopy, %selectedFile%, %A_ScriptDir%\arrow_black.png, 1
ToolTip, 黑色箭头图片已保存, , , , 16
SetTimer, RemoveTooltip, -2000; 选择黑色方块
Run, %TempFolder%
MsgBox, 64, 提示, 请在打开的文件夹中选择一张黑色方块的图片,然后点击确定。
FileSelectFile, selectedFile, 1, %TempFolder%, 请选择黑色方块的图片, 图片文件 (*.png)
if (selectedFile = "") {MsgBox, 未选择黑色方块的图片,请重新采集!return
}
FileCopy, %selectedFile%, %A_ScriptDir%\block_black.png, 1
ToolTip, 黑色方块图片已保存, , , , 16
SetTimer, RemoveTooltip, -2000; 清理临时文件夹
FileDelete, %TempFolder%\*.png
ToolTip, 所有参考图片已保存,临时文件已清理, , , , 16
SetTimer, RemoveTooltip, -2000
LogMessage("参考图片已重新采集并保存")
Gosub, UpdateMonitoringStatus
returnCaptureScreen(filePath, x1, y1, x2, y2) {width := (x2 - x1 + 1)height := (y2 - y1 + 1)pBmp := Gdip_BitmapFromScreen(x1 "|" y1 "|" width "|" height)if (pBmp) {Gdip_SaveBitmapToFile(pBmp, filePath)Gdip_DisposeImage(pBmp)} else {ToolTip, 截图失败,请检查监控区域设置, , , , 16SetTimer, RemoveTooltip, -2000LogMessage("截图失败: 检查监控区域设置")}
}CompareImages(img1, img2) {pBmp1 := Gdip_CreateBitmapFromFile(img1)pBmp2 := Gdip_CreateBitmapFromFile(img2)if (!pBmp1 || !pBmp2) {if (pBmp1) Gdip_DisposeImage(pBmp1)if (pBmp2) Gdip_DisposeImage(pBmp2)return 0}width1 := Gdip_GetImageWidth(pBmp1)height1 := Gdip_GetImageHeight(pBmp1)width2 := Gdip_GetImageWidth(pBmp2)height2 := Gdip_GetImageHeight(pBmp2)if (width1 != width2 || height1 != height2) {Gdip_DisposeImage(pBmp1)Gdip_DisposeImage(pBmp2)return 0}totalPixels := width1 * height1matchPixels := 0tolerance := 100Loop, %height1% {y := A_Index - 1Loop, %width1% {x := A_Index - 1color1 := Gdip_GetPixel(pBmp1, x, y)color2 := Gdip_GetPixel(pBmp2, x, y)r1 := color1 & 0xFF, g1 := (color1 >> 8) & 0xFF, b1 := (color1 >> 16) & 0xFFr2 := color2 & 0xFF, g2 := (color2 >> 8) & 0xFF, b2 := (color2 >> 16) & 0xFFif (Abs(r1 - r2) <= tolerance && Abs(g1 - g2) <= tolerance && Abs(b1 - b2) <= tolerance)matchPixels++}}similarity := (matchPixels / totalPixels) * 100Gdip_DisposeImage(pBmp1)Gdip_DisposeImage(pBmp2)return similarity
}ManageDebugImages(newImage) {DebugImages.Push(newImage)if (DebugImages.Length() > 3) {oldImage := DebugImages.RemoveAt(1)FileDelete, %oldImage%}
}CreateOverlay:
borderThickness := 5
width := MonitorX2 - MonitorX1 + 1
height := MonitorY2 - MonitorY1 + 1
yBottom := MonitorY2 - borderThickness + 1
xRight := MonitorX2 - borderThickness + 1
transparency := 150
Gui, OverlayTop: Destroy
Gui, OverlayTop: +AlwaysOnTop -Caption +ToolWindow +LastFound +E0x20
Gui, OverlayTop: Color, FF4500
Gui, OverlayTop: Show, x%MonitorX1% y%MonitorY1% w%width% h%borderThickness% NoActivate
WinSet, Transparent, %transparency%, OverlayTop
Gui, OverlayBottom: Destroy
Gui, OverlayBottom: +AlwaysOnTop -Caption +ToolWindow +LastFound +E0x20
Gui, OverlayBottom: Color, FF4500
Gui, OverlayBottom: Show, x%MonitorX1% y%yBottom% w%width% h%borderThickness% NoActivate
WinSet, Transparent, %transparency%, OverlayBottom
Gui, OverlayLeft: Destroy
Gui, OverlayLeft: +AlwaysOnTop -Caption +ToolWindow +LastFound +E0x20
Gui, OverlayLeft: Color, FF4500
Gui, OverlayLeft: Show, x%MonitorX1% y%MonitorY1% w%borderThickness% h%height% NoActivate
WinSet, Transparent, %transparency%, OverlayLeft
Gui, OverlayRight: Destroy
Gui, OverlayRight: +AlwaysOnTop -Caption +ToolWindow +LastFound +E0x20
Gui, OverlayRight: Color, FF4500
Gui, OverlayRight: Show, x%xRight% y%MonitorY1% w%borderThickness% h%height% NoActivate
WinSet, Transparent, %transparency%, OverlayRight
returnRemoveTooltip:
ToolTip
returnGuiClose:
Gui, Main:Hide
GuiVisible := 0
IniWrite, %GuiVisible%, %ConfigFile%, Settings, GuiVisible
SetTimer, MonitorArea, Off
Gui, OverlayTop: Destroy
Gui, OverlayBottom: Destroy
Gui, OverlayLeft: Destroy
Gui, OverlayRight: Destroy
Gui, Float:Destroy
LogMessage("GUI 关闭")
returnOnExit:
SetTimer, MonitorArea, Off
Gui, OverlayTop: Destroy
Gui, OverlayBottom: Destroy
Gui, OverlayLeft: Destroy
Gui, OverlayRight: Destroy
Gui, Float:Destroy
Gdip_Shutdown(pToken)
LogMessage("脚本退出")
ExitApp
return
配合gdip_all.ahk使用
Gdip_All.ahk
; Gdip standard library v1.54 on 11/15/2017
; Gdip standard library v1.53 on 6/19/2017
; Gdip standard library v1.52 on 6/11/2017
; Gdip standard library v1.51 on 1/27/2017
; Gdip standard library v1.50 on 11/20/16
; Gdip standard library v1.45 by tic (Tariq Porter) 07/09/11
; Modifed by Rseding91 using fincs 64 bit compatible Gdip library 5/1/2013
; Supports: Basic, _L ANSi, _L Unicode x86 and _L Unicode x64
;
; Updated 11/15/2017 - compatibility with both AHK v2 and v1, restored by nnnik
; Updated 6/19/2017 - Fixed few bugs from old syntax by Bartlomiej Uliasz
; Updated 6/11/2017 - made code compatible with new AHK v2.0-a079-be5df98 by Bartlomiej Uliasz
; Updated 1/27/2017 - fixed some bugs and made #Warn All compatible by Bartlomiej Uliasz
; Updated 11/20/2016 - fixed Gdip_BitmapFromBRA() by 'just me'
; Updated 11/18/2016 - backward compatible support for both AHK v1.1 and AHK v2
; Updated 11/15/2016 - initial AHK v2 support by guest3456
; Updated 2/20/2014 - fixed Gdip_CreateRegion() and Gdip_GetClipRegion() on AHK Unicode x86
; Updated 5/13/2013 - fixed Gdip_SetBitmapToClipboard() on AHK Unicode x64
;
;#####################################################################################
;#####################################################################################
; STATUS ENUMERATION
; Return values for functions specified to have status enumerated return type
;#####################################################################################
;
; Ok = = 0
; GenericError = 1
; InvalidParameter = 2
; OutOfMemory = 3
; ObjectBusy = 4
; InsufficientBuffer = 5
; NotImplemented = 6
; Win32Error = 7
; WrongState = 8
; Aborted = 9
; FileNotFound = 10
; ValueOverflow = 11
; AccessDenied = 12
; UnknownImageFormat = 13
; FontFamilyNotFound = 14
; FontStyleNotFound = 15
; NotTrueTypeFont = 16
; UnsupportedGdiplusVersion = 17
; GdiplusNotInitialized = 18
; PropertyNotFound = 19
; PropertyNotSupported = 20
; ProfileNotFound = 21
;
;#####################################################################################
;#####################################################################################
; FUNCTIONS
;#####################################################################################
;
; UpdateLayeredWindow(hwnd, hdc, x:="", y:="", w:="", h:="", Alpha:=255)
; BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster:="")
; StretchBlt(dDC, dx, dy, dw, dh, sDC, sx, sy, sw, sh, Raster:="")
; SetImage(hwnd, hBitmap)
; Gdip_BitmapFromScreen(Screen:=0, Raster:="")
; CreateRectF(ByRef RectF, x, y, w, h)
; CreateSizeF(ByRef SizeF, w, h)
; CreateDIBSection
;
;#####################################################################################; Function: UpdateLayeredWindow
; Description: Updates a layered window with the handle to the DC of a gdi bitmap
;
; hwnd Handle of the layered window to update
; hdc Handle to the DC of the GDI bitmap to update the window with
; Layeredx x position to place the window
; Layeredy y position to place the window
; Layeredw Width of the window
; Layeredh Height of the window
; Alpha Default = 255 : The transparency (0-255) to set the window transparency
;
; return If the function succeeds, the return value is nonzero
;
; notes If x or y omitted, then layered window will use its current coordinates
; If w or h omitted then current width and height will be usedUpdateLayeredWindow(hwnd, hdc, x:="", y:="", w:="", h:="", Alpha:=255)
{Ptr := A_PtrSize ? "UPtr" : "UInt"if ((x != "") && (y != ""))VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")if (w = "") || (h = ""){WinGetRect(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)
};#####################################################################################; Function BitBlt
; Description The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle
; of pixels from the specified source device context into a destination device context.
;
; dDC handle to destination DC
; dx x-coord of destination upper-left corner
; dy y-coord of destination upper-left corner
; dw width of the area to copy
; dh height of the area to copy
; sDC handle to source DC
; sx x-coordinate of source upper-left corner
; sy y-coordinate of source upper-left corner
; Raster raster operation code
;
; return If the function succeeds, the return value is nonzero
;
; notes If no raster operation is specified, then SRCCOPY is used, which copies the source directly to the destination rectangle
;
; BLACKNESS = 0x00000042
; NOTSRCERASE = 0x001100A6
; NOTSRCCOPY = 0x00330008
; SRCERASE = 0x00440328
; DSTINVERT = 0x00550009
; PATINVERT = 0x005A0049
; SRCINVERT = 0x00660046
; SRCAND = 0x008800C6
; MERGEPAINT = 0x00BB0226
; MERGECOPY = 0x00C000CA
; SRCCOPY = 0x00CC0020
; SRCPAINT = 0x00EE0086
; PATCOPY = 0x00F00021
; PATPAINT = 0x00FB0A09
; WHITENESS = 0x00FF0062
; CAPTUREBLT = 0x40000000
; NOMIRRORBITMAP = 0x80000000BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster:="")
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdi32\BitBlt", Ptr, dDC, "int", dx, "int", dy, "int", dw, "int", dh, Ptr, sDC, "int", sx, "int", sy, "uint", Raster ? Raster : 0x00CC0020)
};#####################################################################################; Function StretchBlt
; Description The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle,
; stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary.
; The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context.
;
; ddc handle to destination DC
; dx x-coord of destination upper-left corner
; dy y-coord of destination upper-left corner
; dw width of destination rectangle
; dh height of destination rectangle
; sdc handle to source DC
; sx x-coordinate of source upper-left corner
; sy y-coordinate of source upper-left corner
; sw width of source rectangle
; sh height of source rectangle
; Raster raster operation code
;
; return If the function succeeds, the return value is nonzero
;
; notes If no raster operation is specified, then SRCCOPY is used. It uses the same raster operations as BitBltStretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster:="")
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdi32\StretchBlt", Ptr, ddc, "int", dx, "int", dy, "int", dw, "int", dh, Ptr, sdc, "int", sx, "int", sy, "int", sw, "int", sh, "uint", Raster ? Raster : 0x00CC0020)
};#####################################################################################; Function SetStretchBltMode
; Description The SetStretchBltMode function sets the bitmap stretching mode in the specified device context
;
; hdc handle to the DC
; iStretchMode The stretching mode, describing how the target will be stretched
;
; return If the function succeeds, the return value is the previous stretching mode. If it fails it will return 0
;
; STRETCH_ANDSCANS = 0x01
; STRETCH_ORSCANS = 0x02
; STRETCH_DELETESCANS = 0x03
; STRETCH_HALFTONE = 0x04SetStretchBltMode(hdc, iStretchMode:=4)
{return DllCall("gdi32\SetStretchBltMode", A_PtrSize ? "UPtr" : "UInt", hdc, "int", iStretchMode)
};#####################################################################################; Function SetImage
; Description Associates a new image with a static control
;
; hwnd handle of the control to update
; hBitmap a gdi bitmap to associate the static control with
;
; return If the function succeeds, the return value is nonzeroSetImage(hwnd, hBitmap)
{Ptr := A_PtrSize ? "UPtr" : "UInt"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
;
; COLOR_3DDKSHADOW = 21
; COLOR_3DFACE = 15
; COLOR_3DHIGHLIGHT = 20
; COLOR_3DHILIGHT = 20
; COLOR_3DLIGHT = 22
; COLOR_3DSHADOW = 16
; COLOR_ACTIVEBORDER = 10
; COLOR_ACTIVECAPTION = 2
; COLOR_APPWORKSPACE = 12
; COLOR_BACKGROUND = 1
; COLOR_BTNFACE = 15
; COLOR_BTNHIGHLIGHT = 20
; COLOR_BTNHILIGHT = 20
; COLOR_BTNSHADOW = 16
; COLOR_BTNTEXT = 18
; COLOR_CAPTIONTEXT = 9
; COLOR_DESKTOP = 1
; COLOR_GRADIENTACTIVECAPTION = 27
; COLOR_GRADIENTINACTIVECAPTION = 28
; COLOR_GRAYTEXT = 17
; COLOR_HIGHLIGHT = 13
; COLOR_HIGHLIGHTTEXT = 14
; COLOR_HOTLIGHT = 26
; COLOR_INACTIVEBORDER = 11
; COLOR_INACTIVECAPTION = 3
; COLOR_INACTIVECAPTIONTEXT = 19
; COLOR_INFOBK = 24
; COLOR_INFOTEXT = 23
; COLOR_MENU = 4
; COLOR_MENUHILIGHT = 29
; COLOR_MENUBAR = 30
; COLOR_MENUTEXT = 7
; COLOR_SCROLLBAR = 0
; COLOR_WINDOW = 5
; COLOR_WINDOWFRAME = 6
; COLOR_WINDOWTEXT = 8SetSysColorToControl(hwnd, SysColor:=15)
{WinGetRect(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 not passed properly
;
; notes If no raster operation is specified, then SRCCOPY is used to the returned bitmapGdip_BitmapFromScreen(Screen:=0, Raster:="")
{hhdc := 0Ptr := A_PtrSize ? "UPtr" : "UInt"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:"){Screen := SubStr(Screen, 6)if !WinExist("ahk_id " Screen)return -2WinGetRect(Screen,,, _w, _h)_x := _y := 0hhdc := GetDCEx(Screen, 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 -1chdc := CreateCompatibleDC(), hbm := CreateDIBSection(_w, _h, chdc), obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()BitBlt(chdc, 0, 0, _w, _h, hhdc, _x, _y, Raster)ReleaseDC(hhdc)pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)return pBitmap
};#####################################################################################; Function Gdip_BitmapFromHWND
; Description Uses PrintWindow to get a handle to the specified window and return a bitmap from it
;
; hwnd handle to the window to get a bitmap from
;
; return If the function succeeds, the return value is a pointer to a gdi+ bitmap
;
; notes Window must not be not minimised in order to get a handle to it's client areaGdip_BitmapFromHWND(hwnd)
{WinGetRect(hwnd,,, Width, Height)hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)PrintWindow(hwnd, hdc)pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)return pBitmap
};#####################################################################################; Function CreateRectF
; Description Creates a RectF object, containing a the coordinates and dimensions of a rectangle
;
; RectF Name to call the RectF object
; x x-coordinate of the upper left corner of the rectangle
; y y-coordinate of the upper left corner of the rectangle
; w Width of the rectangle
; h Height of the rectangle
;
; return No return valueCreateRectF(ByRef RectF, x, y, w, h)
{VarSetCapacity(RectF, 16)NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
};#####################################################################################; Function CreateRect
; Description Creates a Rect object, containing a the coordinates and dimensions of a rectangle
;
; RectF Name to call the RectF object
; x x-coordinate of the upper left corner of the rectangle
; y y-coordinate of the upper left corner of the rectangle
; w Width of the rectangle
; h Height of the rectangle
;
; return No return valueCreateRect(ByRef Rect, x, y, w, h)
{VarSetCapacity(Rect, 16)NumPut(x, Rect, 0, "uint"), NumPut(y, Rect, 4, "uint"), NumPut(w, Rect, 8, "uint"), NumPut(h, Rect, 12, "uint")
}
;#####################################################################################; Function CreateSizeF
; Description Creates a SizeF object, containing an 2 values
;
; SizeF Name to call the SizeF object
; w w-value for the SizeF object
; h h-value for the SizeF object
;
; return No Return valueCreateSizeF(ByRef SizeF, w, h)
{VarSetCapacity(SizeF, 8)NumPut(w, SizeF, 0, "float"), NumPut(h, SizeF, 4, "float")
}
;#####################################################################################; Function CreatePointF
; Description Creates a SizeF object, containing an 2 values
;
; SizeF Name to call the SizeF object
; w w-value for the SizeF object
; h h-value for the SizeF object
;
; return No Return valueCreatePointF(ByRef PointF, x, y)
{VarSetCapacity(PointF, 8)NumPut(x, PointF, 0, "float"), NumPut(y, PointF, 4, "float")
}
;#####################################################################################; Function CreateDIBSection
; Description The CreateDIBSection function creates a DIB (Device Independent Bitmap) that applications can write to directly
;
; w width of the bitmap to create
; h height of the bitmap to create
; hdc a handle to the device context to use the palette from
; bpp bits per pixel (32 = ARGB)
; ppvBits A pointer to a variable that receives a pointer to the location of the DIB bit values
;
; return returns a DIB. A gdi bitmap
;
; notes ppvBits will receive the location of the pixels in the DIBCreateDIBSection(w, h, hdc:="", bpp:=32, ByRef ppvBits:=0)
{Ptr := A_PtrSize ? "UPtr" : "UInt"hdc2 := hdc ? hdc : GetDC()VarSetCapacity(bi, 40, 0)NumPut(w, bi, 4, "uint"), NumPut(h, bi, 8, "uint"), NumPut(40, bi, 0, "uint"), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16, "uInt"), NumPut(bpp, bi, 14, "ushort")hbm := DllCall("CreateDIBSection", Ptr, hdc2, Ptr, &bi, "uint", 0, A_PtrSize ? "UPtr*" : "uint*", ppvBits, Ptr, 0, "uint", 0, Ptr)if !hdcReleaseDC(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 = 1PrintWindow(hwnd, hdc, Flags:=0)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("PrintWindow", Ptr, hwnd, Ptr, hdc, "uint", Flags)
};#####################################################################################; Function DestroyIcon
; Description Destroys an icon and frees any memory the icon occupied
;
; hIcon Handle to the icon to be destroyed. The icon must not be in use
;
; return If the function succeeds, the return value is nonzeroDestroyIcon(hIcon)
{return DllCall("DestroyIcon", A_PtrSize ? "UPtr" : "UInt", hIcon)
};#####################################################################################; Function: GetIconDimensions
; Description: Retrieves a given icon/cursor's width and height
;
; hIcon Pointer to an icon or cursor
; Width ByRef variable. This variable is set to the icon's width
; Height ByRef variable. This variable is set to the icon's 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 bitmapGetIconDimensions(hIcon, ByRef Width, ByRef Height) {Ptr := A_PtrSize ? "UPtr" : "UInt"Width := Height := 0VarSetCapacity(ICONINFO, size := 16 + 2 * A_PtrSize, 0)if !DllCall("user32\GetIconInfo", Ptr, hIcon, Ptr, &ICONINFO)return -1hbmMask := 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 !DllCall("gdi32\DeleteObject", Ptr, hbmMask)return -2if !DllCall("gdi32\DeleteObject", Ptr, hbmColor)return -3return 0
};#####################################################################################PaintDesktop(hdc)
{return DllCall("PaintDesktop", A_PtrSize ? "UPtr" : "UInt", hdc)
};#####################################################################################CreateCompatibleBitmap(hdc, w, h)
{return DllCall("gdi32\CreateCompatibleBitmap", A_PtrSize ? "UPtr" : "UInt", hdc, "int", w, "int", h)
};#####################################################################################; Function CreateCompatibleDC
; Description This function creates a memory device context (DC) compatible with the specified device
;
; hdc Handle to an existing device context
;
; return returns the handle to a device context or 0 on failure
;
; notes If this handle is 0 (by default), the function creates a memory device context compatible with the application's current screenCreateCompatibleDC(hdc:=0)
{return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
};#####################################################################################; Function SelectObject
; Description The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type
;
; hdc Handle to a DC
; hgdiobj A handle to the object to be selected into the DC
;
; return If the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced
;
; notes The specified object must have been created by using one of the following functions
; Bitmap - CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBSection (A single bitmap cannot be selected into more than one DC at the same time)
; Brush - CreateBrushIndirect, CreateDIBPatternBrush, CreateDIBPatternBrushPt, CreateHatchBrush, CreatePatternBrush, CreateSolidBrush
; Font - CreateFont, CreateFontIndirect
; Pen - CreatePen, CreatePenIndirect
; Region - CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect
;
; notes If the selected object is a region and the function succeeds, the return value is one of the following value
;
; SIMPLEREGION = 2 Region consists of a single rectangle
; COMPLEXREGION = 3 Region consists of more than one rectangle
; NULLREGION = 1 Region is emptySelectObject(hdc, hgdiobj)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
};#####################################################################################; Function DeleteObject
; Description This function deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object
; After the object is deleted, the specified handle is no longer valid
;
; hObject Handle to a logical pen, brush, font, bitmap, region, or palette to delete
;
; return Nonzero indicates success. Zero indicates that the specified handle is not valid or that the handle is currently selected into a device contextDeleteObject(hObject)
{return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
};#####################################################################################; Function GetDC
; Description This function retrieves a handle to a display device context (DC) for the client area of the specified window.
; The display device context can be used in subsequent graphics display interface (GDI) functions to draw in the client area of the window.
;
; hwnd Handle to the window whose device context is to be retrieved. If this value is NULL, GetDC retrieves the device context for the entire screen
;
; return The handle the device context for the specified window's client area indicates success. NULL indicates failureGetDC(hwnd:=0)
{return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
};#####################################################################################; DCX_CACHE = 0x2
; DCX_CLIPCHILDREN = 0x8
; DCX_CLIPSIBLINGS = 0x10
; DCX_EXCLUDERGN = 0x40
; DCX_EXCLUDEUPDATE = 0x100
; DCX_INTERSECTRGN = 0x80
; DCX_INTERSECTUPDATE = 0x200
; DCX_LOCKWINDOWUPDATE = 0x400
; DCX_NORECOMPUTE = 0x100000
; DCX_NORESETATTRS = 0x4
; DCX_PARENTCLIP = 0x20
; DCX_VALIDATE = 0x200000
; DCX_WINDOW = 0x1GetDCEx(hwnd, flags:=0, hrgnClip:=0)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
};#####################################################################################; Function ReleaseDC
; Description This function releases a device context (DC), freeing it for use by other applications. The effect of ReleaseDC depends on the type of device context
;
; hdc Handle to the device context to be released
; hwnd Handle to the window whose device context is to be released
;
; return 1 = released
; 0 = not released
;
; notes The application must call the ReleaseDC function for each call to the GetWindowDC function and for each call to the GetDC function that retrieves a common device context
; An application cannot use the ReleaseDC function to release a device context that was created by calling the CreateDC function; instead, it must use the DeleteDC function.ReleaseDC(hdc, hwnd:=0)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
};#####################################################################################; Function DeleteDC
; Description The DeleteDC function deletes the specified device context (DC)
;
; hdc A handle to the device context
;
; return If the function succeeds, the return value is nonzero
;
; notes An application must not delete a DC whose handle was obtained by calling the GetDC function. Instead, it must call the ReleaseDC function to free the DCDeleteDC(hdc)
{return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
;#####################################################################################; Function Gdip_LibraryVersion
; Description Get the current library version
;
; return the library version
;
; notes This is useful for non compiled programs to ensure that a person doesn't run an old version when testing your scriptsGdip_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
Gdip_LibrarySubVersion()
{return 1.54
};#####################################################################################; 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 BRAGdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate := 0) {pBitmap := 0pStream := 0If !(BRAFromMemIn)Return -1Headers := StrSplit(StrGet(&BRAFromMemIn, 256, "CP0"), "`n")Header := StrSplit(Headers[1], "|")HeaderLength := (A_AhkVersion < "2") ? Header.Length() : Header.LengthIf (HeaderLength != 4) || (Header[2] != "BRA!")Return -2_Info := StrSplit(Headers[2], "|")_InfoLength := (A_AhkVersion < "2") ? _Info.Length() : _Info.LengthIf (_InfoLength != 3)Return -3OffsetTOC := StrPut(Headers[1], "CP0") + StrPut(Headers[2], "CP0") ; + 2OffsetData := _Info[2]SearchIndex := Alternate ? 1 : 2TOC := StrGet(&BRAFromMemIn + OffsetTOC, OffsetData - OffsetTOC - 1, "CP0")RX1 := A_AhkVersion < "2" ? "mi`nO)^" : "mi`n)^"Offset := Size := 0If RegExMatch(TOC, RX1 . (Alternate ? File "\|.+?" : "\d+\|" . File) . "\|(\d+)\|(\d+)$", FileInfo) {Offset := OffsetData + FileInfo[1]Size := FileInfo[2]}If (Size = 0)Return -4hData := 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)DllCall("Gdiplus.dll\GdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap)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 streamGdip_BitmapFromBase64(ByRef Base64)
{Ptr := A_PtrSize ? "UPtr" : "UInt"DecLen := 0pBitmap := 0; calculate the length of the buffer neededif !(DllCall("crypt32\CryptStringToBinary", Ptr, &Base64, "UInt", 0, "UInt", 0x01, Ptr, 0, "UIntP", DecLen, Ptr, 0, Ptr, 0))return -1VarSetCapacity(Dec, DecLen, 0); decode the Base64 encoded stringif !(DllCall("crypt32\CryptStringToBinary", Ptr, &Base64, "UInt", 0, "UInt", 0x01, Ptr, &Dec, "UIntP", DecLen, Ptr, 0, Ptr, 0))return -2; create a memory streamif !(pStream := DllCall("shlwapi\SHCreateMemStream", Ptr, &Dec, "UInt", DecLen, "UPtr"))return -3DllCall("gdiplus\GdipCreateBitmapFromStreamICM", Ptr, pStream, "PtrP", pBitmap)ObjRelease(pStream)return pBitmap
};#####################################################################################; Function Gdip_DrawRectangle
; Description This function uses a pen to draw the outline of a rectangle into the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; x x-coordinate of the top left of the rectangle
; y y-coordinate of the top left of the rectangle
; w width of the rectanlge
; h height of the rectangle
;
; return status enumeration. 0 = success
;
; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen widthGdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipDrawRectangle", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h)
};#####################################################################################; Function Gdip_DrawRoundedRectangle
; Description This function uses a pen to draw the outline of a rounded rectangle into the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; x x-coordinate of the top left of the rounded rectangle
; y y-coordinate of the top left of the rounded rectangle
; w width of the rectanlge
; h height of the rectangle
; r radius of the rounded corners
;
; return status enumeration. 0 = success
;
; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen widthGdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r)
{Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)_E := Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)Gdip_ResetClip(pGraphics)Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)Gdip_DrawEllipse(pGraphics, pPen, x, y, 2*r, 2*r)Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y, 2*r, 2*r)Gdip_DrawEllipse(pGraphics, pPen, x, y+h-(2*r), 2*r, 2*r)Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y+h-(2*r), 2*r, 2*r)Gdip_ResetClip(pGraphics)return _E
};#####################################################################################; Function Gdip_DrawEllipse
; Description This function uses a pen to draw the outline of an ellipse into the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; x x-coordinate of the top left of the rectangle the ellipse will be drawn into
; y y-coordinate of the top left of the rectangle the ellipse will be drawn into
; w width of the ellipse
; h height of the ellipse
;
; return status enumeration. 0 = success
;
; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen widthGdip_DrawEllipse(pGraphics, pPen, x, y, w, h)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipDrawEllipse", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h)
};#####################################################################################; Function Gdip_DrawBezier
; Description This function uses a pen to draw the outline of a bezier (a weighted curve) into the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; x1 x-coordinate of the start of the bezier
; y1 y-coordinate of the start of the bezier
; x2 x-coordinate of the first arc of the bezier
; y2 y-coordinate of the first arc of the bezier
; x3 x-coordinate of the second arc of the bezier
; y3 y-coordinate of the second arc of the bezier
; x4 x-coordinate of the end of the bezier
; y4 y-coordinate of the end of the bezier
;
; return status enumeration. 0 = success
;
; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen widthGdip_DrawBezier(pGraphics, pPen, x1, y1, x2, y2, x3, y3, x4, y4)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipDrawBezier", Ptr, pgraphics, Ptr, pPen, "float", x1, "float", y1, "float", x2, "float", y2, "float", x3, "float", y3, "float", x4, "float", y4)
};#####################################################################################; Function Gdip_DrawArc
; Description This function uses a pen to draw the outline of an arc into the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; x x-coordinate of the start of the arc
; y y-coordinate of the start of the arc
; w width of the arc
; h height of the arc
; StartAngle specifies the angle between the x-axis and the starting point of the arc
; SweepAngle specifies the angle between the starting and ending points of the arc
;
; return status enumeration. 0 = success
;
; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen widthGdip_DrawArc(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipDrawArc", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
};#####################################################################################; Function Gdip_DrawPie
; Description This function uses a pen to draw the outline of a pie into the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; x x-coordinate of the start of the pie
; y y-coordinate of the start of the pie
; w width of the pie
; h height of the pie
; StartAngle specifies the angle between the x-axis and the starting point of the pie
; SweepAngle specifies the angle between the starting and ending points of the pie
;
; return status enumeration. 0 = success
;
; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen widthGdip_DrawPie(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipDrawPie", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
};#####################################################################################; Function Gdip_DrawLine
; Description This function uses a pen to draw a line into the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; x1 x-coordinate of the start of the line
; y1 y-coordinate of the start of the line
; x2 x-coordinate of the end of the line
; y2 y-coordinate of the end of the line
;
; return status enumeration. 0 = successGdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipDrawLine", Ptr, pGraphics, Ptr, pPen, "float", x1, "float", y1, "float", x2, "float", y2)
};#####################################################################################; Function Gdip_DrawLines
; Description This function uses a pen to draw a series of joined lines into the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return status enumeration. 0 = successGdip_DrawLines(pGraphics, pPen, Points)
{Ptr := A_PtrSize ? "UPtr" : "UInt"Points := StrSplit(Points, "|")PointsLength := (A_AhkVersion < "2") ? Points.Length() : Points.LengthVarSetCapacity(PointF, 8*PointsLength)for eachPoint, Point in Points{Coord := StrSplit(Point, ",")NumPut(Coord[1], PointF, 8*(A_Index-1), "float"), NumPut(Coord[2], PointF, (8*(A_Index-1))+4, "float")}return DllCall("gdiplus\GdipDrawLines", Ptr, pGraphics, Ptr, pPen, Ptr, &PointF, "int", PointsLength)
};#####################################################################################; Function Gdip_FillRectangle
; Description This function uses a brush to fill a rectangle in the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pBrush Pointer to a brush
; x x-coordinate of the top left of the rectangle
; y y-coordinate of the top left of the rectangle
; w width of the rectanlge
; h height of the rectangle
;
; return status enumeration. 0 = successGdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipFillRectangle", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
};#####################################################################################; Function Gdip_FillRoundedRectangle
; Description This function uses a brush to fill a rounded rectangle in the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pBrush Pointer to a brush
; x x-coordinate of the top left of the rounded rectangle
; y y-coordinate of the top left of the rounded rectangle
; w width of the rectanlge
; h height of the rectangle
; r radius of the rounded corners
;
; return status enumeration. 0 = successGdip_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 = 1Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode:=0)
{Ptr := A_PtrSize ? "UPtr" : "UInt"Points := StrSplit(Points, "|")PointsLength := (A_AhkVersion < "2") ? Points.Length() : Points.LengthVarSetCapacity(PointF, 8*PointsLength)For eachPoint, Point in Points{Coord := StrSplit(Point, ",")NumPut(Coord[1], PointF, 8*(A_Index-1), "float"), NumPut(Coord[2], PointF, (8*(A_Index-1))+4, "float")}return DllCall("gdiplus\GdipFillPolygon", Ptr, pGraphics, Ptr, pBrush, Ptr, &PointF, "int", PointsLength, "int", FillMode)
};#####################################################################################; Function Gdip_FillPie
; Description This function uses a brush to fill a pie in the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pBrush Pointer to a brush
; x x-coordinate of the top left of the pie
; y y-coordinate of the top left of the pie
; w width of the pie
; h height of the pie
; StartAngle specifies the angle between the x-axis and the starting point of the pie
; SweepAngle specifies the angle between the starting and ending points of the pie
;
; return status enumeration. 0 = successGdip_FillPie(pGraphics, pBrush, x, y, w, h, StartAngle, SweepAngle)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipFillPie", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
};#####################################################################################; Function Gdip_FillEllipse
; Description This function uses a brush to fill an ellipse in the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pBrush Pointer to a brush
; x x-coordinate of the top left of the ellipse
; y y-coordinate of the top left of the ellipse
; w width of the ellipse
; h height of the ellipse
;
; return status enumeration. 0 = successGdip_FillEllipse(pGraphics, pBrush, x, y, w, h)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipFillEllipse", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
};#####################################################################################; Function Gdip_FillRegion
; Description This function uses a brush to fill a region in the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pBrush Pointer to a brush
; Region Pointer to a Region
;
; return status enumeration. 0 = success
;
; notes You can create a region Gdip_CreateRegion() and then add to thisGdip_FillRegion(pGraphics, pBrush, Region)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipFillRegion", Ptr, pGraphics, Ptr, pBrush, Ptr, Region)
};#####################################################################################; Function Gdip_FillPath
; Description This function uses a brush to fill a path in the Graphics of a bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pBrush Pointer to a brush
; Region Pointer to a Path
;
; return status enumeration. 0 = successGdip_FillPath(pGraphics, pBrush, pPath)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipFillPath", Ptr, pGraphics, Ptr, pBrush, Ptr, pPath)
};#####################################################################################; Function Gdip_DrawImagePointsRect
; Description This function draws a bitmap into the Graphics of another bitmap and skews it
;
; pGraphics Pointer to the Graphics of a bitmap
; pBitmap Pointer to a bitmap to be drawn
; Points Points passed as x1,y1|x2,y2|x3,y3 (3 points: top left, top right, bottom left) describing the drawing of the bitmap
; sx x-coordinate of source upper-left corner
; sy y-coordinate of source upper-left corner
; sw width of source rectangle
; sh height of source rectangle
; Matrix a matrix used to alter image attributes when drawing
;
; return status enumeration. 0 = success
;
; notes if sx,sy,sw,sh are missed then the entire source bitmap will be used
; Matrix can be omitted to just draw with no alteration to ARGB
; Matrix may be passed as a digit from 0 - 1 to change just transparency
; Matrix can be passed as a matrix with any delimiterGdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx:="", sy:="", sw:="", sh:="", Matrix:=1)
{Ptr := A_PtrSize ? "UPtr" : "UInt"Points := StrSplit(Points, "|")PointsLength := (A_AhkVersion < "2") ? Points.Length() : Points.LengthVarSetCapacity(PointF, 8*PointsLength)For eachPoint, Point in Points{Coord := StrSplit(Point, ",")NumPut(Coord[1], PointF, 8*(A_Index-1), "float"), NumPut(Coord[2], PointF, (8*(A_Index-1))+4, "float")}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")if (sx = "" && sy = "" && sw = "" && sh = ""){sx := 0, sy := 0sw := Gdip_GetImageWidth(pBitmap)sh := Gdip_GetImageHeight(pBitmap)}_E := DllCall("gdiplus\GdipDrawImagePointsRect", Ptr, pGraphics, Ptr, pBitmap, Ptr, &PointF, "int", PointsLength, "float", sx, "float", sy, "float", sw, "float", sh, "int", 2, Ptr, ImageAttr, Ptr, 0, Ptr, 0)if ImageAttrGdip_DisposeImageAttributes(ImageAttr)return _E
};#####################################################################################; Function Gdip_DrawImage
; Description This function draws a bitmap into the Graphics of another bitmap
;
; pGraphics Pointer to the Graphics of a bitmap
; pBitmap Pointer to a bitmap to be drawn
; dx x-coord of destination upper-left corner
; dy y-coord of destination upper-left corner
; dw width of destination image
; dh height of destination image
; sx x-coordinate of source upper-left corner
; sy y-coordinate of source upper-left corner
; sw width of source image
; sh height of source image
; Matrix a matrix used to alter image attributes when drawing
;
; return status enumeration. 0 = success
;
; notes if sx,sy,sw,sh are missed then the entire source bitmap will be used
; Gdip_DrawImage performs faster
; Matrix can be omitted to just draw with no alteration to ARGB
; Matrix may be passed as a digit from 0 - 1 to change just transparency
; Matrix can be passed as a matrix with any delimiter. For example:
; MatrixBright=
; (
; 1.5 |0 |0 |0 |0
; 0 |1.5 |0 |0 |0
; 0 |0 |1.5 |0 |0
; 0 |0 |0 |1 |0
; 0.05 |0.05 |0.05 |0 |1
; )
;
; notes MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
; MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
; MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|1|1|1|0|1Gdip_DrawImage(pGraphics, pBitmap, dx:="", dy:="", dw:="", dh:="", sx:="", sy:="", sw:="", sh:="", Matrix:=1)
{Ptr := A_PtrSize ? "UPtr" : "UInt"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")if (sx = "" && sy = "" && sw = "" && sh = ""){if (dx = "" && dy = "" && dw = "" && dh = ""){sx := dx := 0, sy := dy := 0sw := dw := Gdip_GetImageWidth(pBitmap)sh := dh := Gdip_GetImageHeight(pBitmap)}else{sx := sy := 0sw := Gdip_GetImageWidth(pBitmap)sh := Gdip_GetImageHeight(pBitmap)}}_E := DllCall("gdiplus\GdipDrawImageRectRect", Ptr, pGraphics, Ptr, pBitmap, "float", dx, "float", dy, "float", dw, "float", dh, "float", sx, "float", sy, "float", sw, "float", sh, "int", 2, Ptr, ImageAttr ? ImageAttr : 0, Ptr, 0, Ptr, 0)if ImageAttrGdip_DisposeImageAttributes(ImageAttr)return _E
};#####################################################################################; Function Gdip_SetImageAttributesColorMatrix
; Description This function creates an image matrix ready for drawing
;
; Matrix a matrix used to alter image attributes when drawing
; passed with any delimeter
;
; return returns an image matrix on sucess or 0 if it fails
;
; notes MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
; MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
; MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|1|1|1|0|1Gdip_SetImageAttributesColorMatrix(Matrix)
{Ptr := A_PtrSize ? "UPtr" : "UInt"ImageAttr := 0VarSetCapacity(ColourMatrix, 100, 0)Matrix := RegExReplace(RegExReplace(Matrix, "^[^\d-\.]+([\d\.])", "$1", , 1), "[^\d-\.]+", "|")Matrix := StrSplit(Matrix, "|")Loop 25{M := (Matrix[A_Index] != "") ? Matrix[A_Index] : Mod(A_Index-1, 6) ? 0 : 1NumPut(M, ColourMatrix, (A_Index-1)*4, "float")}DllCall("gdiplus\GdipCreateImageAttributes", A_PtrSize ? "UPtr*" : "uint*", ImageAttr)DllCall("gdiplus\GdipSetImageAttributesColorMatrix", Ptr, ImageAttr, "int", 1, "int", 1, Ptr, &ColourMatrix, Ptr, 0, "int", 0)return ImageAttr
};#####################################################################################; Function Gdip_GraphicsFromImage
; Description This function gets the graphics for a bitmap used for drawing functions
;
; pBitmap Pointer to a bitmap to get the pointer to its graphics
;
; return returns a pointer to the graphics of a bitmap
;
; notes a bitmap can be drawn into the graphics of another bitmapGdip_GraphicsFromImage(pBitmap)
{pGraphics := 0DllCall("gdiplus\GdipGetImageGraphicsContext", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)return pGraphics
};#####################################################################################; Function Gdip_GraphicsFromHDC
; Description This function gets the graphics from the handle to a device context
;
; hdc This is the handle to the device context
;
; return returns a pointer to the graphics of a bitmap
;
; notes You can draw a bitmap into the graphics of another bitmapGdip_GraphicsFromHDC(hdc)
{pGraphics := 0DllCall("gdiplus\GdipCreateFromHDC", A_PtrSize ? "UPtr" : "UInt", hdc, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)return pGraphics
};#####################################################################################; Function Gdip_GetDC
; Description This function gets the device context of the passed Graphics
;
; hdc This is the handle to the device context
;
; return returns the device context for the graphics of a bitmapGdip_GetDC(pGraphics)
{hdc := 0DllCall("gdiplus\GdipGetDC", A_PtrSize ? "UPtr" : "UInt", pGraphics, A_PtrSize ? "UPtr*" : "UInt*", hdc)return hdc
};#####################################################################################; Function Gdip_ReleaseDC
; Description This function releases a device context from use for further use
;
; pGraphics Pointer to the graphics of a bitmap
; hdc This is the handle to the device context
;
; return status enumeration. 0 = successGdip_ReleaseDC(pGraphics, hdc)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipReleaseDC", Ptr, pGraphics, Ptr, hdc)
};#####################################################################################; Function Gdip_GraphicsClear
; Description Clears the graphics of a bitmap ready for further drawing
;
; pGraphics Pointer to the graphics of a bitmap
; ARGB The colour to clear the graphics to
;
; return status enumeration. 0 = success
;
; notes By default this will make the background invisible
; Using clipping regions you can clear a particular area on the graphics rather than clearing the entire graphicsGdip_GraphicsClear(pGraphics, ARGB:=0x00ffffff)
{return DllCall("gdiplus\GdipGraphicsClear", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", ARGB)
};#####################################################################################; Function Gdip_BlurBitmap
; Description Gives a pointer to a blurred bitmap from a pointer to a bitmap
;
; pBitmap Pointer to a bitmap to be blurred
; Blur The Amount to blur a bitmap by from 1 (least blur) to 100 (most blur)
;
; return If the function succeeds, the return value is a pointer to the new blurred bitmap
; -1 = The blur parameter is outside the range 1-100
;
; notes This function will not dispose of the original bitmapGdip_BlurBitmap(pBitmap, Blur)
{if (Blur > 100) || (Blur < 1)return -1sWidth := Gdip_GetImageWidth(pBitmap), sHeight := Gdip_GetImageHeight(pBitmap)dWidth := sWidth//Blur, dHeight := sHeight//BlurpBitmap1 := Gdip_CreateBitmap(dWidth, dHeight)G1 := Gdip_GraphicsFromImage(pBitmap1)Gdip_SetInterpolationMode(G1, 7)Gdip_DrawImage(G1, pBitmap, 0, 0, dWidth, dHeight, 0, 0, sWidth, sHeight)Gdip_DeleteGraphics(G1)pBitmap2 := Gdip_CreateBitmap(sWidth, sHeight)G2 := Gdip_GraphicsFromImage(pBitmap2)Gdip_SetInterpolationMode(G2, 7)Gdip_DrawImage(G2, pBitmap1, 0, 0, sWidth, sHeight, 0, 0, dWidth, dHeight)Gdip_DeleteGraphics(G2)Gdip_DisposeImage(pBitmap1)return pBitmap2
};#####################################################################################; Function: Gdip_SaveBitmapToFile
; Description: Saves a bitmap to a file in any supported format onto disk
;
; pBitmap Pointer to a bitmap
; sOutput The name of the file that the bitmap will be saved to. Supported extensions are: .BMP,.DIB,.RLE,.JPG,.JPEG,.JPE,.JFIF,.GIF,.TIF,.TIFF,.PNG
; Quality If saving as jpg (.JPG,.JPEG,.JPE,.JFIF) then quality can be 1-100 with default at maximum quality
;
; return If the function succeeds, the return value is zero, otherwise:
; -1 = Extension supplied is not a supported file format
; -2 = Could not get a list of encoders on system
; -3 = Could not find matching encoder for specified file format
; -4 = Could not get WideChar name of output file
; -5 = Could not save file to disk
;
; notes This function will use the extension supplied from the sOutput parameter to determine the output formatGdip_SaveBitmapToFile(pBitmap, sOutput, Quality:=75)
{Ptr := A_PtrSize ? "UPtr" : "UInt"nCount := 0nSize := 0_p := 0SplitPath sOutput,,, Extensionif !RegExMatch(Extension, "^(?i:BMP|DIB|RLE|JPG|JPEG|JPE|JFIF|GIF|TIF|TIFF|PNG)$")return -1Extension := "." ExtensionDllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)VarSetCapacity(ci, nSize)DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)if !(nCount && nSize)return -2If (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)continuepCodec := &ci+idxbreak}} 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)continuepCodec := &ci+76*(A_Index-1)break}}if !pCodecreturn -3if (Quality != 75){Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Qualityif 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_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6){_p := elem+&EncoderParameters-pad-4NumPut(Quality, NumGet(NumPut(4, NumPut(1, _p+0)+20, "UInt")), "UInt")break}}}}if (!A_IsUnicode){nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)VarSetCapacity(wOutput, nSize*2)DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)VarSetCapacity(wOutput, -1)if !VarSetCapacity(wOutput)return -4_E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", _p ? _p : 0)}else_E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", _p ? _p : 0)return _E ? -5 : 0
};#####################################################################################; Function Gdip_GetPixel
; Description Gets the ARGB of a pixel in a bitmap
;
; pBitmap Pointer to a bitmap
; x x-coordinate of the pixel
; y y-coordinate of the pixel
;
; return Returns the ARGB value of the pixelGdip_GetPixel(pBitmap, x, y)
{ARGB := 0DllCall("gdiplus\GdipBitmapGetPixel", A_PtrSize ? "UPtr" : "UInt", pBitmap, "int", x, "int", y, "uint*", ARGB)return ARGB
};#####################################################################################; Function Gdip_SetPixel
; Description Sets the ARGB of a pixel in a bitmap
;
; pBitmap Pointer to a bitmap
; x x-coordinate of the pixel
; y y-coordinate of the pixel
;
; return status enumeration. 0 = successGdip_SetPixel(pBitmap, x, y, ARGB)
{return DllCall("gdiplus\GdipBitmapSetPixel", A_PtrSize ? "UPtr" : "UInt", pBitmap, "int", x, "int", y, "int", ARGB)
};#####################################################################################; Function Gdip_GetImageWidth
; Description Gives the width of a bitmap
;
; pBitmap Pointer to a bitmap
;
; return Returns the width in pixels of the supplied bitmapGdip_GetImageWidth(pBitmap)
{Width := 0DllCall("gdiplus\GdipGetImageWidth", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Width)return Width
};#####################################################################################; Function Gdip_GetImageHeight
; Description Gives the height of a bitmap
;
; pBitmap Pointer to a bitmap
;
; return Returns the height in pixels of the supplied bitmapGdip_GetImageHeight(pBitmap)
{Height := 0DllCall("gdiplus\GdipGetImageHeight", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Height)return Height
};#####################################################################################; Function Gdip_GetDimensions
; Description Gives the width and height of a bitmap
;
; pBitmap Pointer to a bitmap
; Width ByRef variable. This variable will be set to the width of the bitmap
; Height ByRef variable. This variable will be set to the height of the bitmap
;
; return No return value
; Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the heightGdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height)
{Width := 0Height := 0Ptr := A_PtrSize ? "UPtr" : "UInt"DllCall("gdiplus\GdipGetImageWidth", Ptr, pBitmap, "uint*", Width)DllCall("gdiplus\GdipGetImageHeight", Ptr, pBitmap, "uint*", Height)
};#####################################################################################Gdip_GetDimensions(pBitmap, ByRef Width, ByRef Height)
{Gdip_GetImageDimensions(pBitmap, Width, Height)
};#####################################################################################Gdip_GetImagePixelFormat(pBitmap)
{Format := 0DllCall("gdiplus\GdipGetImagePixelFormat", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "UInt*", Format)return Format
};#####################################################################################; Function Gdip_GetDpiX
; Description Gives the horizontal dots per inch of the graphics of a bitmap
;
; pBitmap Pointer to a bitmap
; Width ByRef variable. This variable will be set to the width of the bitmap
; Height ByRef variable. This variable will be set to the height of the bitmap
;
; return No return value
; Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the heightGdip_GetDpiX(pGraphics)
{dpix := 0DllCall("gdiplus\GdipGetDpiX", A_PtrSize ? "UPtr" : "uint", pGraphics, "float*", dpix)return Round(dpix)
};#####################################################################################Gdip_GetDpiY(pGraphics)
{dpiy := 0DllCall("gdiplus\GdipGetDpiY", A_PtrSize ? "UPtr" : "uint", pGraphics, "float*", dpiy)return Round(dpiy)
};#####################################################################################Gdip_GetImageHorizontalResolution(pBitmap)
{dpix := 0DllCall("gdiplus\GdipGetImageHorizontalResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float*", dpix)return Round(dpix)
};#####################################################################################Gdip_GetImageVerticalResolution(pBitmap)
{dpiy := 0DllCall("gdiplus\GdipGetImageVerticalResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float*", dpiy)return Round(dpiy)
};#####################################################################################Gdip_BitmapSetResolution(pBitmap, dpix, dpiy)
{return DllCall("gdiplus\GdipBitmapSetResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float", dpix, "float", dpiy)
};#####################################################################################Gdip_CreateBitmapFromFile(sFile, IconNumber:=1, IconSize:="")
{pBitmap := 0pBitmapOld := 0hIcon := 0Ptr := A_PtrSize ? "UPtr" : "UInt", PtrA := A_PtrSize ? "UPtr*" : "UInt*"SplitPath sFile,,, Extensionif RegExMatch(Extension, "^(?i:exe|dll)$"){Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16BufSize := 16 + (2*(A_PtrSize ? A_PtrSize : 4))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 !hIconcontinueif !DllCall("GetIconInfo", Ptr, hIcon, Ptr, &buf){DestroyIcon(hIcon)continue}hbmMask := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4))hbmColor := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4) + (A_PtrSize ? A_PtrSize : 4))if !(hbmColor && DllCall("GetObject", Ptr, hbmColor, "int", BufSize, Ptr, &buf)){DestroyIcon(hIcon)continue}break}if !hIconreturn -1Width := 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_PtrSizeStride := NumGet(dib, 12, "Int"), Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0)) ; paddingDllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", Stride, "int", 0x26200A, Ptr, Bits, PtrA, pBitmapOld)pBitmap := Gdip_CreateBitmap(Width, Height)_G := Gdip_GraphicsFromImage(pBitmap), Gdip_DrawImage(_G, pBitmapOld, 0, 0, Width, Height, 0, 0, Width, Height)SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)Gdip_DeleteGraphics(_G), Gdip_DisposeImage(pBitmapOld)DestroyIcon(hIcon)}else{if (!A_IsUnicode){VarSetCapacity(wFile, 1024)DllCall("kernel32\MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sFile, "int", -1, Ptr, &wFile, "int", 512)DllCall("gdiplus\GdipCreateBitmapFromFile", Ptr, &wFile, PtrA, pBitmap)}elseDllCall("gdiplus\GdipCreateBitmapFromFile", Ptr, &sFile, PtrA, pBitmap)}return pBitmap
};#####################################################################################Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette:=0)
{Ptr := A_PtrSize ? "UPtr" : "UInt"pBitmap := 0DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)return pBitmap
};#####################################################################################Gdip_CreateHBITMAPFromBitmap(pBitmap, Background:=0xffffffff)
{hbm := 0DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "uint*", hbm, "int", Background)return hbm
};#####################################################################################Gdip_CreateARGBBitmapFromHBITMAP(ByRef hBitmap) {; struct BITMAP - https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapDllCall("GetObject", "ptr", hBitmap, "int", VarSetCapacity(dib, 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize), "ptr", &dib) ; sizeof(DIBSECTION) = 84, 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 32-bit ARGB.if (bpp != 32) { ; This built-in version is 120% faster but ignores transparency.DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "ptr", hBitmap, "ptr", 0, "ptr*", pBitmap:=0)return pBitmap}; Create a handle to a device context and associate the image.hdc := DllCall("CreateCompatibleDC", "ptr", 0, "ptr") ; Creates a memory DC compatible with the current screen.obm := DllCall("SelectObject", "ptr", hdc, "ptr", hBitmap, "ptr") ; Put the (hBitmap) image onto the device context.; Create a device independent bitmap with negative height. All DIBs use the screen pixel format (pARGB).; Use hbm to buffer the image such that top-down and bottom-up images are mapped to this top-down buffer.cdc := DllCall("CreateCompatibleDC", "ptr", hdc, "ptr")VarSetCapacity(bi, 40, 0) ; sizeof(bi) = 40, NumPut( 40, bi, 0, "uint") ; Size, NumPut( width, bi, 4, "uint") ; Width, NumPut( -height, bi, 8, "int") ; Height - Negative so (0, 0) is top-left., NumPut( 1, bi, 12, "ushort") ; Planes, NumPut( 32, bi, 14, "ushort") ; BitCount / BitsPerPixelhbm := DllCall("CreateDIBSection", "ptr", cdc, "ptr", &bi, "uint", 0, "ptr*", pBits:=0 ; pBits is the pointer to (top-down) pixel values., "ptr", 0, "uint", 0, "ptr")ob2 := DllCall("SelectObject", "ptr", cdc, "ptr", hbm, "ptr"); This is the 32-bit ARGB pBitmap (different from an hBitmap) that will receive the final converted pixels.DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", width, "int", height, "int", 0, "int", 0x26200A, "ptr", 0, "ptr*", pBitmap:=0); Create a Scan0 buffer pointing to pBits. The buffer has pixel format pARGB.VarSetCapacity(Rect, 16, 0) ; sizeof(Rect) = 16, NumPut( width, Rect, 8, "uint") ; Width, NumPut( height, Rect, 12, "uint") ; HeightVarSetCapacity(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; Use LockBits to create a writable buffer that converts pARGB to ARGB.DllCall("gdiplus\GdipBitmapLockBits", "ptr", pBitmap, "ptr", &Rect, "uint", 6 ; ImageLockMode.UserInputBuffer | ImageLockMode.WriteOnly, "int", 0xE200B ; Format32bppPArgb, "ptr", &BitmapData) ; Contains the pointer (pBits) to the hbm.; Copies the image (hBitmap) to a top-down bitmap. Removes bottom-up-ness if present.DllCall("gdi32\BitBlt", "ptr", cdc, "int", 0, "int", 0, "int", width, "int", height, "ptr", hdc, "int", 0, "int", 0, "uint", 0x00CC0020) ; SRCCOPY; 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.DllCall("SelectObject", "ptr", cdc, "ptr", ob2)DllCall("DeleteObject", "ptr", hbm)DllCall("DeleteDC", "ptr", cdc)DllCall("SelectObject", "ptr", hdc, "ptr", obm)DllCall("DeleteDC", "ptr", hdc)return pBitmap
};#####################################################################################Gdip_CreateARGBHBITMAPFromBitmap(ByRef pBitmap) {; This version is about 25% faster than Gdip_CreateHBITMAPFromBitmap().; Get Bitmap width and height.DllCall("gdiplus\GdipGetImageWidth", "ptr", pBitmap, "uint*", width:=0)DllCall("gdiplus\GdipGetImageHeight", "ptr", pBitmap, "uint*", height:=0); Convert the source pBitmap into a hBitmap manually.; struct BITMAPINFOHEADER - https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheaderhdc := DllCall("CreateCompatibleDC", "ptr", 0, "ptr")VarSetCapacity(bi, 40, 0) ; sizeof(bi) = 40, NumPut( 40, bi, 0, "uint") ; Size, NumPut( width, bi, 4, "uint") ; Width, NumPut( -height, bi, 8, "int") ; Height - Negative so (0, 0) is top-left., NumPut( 1, bi, 12, "ushort") ; Planes, NumPut( 32, bi, 14, "ushort") ; BitCount / BitsPerPixelhbm := DllCall("CreateDIBSection", "ptr", hdc, "ptr", &bi, "uint", 0, "ptr*", pBits:=0, "ptr", 0, "uint", 0, "ptr")obm := DllCall("SelectObject", "ptr", hdc, "ptr", hbm, "ptr"); Transfer data from source pBitmap to an hBitmap manually.VarSetCapacity(Rect, 16, 0) ; sizeof(Rect) = 16, NumPut( width, Rect, 8, "uint") ; Width, NumPut( height, Rect, 12, "uint") ; HeightVarSetCapacity(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") ; Scan0DllCall("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.DllCall("SelectObject", "ptr", hdc, "ptr", obm)DllCall("DeleteDC", "ptr", hdc)return hbm
};#####################################################################################Gdip_CreateBitmapFromHICON(hIcon)
{pBitmap := 0DllCall("gdiplus\GdipCreateBitmapFromHICON", A_PtrSize ? "UPtr" : "UInt", hIcon, A_PtrSize ? "UPtr*" : "uint*", pBitmap)return pBitmap
};#####################################################################################Gdip_CreateHICONFromBitmap(pBitmap)
{hIcon := 0DllCall("gdiplus\GdipCreateHICONFromBitmap", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "uint*", hIcon)return hIcon
};#####################################################################################Gdip_CreateBitmap(Width, Height, Format:=0x26200A)
{pBitmap := 0DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", 0, "int", Format, A_PtrSize ? "UPtr" : "UInt", 0, A_PtrSize ? "UPtr*" : "uint*", pBitmap)Return pBitmap
};#####################################################################################Gdip_CreateBitmapFromClipboard()
{Ptr := A_PtrSize ? "UPtr" : "UInt"if !DllCall("IsClipboardFormatAvailable", "uint", 8)return -2if !DllCall("OpenClipboard", Ptr, 0)return -1hBitmap := DllCall("GetClipboardData", "uint", 2, Ptr)if !DllCall("CloseClipboard")return -5if !hBitmapreturn -3if !pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap)return -4DeleteObject(hBitmap)return pBitmap
};#####################################################################################Gdip_SetBitmapToClipboard(pBitmap)
{Ptr := A_PtrSize ? "UPtr" : "UInt"off1 := A_PtrSize = 8 ? 52 : 44, off2 := A_PtrSize = 8 ? 32 : 24hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)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 ? A_PtrSize : 4), Ptr), Ptr, NumGet(oi, off1, "UInt"))DllCall("GlobalUnlock", Ptr, hdib)DllCall("DeleteObject", Ptr, hBitmap)DllCall("OpenClipboard", Ptr, 0)DllCall("EmptyClipboard")DllCall("SetClipboardData", "uint", 8, Ptr, hdib)DllCall("CloseClipboard")
};#####################################################################################Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format:=0x26200A)
{pBitmapDest := 0DllCall("gdiplus\GdipCloneBitmapArea", "float", x, "float", y, "float", w, "float", h, "int", Format, A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "UInt*", pBitmapDest)return pBitmapDest
};#####################################################################################
; Create resources
;#####################################################################################Gdip_CreatePen(ARGB, w)
{pPen := 0DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)return pPen
};#####################################################################################Gdip_CreatePenFromBrush(pBrush, w)
{pPen := 0DllCall("gdiplus\GdipCreatePen2", A_PtrSize ? "UPtr" : "UInt", pBrush, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)return pPen
};#####################################################################################Gdip_BrushCreateSolid(ARGB:=0xff000000)
{pBrush := 0DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, A_PtrSize ? "UPtr*" : "UInt*", pBrush)return pBrush
};#####################################################################################; HatchStyleHorizontal = 0
; HatchStyleVertical = 1
; HatchStyleForwardDiagonal = 2
; HatchStyleBackwardDiagonal = 3
; HatchStyleCross = 4
; HatchStyleDiagonalCross = 5
; HatchStyle05Percent = 6
; HatchStyle10Percent = 7
; HatchStyle20Percent = 8
; HatchStyle25Percent = 9
; HatchStyle30Percent = 10
; HatchStyle40Percent = 11
; HatchStyle50Percent = 12
; HatchStyle60Percent = 13
; HatchStyle70Percent = 14
; HatchStyle75Percent = 15
; HatchStyle80Percent = 16
; HatchStyle90Percent = 17
; HatchStyleLightDownwardDiagonal = 18
; HatchStyleLightUpwardDiagonal = 19
; HatchStyleDarkDownwardDiagonal = 20
; HatchStyleDarkUpwardDiagonal = 21
; HatchStyleWideDownwardDiagonal = 22
; HatchStyleWideUpwardDiagonal = 23
; HatchStyleLightVertical = 24
; HatchStyleLightHorizontal = 25
; HatchStyleNarrowVertical = 26
; HatchStyleNarrowHorizontal = 27
; HatchStyleDarkVertical = 28
; HatchStyleDarkHorizontal = 29
; HatchStyleDashedDownwardDiagonal = 30
; HatchStyleDashedUpwardDiagonal = 31
; HatchStyleDashedHorizontal = 32
; HatchStyleDashedVertical = 33
; HatchStyleSmallConfetti = 34
; HatchStyleLargeConfetti = 35
; HatchStyleZigZag = 36
; HatchStyleWave = 37
; HatchStyleDiagonalBrick = 38
; HatchStyleHorizontalBrick = 39
; HatchStyleWeave = 40
; HatchStylePlaid = 41
; HatchStyleDivot = 42
; HatchStyleDottedGrid = 43
; HatchStyleDottedDiamond = 44
; HatchStyleShingle = 45
; HatchStyleTrellis = 46
; HatchStyleSphere = 47
; HatchStyleSmallGrid = 48
; HatchStyleSmallCheckerBoard = 49
; HatchStyleLargeCheckerBoard = 50
; HatchStyleOutlinedDiamond = 51
; HatchStyleSolidDiamond = 52
; HatchStyleTotal = 53
Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle:=0)
{pBrush := 0DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, A_PtrSize ? "UPtr*" : "UInt*", pBrush)return pBrush
};#####################################################################################Gdip_CreateTextureBrush(pBitmap, WrapMode:=1, x:=0, y:=0, w:="", h:="")
{Ptr := A_PtrSize ? "UPtr" : "UInt", PtrA := A_PtrSize ? "UPtr*" : "UInt*"pBrush := 0if !(w && h)DllCall("gdiplus\GdipCreateTexture", Ptr, pBitmap, "int", WrapMode, PtrA, pBrush)elseDllCall("gdiplus\GdipCreateTexture2", Ptr, pBitmap, "int", WrapMode, "float", x, "float", y, "float", w, "float", h, PtrA, pBrush)return pBrush
};#####################################################################################; WrapModeTile = 0
; WrapModeTileFlipX = 1
; WrapModeTileFlipY = 2
; WrapModeTileFlipXY = 3
; WrapModeClamp = 4
Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode:=1)
{Ptr := A_PtrSize ? "UPtr" : "UInt"LGpBrush := 0CreatePointF(PointF1, x1, y1), CreatePointF(PointF2, x2, y2)DllCall("gdiplus\GdipCreateLineBrush", Ptr, &PointF1, Ptr, &PointF2, "Uint", ARGB1, "Uint", ARGB2, "int", WrapMode, A_PtrSize ? "UPtr*" : "UInt*", LGpBrush)return LGpBrush
};#####################################################################################; LinearGradientModeHorizontal = 0
; LinearGradientModeVertical = 1
; LinearGradientModeForwardDiagonal = 2
; LinearGradientModeBackwardDiagonal = 3
Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode:=1, WrapMode:=1)
{CreateRectF(RectF, x, y, w, h)LGpBrush := 0DllCall("gdiplus\GdipCreateLineBrushFromRect", A_PtrSize ? "UPtr" : "UInt", &RectF, "int", ARGB1, "int", ARGB2, "int", LinearGradientMode, "int", WrapMode, A_PtrSize ? "UPtr*" : "UInt*", LGpBrush)return LGpBrush
};#####################################################################################Gdip_CloneBrush(pBrush)
{pBrushClone := 0DllCall("gdiplus\GdipCloneBrush", A_PtrSize ? "UPtr" : "UInt", pBrush, A_PtrSize ? "UPtr*" : "UInt*", pBrushClone)return pBrushClone
};#####################################################################################
; Delete resources
;#####################################################################################Gdip_DeletePen(pPen)
{return DllCall("gdiplus\GdipDeletePen", A_PtrSize ? "UPtr" : "UInt", pPen)
};#####################################################################################Gdip_DeleteBrush(pBrush)
{return DllCall("gdiplus\GdipDeleteBrush", A_PtrSize ? "UPtr" : "UInt", pBrush)
};#####################################################################################Gdip_DisposeImage(pBitmap)
{return DllCall("gdiplus\GdipDisposeImage", A_PtrSize ? "UPtr" : "UInt", pBitmap)
};#####################################################################################Gdip_DeleteGraphics(pGraphics)
{return DllCall("gdiplus\GdipDeleteGraphics", A_PtrSize ? "UPtr" : "UInt", pGraphics)
};#####################################################################################Gdip_DisposeImageAttributes(ImageAttr)
{return DllCall("gdiplus\GdipDisposeImageAttributes", A_PtrSize ? "UPtr" : "UInt", ImageAttr)
};#####################################################################################Gdip_DeleteFont(hFont)
{return DllCall("gdiplus\GdipDeleteFont", A_PtrSize ? "UPtr" : "UInt", hFont)
};#####################################################################################Gdip_DeleteStringFormat(hFormat)
{return DllCall("gdiplus\GdipDeleteStringFormat", A_PtrSize ? "UPtr" : "UInt", hFormat)
};#####################################################################################Gdip_DeleteFontFamily(hFamily)
{return DllCall("gdiplus\GdipDeleteFontFamily", A_PtrSize ? "UPtr" : "UInt", hFamily)
};#####################################################################################Gdip_DeleteMatrix(Matrix)
{return DllCall("gdiplus\GdipDeleteMatrix", A_PtrSize ? "UPtr" : "UInt", Matrix)
};#####################################################################################
; Text functions
;#####################################################################################Gdip_TextToGraphics(pGraphics, Text, Options, Font:="Arial", Width:="", Height:="", Measure:=0)
{IWidth := Width, IHeight:= Heightpattern_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 -1Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"For eachStyle, valStyle in StrSplit( Styles, "|" ){if RegExMatch(Options, "\b" valStyle)Style |= (valStyle != "StrikeOut") ? (A_Index-1) : 8}Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"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] : 0ypos := (ypos && (ypos[1] != "")) ? ypos[2] ? IHeight*(ypos[1]/100) : ypos[1] : 0Width := (Width && Width[1]) ? Width[2] ? IWidth*(Width[1]/100) : Width[1] : IWidthHeight := (Height && Height[1]) ? Height[2] ? IHeight*(Height[1]/100) : Height[1] : IHeightif !PassBrushColour := "0x" (Colour && Colour[2] ? Colour[2] : "ff000000")Rendering := (Rendering && (Rendering[1] >= 0) && (Rendering[1] <= 5)) ? Rendering[1] : 4Size := (Size && (Size[1] > 0)) ? Size[2] ? IHeight*(Size[1]/100) : Size[1] : 12hFamily := Gdip_FontFamilyCreate(Font)hFont := Gdip_FontCreate(hFamily, Size, Style)FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000hFormat := Gdip_StringFormatCreate(FormatStyle)pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)if !(hFamily && hFont && hFormat && pBrush && pGraphics)return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0CreateRectF(RC, xpos, ypos, Width, Height)Gdip_SetStringFormatAlign(hFormat, Align)Gdip_SetTextRenderingHint(pGraphics, Rendering)ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)if vPos{ReturnRC := StrSplit(ReturnRC, "|")if (vPos[0] = "vCentre") || (vPos[0] = "vCenter")ypos += (Height-ReturnRC[4])//2else if (vPos[0] = "Top") || (vPos[0] = "Up")ypos := 0else if (vPos[0] = "Bottom") || (vPos[0] = "Down")ypos := Height-ReturnRC[4]CreateRectF(RC, xpos, ypos, Width, ReturnRC[4])ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)}if !Measure_E := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)if !PassBrushGdip_DeleteBrush(pBrush)Gdip_DeleteStringFormat(hFormat)Gdip_DeleteFont(hFont)Gdip_DeleteFontFamily(hFamily)return _E ? _E : ReturnRC
};#####################################################################################Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{Ptr := A_PtrSize ? "UPtr" : "UInt"if (!A_IsUnicode){nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, 0, "int", 0)VarSetCapacity(wString, nSize*2)DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)}return DllCall("gdiplus\GdipDrawString", Ptr, pGraphics, Ptr, A_IsUnicode ? &sString : &wString, "int", -1, Ptr, hFont, Ptr, &RectF, Ptr, hFormat, Ptr, pBrush)
};#####################################################################################Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{Ptr := A_PtrSize ? "UPtr" : "UInt"VarSetCapacity(RC, 16)if !A_IsUnicode{nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, "uint", 0, "int", 0)VarSetCapacity(wString, nSize*2)DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)}Chars := 0Lines := 0DllCall("gdiplus\GdipMeasureString", Ptr, pGraphics, Ptr, A_IsUnicode ? &sString : &wString, "int", -1, Ptr, hFont, Ptr, &RectF, Ptr, hFormat, Ptr, &RC, "uint*", Chars, "uint*", Lines)return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}; Near = 0
; Center = 1
; Far = 2
Gdip_SetStringFormatAlign(hFormat, Align)
{return DllCall("gdiplus\GdipSetStringFormatAlign", A_PtrSize ? "UPtr" : "UInt", hFormat, "int", Align)
}; StringFormatFlagsDirectionRightToLeft = 0x00000001
; StringFormatFlagsDirectionVertical = 0x00000002
; StringFormatFlagsNoFitBlackBox = 0x00000004
; StringFormatFlagsDisplayFormatControl = 0x00000020
; StringFormatFlagsNoFontFallback = 0x00000400
; StringFormatFlagsMeasureTrailingSpaces = 0x00000800
; StringFormatFlagsNoWrap = 0x00001000
; StringFormatFlagsLineLimit = 0x00002000
; StringFormatFlagsNoClip = 0x00004000
Gdip_StringFormatCreate(Format:=0, Lang:=0)
{hFormat := 0DllCall("gdiplus\GdipCreateStringFormat", "int", Format, "int", Lang, A_PtrSize ? "UPtr*" : "UInt*", hFormat)return hFormat
}; Regular = 0
; Bold = 1
; Italic = 2
; BoldItalic = 3
; Underline = 4
; Strikeout = 8
Gdip_FontCreate(hFamily, Size, Style:=0)
{hFont := 0DllCall("gdiplus\GdipCreateFont", A_PtrSize ? "UPtr" : "UInt", hFamily, "float", Size, "int", Style, "int", 0, A_PtrSize ? "UPtr*" : "UInt*", hFont)return hFont
}Gdip_FontFamilyCreate(Font)
{Ptr := A_PtrSize ? "UPtr" : "UInt"if (!A_IsUnicode){nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, "uint", 0, "int", 0)VarSetCapacity(wFont, nSize*2)DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, Ptr, &wFont, "int", nSize)}hFamily := 0DllCall("gdiplus\GdipCreateFontFamilyFromName", Ptr, A_IsUnicode ? &Font : &wFont, "uint", 0, A_PtrSize ? "UPtr*" : "UInt*", hFamily)return hFamily
};#####################################################################################
; Matrix functions
;#####################################################################################Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y)
{Matrix := 0DllCall("gdiplus\GdipCreateMatrix2", "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y, A_PtrSize ? "UPtr*" : "UInt*", Matrix)return Matrix
}Gdip_CreateMatrix()
{Matrix := 0DllCall("gdiplus\GdipCreateMatrix", A_PtrSize ? "UPtr*" : "UInt*", Matrix)return Matrix
};#####################################################################################
; GraphicsPath functions
;#####################################################################################; Alternate = 0
; Winding = 1
Gdip_CreatePath(BrushMode:=0)
{pPath := 0DllCall("gdiplus\GdipCreatePath", "int", BrushMode, A_PtrSize ? "UPtr*" : "UInt*", pPath)return pPath
}Gdip_AddPathEllipse(pPath, x, y, w, h)
{return DllCall("gdiplus\GdipAddPathEllipse", A_PtrSize ? "UPtr" : "UInt", pPath, "float", x, "float", y, "float", w, "float", h)
}Gdip_AddPathPolygon(pPath, Points)
{Ptr := A_PtrSize ? "UPtr" : "UInt"Points := StrSplit(Points, "|")PointsLength := (A_AhkVersion < "2") ? Points.Length() : Points.LengthVarSetCapacity(PointF, 8*PointsLength)for eachPoint, Point in Points{Coord := StrSplit(Point, ",")NumPut(Coord[1], PointF, 8*(A_Index-1), "float"), NumPut(Coord[2], PointF, (8*(A_Index-1))+4, "float")}return DllCall("gdiplus\GdipAddPathPolygon", Ptr, pPath, Ptr, &PointF, "int", PointsLength)
}Gdip_DeletePath(pPath)
{return DllCall("gdiplus\GdipDeletePath", A_PtrSize ? "UPtr" : "UInt", pPath)
};#####################################################################################
; Quality functions
;#####################################################################################; SystemDefault = 0
; SingleBitPerPixelGridFit = 1
; SingleBitPerPixel = 2
; AntiAliasGridFit = 3
; AntiAlias = 4
Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
{return DllCall("gdiplus\GdipSetTextRenderingHint", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", RenderingHint)
}; Default = 0
; LowQuality = 1
; HighQuality = 2
; Bilinear = 3
; Bicubic = 4
; NearestNeighbor = 5
; HighQualityBilinear = 6
; HighQualityBicubic = 7
Gdip_SetInterpolationMode(pGraphics, InterpolationMode)
{return DllCall("gdiplus\GdipSetInterpolationMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", InterpolationMode)
}; Default = 0
; HighSpeed = 1
; HighQuality = 2
; None = 3
; AntiAlias = 4
Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
{return DllCall("gdiplus\GdipSetSmoothingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", SmoothingMode)
}; CompositingModeSourceOver = 0 (blended)
; CompositingModeSourceCopy = 1 (overwrite)
Gdip_SetCompositingMode(pGraphics, CompositingMode:=0)
{return DllCall("gdiplus\GdipSetCompositingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", CompositingMode)
};#####################################################################################
; Extra functions
;#####################################################################################Gdip_Startup()
{Ptr := A_PtrSize ? "UPtr" : "UInt"pToken := 0if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)DllCall("LoadLibrary", "str", "gdiplus")VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)return pToken
}Gdip_Shutdown(pToken)
{Ptr := A_PtrSize ? "UPtr" : "UInt"DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)DllCall("FreeLibrary", Ptr, hModule)return 0
}; Prepend = 0; The new operation is applied before the old operation.
; Append = 1; The new operation is applied after the old operation.
Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder:=0)
{return DllCall("gdiplus\GdipRotateWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", Angle, "int", MatrixOrder)
}Gdip_ScaleWorldTransform(pGraphics, x, y, MatrixOrder:=0)
{return DllCall("gdiplus\GdipScaleWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "int", MatrixOrder)
}Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder:=0)
{return DllCall("gdiplus\GdipTranslateWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "int", MatrixOrder)
}Gdip_ResetWorldTransform(pGraphics)
{return DllCall("gdiplus\GdipResetWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}Gdip_GetRotatedTranslation(Width, Height, Angle, ByRef xTranslation, ByRef yTranslation)
{pi := 3.14159, TAngle := Angle*(pi/180)Bound := (Angle >= 0) ? Mod(Angle, 360) : 360-Mod(-Angle, -360)if ((Bound >= 0) && (Bound <= 90))xTranslation := Height*Sin(TAngle), yTranslation := 0else if ((Bound > 90) && (Bound <= 180))xTranslation := (Height*Sin(TAngle))-(Width*Cos(TAngle)), yTranslation := -Height*Cos(TAngle)else if ((Bound > 180) && (Bound <= 270))xTranslation := -(Width*Cos(TAngle)), yTranslation := -(Height*Cos(TAngle))-(Width*Sin(TAngle))else if ((Bound > 270) && (Bound <= 360))xTranslation := 0, yTranslation := -Width*Sin(TAngle)
}Gdip_GetRotatedDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight)
{pi := 3.14159, TAngle := Angle*(pi/180)if !(Width && Height)return -1RWidth := Ceil(Abs(Width*Cos(TAngle))+Abs(Height*Sin(TAngle)))RHeight := Ceil(Abs(Width*Sin(TAngle))+Abs(Height*Cos(Tangle)))
}; RotateNoneFlipNone = 0
; Rotate90FlipNone = 1
; Rotate180FlipNone = 2
; Rotate270FlipNone = 3
; RotateNoneFlipX = 4
; Rotate90FlipX = 5
; Rotate180FlipX = 6
; Rotate270FlipX = 7
; RotateNoneFlipY = Rotate180FlipX
; Rotate90FlipY = Rotate270FlipX
; Rotate180FlipY = RotateNoneFlipX
; Rotate270FlipY = Rotate90FlipX
; RotateNoneFlipXY = Rotate180FlipNone
; Rotate90FlipXY = Rotate270FlipNone
; Rotate180FlipXY = RotateNoneFlipNone
; Rotate270FlipXY = Rotate90FlipNoneGdip_ImageRotateFlip(pBitmap, RotateFlipType:=1)
{return DllCall("gdiplus\GdipImageRotateFlip", A_PtrSize ? "UPtr" : "UInt", pBitmap, "int", RotateFlipType)
}; Replace = 0
; Intersect = 1
; Union = 2
; Xor = 3
; Exclude = 4
; Complement = 5
Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode:=0)
{return DllCall("gdiplus\GdipSetClipRect", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
}Gdip_SetClipPath(pGraphics, pPath, CombineMode:=0)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipSetClipPath", Ptr, pGraphics, Ptr, pPath, "int", CombineMode)
}Gdip_ResetClip(pGraphics)
{return DllCall("gdiplus\GdipResetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}Gdip_GetClipRegion(pGraphics)
{Region := Gdip_CreateRegion()DllCall("gdiplus\GdipGetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics, "UInt", Region)return Region
}Gdip_SetClipRegion(pGraphics, Region, CombineMode:=0)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("gdiplus\GdipSetClipRegion", Ptr, pGraphics, Ptr, Region, "int", CombineMode)
}Gdip_CreateRegion()
{Region := 0DllCall("gdiplus\GdipCreateRegion", "UInt*", Region)return Region
}Gdip_DeleteRegion(Region)
{return DllCall("gdiplus\GdipDeleteRegion", A_PtrSize ? "UPtr" : "UInt", Region)
};#####################################################################################
; BitmapLockBits
;#####################################################################################Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode := 3, PixelFormat := 0x26200a)
{Ptr := A_PtrSize ? "UPtr" : "UInt"CreateRect(_Rect, x, y, w, h)VarSetCapacity(BitmapData, 16+2*(A_PtrSize ? A_PtrSize : 4), 0)_E := DllCall("Gdiplus\GdipBitmapLockBits", Ptr, pBitmap, Ptr, &_Rect, "uint", LockMode, "int", PixelFormat, Ptr, &BitmapData)Stride := NumGet(BitmapData, 8, "Int")Scan0 := NumGet(BitmapData, 16, Ptr)return _E
};#####################################################################################Gdip_UnlockBits(pBitmap, ByRef BitmapData)
{Ptr := A_PtrSize ? "UPtr" : "UInt"return DllCall("Gdiplus\GdipBitmapUnlockBits", Ptr, pBitmap, Ptr, &BitmapData)
};#####################################################################################Gdip_SetLockBitPixel(ARGB, Scan0, x, y, Stride)
{Numput(ARGB, Scan0+0, (x*4)+(y*Stride), "UInt")
};#####################################################################################Gdip_GetLockBitPixel(Scan0, x, y, Stride)
{return NumGet(Scan0+0, (x*4)+(y*Stride), "UInt")
};#####################################################################################Gdip_PixelateBitmap(pBitmap, ByRef pBitmapOut, BlockSize)
{static PixelateBitmapPtr := A_PtrSize ? "UPtr" : "UInt"if (!PixelateBitmap){if A_PtrSize != 8 ; x86 machine codeMCode_PixelateBitmap := "(LTrim Join558BEC83EC3C8B4514538B5D1C99F7FB56578BC88955EC894DD885C90F8E830200008B451099F7FB8365DC008365E000894DC88955F08945E833FF897DD4397DE80F8E160100008BCB0FAFCB894DCC33C08945F88945FC89451C8945143BD87E608B45088D50028BC82BCA8BF02BF2418945F48B45E02955F4894DC48D0CB80FAFCB03CA895DD08BD1895DE40FB64416030145140FB60201451C8B45C40FB604100145FC8B45F40FB604020145F883C204FF4DE475D6034D18FF4DD075C98B4DCC8B451499F7F98945148B451C99F7F989451C8B45FC99F7F98945FC8B45F899F7F98945F885DB7E648B450C8D50028BC82BCA83C103894DC48BC82BCA41894DF48B4DD48945E48B45E02955E48D0C880FAFCB03CA895DD08BD18BF38A45148B7DC48804178A451C8B7DF488028A45FC8804178A45F88B7DE488043A83C2044E75DA034D18FF4DD075CE8B4DCC8B7DD447897DD43B7DE80F8CF2FEFFFF837DF0000F842C01000033C08945F88945FC89451C8945148945E43BD87E65837DF0007E578B4DDC034DE48B75E80FAF4D180FAFF38B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945CC0FB6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604010145F883C104FF4DCC75D8FF45E4395DE47C9B8B4DF00FAFCB85C9740B8B451499F7F9894514EB048365140033F63BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975E43BDE7E5A837DF0007E4C8B4DDC034DE48B75E80FAF4D180FAFF38B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955CC8A551488540E038A551C88118A55FC88540F018A55F888140183C104FF4DCC75DFFF45E4395DE47CA68B45180145E0015DDCFF4DC80F8594FDFFFF8B451099F7FB8955F08945E885C00F8E450100008B45EC0FAFC38365DC008945D48B45E88945CC33C08945F88945FC89451C8945148945103945EC7E6085DB7E518B4DD88B45080FAFCB034D108D50020FAF4D18034DDC8BF08BF88945F403CA2BF22BFA2955F4895DC80FB6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604080145F883C104FF4DC875D8FF45108B45103B45EC7CA08B4DD485C9740B8B451499F7F9894514EB048365140033F63BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975103975EC7E5585DB7E468B4DD88B450C0FAFCB034D108D50020FAF4D18034DDC8BF08BF803CA2BF22BFA2BC2895DC88A551488540E038A551C88118A55FC88540F018A55F888140183C104FF4DC875DFFF45108B45103B45EC7CAB8BC3C1E0020145DCFF4DCC0F85CEFEFFFF8B4DEC33C08945F88945FC89451C8945148945103BC87E6C3945F07E5C8B4DD88B75E80FAFCB034D100FAFF30FAF4D188B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945C80FB6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604010145F883C104FF4DC875D833C0FF45108B4DEC394D107C940FAF4DF03BC874068B451499F7F933F68945143BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975083975EC7E63EB0233F63975F07E4F8B4DD88B75E80FAFCB034D080FAFF30FAF4D188B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955108A551488540E038A551C88118A55FC88540F018A55F888140883C104FF4D1075DFFF45088B45083B45EC7C9F5F5E33C05BC9C21800)"else ; x64 machine codeMCode_PixelateBitmap := "(LTrim Join4489442418488954241048894C24085355565741544155415641574883EC28418BC1448B8C24980000004C8BDA99488BD941F7F9448BD0448BFA8954240C448994248800000085C00F8E9D020000418BC04533E4458BF299448924244C8954241041F7F933C9898C24980000008BEA89542404448BE889442408EB054C8B5C24784585ED0F8E1A010000458BF1418BFD48897C2418450FAFF14533D233F633ED4533E44533ED4585C97E5B4C63BC2490000000418D040A410FAFC148984C8D441802498BD9498BD04D8BD90FB642010FB64AFF4403E80FB60203E90FB64AFE4883C2044403E003F149FFCB75DE4D03C748FFCB75D0488B7C24188B8C24980000004C8B5C2478418BC59941F7FE448BE8418BC49941F7FE448BE08BC59941F7FE8BE88BC69941F7FE8BF04585C97E4048639C24900000004103CA4D8BC1410FAFC94863C94A8D541902488BCA498BC144886901448821408869FF408871FE4883C10448FFC875E84803D349FFC875DA8B8C2498000000488B5C24704C8B5C24784183C20448FFCF48897C24180F850AFFFFFF8B6C2404448B2424448B6C24084C8B74241085ED0F840A01000033FF33DB4533DB4533D24533C04585C97E53488B74247085ED7E42438D0C04418BC50FAF8C2490000000410FAFC18D04814863C8488D5431028BCD0FB642014403D00FB6024883C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC17CB28BCD410FAFC985C9740A418BC299F7F98BF0EB0233F685C9740B418BC399F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585C97E4D4C8B74247885ED7E38418D0C14418BC50FAF8C2490000000410FAFC18D04814863C84A8D4431028BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2413BD17CBD4C8B7424108B8C2498000000038C2490000000488B5C24704503E149FFCE44892424898C24980000004C897424100F859EFDFFFF448B7C240C448B842480000000418BC09941F7F98BE8448BEA89942498000000896C240C85C00F8E3B010000448BAC2488000000418BCF448BF5410FAFC9898C248000000033FF33ED33F64533DB4533D24533C04585FF7E524585C97E40418BC5410FAFC14103C00FAF84249000000003C74898488D541802498BD90FB642014403D00FB6024883C2044403D80FB642FB03F00FB642FA03E848FFCB75DE488B5C247041FFC0453BC77CAE85C9740B418BC299F7F9448BE0EB034533E485C9740A418BC399F7F98BD8EB0233DB85C9740A8BC699F7F9448BD8EB034533DB85C9740A8BC599F7F9448BD0EB034533D24533C04585FF7E4E488B4C24784585C97E35418BC5410FAFC14103C00FAF84249000000003C74898488D540802498BC144886201881A44885AFF448852FE4883C20448FFC875E941FFC0453BC77CBE8B8C2480000000488B5C2470418BC1C1E00203F849FFCE0F85ECFEFFFF448BAC24980000008B6C240C448BA4248800000033FF33DB4533DB4533D24533C04585FF7E5A488B7424704585ED7E48418BCC8BC5410FAFC94103C80FAF8C2490000000410FAFC18D04814863C8488D543102418BCD0FB642014403D00FB6024883C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC77CAB418BCF410FAFCD85C9740A418BC299F7F98BF0EB0233F685C9740B418BC399F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585FF7E4E4585ED7E42418BCC8BC5410FAFC903CA0FAF8C2490000000410FAFC18D04814863C8488B442478488D440102418BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2413BD77CB233C04883C428415F415E415D415C5F5E5D5BC3)"VarSetCapacity(PixelateBitmap, StrLen(MCode_PixelateBitmap)//2)nCount := StrLen(MCode_PixelateBitmap)//2N := (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, A_PtrSize ? "UPtr*" : "UInt*", 0)}Gdip_GetImageDimensions(pBitmap, Width, Height)if (Width != Gdip_GetImageWidth(pBitmapOut) || Height != Gdip_GetImageHeight(pBitmapOut))return -1if (BlockSize > Width || BlockSize > Height)return -2E1 := 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 codeDllCall(&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) >> 24R := (0x00ff0000 & ARGB) >> 16G := (0x0000ff00 & ARGB) >> 8B := 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 := 1200else if (Encoding = "UTF-8")Encoding := 65001else 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
};#####################################################################################
; 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 IntegerReturn TrueReturn False
}IsNumber(Var) {Static number := "number"If Var Is numberReturn TrueReturn 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 Monitorscount := A_Indexreturn count
}GetMonitorInfo(MonitorNum)
{Monitors := MDMF_Enum()for k,v in Monitorsif (v.Num = MonitorNum)return v
}GetPrimaryMonitor()
{Monitors := MDMF_Enum()for k,v in MonitorsIf (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"] := HMONReturn 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
}; Based on WinGetClientPos by dd900 and Frosti - https://www.autohotkey.com/boards/viewtopic.php?t=484
WinGetRect( hwnd, ByRef x:="", ByRef y:="", ByRef w:="", ByRef h:="" ) {Ptr := A_PtrSize ? "UPtr" : "UInt"CreateRect(winRect, 0, 0, 0, 0) ;is 16 on both 32 and 64;VarSetCapacity( winRect, 16, 0 ) ; Alternative of above two linesDllCall( "GetWindowRect", Ptr, hwnd, Ptr, &winRect )x := NumGet(winRect, 0, "UInt")y := NumGet(winRect, 4, "UInt")w := NumGet(winRect, 8, "UInt") - xh := NumGet(winRect, 12, "UInt") - y
}