Currently using v2 a102 version https://www.autohotkey.com/download/2.0/AutoHotkey_2.0-a102-5c9fb78f.zip
All my scripts are concentrated in one process, and the amount of code is quite large. I want to continue to upgrade to the new version, but I get stuck.
I don’t know how to adjust some grammatical changes of a104 . The documentation in this area does not seem to be comprehensive. I hope someone can clearly tell how to adjust the grammar.
This time I share the Class_Gdip.ahk and partially rewritten sample examples, as well as autohotkey_gdi.snippets for Vim ultisnips,
gdip is learned from the https://github.com/mmikeww/AHKv2-Gdip , thanks for the detailed examples inside.
I have been groping for many days, but I still feel that it will be tiring to write.
There are also some class_gdip.ahk I found at network, but the global functions are still used, and the design ideas do not suit my taste.
So I wrote Class_Gdip.ahk again as practice by the way, I rewrite some of the sample examples into my scripts for comparison.
I am not a professional programmer, the ideas inside may need to be adjusted again. I hope someone can help and improve it.
And I don't know what's the difference of hBitmap and pBitmap.
The classes and methods inside are not complete yet, need to be improved over time.
Not sure if this script is suitable for people who do not understand gdip to take pictures of cats and tigers.
example1: Class_Gdip.01-simple draw.ahk
Code: Select all
#SingleInstance Force
#Include ../Class_Gdip.ahk
;rectangle to draw
w := 800
h := 600
oGdip := new _GDIP() ;pToken
oHBitmap := new GDIP_HBitmap(w, h)
;Encapsulate 'DC' into 'GDIP_Graphics'
;auto run SelectObject(oHBitmap) and save to oGraphics.pSelectSave
oGraphics := new GDIP_Graphics(oHBitmap)
oGraphics.GdipSetSmoothingMode(4)
oBrush := new GDIP_Brush(0xFFFF0000)
oGraphics.GdipFillEllipse(oBrush.ptr, [100,300,200,300])
;modify oBrush.ptr, needn't new oBrush2
oBrush.GdipCreateSolidFill(0x660000FF)
oGraphics.GdipFillRectangle(oBrush.ptr, [300,300,300,200])
oPen := new GDIP_Pen(0xFFFF0000, 3)
oGraphics.GdipDrawEllipse(oPen.ptr, [100,50,200,300])
;modify oPen.ptr, needn't new oPen2
oPen.createByArgb(0x660000FF, 10)
oGraphics.GdipDrawEllipse(oPen.ptr, [250,80,300,200])
oPen := "" ;release here
oBrush.GdipCreateSolidFill(0x77000000)
oGraphics.fillRoundedRectangle(oBrush.ptr, [0,0,100,100], 20)
oBrush := "" ;release here
oGui := GuiCreate("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs")
oGui.Show("NA")
OnMessage(0x201, ()=>PostMessage(0xA1, 2))
oGraphics.UpdateLayeredWindow(oGui.hwnd, [100,0,w,h])
;restore oGraphics.pSelectSave
oGraphics.SelectObject()
;NOTE order is important
oHBitmap := ""
oGraphics := ""
oGdip := ""
return
Code: Select all
#SingleInstance Force
#Include ../Class_Gdip.ahk
oGdip := new _GDIP()
oPBitmap := new GDIP_PBitmap("bs.jpg")
w := oPBitmap.getWidth()
h := oPBitmap.getHeight()
; 创建一个gdi位图,其宽度和高度与我们要绘制的位图相同。 这是所有内容的整个绘制区域
; 我们正在以实际图像大小的一半创建此“画布”
; 我们将其减半,因为我们希望图像以一半的尺寸显示在屏幕上的图形用户界面中
oHBitmap := new GDIP_HBitmap(w//2, h//2)
oGraphics := new GDIP_Graphics(oHBitmap)
; 我们不需要前面的示例中绘制图像时所需要的SmoothingMode
; 相反,我们必须设置InterpolationMode。 这指定了如何调整文件大小(调整大小的质量)
; 插值模式已设置为HighQualityBicubic = 7
oGraphics.GdipSetInterpolationMode(7)
oGraphics.drawImage(oPBitmap, [0,0,w//2,h//2])
oGui := GuiCreate("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs")
oGui.Show("NA")
oGraphics.UpdateLayeredWindow(oGui.hwnd, [200,0,w//2,h//2])
oGraphics.SelectObject()
oHBitmap := ""
oGraphics := ""
oPBitmap := ""
oGdip := ""
return
Code: Select all
;Gdip_All.ahk - GDI+ library compilation of user contributed GDI+ functions
;made by Marius Șucan: https://github.com/marius-sucan/AHK-GDIp-Library-Compilation
;a fork from: https://github.com/mmikeww/AHKv2-Gdip
;based on https://github.com/tariqporter/Gdip
;Features:
; The parent class is '_GDIP', all other 'GDIP_*' inherit from it
; Use the object method, the logic is clear
; Simplified release, only need oInstance := "" (but pay attention to the order)
; Encapsulate 'DC' into 'GDIP_Graphics', no need to consider the generation and release order
; Two methods 'SelectObject' and 'UpdateLayeredWindow' are converted into 'GDIP_Graphics' methods
; Simplified 'SelectObject': no need to record the old object, if not pass the parameter, will restore it.
; Simplify the method call parameters, no need to pass in the properties of the object itself, for example, 'oPen' method needn't to pass in the 'pPen' parameter
; The parameters of (x, y, w, h) are packaged and passed in in 'aRect' array instead of 4 parameters
; Important note:
; Generally, 'oInstance := new class()' is required, for example, 'oPen' is an instance, and 'oPen.ptr' is the native 'pPen' of gdip. For the time being, oInstance only supports 1 'ptr' attribute.
;【OInstance】Used to call methods, or used as parameters by other class new (because 'oInstance.__class' can be used to determine), such as new GDIP_Graphics(oPBitmap/oHBitmap) instead of oPBitmap.ptr.
;【method】
; The name is generally the same as the dllcall function. Those that do not involve dllcall do not start with 'Gdip'. 'DrawImage' is an exception (support oPBitmap)
; Parameter, using pPen (compatible with native calls)
; PS: If the parameter is filled with oPen, v2 a108+ will automatically read its ptr attribute, for example, the following two sentences are equivalent
; oGraphics.GdipDrawEllipse(oPen, [0,0,w,h])
; oGraphics.GdipDrawEllipse(oPen.ptr, [0,0,w,h])
; Main class and its representation method: (used in ultisnips and positioning: for example, search pp to find the position of the GDIP_Pen class)
;主要 class 及其表示方法:(用在 ultisnips 和定位:比如搜索 pp 就能搜索到 GDIP_Pen 类的位置)
; GDIP_PBitmap = m(NOTE)
; GDIP_FontFamily = v(NOTE)
; GDIP_Brush = b
; GDIP_Font = f
; GDIP_Graphics = g
; GDIP_HBitmap = h
; GDIP_Pen = p
; GDIP_StringFormat = s
;所有 UPtr 都是由这句简化 A_PtrSize ? "UPtr" : "uint"
;特色:
; 父类是 _GDIP,其他 GDIP_* 全继承于它
; 用对象的方式,逻辑清晰
; 简化了释放,只需要 oInstance := "" 即可(但要注意顺序)
; 把 DC 封装到 GDIP_Graphics,不用考虑生成和释放顺序,使用更简单
; 两个方法 SelectObject 和 UpdateLayeredWindow 转成 GDIP_Graphics 的方法
; 简化了 SelectObject,不需要记录旧对象,不要传参即是还原
; 简化了方法调用的参数,无需传入对象本身的属性,比如 oPen的方法不需要传入 pPen 参数
; x,y,w,h 的参数统一用 aRect 数组方式打包传入,而不是传入4个参数
; NOTE 重要说明:
;一般都需要 oInstance := new class(),比如 oPen 为实例,oPen.ptr 为 gdip 原生的 pPen。暂时 oInstance 只支持一个 ptr 属性。
;【oInstance】用来调用方法,或被其他 class new 当参数用(因为可用 oInstance.__class 判断),比如 new GDIP_Graphics(oPBitmap/oHBitmap),而不是用 oPBitmap.ptr。
;【方法】
; 名称,一般都是和 dllcall 函数同名,没涉及 dllcall 的则不是以 Gdip 开头,drawImage 是个例外(支持 oPBitmap)
; 参数,用的是 pPen(兼容原生调用)
; PS:如果参数填oPen,v2 a108+会自动读取其 ptr 属性,比如以下两句等效
; oGraphics.GdipDrawEllipse(oPen, [0,0,w,h])
; oGraphics.GdipDrawEllipse(oPen.ptr, [0,0,w,h])
class _GDIP {
pToken := 0
__new() {
Ptr := A_PtrSize ? "UPtr" : "uint"
pToken := 0
if !dllcall("GetModuleHandle", "str", "gdiplus",Ptr)
dllcall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize == 8 ? 24 : 16, 0), si := chr(1)
dllcall("gdiplus\GdiplusStartup",A_PtrSize ? "UPtr*" : "uint*",pToken, Ptr,&si, Ptr,0)
this.pToken := pToken
}
__delete() {
dllcall("gdiplus\GdiplusShutdown", "UPtr",this.pToken)
if hModule := dllcall("GetModuleHandle", "str","gdiplus", "UPtr")
dllcall("FreeLibrary", "UPtr",hModule)
return 0
}
; aRect := [100,200,(arrWH)=>0.3*arrWH[1]+20, (arrWH)=>0.4*arrWH[2]]
; arrWH := [300,400]
;aRect的每个项目都可以是函数,参数是图片的[宽,高] arrWH
;转成 [100, 200, 110, 160]
rectDeal(aRect, arrWH) {
for k, v in aRect {
if isobject(v)
aRect[k] := v.call(arrWH)
else if (v < 0)
aRect[k] := arrWH[mod(k-1,2)+1] + v ;1,3转成 w+v, 2,4转成 h+v
else if (v < 1)
aRect[k] := integer(arrWH[mod(k-1,2)+1] * v) ;1,3转成 w*v, 2,4转成 h*v
}
return aRect
}
;确认鼠标选择区域
;aRect := _GDIP.getRect(()=>GetKeyState(RegExReplace(A_ThisLabel, ".*\s"), "P"))
;同 _Mouse.getRect
getRect(funDo:="") {
if !isobject(funDo)
funDo := ()=>GetKeyState("LButton", "P")
;截图时显示的Gui
oGui := GuiCreate("-caption +AlwaysOnTop +Border +E0x80000 +LastFound +OwnDialogs +ToolWindow")
oGui.BackColor := "FFFFFF"
WinSetTransparent(110)
;记录初始位置
CoordMode("Mouse", "screen")
MouseGetPos(x0, y0)
while(funDo.call()) { ;左键按住不放
sleep(10)
MouseGetPos(x1, y1)
x := min(x0, x1)
y := min(y0, y1)
w := abs(x0 - x1)
h := abs(y0 - y1)
oGui.show(format("x{1} y{2} w{3} h{4} NA", x,y,w,h))
tooltip(format("{1}x{2}",w,h))
}
oGui.destroy()
SetTimer("tooltip", -100)
if (w<=3 || h<=3)
exit
return [x,y,w,h]
}
DeleteObject(hObject) {
return dllcall("DeleteObject", "UPtr",hObject)
}
StretchBlt(ddc, aRectTo, sdc, aRectFrom, Raster:=0x00CC0020) {
return dllcall("gdi32\StretchBlt"
, "UPtr", ddc
, "int", aRectTo[1],"int",aRectTo[2],"int",aRectTo[3],"int", aRectTo[4]
, "UPtr", sdc
, "int",aRectFrom[1],"int",aRectFrom[2],"int",aRectFrom[3],"int",aRectFrom[4]
, "uint", Raster)
}
GetMonitorInfo(MonitorNum) {
Monitors := this.MDMF_Enum()
for k,v in Monitors
if (v.Num = MonitorNum)
return v
}
;数组 aRect 转成 struct
CreateRect(byref Rect, aRect) {
VarSetCapacity(Rect, 16)
numput(aRect[1], Rect, 0, "uint")
numput(aRect[2], Rect, 4, "uint")
numput(aRect[3], Rect, 8, "uint")
numput(aRect[4], Rect, 12, "uint")
}
; ======================================================================================================================
; 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 := this.MDMF_Enum()
for k,v in Monitors
count := A_Index
return count
}
GetPrimaryMonitor() {
Monitors := this.MDMF_Enum()
for k,v in Monitors
if (v.Primary)
return v.Num
}
; ======================================================================================================================
; Enumerates display monitors and returns an object containing the properties of all monitors or the specified monitor.
; ======================================================================================================================
MDMF_Enum(HMON:="") {
static CbFunc := (A_AhkVersion < "2") ? func("RegisterCallback") : func("CallbackCreate")
static Monitors := {}
this.EnumProc := CbFunc.call("MDMF_EnumProc")
if (HMON == "") ; new enumeration
Monitors := {}
if (Monitors.MaxIndex() = "") ; enumerate
if !dllcall("User32.dll\EnumDisplayMonitors", "Ptr",0, "Ptr",0, "Ptr",this.EnumProc, "Ptr",&Monitors, "uint")
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] := this.MDMF_GetInfo(HMON)
return true
}
; ======================================================================================================================
; Retrieves the display monitor that has the largest area of intersection with a specified window.
; ======================================================================================================================
MDMF_FromHWND(hwnd) {
return dllcall("User32.dll\MonitorFromWindow", "Ptr",hwnd, "uint",0, "UPtr")
}
; ======================================================================================================================
; 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.
; ======================================================================================================================
MDMF_FromPoint(X := "", Y := "") {
VarSetCapacity(PT, 8, 0)
if (X = "") || (Y = "") {
dllcall("User32.dll\GetCursorPos", "Ptr", &PT)
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",0, "UPtr")
}
; ======================================================================================================================
; 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.
; ======================================================================================================================
MDMF_FromRect(X, Y, W, H) {
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",0, "UPtr")
}
; ======================================================================================================================
; 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) {
MonName := strget(&MIEX + 40, 32) ; CCHDEVICENAME = 32
MonNum := RegExReplace(MonName, ".*(\d+)$", "$1")
return { Name: (Name := strget(&MIEX + 40, 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
}
}
;mm
class GDIP_PBitmap extends _GDIP {
ptr := 0
w := 0
h := 0
;fp 文件存在
;w,h w是数字
;oHBitmap
;[x,y,w,h] aRect
__new(w:="", h:=0) {
if isobject(w) {
if (w.__class == "GDIP_HBitmap")
this.GdipCreateBitmapFromHBITMAP(hBitmap, Palette:=0)
else if (w.length() == 4)
this.getFromScreen(w)
} else {
if (w ~= "^\d+$")
this.GdipCreateBitmapFromScan0(w, h)
else if FileExist(w)
this.GdipCreateBitmapFromFile(w)
else
msgbox(A_ThisFunc . "`n" . w . "`n" . h)
}
}
;出错,可排查释放顺序
__delete() {
; msgbox(A_ThisFunc . '---')
dllcall("gdiplus\GdipDisposeImage", "UPtr",this.ptr)
return
}
GdipCreateBitmapFromScan0(w, h, PixelFormat:=0x26200A) {
dllcall("gdiplus\GdipCreateBitmapFromScan0", "int",w, "int",h, "int",0, "int",PixelFormat, "UPtr",0, "UPtr*",pBitmap)
if !pBitmap {
msgbox(A_ThisFunc . "`n" . w . "`n" . h)
}
this.w := w
this.h := h
this.ptr := pBitmap
}
; GdipCreateBitmapFromFile(fp, IconNumber:=1, IconSize:="")
GdipCreateBitmapFromFile(fp) {
dllcall("gdiplus\GdipCreateBitmapFromFile", "UPtr",&fp, "UPtr*",pBitmap)
if (!pBitmap)
msgbox(A_ThisFunc . "`n" . fp)
this.w := 0
this.h := 0
this.ptr := pBitmap
; SplitPath(fp,,, ext)
; if RegExMatch(ext, "^(i:exe|dll)$") {
; Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16
; BufSize := 16 + (2*A_PtrSize)
; VarSetCapacity(buf, BufSize, 0)
; for eachSize, Size in StrSplit(Sizes, "|") {
; dllcall("PrivateExtractIcons", "str",fp, "int",IconNumber-1, "int",Size, "int",Size, "UPtr*",hIcon, "UPtr*",0, "uint",1, "uint",0)
; if !hIcon
; continue
; if !dllcall("GetIconInfo", "UPtr",hIcon, "UPtr",&buf) {
; DestroyIcon(hIcon)
; continue
; }
; hbmMask := numget(buf, 12 + (A_PtrSize - 4))
; hbmColor := numget(buf, 12 + (A_PtrSize - 4) + A_PtrSize)
; if !(hbmColor && dllcall("GetObject", "UPtr",hbmColor, "int",BufSize, "UPtr",&buf)) {
; DestroyIcon(hIcon)
; continue
; }
; break
; }
; if !hIcon
; return -1
; width := numget(buf, 4, "int"), height := numget(buf, 8, "int")
; hbm := CreateDIBSection(width, -height)
; hDC := GDIP_DC.create()
; obm := SelectObject(hDC, hbm)
; if !dllcall("DrawIconEx", "UPtr",hDC, "int",0, "int",0, "UPtr",hIcon, "uint",width, "uint",height, "uint",0, "UPtr",0, "uint",3) {
; DestroyIcon(hIcon)
; return -2
; }
; VarSetCapacity(dib, 104)
; ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize
; dllcall("GetObject", "UPtr",hbm, "int",A_PtrSize == 8 ? 104 : 84, "UPtr",&dib)
; Stride := numget(dib, 12, "int"), Bits := numget(dib, 20 + (A_PtrSize - 4)) ; padding
; dllcall("gdiplus\GdipCreateBitmapFromScan0", "int",width, "int",height, "int",Stride, "int",0x26200A, "UPtr",Bits, "UPtr*",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), dllcall("gdi32\DeleteObject", "UPtr",hbm), DeleteDC(hDC)
; Gdip_DeleteGraphics(_G), Gdip_DisposeImage(pBitmapOld)
; DestroyIcon(hIcon)
; return this.ptr := pBitmap
; }
}
; GdipCreateBitmapFromFileICM(bitmap) {
; dllcall("gdiplus\GdipCreateBitmapFromFileICM", "wstr",bitmap, "ptr*",pBitmap)
; if (!pBitmap)
; msgbox(A_ThisFunc)
; return this.ptr := pBitmap
; }
getFromScreen(aRect, Raster:="") {
this.GdipCreateBitmapFromHBITMAP(new GDIP_HBitmap(aRect))
}
GdipCreateBitmapFromHBITMAP(oHBitmap, Palette:=0) {
dllcall("gdiplus\GdipCreateBitmapFromHBITMAP", "UPtr",oHBitmap.ptr, "UPtr",Palette, "UPtr*",pBitmap)
return this.ptr := pBitmap
}
; getFromClipboard() {
; if !dllcall("IsClipboardFormatAvailable", "uint",8)
; return -2
; if !dllcall("OpenClipboard", "UPtr",0)
; return -1
; if !hBitmap := dllcall("GetClipboardData", "uint",2, "UPtr")
; return -3
; if !pBitmap := this.GdipCreateBitmapFromHBITMAP(oHBitmap)
; return -4
; if !dllcall("CloseClipboard")
; return -5
; dllcall("gdi32\DeleteObject", "UPtr",hBitmap)
; return this.ptr := pBitmap
; }
; getFromHICON(hIcon) {
; dllcall("gdiplus\GdipCreateBitmapFromHICON",A_PtrSize ? "UPtr" : "uint",hIcon, A_PtrSize ? "UPtr*" : "uint*",pBitmap)
; return this.ptr := pBitmap
; }
getSize(byref w, byref h) {
if !this.w {
dllcall("gdiplus\GdipGetImageWidth", "UPtr",this.ptr, "uint*",w)
this.w := w
}
if !this.h {
dllcall("gdiplus\GdipGetImageHeight", "UPtr",this.ptr, "uint*",h)
this.h := h
}
return [this.w, this.h]
}
getWidth() {
if !this.w {
dllcall("gdiplus\GdipGetImageWidth", "UPtr",this.ptr, "uint*",w)
this.w := w
}
return this.w
}
getHeight() {
if !this.h {
dllcall("gdiplus\GdipGetImageHeight", "UPtr",this.ptr, "uint*",h)
this.h := h
}
return this.h
}
getPixel(x, y) {
dllcall("gdiplus\GdipBitmapGetPixel", "Ptr",this.ptr, "int",x, "int",y, "Uint*",ARGB:=0)
return ARGB
}
setPixel(x, y, ARGB) {
return dllcall("gdiplus\GdipBitmapSetPixel", "Ptr",this.ptr, "int",x, "int",y, "int",ARGB)
}
; TODO
; https://autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/page-58#entry455137
rotate(angle) {
this.getSize(w, h)
aRect := GDIP_Graphics.getRotatedRect(w, h, angle)
xOffset := aRect[1]
yOffset := aRect[2]
wNew := aRect[3]
hNew := aRect[4]
oPBitmap := new GDIP_PBitmap(wNew, hNew)
oGraphics := new GDIP_Graphics(oPBitmap)
oGraphics.GdipSetInterpolationMode(7)
oGraphics.GdipSetSmoothingMode(4)
oGraphics.GdipDrawImageRectRect(this.ptr, [0,0,wNew,hNew], [0,0,wNew,hNew])
oGraphics := ""
this.ptr := oPBitmap.ptr
oPBitmap := ""
return this.ptr
}
;剪切
crop(left:=0, right:=0, up:=0, down:=0, Dispose:=1) {
this.getSize(w, h)
wNew := w-left-right
hNew := h-up-down
oPBitmap := new GDIP_PBitmap(wNew, hNew)
oGraphics := new GDIP_Graphics(oPBitmap)
oGraphics.GdipSetInterpolationMode(7)
oGraphics.GdipSetSmoothingMode(4)
oGraphics.GdipDrawImageRectRect(this.ptr, [0,0,wNew,hNew], [left,up,wNew,hNew])
oGraphics := ""
this.ptr := oPBitmap.ptr
oPBitmap := ""
return this.ptr
}
; http://www.autohotkey.com/community/viewtopic.php?p=477333
; returns resized bitmap. By Learning one.
resize(PercentOrWH, Dispose:=1) {
this.getSize(w, h)
if isobject(PercentOrWH) {
wNew := PercentOrWH[1]
hNew := PercentOrWH[2]
} else {
wNew := w*PercentOrWH/100
hNew := h*PercentOrWH/100
}
oPBitmap := new GDIP_PBitmap(wNew, hNew)
oGraphics := new GDIP_Graphics(oPBitmap)
oGraphics.GdipSetInterpolationMode(7)
oGraphics.GdipSetSmoothingMode(4)
oGraphics.GdipDrawImageRectRect(this.ptr, [0,0,wNew,hNew], [0,0,w,h])
oGraphics := ""
this.ptr := oPBitmap.ptr
if Dispose
oPBitmap := ""
return this.ptr
}
;FIXME 马赛克
; GdipPixelateBitmap(pBitmap, oBitmapOut, BlockSize) {
; if (!PixelateBitmap) {
; if A_PtrSize != 8 {
; MCode_PixelateBitmap := "
; (ltrim join
; 558BEC83EC3C8B4514538B5D1C99F7FB56578BC88955EC894DD885C90F8E830200008B451099F7FB8365DC008365E000894DC88955F08945E833FF897DD4
; 397DE80F8E160100008BCB0FAFCB894DCC33C08945F88945FC89451C8945143BD87E608B45088D50028BC82BCA8BF02BF2418945F48B45E02955F4894DC4
; 8D0CB80FAFCB03CA895DD08BD1895DE40FB64416030145140FB60201451C8B45C40FB604100145FC8B45F40FB604020145F883C204FF4DE475D6034D18FF
; 4DD075C98B4DCC8B451499F7F98945148B451C99F7F989451C8B45FC99F7F98945FC8B45F899F7F98945F885DB7E648B450C8D50028BC82BCA83C103894D
; C48BC82BCA41894DF48B4DD48945E48B45E02955E48D0C880FAFCB03CA895DD08BD18BF38A45148B7DC48804178A451C8B7DF488028A45FC8804178A45F8
; 8B7DE488043A83C2044E75DA034D18FF4DD075CE8B4DCC8B7DD447897DD43B7DE80F8CF2FEFFFF837DF0000F842C01000033C08945F88945FC89451C8945
; 148945E43BD87E65837DF0007E578B4DDC034DE48B75E80FAF4D180FAFF38B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945CC0F
; B6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604010145F883C104FF4DCC75D8FF45E4395DE47C9B8B4DF00FAFCB85C9740B8B451499F7
; F9894514EB048365140033F63BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB
; 038975F88975E43BDE7E5A837DF0007E4C8B4DDC034DE48B75E80FAF4D180FAFF38B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955CC8A55
; 1488540E038A551C88118A55FC88540F018A55F888140183C104FF4DCC75DFFF45E4395DE47CA68B45180145E0015DDCFF4DC80F8594FDFFFF8B451099F7
; FB8955F08945E885C00F8E450100008B45EC0FAFC38365DC008945D48B45E88945CC33C08945F88945FC89451C8945148945103945EC7E6085DB7E518B4D
; D88B45080FAFCB034D108D50020FAF4D18034DDC8BF08BF88945F403CA2BF22BFA2955F4895DC80FB6440E030145140FB60101451C0FB6440F010145FC8B
; 45F40FB604080145F883C104FF4DC875D8FF45108B45103B45EC7CA08B4DD485C9740B8B451499F7F9894514EB048365140033F63BCE740B8B451C99F7F9
; 89451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975103975EC7E5585DB7E468B4DD88B450C
; 0FAFCB034D108D50020FAF4D18034DDC8BF08BF803CA2BF22BFA2BC2895DC88A551488540E038A551C88118A55FC88540F018A55F888140183C104FF4DC8
; 75DFFF45108B45103B45EC7CAB8BC3C1E0020145DCFF4DCC0F85CEFEFFFF8B4DEC33C08945F88945FC89451C8945148945103BC87E6C3945F07E5C8B4DD8
; 8B75E80FAFCB034D100FAFF30FAF4D188B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945C80FB6440E030145140FB60101451C0F
; B6440F010145FC8B45F40FB604010145F883C104FF4DC875D833C0FF45108B4DEC394D107C940FAF4DF03BC874068B451499F7F933F68945143BCE740B8B
; 451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975083975EC7E63EB0233F639
; 75F07E4F8B4DD88B75E80FAFCB034D080FAFF30FAF4D188B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955108A551488540E038A551C8811
; 8A55FC88540F018A55F888140883C104FF4D1075DFFF45088B45083B45EC7C9F5F5E33C05BC9C21800
; )"
; } else {
; MCode_PixelateBitmap := "
; (ltrim join
; 4489442418488954241048894C24085355565741544155415641574883EC28418BC1448B8C24980000004C8BDA99488BD941F7F9448BD0448BFA8954240C
; 448994248800000085C00F8E9D020000418BC04533E4458BF299448924244C8954241041F7F933C9898C24980000008BEA89542404448BE889442408EB05
; 4C8B5C24784585ED0F8E1A010000458BF1418BFD48897C2418450FAFF14533D233F633ED4533E44533ED4585C97E5B4C63BC2490000000418D040A410FAF
; C148984C8D441802498BD9498BD04D8BD90FB642010FB64AFF4403E80FB60203E90FB64AFE4883C2044403E003F149FFCB75DE4D03C748FFCB75D0488B7C
; 24188B8C24980000004C8B5C2478418BC59941F7FE448BE8418BC49941F7FE448BE08BC59941F7FE8BE88BC69941F7FE8BF04585C97E4048639C24900000
; 004103CA4D8BC1410FAFC94863C94A8D541902488BCA498BC144886901448821408869FF408871FE4883C10448FFC875E84803D349FFC875DA8B8C249800
; 0000488B5C24704C8B5C24784183C20448FFCF48897C24180F850AFFFFFF8B6C2404448B2424448B6C24084C8B74241085ED0F840A01000033FF33DB4533
; DB4533D24533C04585C97E53488B74247085ED7E42438D0C04418BC50FAF8C2490000000410FAFC18D04814863C8488D5431028BCD0FB642014403D00FB6
; 024883C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC17CB28BCD410FAFC985C9740A418BC299F7F98BF0EB0233F685C9740B418BC3
; 99F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585C97E4D4C8B74247885ED7E3841
; 8D0C14418BC50FAF8C2490000000410FAFC18D04814863C84A8D4431028BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2413BD17CBD
; 4C8B7424108B8C2498000000038C2490000000488B5C24704503E149FFCE44892424898C24980000004C897424100F859EFDFFFF448B7C240C448B842480
; 000000418BC09941F7F98BE8448BEA89942498000000896C240C85C00F8E3B010000448BAC2488000000418BCF448BF5410FAFC9898C248000000033FF33
; ED33F64533DB4533D24533C04585FF7E524585C97E40418BC5410FAFC14103C00FAF84249000000003C74898488D541802498BD90FB642014403D00FB602
; 4883C2044403D80FB642FB03F00FB642FA03E848FFCB75DE488B5C247041FFC0453BC77CAE85C9740B418BC299F7F9448BE0EB034533E485C9740A418BC3
; 99F7F98BD8EB0233DB85C9740A8BC699F7F9448BD8EB034533DB85C9740A8BC599F7F9448BD0EB034533D24533C04585FF7E4E488B4C24784585C97E3541
; 8BC5410FAFC14103C00FAF84249000000003C74898488D540802498BC144886201881A44885AFF448852FE4883C20448FFC875E941FFC0453BC77CBE8B8C
; 2480000000488B5C2470418BC1C1E00203F849FFCE0F85ECFEFFFF448BAC24980000008B6C240C448BA4248800000033FF33DB4533DB4533D24533C04585
; FF7E5A488B7424704585ED7E48418BCC8BC5410FAFC94103C80FAF8C2490000000410FAFC18D04814863C8488D543102418BCD0FB642014403D00FB60248
; 83C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC77CAB418BCF410FAFCD85C9740A418BC299F7F98BF0EB0233F685C9740B418BC399
; F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585FF7E4E4585ED7E42418BCC8BC541
; 0FAFC903CA0FAF8C2490000000410FAFC18D04814863C8488B442478488D440102418BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2
; 413BD77CB233C04883C428415F415E415D415C5F5E5D5BC3
; )"
; }
; VarSetCapacity(PixelateBitmap, strlen(MCode_PixelateBitmap)//2)
; loop(strlen(MCode_PixelateBitmap)//2)
; NumPut("0x" substr(MCode_PixelateBitmap, (2*A_Index)-1, 2), PixelateBitmap, A_Index-1, "uchar")
; dllcall("VirtualProtect", "UPtr",&PixelateBitmap, "UPtr",VarSetCapacity(PixelateBitmap), "uint",0x40, "UPtr*",0)
; }
; this.getSize(Width, Height)
; E1 := this.GdipBitmapLockBits([0, 0, Width, Height], Stride1, Scan01, BitmapData1)
; E2 := oBitmapOut.GdipBitmapLockBits([0, 0, Width, Height], Stride2, Scan02, BitmapData2)
; if (E1 || E2)
; return -3
; ; E := - unused exit code
; dllcall(&PixelateBitmap, "UPtr",Scan01, "UPtr",Scan02, "int",Width, "int",Height, "int",Stride1, "int",BlockSize)
; this.GdipBitmapUnlockBits(BitmapData1)
; oBitmapOut.GdipBitmapUnlockBits(BitmapData2)
; return 0
; }
;Quality 0-100
GdipSaveImageToFile(fp, Quality:=75) {
SplitPath(fp,,, ext)
if !(ext ~= "^(?i:bmp|dib|rle|jpg|jpeg|jpe|jfif|gif|tif|tiff|png)$")
return -1
ext := "." . ext
dllcall("gdiplus\GdipGetImageEncodersSize", "uint*",nCount, "uint*",nSize)
VarSetCapacity(ci, nSize)
dllcall("gdiplus\GdipGetImageEncoders", "uint",nCount, "uint",nSize, "UPtr", &ci)
if !(nCount && nSize)
return -2
loop(nCount) {
sString := strget(numget(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !instr(sString, "*" . ext)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
pQuality := 0
if (Quality != 75) {
Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
if (ext ~= "^\.(?i:JPG|JPEG|JPE|JFIF)$") {
dllcall("gdiplus\GdipGetEncoderParameterListSize","UPtr",this.ptr, "UPtr",pCodec, "uint*",nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
dllcall("gdiplus\GdipGetEncoderParameterList","UPtr",this.ptr, "UPtr",pCodec, "uint",nSize, "UPtr",&EncoderParameters)
loop(numget(EncoderParameters, "uint")) {
elem := (24+(A_PtrSize ? A_PtrSize : 4)) * (A_Index-1) + 4 + (pad := A_PtrSize-4)
if (numget(EncoderParameters, elem+16, "uint") == 1) && (numget(EncoderParameters, elem+20, "uint") == 6) {
pQuality := elem + &EncoderParameters - pad - 4
numput(Quality, numget(numput(4, numput(1, pQuality+0)+20, "uint")), "uint")
break
}
}
}
}
_E := dllcall("gdiplus\GdipSaveImageToFile","UPtr",this.ptr, "UPtr",&fp, "UPtr",pCodec, "uint",pQuality)
return _E ? -5 : 0
}
; https://docs.microsoft.com/en-us/windows/win32/api/gdiplusheaders/nf-gdiplusheaders-bitmap-lockbits
; LockMode https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.imagelockmode
; ReadOnly 1
; WriteOnly 2
; ReadWrite 3
; UserInputBuffer 4
; PixelFormat https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.pixelformat
; Argb 0x26200A
; rgb ?不是0x21808
GdipBitmapLockBits(aRect, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode:=3, PixelFormat:=0x21808) {
VarSetCapacity(_Rect, A_PtrSize*4)
numput(aRect[1], _Rect, A_PtrSize*0, "uint")
numput(aRect[2], _Rect, A_PtrSize*1, "uint")
numput(aRect[3], _Rect, A_PtrSize*2, "uint")
numput(aRect[4], _Rect, A_PtrSize*3, "uint")
VarSetCapacity(BitmapData, A_PtrSize*6, 0)
_E := dllcall("Gdiplus\GdipBitmapLockBits", "UPtr",this.ptr, "UPtr",&_Rect, "uint",LockMode, "int",PixelFormat, "UPtr",&BitmapData)
Stride := NumGet(BitmapData, 8, "Int")
Scan0 := NumGet(BitmapData, 16, "UPtr")
return _E
}
;获取的可能是 agrb
getLockBitPixel(Scan0, x, y, Stride) {
return NumGet(Scan0, (x*4)+(y*Stride), "UInt")
}
GdipBitmapUnlockBits(ByRef BitmapData) {
return dllcall("Gdiplus\GdipBitmapUnlockBits", "UPtr",this.ptr, "UPtr",&BitmapData)
}
}
;hh
;需要用 Gui 显示的,需要 oHBitmap 并生成 oGraphics
class GDIP_HBitmap extends _GDIP {
ptr := 0
__new(widthOrPBitmap, heightOrColor:=0xffFFFFFF, hDC:=0) {
if isobject(widthOrPBitmap) {
if (widthOrPBitmap.__class == "GDIP_PBitmap") {
dllcall("gdiplus\GdipCreateHBITMAPFromBitmap", "UPtr",widthOrPBitmap.ptr, "UPtr*",hBitmap, "int",heightOrColor)
this.ptr := hBitmap
} else if (widthOrPBitmap.length() == 4)
this.getFromScreen(widthOrPBitmap)
} else
this.CreateDIBSection(widthOrPBitmap, heightOrColor, hDC)
}
__delete() {
; msgbox(A_ThisFunc . '---')
base.DeleteObject(this.ptr)
}
getFromScreen(aRect:=0) {
x := aRect[1]
y := aRect[2]
w := aRect[3]
h := aRect[4]
;方式1,原始
tDC := dllcall("CreateCompatibleDC", "Uint", 0)
;创建 hBitmap
this.CreateDIBSection(w, h, tDC)
;修改 hBitmap
oBM := dllcall("SelectObject", "Uint", tDC, "Uint", this.ptr)
hDC := dllcall("GetDC", "Uint", 0)
dllcall("BitBlt", "Uint", tDC, "int",0, "int",0, "int",w, "int",h, "Uint",hDC, "int",x, "int",y, "Uint",0x40000000 | 0x00CC0020)
dllcall("ReleaseDC", "Uint", 0, "Uint", hDC)
dllcall("SelectObject", "Uint",tDC, "Uint",oBM)
dllcall("DeleteDC", "Uint", tDC)
}
CreateDIBSection(w, h, hDC:=0, bpp:=32, ByRef ppvBits:=0) {
hDC2 := hDC ? hDC : dllcall("GetDC", "UPtr",0)
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")
hBitmap := dllcall("CreateDIBSection", "ptr",hDC2, "ptr",&bi, "uint",0, "UPtr*",ppvBits, "ptr",0, "uint",0, "UPtr")
if !hDC
dllcall("ReleaseDC", "UPtr",0, "UPtr",hDC2)
if (!hBitmap)
msgbox(A_ThisFunc . "`n" . w . "`n" . h)
return this.ptr := hBitmap
}
; Gdip_CreateHICONFromBitmap(pBitmap) {
; pBitmap := ""
; hIcon := 0
; dllcall("gdiplus\GdipCreateHICONFromBitmap", "UPtr",pBitmap, "UPtr*",hIcon)
; return hIcon
; }
; SetImage(ctlID) {
; res := SendMessage(0x172,, this.ptr,, "ahk_id " . ctlID)
; dllcall("DeleteObject", "Uint",res)
; return res
; }
;复制 hBitmap 图像到剪切板
SetClipboardData(bDelete:=false) {
dllcall("GetObject", "Uint",this.ptr, "int",VarSetCapacity(oi,84,0), "Uint",&oi)
hDIB := dllcall("GlobalAlloc", "Uint",2, "Uint",40+NumGet(oi,44))
pDIB := dllcall("GlobalLock", "Uint",hDIB)
dllcall("RtlMoveMemory", "Uint",pDIB, "Uint",&oi+24, "Uint",40)
dllcall("RtlMoveMemory", "Uint",pDIB+40, "Uint",NumGet(oi,20), "Uint",NumGet(oi,44))
dllcall("GlobalUnlock", "Uint",hDIB)
if bDelete
dllcall("DeleteObject", "Uint",this.ptr)
dllcall("OpenClipboard", "Uint",0)
dllcall("EmptyClipboard")
dllcall("SetClipboardData", "Uint",8, "Uint",hDIB)
dllcall("CloseClipboard")
}
showByGui(aRect) {
;放入gui
oGui := GuiCreate("-Caption +ToolWindow +AlwaysOnTop +LastFound +Border -DPIScale")
;oGui.title := "hyd-" . A_Now
oGui.OnEvent("ContextMenu", ()=>oGui.destroy())
oGui.MarginX := 0
oGui.MarginY := 0
oPic := oGui.Addpicture(format("w{1} h{2} +0xE", aRect[3],aRect[4]))
oPic.OnEvent("click", ()=>PostMessage(0xA1, 2)) ;WM_NCLBUTTONDOWN 随着鼠标移动
oPic.OnEvent("DoubleClick", ObjBindMethod(this,"zoom"))
SendMessage(STM_SETIMAGE:=0x172,, this.ptr,, "ahk_id " . oPic.hwnd)
oGui.show(format("x{1} y{2}", aRect[1]-1,aRect[2]-1))
}
zoom(oCtl) {
n := 2
objPos := oCtl.pos
objGuiPos := oCtl.Gui.pos
w := objPos.w
h := objPos.h
oGdip := new _GDIP()
oPBitmap := new GDIP_PBitmap([objGuiPos.x+1,objGuiPos.y+1,w,h])
this.resize(n*100)
oHBitmap := new GDIP_HBitmap(oPBitmap)
oPBitmap := ""
SendMessage(STM_SETIMAGE:=0x172,, this.ptr,, "ahk_id " . oCtl.hwnd)
ControlMove(,,w*n,h*n, oCtl)
WinMove(,, w*n, h*n, "ahk_id " . oCtl.Gui.hwnd)
;if !isobject(oCtl)
;{
;MouseGetPos(,, idWin, oCtl)
;ControlGetPos(x,y,w,h, oCtl, "ahk_id " . idWin)
;}
;else
;{
;objPos := oCtl.pos
;w := objPos.w
;h := objPos.h
;objGuiPos := oCtl.Gui.pos
;x := objGuiPos.x+1
;y := objGuiPos.y+1
;}
;pToken := Gdip_Startup()
;pBitmap := Gdip_BitmapFromScreen(format("{1}|{2}|{3}|{4}", x,y,w,h))
;pBitmap := Gdip_ResizeBitmap(pBitmap, 200)
;hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
;Gdip_DisposeImage(pBitmap)
;Gdip_Shutdown(pToken)
;E := SendMessage(0x172, 0, hBitmap,, "ahk_id " . oCtl)
;;E := SendMessage(0x172, 0, hBitmap,, "ahk_id " . oCtl.hwnd)
;DllCall("DeleteObject", "UPtr",E)
;ControlMove(,,w*2,h*2, oCtl)
;WinMove(,,w*2, h*2,"ahk_id " . oCtl.Gui.hwnd)
}
}
;gg
;NOTE 写内容都通过 GDIP_Graphics,写好后,相应的 GDIP_PBitmap就已修改,可直接 GdipSaveImageToFile
class GDIP_Graphics extends _GDIP {
ptr := 0
hDC := 0
__new(oInstance) {
if isobject(oInstance) {
if (oInstance.__class == "GDIP_PBitmap")
this.GdipGetImageGraphicsContext(oInstance)
else if (oInstance.__class == "GDIP_HBitmap") { ;NOTE 先生成 this.hDC
this.hDC := dllcall("CreateCompatibleDC", "UPtr",0)
this.SelectObject(oInstance.ptr) ;NOTE 必须先运行
res := dllcall("gdiplus\GdipCreateFromHDC", "UPtr",this.hDC, "UPtr*",pGraphics)
if (!pGraphics)
msgbox(A_ThisFunc . "`n" . res . "`n" . oInstance)
this.ptr := pGraphics
}
}
}
__delete() {
if this.hDC
dllcall("DeleteDC", "UPtr",this.hDC)
dllcall("gdiplus\GdipDeleteGraphics", "Ptr",this.ptr)
}
GdipGetImageGraphicsContext(oPBitmap) {
dllcall("gdiplus\GdipGetImageGraphicsContext",A_PtrSize ? "UPtr" : "uint",oPBitmap.ptr, A_PtrSize ? "UPtr*" : "uint*",pGraphics)
if (!pGraphics)
msgbox(A_ThisFunc)
this.ptr := pGraphics
}
GdipGraphicsClear(color := 0) {
return dllcall("gdiplus\GdipGraphicsClear", "Ptr",this.ptr, "uint",color)
}
GdipResetClip() {
dllcall("gdiplus\GdipResetClip", "UPtr",this.ptr)
}
; default = 0
; HighSpeed = 1
; HighQuality = 2
; None = 3
; AntiAlias = 4 边缘平滑
GdipSetSmoothingMode(smoothingMode:=4) {
return dllcall("gdiplus\GdipSetSmoothingMode", "Ptr",this.ptr, "int",smoothingMode)
}
; default = 0
; LowQuality = 1
; HighQuality = 2
; Bilinear = 3
; Bicubic = 4
; NearestNeighbor = 5
; HighQualityBilinear = 6
; HighQualityBicubic = 7
GdipSetInterpolationMode(interpolationMode:=7) {
return dllcall("gdiplus\GdipSetInterpolationMode", "Ptr",this.ptr, "int",interpolationMode)
}
;TextRenderingHintSystemDefault = 0,
;TextRenderingHintSingleBitPerPixelGridFit = 1,
;TextRenderingHintSingleBitPerPixel = 2,
;TextRenderingHintAntiAliasGridFit = 3,
;TextRenderingHintAntiAlias = 4,
;TextRenderingHintClearTypeGridFit = 5
GdipSetTextRenderingHint(TextRenderingHint:=0) {
return dllcall("gdiplus\GdipSetTextRenderingHint", "Ptr",this.ptr, "uint",textRenderingHint)
}
;------------------------------------------------rotate------------------------------------------------
;旋转相关
;根据【左上角】旋转,新的画布宽高会调整为最小矩形
;是给 GdipDrawImageRectRect 等【绘制】工作指定参数
; 1.getRotatedRect 旋转后的左上角坐标-原坐标【差值】和【新的宽高】
;旋转后新的宽高
;原左上角坐标相对新左上角坐标的偏移:xOffset, yOffset
;后续
; oGraphics.GdipTranslateWorldTransform(xOffset, yOffset)
getRotatedRect(w, h, angle) {
pi := 3.14159
TAngle := angle*(pi/180)
bound := (angle >= 0) ? mod(angle, 360) : 360-mod(-angle, -360)
if (bound <= 90) {
xOffset := h*sin(TAngle)
yOffset := 0
} else if (bound <= 180) {
xOffset := (h*sin(TAngle))-(w*cos(TAngle))
yOffset := -h*cos(TAngle)
} else if (bound <= 270) {
xOffset := -w*cos(TAngle)
yOffset := -(h*cos(TAngle))-(w*sin(TAngle))
} else {
xOffset := 0
yOffset := -w*sin(TAngle)
}
newW := ceil(abs(w*cos(TAngle))+abs(h*sin(TAngle)))
newH := ceil(abs(w*sin(TAngle))+abs(h*cos(Tangle)))
return [xOffset, yOffset, newW, newH]
}
;翻转
;水平翻转(以右线翻转)
; GdipScaleWorldTransform(-1, 1)
; GdipTranslateWorldTransform(-w, 0)
;垂直翻转(以下线翻转)
; GdipScaleWorldTransform(1, -1)
; GdipTranslateWorldTransform(0, -h)
GdipScaleWorldTransform(xScale, yScale, MatrixOrder:=0) {
return dllcall("gdiplus\GdipScaleWorldTransform", "Ptr",this.ptr, "float",xScale, "float",yScale, "int",MatrixOrder)
}
;偏移坐标(新-旧)
;NOTE 要在 GdipRotateWorldTransform 之后运行
GdipTranslateWorldTransform(xOffset, yOffset, MatrixOrder:=0) {
return dllcall("gdiplus\GdipTranslateWorldTransform", "Ptr",this.ptr, "float",xOffset, "float",yOffset, "int",MatrixOrder)
}
;回收
GdipResetWorldTransform() {
return dllcall("gdiplus\GdipResetWorldTransform", "Ptr",this.ptr)
}
;旋转 angle 度
;TODO MatrixOrder = 0; The new operation is applied before the old operation.
; MatrixOrder = 1; The new operation is applied after the old operation.
;NOTE 要在 GdipTranslateWorldTransform 等调整好之后再运行
GdipRotateWorldTransform(angle:=90, MatrixOrder:=0) {
return dllcall("gdiplus\GdipRotateWorldTransform", "Ptr",this.ptr, "float",angle, "int",MatrixOrder)
}
;------------------------------------------------draw------------------------------------------------
;推荐 drawImage
GdipDrawImageRectRect(pBitmap, aRectTo, aRectFrom:="", Matrix:=1) {
if !(Matrix ~= "^\d+$")
ImageAttr := this.GdipSetImageAttributesColorMatrix(Matrix)
else if (Matrix != 1)
ImageAttr := this.GdipSetImageAttributesColorMatrix(format("1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|{1}|0|0|0|0|0|1", Matrix))
return dllcall("gdiplus\GdipDrawImageRectRect", "Ptr",this.ptr, "Ptr",pBitmap
, "float",aRectTo[1],"float",aRectTo[2],"float",aRectTo[3],"float",aRectTo[4]
, "float",aRectFrom[1],"float",aRectFrom[2],"float",aRectFrom[3],"float",aRectFrom[4]
, "uint",2 , "Ptr",ImageAttr, "Ptr",0, "Ptr",0)
}
;GdipDrawImageRectRect 简化,用 oPBitmap 当参数,可省略 aRectFrom(默认是全图)
drawImage(oPBitmap, aRectTo, aRectFrom:="", Matrix:=1) {
if (!isobject(aRectFrom))
aRectFrom := [0,0,oPBitmap.getWidth(),oPBitmap.getHeight()]
if !(Matrix ~= "^\d+$")
ImageAttr := this.GdipSetImageAttributesColorMatrix(Matrix)
else if (Matrix != 1)
ImageAttr := this.GdipSetImageAttributesColorMatrix(format("1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|{1}|0|0|0|0|0|1", Matrix))
return dllcall("gdiplus\GdipDrawImageRectRect", "Ptr",this.ptr, "Ptr",oPBitmap.ptr
, "float",aRectTo[1],"float",aRectTo[2],"float",aRectTo[3],"float",aRectTo[4]
, "float",aRectFrom[1],"float",aRectFrom[2],"float",aRectFrom[3],"float",aRectFrom[4]
, "uint",2 , "Ptr",ImageAttr, "Ptr",0, "Ptr",0)
}
GdipSetImageAttributesColorMatrix(Matrix) {
VarSetCapacity(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 : 1
NumPut(M, ColourMatrix, (A_Index-1)*4, "float")
}
DllCall("gdiplus\GdipCreateImageAttributes", "UPtr*",ImageAttr)
DllCall("gdiplus\GdipSetImageAttributesColorMatrix", "UPtr",ImageAttr, "int",1, "int",1, "UPtr",&ColourMatrix, "UPtr",0, "int",0)
return ImageAttr
}
GdipDrawRectangle(pPen, aRect) {
return dllcall("gdiplus\GdipDrawRectangle", "UPtr",this.ptr, "UPtr",pPen, "float",aRect[1],"float",aRect[2],"float",aRect[3],"float",aRect[4])
}
; Pen: the pen used to draw the line
;points [x1,y1,x2,y2]
GdipDrawLine(pPen, points) {
return dllcall("gdiplus\GdipDrawLine", "UPtr",this.ptr, "UPtr",pPen, "float",points.1, "float",points.2, "float",points.3, "float",points.4)
}
GdipDrawEllipse(pPen, aRect) {
return dllcall("gdiplus\GdipDrawEllipse", "UPtr",this.ptr, "UPtr",pPen, "float",aRect[1],"float",aRect[2],"float",aRect[3],"float",aRect[4])
}
drawLines(pPen, points) {
points := points.clone()
loop(points.length() - 1)
this.GdipDrawLine(pPen, points), points.RemoveAt(1)
}
; GdipDrawString: Writes some text with a specified font, rectangle, _stringFormat and Brush on the Graphics
; sText: The text you want to write.
; font: The font you want to use. Has to be a GDIp.font object
; rect: A 4 value array defining [ x, y, w, h ] of the area you want to write to.
; stringFormat: Some options of the text like the text direction. Has to be a GDIp.StringFormat object
; brush: Defines the color of the text. Has to be a GDI+ Brush object. (currently GDIp.SolidBrush & GDIp.LinearGradientBrush)
; 参数太多,可能不好用
GdipDrawString(sText, pFont, pStringFormat, pBrush, aRect) {
; hyf_objView(aRect, pFont . "`n" . pStringFormat . "`n" . pBrush)
VarSetCapacity(rectF, 16, 0)
for k, entry in aRect
numput(entry, rectF, k * 4 - 4, "float")
return dllcall("gdiplus\GdipDrawString", "UPtr",this.ptr, "WStr",sText, "int",-1, "UPtr",pFont, "UPtr",&rectF, "UPtr",pStringFormat, "UPtr",pBrush)
}
; opts := "x10p y60p w80p Centre cff000000 r4 s18p Bold"
DrawText(sText, opts, sFont:="Arial", width:="", height:="", Measure:=0) {
arrOpt := StrSplit(opts, " ")
objStyle := {
"Regular":0,
"Bold":1,
"Italic":2,
"BoldItalic":3,
"Underline":4,
"Strikeout":8,
}
objAlign := {
"Near":0,
"Left":0,
"Centre":1,
"Center":1,
"Far":2,
"Right":2,
}
objPos := {
"Top":1,
"Up":1,
"Bottom":1,
"Down":1,
"vCentre":1,
"vCenter":1,
}
objRes := {}
style := align := 0
for _, v in arrOpt {
if objStyle.haskey(v)
style |= objStyle[v]
else if objAlign.haskey(v)
align |= objAlign[v]
else if objPos.haskey(v)
arrPos := [1]
else { ;处理其他选项
objType := {
"x":0,
"y":0,
"w":width,
"h":height,
"c":0xff000000,
"r":4,
"s":12,
"NoWrap":0x4000,
}
;完整匹配
if (v == "NoWrap") {
objType["NoWrap"] := 0x4000 | 0x1000
continue
} else if (v ~= "i)Bottom|Down|vCentre|vCenter") {
if (v = "vCentre") || (v = "vCenter")
objType["y"] += (height-objType["h"]) // 2
else if (v = "Bottom") || (v = "Down")
objType["y"] := height - objType["h"]
}
;匹配首字母
RegExMatch(v, "i)([a-z])([a-f0-9]+)([a-z])?", m)
try
tp := StrLower(m[1])
catch
msgbox(v)
; msgbox(m[1] . "`n" . m[2] . "`n" . m[3])
if (tp == "x")
objType[tp] := m[3] ? width*(m[2]/100) : m[2]
else if (tp == "y")
objType[tp] := m[3] ? height*(m[2]/100) : m[2]
else if (tp == "w")
objType[tp] := m[3] ? width*(m[2]/100) : m[2]
else if (tp == "h")
objType[tp] := m[3] ? height*(m[2]/100) : m[2]
else if (tp == "c")
objType[tp] := "0x" . m[2]
else if (tp == "r")
objType[tp] := m[2] ;要求0-5
else if (tp == "s")
objType[tp] := m[2]
}
}
; pattern_opts := (A_AhkVersion < "2") ? "iO)" : "i)"
; RegExMatch(opts, pattern_opts . "X([\-\d\.]+)(p*)", xpos)
; RegExMatch(opts, pattern_opts . "Y([\-\d\.]+)(p*)", ypos)
; RegExMatch(opts, pattern_opts . "W([\-\d\.]+)(p*)", width)
; RegExMatch(opts, pattern_opts . "H([\-\d\.]+)(p*)", height)
; RegExMatch(opts, pattern_opts . "C(?!(entre|enter))([a-f\d]+)", Colour)
; RegExMatch(opts, pattern_opts . "Top|Up|Bottom|Down|vCentre|vCenter", vPos)
; RegExMatch(opts, pattern_opts . "R(\d)", Rendering)
; RegExMatch(opts, pattern_opts . "S(\d+)(p*)", Size)
; ; if Colour && !GdipDeleteBrush(this.GdipCloneBrush(Colour[2])) {
; ; PassBrush := 1
; ; pBrush := Colour[2]
; ; }
; if !(width && IHeight) && ((xpos && xpos[2]) || (ypos && ypos[2]) || (width && width[2]) || (height && height[2]) || (Size && Size[2]))
; return -1
; style := 0
; Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
; for k, valStyle in StrSplit( Styles, "|" ) {
; if RegExMatch(opts, "\b" . valStyle)
; style |= (valStyle != "StrikeOut") ? (A_Index-1) : 8
; }
; Align := 0
; Alignments := [
; "Near",
; "Left",
; "Centre",
; "Center",
; "Far",
; "Right",
; ]
; For k, valAlignment in Alignments {
; if (opts ~= "\b" . valAlignment)
; Align |= A_Index//2.1 ; 0|0|1|1|2|2
; }
; xpos := (xpos && (xpos[1] != "")) ? (xpos[2] ? width*(xpos[1]/100) : xpos[1]) : 0
; ypos := (ypos && (ypos[1] != "")) ? (ypos[2] ? height*(ypos[1]/100) : ypos[1]) : 0
; width := (width && width[1]) ? (width[2] ? width*(width[1]/100) : width[1]) : width
; height := (height && height[1]) ? (height[2] ? IHeight*(height[1]/100) : height[1]) : IHeight
; Colour := "0x" . (Colour && Colour[2] ? Colour[2] : "ff000000")
; ; if !PassBrush
; ; Colour := format("0x{1}", Colour && Colour[2] ? Colour[2] : "ff000000")
; Rendering := (Rendering && (Rendering[1] >= 0) && (Rendering[1] <= 5)) ? Rendering[1] : 4
; Size := (Size && (Size[1] > 0)) ? (Size[2] ? IHeight*(Size[1]/100) : Size[1]) : 12
oFont := new GDIP_Font(sFont, objType["s"])
oStringFormat := new GDIP_StringFormat(objType["NoWrap"])
oBrush := new GDIP_Brush(objType["c"])
; pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)
; if !(hFamily && hFont && hFormat && pBrush && this.ptr)
; return !this.ptr ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0
aRect := [objType["x"], objType["y"], objType["w"], objType["h"]]
this.GdipSetTextRenderingHint(objType["r"])
oStringFormat.GdipSetStringFormatAlign(align)
arrRes := this.GdipMeasureString(sText, oFont.ptr, oStringFormat.ptr, aRect)
if !Measure
_E := this.GdipDrawString(sText, oFont.ptr, oStringFormat.ptr, oBrush.ptr, aRect)
; if !PassBrush
; Gdip_DeleteBrush(pBrush)
oBrush := ""
oStringFormat := ""
oFont := ""
return _E ? _E : arrRes
}
GdipMeasureString(sText, pFont, pStringFormat, aRect) {
base.CreateRect(RectF, aRect)
VarSetCapacity(outRect, 16, 0)
res := dllcall("gdiplus\GdipMeasureString"
, "UPtr",this.ptr
, "UPtr", &sText
, "int",-1
, "UPtr",pFont
, "UPtr",&RectF
, "UPtr",pStringFormat
, "UPtr",&outRect
, "uint*",codePointsFitted
, "uint*",linesFitted)
return [
numget(outRect, 0, "float"),
numget(outRect, 4, "float"),
numget(outRect, 8, "float"),
numget(outRect, 12,"float"),
codePointsFitted,
linesFitted,
]
}
; GdipDrawBeziers: draw a Bezier Curve onto the graphics with the specified pen and points
; pen: the pen you want to use to draw on the graphics
; points: An array of starting and control points of a Bezier line
; A single Bezier line consists of 4 points a starting point 2 control points and an end point
; The line never actually goes through the control points
; The control points control the tangent in the starting and end point and their distance controls how strongly the curve follows there
GdipDrawBeziers(pPen, points) {
pointsBuffer := ""
VarSetCapacity(pointsBuffer, 8 * points.length(), 0)
for each, point in points
numput(point.1, pointsBuffer, each * 8 - 8, "float"), numput(point.2, pointsBuffer, each * 8 - 4, "float")
return dllcall("gdiplus\GdipDrawBeziers", "UPtr",this.ptr, "UPtr",pPen, "UPtr", &pointsBuffer, "uint",points.length())
}
;画箭头:妖提供
;=======================================================
;
; M5
; M4
; A------------------------------------------M1-d-B
; M2
; M3
;
;M1-M2,宽为w1
;M1-M3,宽为w2
;=======================================================
drawArrow(pGraphics, pBrush, Ax, Ay, Bx, By) {
if (Ax=Bx) ;水平线、垂直线的斜率为0、无斜率,对于作图都有问题,所以人为补了1个像素
Bx := Ax+1
if (Ay=By)
By := Ay+1
l := sqrt((Ax- Bx)**2 +(Ay - By)**2) ; 起点终点之间的距离
w1 := 3
w2 := 5
; d:=l/10 ;箭头取1/10长度
if (l < 50)
d := 10
else if (l<100)
d := 20
else
d := 30
My1 := By-(d*(By-Ay))/l
Mx1 := Bx-(d*(Bx-Ax))/l
k := (By-Ay)/(Bx-Ax) ;斜率
kk := -1/k ;垂直线的斜率
zz := sqrt(kk*kk+1)
Mx2 := Mx1+d/(w1*zz)
My2 := My1+kk*d/(w1*zz)
Mx4 := Mx1-d/(w1*zz)
My4 := My1-kk*d/(w1*zz)
Mx3 := Mx1+d/(w2*zz)
My3 := My1+kk*d/(w2*zz)
Mx5 := Mx1-d/(w2*zz)
My5 := My1-kk*d/(w2*zz)
point := format("{1},{2}|{3},{4}|{5},{6}|{7},{8}|{9},{10}|{11},{12}", Ax,Ay,Mx3,My3,Mx2,My2,Bx,By,Mx4,My4,Mx5,My5)
this.GdipFillPolygon(pBrush, point, FillMode:=1)
}
;------------------------------------------------fill------------------------------------------------
fillRoundedRectangle(pBrush, aRect, r) {
x := aRect[1]
y := aRect[2]
w := aRect[3]
h := aRect[4]
this.GdipGetClip()
this.GdipSetClipRect([x-r, y-r, 2*r, 2*r], 4)
this.GdipSetClipRect([x+w-r, y-r, 2*r, 2*r], 4)
this.GdipSetClipRect([x-r, y+h-r, 2*r, 2*r], 4)
this.GdipSetClipRect([x+w-r, y+h-r, 2*r, 2*r], 4)
_E := this.GdipFillRectangle(pBrush, aRect)
this.GdipSetClipRegion(0)
this.GdipSetClipRect([x-(2*r), y+r, w+(4*r), h-(2*r)], 4)
this.GdipSetClipRect([x+r, y-(2*r), w-(2*r), h+(4*r)], 4)
this.GdipFillEllipse(pBrush, [x, y, 2*r, 2*r])
this.GdipFillEllipse(pBrush, [x+w-(2*r), y, 2*r, 2*r])
this.GdipFillEllipse(pBrush, [x, y+h-(2*r), 2*r, 2*r])
this.GdipFillEllipse(pBrush, [x+w-(2*r), y+h-(2*r), 2*r, 2*r])
this.GdipSetClipRegion(0)
this.GdipDeleteRegion()
return _E
}
; extracted from: https://github.com/tariqporter/Gdip2/blob/master/lib/Object.ahk
; and adapted by Marius Șucan
; fillRoundedRectangle2(pBrush, aRect, r) {
; x := aRect[1]
; y := aRect[2]
; w := aRect[3]
; h := aRect[4]
; r := (w <= h) ? (r < w // 2) ? r : w // 2 : (r < h // 2) ? r : h // 2
; path1 := this.GdipCreatePath(0)
; this.GdipAddPathRectangle(path1, [x+r, y, w-(2*r), r])
; this.GdipAddPathRectangle(path1, [x+r, y+h-r, w-(2*r), r])
; this.GdipAddPathRectangle(path1, [x, y+r, r, h-(2*r)])
; this.GdipAddPathRectangle(path1, [x+w-r, y+r, r, h-(2*r)])
; this.GdipAddPathRectangle(path1, [x+r, y+r, w-(2*r), h-(2*r)])
; this.GdipAddPathPie(path1, [x, y, 2*r, 2*r], 180, 90)
; this.GdipAddPathPie(path1, [x+w-(2*r), y, 2*r, 2*r], 270, 90)
; this.GdipAddPathPie(path1, [x, y+h-(2*r), 2*r, 2*r], 90, 90)
; this.GdipAddPathPie(path1, [x+w-(2*r), y+h-(2*r), 2*r, 2*r], 0, 90)
; E := this.GdipFillPath(this.ptr, pBrush, path1)
; this.GdipDeletePath(path1)
; return E
; }
GdipFillRectangle(pBrush, aRect) {
return dllcall("gdiplus\GdipFillRectangle", "Ptr",this.ptr, "Ptr",pBrush, "float",aRect.1, "float",aRect.2, "float",aRect.3, "float",aRect.4)
}
GdipFillEllipse(pBrush, aRect) {
if (!pBrush)
msgbox(A_ThisHotkey)
return dllcall("gdiplus\GdipFillEllipse", "Ptr",this.ptr, "Ptr",pBrush, "float",aRect.1, "float",aRect.2, "float",aRect.3, "float",aRect.4)
}
GdipFillPolygon(pBrush, points, fillMode:=0) {
VarSetCapacity(pointBuffer, 8 * points.length(), 0)
for pointNr, point in points {
numput(point.1, pointBuffer, pointNr * 8 - 8, "float")
numput(point.2, pointBuffer, pointNr * 8 - 4, "float")
}
return dllcall("gdiplus\GdipFillPolygon", "Ptr",this.ptr, "Ptr",pBrush, "Ptr", &pointBuffer, "int",points.length(), "int",fillMode)
}
; 起始角度(右边为0), 阴影角度
GdipFillPie(pBrush, aRect, angles) {
return dllcall("gdiplus\GdipFillPie", "Ptr",this.ptr, "Ptr",pBrush, "float",aRect[1],"float",aRect[2],"float",aRect[3],"float",aRect[4], "float",angles.1, "float",angles.2)
}
GdipFillPath(pGraphics, pBrush, pPath) {
return dllcall("gdiplus\GdipFillPath", "UPtr",pGraphics, "UPtr",pBrush, "UPtr",pPath)
}
GdipCreateRegion() {
dllcall("gdiplus\GdipCreateRegion", "UInt*",region)
if (!region)
msgbox(A_ThisFunc)
return this.region := region
}
GdipGetClip() {
this.GdipCreateRegion()
dllcall("gdiplus\GdipGetClip", "UPtr",this.ptr, "UInt",this.region)
return this.region
}
GdipSetClipRect(aRect, CombineMode:=0) {
return dllcall("gdiplus\GdipSetClipRect", "UPtr",this.ptr, "float",aRect[1],"float",aRect[2],"float",aRect[3],"float",aRect[4], "int",CombineMode)
}
GdipSetClipRegion(CombineMode:=0) {
return dllcall("gdiplus\GdipSetClipRegion", "UPtr",this.ptr, "UPtr",this.region, "int",CombineMode)
}
GdipDeleteRegion() {
return dllcall("gdiplus\GdipDeleteRegion", "UPtr",this.region)
}
GdipCreatePath(BrushMode:=0) {
dllcall("gdiplus\GdipCreatePath", "int",BrushMode, "UPtr*",pPath)
return pPath
}
GdipAddPathRectangle(pPath, aRect) {
return dllcall("gdiplus\GdipAddPathRectangle",A_PtrSize ? "UPtr" : "UInt",pPath, "float",aRect[1],"float",aRect[2],"float",aRect[3],"float",aRect[4])
}
GdipAddPathPie(pPath, aRect, StartAngle, SweepAngle) {
return dllcall("gdiplus\GdipAddPathPie", "UPtr",pPath, "float",aRect[1],"float",aRect[2],"float",aRect[3],"float",aRect[4], "float",StartAngle, "float",SweepAngle)
}
Gdip_AddPathBeziers(pPath, Points) {
Points := StrSplit(Points, "|")
VarSetCapacity(PointF, 8*Points.Length())
for _, 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\GdipAddPathBeziers", "UPtr", pPath, "UPtr", &PointF, "int", Points.Length())
}
; Adds a Bézier spline to the current figure of this path
GdipAddPathBezier(pPath, x1, y1, x2, y2, x3, y3, x4, y4) {
return DllCall("gdiplus\GdipAddPathBezier", "UPtr", pPath
, "float", x1, "float", y1, "float", x2, "float", y2
, "float", x3, "float", y3, "float", x4, "float", y4)
}
;#####################################################################################
; Function Gdip_AddPathLines
; Description Adds a sequence of connected lines to the current figure of this path.
;
; pPath Pointer to the GraphicsPath
; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return status enumeration. 0 = success
GdipAddPathLine2(pPath, Points) {
Points := StrSplit(Points, "|")
VarSetCapacity(PointF, 8*Points.Length())
for _, 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\GdipAddPathLine2", "UPtr", pPath, "UPtr", &PointF, "int", Points0)
}
Gdip_AddPathLine(pPath, aRect) {
return DllCall("gdiplus\GdipAddPathLine", "UPtr", pPath, "float",aRect[1],"float",aRect[2],"float",aRect[3],"float",aRect[4])
}
GdipAddPathArc(pPath, aRect, StartAngle, SweepAngle) {
return DllCall("gdiplus\GdipAddPathArc", "UPtr", pPath, "float",aRect[1],"float",aRect[2],"float",aRect[3],"float",aRect[4], "float", StartAngle, "float", SweepAngle)
}
; Starts a new figure without closing the current figure. Subsequent points added to this path are added to the new figure.
GdipStartPathFigure(pPath) {
return DllCall("gdiplus\GdipStartPathFigure", "UPtr", pPath)
}
; Closes the current figure of this path.
GdipClosePathFigure(pPath) {
return DllCall("gdiplus\GdipClosePathFigure", "UPtr", pPath)
}
; Replaces this path with curves that enclose the area that is filled when this path is drawn by a specified pen. This method also flattens the path.
GdipWidenPath(pPath, pPen, Matrix:=0, Flatness:=1) {
return DllCall("gdiplus\GdipWidenPath", "UPtr", pPath, "uint", pPen, "UPtr", Matrix, "float", Flatness)
}
GdipClonePath(pPath) {
DllCall("gdiplus\GdipClonePath", "UPtr",pPath, "UPtr*",pPathClone)
return pPathClone
}
;#####################################################################################
; Function Gdip_DrawPath
; Description draws a sequence of lines and curves defined by a GraphicsPath object
; pGraphics Pointer to the Graphics of a bitmap
; pPen Pointer to a pen
; pPath Pointer to a Path
; return status enumeration. 0 = success
GdipDrawPath(pPen, pPath) {
return DllCall("gdiplus\GdipDrawPath", "UPtr",this.ptr, "UPtr",pPen, "UPtr",pPath)
}
GdipDeletePath(pPath) {
return dllcall("gdiplus\GdipDeletePath", "UPtr",pPath)
}
;oDC 相关方法
; DCX_CACHE = 0x2
; DCX_CLIPCHILDREN = 0x8
; DCX_CLIPSIBLINGS = 0x10
; DCX_EXCLUDERGN = 0x40
; DCX_EXCLUDEUPDATE = 0x100
; DCX_INTERSECTRGN = 0x80
; DCX_INTERSECTUPDATE = 0x200
; DCX_LOCKWINDOWUPDATE = 0x400
; DCX_NORECOMPUTE = 0x100000
; DCX_NORESETATTRS = 0x4
; DCX_PARENTCLIP = 0x20
; DCX_VALIDATE = 0x200000
; DCX_WINDOW = 0x1
; getEx(hwnd, flags:=0, hrgnClip:=0) {
; Ptr := A_PtrSize ? "UPtr" : "uint"
; return this.hDC := dllcall("GetDCEx",ptr,hwnd, ptr,hrgnClip, "int",flags)
; }
release(hwnd:=0) {
return dllcall("ReleaseDC", "uptr",hwnd, "ptr",this.hDC)
}
;TODO
; Raster
; SRCCOPY = 0x00CC0020
; BLACKNESS = 0x00000042
; NOTSRCERASE = 0x001100A6
; NOTSRCCOPY = 0x00330008
; SRCERASE = 0x00440328
; DSTINVERT = 0x00550009
; PATINVERT = 0x005A0049
; SRCINVERT = 0x00660046
; SRCAND = 0x008800C6
; MERGEPAINT = 0x00BB0226
; MERGECOPY = 0x00C000CA
; SRCPAINT = 0x00EE0086
; PATCOPY = 0x00F00021
; PATPAINT = 0x00FB0A09
; WHITENESS = 0x00FF0062
; CAPTUREBLT = 0x40000000
; NOMIRRORBITMAP = 0x80000000
BitBlt(aRectTo, sDC, sx, sy, Raster:=0x00CC0020) {
if (!this.hDC || !sDC)
msgbox(A_ThisFunc)
return dllcall("gdi32\BitBlt", "UPtr",this.hDC
, "int",aRectTo[1],"int",aRectTo[2],"int",aRectTo[3],"int",aRectTo[4]
, "UPtr",sDC, "int",sx, "int",sy, "uint",Raster)
}
SelectObject(hGdiObj:=0) {
if (hGdiObj) {
if !this.pSelectSave ;只记录一次
return this.pSelectSave := dllcall("SelectObject", "UPtr",this.hDC, "UPtr",hGdiObj)
else
return dllcall("SelectObject", "UPtr",this.hDC, "UPtr",hGdiObj)
} else ;还原
return dllcall("SelectObject", "UPtr",this.hDC, "UPtr",this.pSelectSave)
}
;aRect =屏幕上显示的位置大小
UpdateLayeredWindow(hwnd, aRect, alpha:=255) {
if (!hwnd || !this.hDC)
msgbox(A_ThisFunc)
x := aRect[1]
y := aRect[2]
w := aRect[3]
h := aRect[4]
VarSetCapacity(pt, 8, 0)
numput(x, pt, 0, "uint")
numput(y, pt, 4, "uint")
return dllcall("UpdateLayeredWindow"
, "uptr", hwnd
, "uptr", 0
, "uptr", &pt
, "int64*", w|h<<32
, "uptr", this.hDC
, "int64*", 0
, "uint", 0
, "uint*", alpha<<16|1<<24
, "uint", 2)
}
showByGui() {
oGui := GuiCreate("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs")
oGui.Show("NA")
this.UpdateLayeredWindow(oGui.hwnd, [0, 0, A_ScreenWidth, A_ScreenHeight])
}
}
;pp
class GDIP_Pen extends _GDIP {
ptr := 0
__new(argbOrBrush, width) {
if isobject(argbOrBrush)
this.createByBrush(argbOrBrush)
else
this.createByArgb(argbOrBrush, width)
; base.registerObject(this)
}
__delete() {
; msgbox(A_ThisFunc . '---')
dllcall("gdiplus\GdipDeletePen", "UPtr",this.ptr)
}
createByArgb(argb, width) {
;TODO 是否需要先删除原画笔?
if this.ptr
this.__delete()
res := dllcall("gdiplus\GdipCreatePen1", "uint",argb, "float",width, "int",2, "UPtr*",pPen)
if (!pPen)
msgbox(A_ThisFunc . "`n" . argb . "`n" . width)
this.ptr := pPen
return res
}
createByBrush(oBrush){
if this.ptr
this.__delete()
this.pBrush := oBrush ;TODO 是否需要保存 <2020-12-11 14:36:59> hyaray
res := dllcall("gdiplus\GdipCreatePen2", "UPtr",argbOrBrush, "float",width, "int",2, "UPtr*",pPen)
this.ptr := pPen
return res
}
GdipGetPenWidth() {
dllcall("gdiplus\GdipGetPenWidth", "UPtr",this.ptr, "float*",width)
return width
}
GdipSetPenWidth(width) {
return dllcall("gdiplus\GdipSetPenWidth", "UPtr",this.ptr, "float",width)
}
GdipGetPenColor() {
dllcall("gdiplus\GdipGetPenColor", "UPtr",this.ptr, "uint*",color)
return color
}
GdipSetPenColor(color) {
return dllcall("gdiplus\GdipSetPenColor", "UPtr",this.ptr, "uint",color)
}
; getBrush() {
; return this.ptr
; }
; setBrush(pBrush := "") {
; if (this.haskey("pBrush") && pBrush)
; this.ptr := pBrush
; return dllcall("gdiplus\GdipSetPenBrushFill", "UPtr",this.ptr, "UPtr",this.ptr.getpBrush())
; }
}
;bb
class GDIP_Brush extends _GDIP {
ptr := 0
__new(argb, argbBack:=0, HatchStyle:=0) {
if argbBack
this.GdipCreateHatchBrush(argb, argbBack, HatchStyle)
else
this.GdipCreateSolidFill(argb)
}
__delete() {
; msgbox(A_ThisFunc . '---')
dllcall("gdiplus\GdipDeleteBrush", "UPtr",this.ptr)
}
GdipCreateSolidFill(argb) {
if !argb
msgbox(A_ThisFunc . "`nargb = 0")
;TODO 是否需要先删除原画刷?
if this.ptr
this.__delete()
dllcall("gdiplus\GdipCreateSolidFill", "uint",argb, "UPtr*",pBrush)
if (!pBrush)
msgbox(A_ThisFunc)
this.ptr := pBrush
}
; LinearGradientModeHorizontal = 0
; LinearGradientModeVertical = 1
; LinearGradientModeForwardDiagonal = 2
; LinearGradientModeBackwardDiagonal = 3
GdipCreateLineBrushFromRect(aRect, ARGB1, ARGB2, LinearGradientMode:=1, WrapMode:=1) {
this.CreateRect(Rect, aRect)
dllcall("gdiplus\GdipCreateLineBrushFromRect", "UPtr",&Rect, "int",ARGB1, "int",ARGB2, "int",LinearGradientMode, "int",WrapMode, "UPtr*",LGpBrush)
return this.ptr := LGpBrush
}
; 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
; https://docs.microsoft.com/en-us/windows/win32/api/gdiplusenums/ne-gdiplusenums-hatchstyle
GdipCreateHatchBrush(argbFront, argbBack, HatchStyle:=0) {
dllcall("gdiplus\GdipCreateHatchBrush", "int",HatchStyle, "UInt",argbFront, "UInt",argbBack, "UPtr*",pBrush)
if (!pBrush)
msgbox(A_ThisFunc)
return this.ptr := pBrush
}
GdipCloneBrush() {
dllcall("gdiplus\GdipCloneBrush", "UPtr",this.ptr, "UPtr*",pBrushClone)
return pBrushClone
}
SetColor(argb) {
dllcall("gdiplus\GdipSetSolidFillColor", "UPtr",this.ptr, "uint",argb)
}
getColor() {
dllcall("gdiplus\GdipSetSolidFillColor", "UPtr",this.ptr, "uint*",argb)
return argb
}
}
;ff
class GDIP_Font extends _GDIP {
ptr := 0
;oInstance
; oDC
; oFontFamily
; sFont
__new(oInstance:="Arial", size:=12) {
if isobject(oInstance) {
if (oInstance.__class == "GDIP_Graphics")
res := dllcall("gdiplus\GdipCreateFontFromDC", "UPtr",oInstance.hDC, "UPtr*",pFont)
else if (oInstance.__class == "GDIP_FontFamily")
this.GdipCreateFont(oInstance.ptr, size)
} else { ;字体名称
oFontFamily := new GDIP_FontFamily(oInstance)
this.GdipCreateFont(oFontFamily.ptr, size)
oFontFamily := ""
}
if res
msgbox(A_ThisFunc)
}
__delete() {
dllcall("gdiplus\GdipDeleteFont", "UPtr",this.ptr)
}
; Regular = 0
; Bold = 1
; Italic = 2
; BoldItalic = 3
; Underline = 4
; Strikeout = 8
GdipCreateFont(pFontFamily, size, style:=0) {
res := dllcall("gdiplus\GdipCreateFont", "UPtr",pFontFamily, "float",size, "uint",style, "uint",0, "UPtr*",pFont)
if res
msgbox(A_ThisFunc)
return this.ptr := pFont
}
}
class GDIP_FontFamily {
__new(sFont) {
; res := dllcall("gdiplus\GdipCreateFontFamilyFromName" , "UPtr",&sFont , "uint",0 , "UPtr*",pFontFamily)
res := dllcall("gdiplus\GdipCreateFontFamilyFromName", "WStr",sFont, "UPtr",0, "UPtr*",pFontFamily )
if !pFontFamily {
msgbox(format("字体{1}不存在", sFont),,0x40000)
exit
}
this.ptr := pFontFamily
}
__delete() {
dllcall( "gdiplus\GdipDeleteFontFamily", "UPtr",this.ptr )
}
}
;ss
;文字在框中的对齐方式
class GDIP_StringFormat extends _GDIP {
/*
formatFlags: Defines some settings of the _StringFormat object
typedef enum {
StringFormatFlagsDirectionRightToLeft = 0x0001,
StringFormatFlagsDirectionVertical = 0x0002,
StringFormatFlagsNoFitBlackBox = 0x0004,
StringFormatFlagsDisplayFormatControl = 0x0020,
StringFormatFlagsNoFontFallback = 0x0400,
StringFormatFlagsMeasureTrailingSpaces = 0x0800,
StringFormatFlagsNoWrap = 0x1000,
StringFormatFlagsLineLimit = 0x2000,
StringFormatFlagsNoClip = 0x4000
} StringFormatFlags;
langId: Defines the language this _StringFormat object should use.
I don't actually know any besides 0 which is LANG_NEUTRAL and represents the users language - further research is necessary.
*/
__new(formatFlags:=0, langId:=0) {
this.GdipCreateStringFormat(formatFlags, langId)
}
__delete() {
dllcall("gdiplus\GdipDeleteStringFormat", "UPtr",this.ptr)
}
GdipCreateStringFormat(formatFlags, langId) {
res := dllcall("gdiplus\GdipCreateStringFormat", "uint",formatFlags, "UShort",langId, "UPtr*",pStringFormat)
if res
msgbox(A_ThisFunc)
this.ptr := pStringFormat
}
; Near = 0
; Center = 1
; Far = 2
GdipSetStringFormatAlign(align:=1) {
return dllcall("gdiplus\GdipSetStringFormatAlign", "UPtr",this.ptr, "int",align)
}
}