Понял, как применить CachedBitmap к обычному окну, но разницы не ощутил. Основное время в данном случае занимает отрисовка контрола через
GuiControl,, % hPic, HBITMAP: %hBitmap%
Вот первоначальный вариант с добавленным позиционированием множества контролов:
#NoEnv
SetBatchLines, -1
filePath := "D:\OneDrive\Scripts\GDI+\Gif\gif files\girl.gif"
AnimateGif.Gifs := {}
exStyles := (WS_EX_COMPOSITED := 0x02000000) | (WS_EX_LAYERED := 0x80000)
Gui, New, +E%exStyles%
Gui, Margin, 5, 5
GuiW := 12 + 5 ; borders + margin
Loop 20 {
if (A_Index > 1) {
GuiW += W + 5
if (GuiW < A_ScreenWidth)
x := "x+5", y := "yp"
else
x := "xm", y := "y+5", GuiW := 12 + 5 + W
}
Gui, Add, Pic, % "hwndhGif" . A_Index . " " . (A_Index = 1 ? "" : x . " " . y), % "HBITMAP:" . LoadPicture(filePath, "GDI+")
if (A_Index = 1) {
WinGetPos,,, W,, % "ahk_id" hGif%A_Index%
GuiW += W
}
handler := Func("OnClick").Bind(hGif%A_Index%)
GuiControl, +g, % hGif%A_Index%, % handler
AnimateGif.Gifs[hGif%A_Index%] := new AnimateGif(filePath, Func("PlayGif").Bind(hGif%A_Index%))
AnimateGif.Gifs[hGif%A_Index%].Play()
}
OnMessage(0x20, "WM_SETCURSOR")
Gui, Show
Return
GuiClose:
AnimateGif.Gifs := ""
ExitApp
PlayGif(hPic, currentFrameIdx, hBitmap) {
GuiControl,, % hPic, HBITMAP: %hBitmap%
}
OnClick(hPic) {
if AnimateGif.Gifs[hPic].playing
AnimateGif.Gifs[hPic].Pause()
Else
AnimateGif.Gifs[hPic].Play()
}
WM_SETCURSOR(wp) {
static hCursor, flags := (LR_DEFAULTSIZE := 0x40) | (LR_SHARED := 0x8000)
, params := [ "Ptr", 0, "UInt", OCR_HAND := 32649
, "UInt", IMAGE_CURSOR := 2
, "Int", 0, "Int", 0, "UInt", flags, "Ptr" ]
(!hCursor && hCursor := DllCall("LoadImage", params*))
if AnimateGif.Gifs.HasKey(wp)
Return DllCall("SetCursor", "Ptr", hCursor)
}
class AnimateGif
{
__New(gifFile, UserFunc := "", cycle := true) {
this.GDIp := new GDIplus
this.pBitmap := this.GDIp.CreateBitmapFromFile(gifFile)
this.Frames := new this._FramesHandling(this.GDIp, this.pBitmap, UserFunc, cycle)
this.GDIp.GetImageDimensions(this.pBitmap, width, height)
this.width := width
this.height := height
}
Play() { ; UserFunc will be called with two params: currentFrameIdx and hBitmap
this.playing := true ; user is responsible for deleting hBitmap
this.Frames.PlayFrames()
}
Pause() {
if this.playing {
this.playing := false
timer := this.Frames._PlayTimer
SetTimer, % timer, Delete
}
}
Stop() {
this.Pause()
this.ShowFrame(1)
}
Prev() {
this.ShowFrame("prev")
}
Next() {
this.ShowFrame("next")
}
ShowFrame(which) { ; 'which' can be "prev", "next" or "", or 1-based frame index
this.Pause()
(which = "prev" && this.Frames.currentFrame -= 2)
(which + 0 && this.Frames.currentFrame := which - 1)
this.Frames.PlayFrames()
}
GetFrameByIndex(idx) {
Return hBitmap := this.Frames.GetFrame(idx - 1)
}
playing[] {
get {
Return this.Frames.playing
}
set {
Return this.Frames.playing := value
}
}
framesCount[] {
get {
Return this.Frames.frameCount
}
}
__Delete() {
this.Frames.Clear()
this.GDIp.DisposeImage(this.pBitmap)
this.Delete("Frames")
this.GDIp.Release()
}
class _FramesHandling {
__New(GDIp, pBitmap, userFunc, cycle) {
this.GDIp := GDIp
this.pBitmap := pBitmap
this.userFunc := userFunc
this.cycle := cycle
this.GetFrameCount()
this.GetFrameDelay()
this._PlayTimer := ObjBindMethod(this, "PlayFrames")
this._currentFrame := 1
}
currentFrame[] {
get {
Return this._currentFrame
}
set {
Return this._currentFrame := value < 1 ? this.frameCount + value : value > this.frameCount ? 1 : value
}
}
PlayFrames() {
Critical
frameIdx := ++this.currentFrame - 1
if ( this.playing && this.currentFrame != (this.cycle ? 0xFFFFFFFF : this.frameCount) ) {
timer := this._PlayTimer
SetTimer, % timer, % "-" this.frameDelay[frameIdx]
}
if userFunc := this.userFunc
%userFunc%(this.currentFrame, this.GetFrame(frameIdx))
}
GetFrameCount() {
this.frameCount := this.GDIp.GetFrameCount(this.pBitmap, dimensionIDs, size)
this.SetCapacity("dimensionIDs", size)
this.pDimensionIDs := this.GetAddress("dimensionIDs")
DllCall("RtlMoveMemory", "Ptr", this.pDimensionIDs, "Ptr", &dimensionIDs, "Ptr", size)
VarSetCapacity(dimensionIDs, 0), dimensionIDs := ""
this.currentFrame := 0
}
GetFrameDelay() {
this.GDIp.GetPropertyItem(this.pBitmap, PropertyTagFrameDelay := 0x5100, item)
len := NumGet(item, 4, "UInt")
val := NumGet(item, 8 + A_PtrSize, "UPtr")
this.frameDelay := []
Loop, % len//4 {
i := A_Index - 1
n := NumGet(val + i*4, "UInt") * 10
this.frameDelay[i] := n ? n : 100
}
}
GetFrame(idx) {
this.GDIp.ImageSelectActiveFrame(this.pBitmap, this.pDimensionIDs, idx)
Return this.GDIp.CreateHBITMAPFromBitmap(this.pBitmap)
}
Clear() {
this.playing := false
timer := this._PlayTimer
SetTimer, % timer, Delete
this.Delete("dimensionIDs")
}
}
}
class GDIplus {
__New() {
static Instance := ""
if Instance.references {
++Instance.references
Return Instance
}
this.references := 1
if !DllCall("GetModuleHandle", "Str", "gdiplus", "Ptr")
DllCall("LoadLibrary", "Str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "UPtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
Return Instance := this
}
Release() {
if --this.references
Return
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
if hModule := DllCall("GetModuleHandle", "Str", "gdiplus", "Ptr")
DllCall("FreeLibrary", "Ptr", hModule)
}
CreateBitmapFromFile(sFile) {
DllCall("gdiplus\GdipCreateBitmapFromFile", "WStr", sFile, "PtrP", pBitmap)
Return pBitmap
}
CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff) {
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hbm, "Int", Background)
Return hbm
}
GetImageDimensions(pBitmap, ByRef Width, ByRef Height) {
DllCall("gdiplus\GdipGetImageWidth", "Ptr", pBitmap, "UIntP", Width)
DllCall("gdiplus\GdipGetImageHeight", "Ptr", pBitmap, "UIntP", Height)
}
GetFrameCount(pBitmap, ByRef dimensionIDs, ByRef size) {
DllCall("gdiplus\GdipImageGetFrameDimensionsCount", "Ptr", pBitmap, "UIntP", frameDimensions)
VarSetCapacity(dimensionIDs, size := 16*frameDimensions)
DllCall("gdiplus\GdipImageGetFrameDimensionsList", "Ptr", pBitmap, "Ptr", &dimensionIDs, "UInt", frameDimensions)
DllCall("gdiplus\GdipImageGetFrameCount", "Ptr", pBitmap, "Ptr", &dimensionIDs, "UIntP", count)
Return count
}
GetPropertyItem(pBitmap, tag, ByRef item) {
DllCall("gdiplus\GdipGetPropertyItemSize", "Ptr", pBitmap, "UInt", tag, "UIntP", size)
VarSetCapacity(item, size, 0)
DllCall("gdiplus\GdipGetPropertyItem", "Ptr", pBitmap, "UInt", tag, "UInt", size, "Ptr", &item)
Return size
}
ImageSelectActiveFrame(pBitmap, pDimensionIDs, idx) {
Return DllCall("gdiplus\GdipImageSelectActiveFrame", "Ptr", pBitmap, "Ptr", pDimensionIDs, "Int", idx)
}
DisposeImage(pBitmap) {
Return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}
}
Вот с CachedBitmap:
#NoEnv
SetBatchLines, -1
filePath := "D:\OneDrive\Scripts\GDI+\Gif\gif files\girl.gif"
AnimateGif.Gifs := {}
exStyles := (WS_EX_COMPOSITED := 0x02000000) | (WS_EX_LAYERED := 0x80000)
Gui, New, +E%exStyles%
Gui, Margin, 5, 5
GuiW := 12 + 5 ; borders + margin
Loop 20 {
if (A_Index > 1) {
GuiW += W + 5
if (GuiW < A_ScreenWidth)
x := "x+5", y := "yp"
else
x := "xm", y := "y+5", GuiW := 12 + 5 + W
}
Gui, Add, Pic, % "hwndhGif" . A_Index . " " . (A_Index = 1 ? "" : x . " " . y), % "HBITMAP:" . LoadPicture(filePath, "GDI+")
if (A_Index = 1) {
WinGetPos,,, W,, % "ahk_id" hGif%A_Index%
GuiW += W
}
handler := Func("OnClick").Bind(hGif%A_Index%)
GuiControl, +g, % hGif%A_Index%, % handler
AnimateGif.Gifs[hGif%A_Index%] := new AnimateGif(filePath, Func("PlayGif").Bind(hGif%A_Index%))
AnimateGif.Gifs[hGif%A_Index%].Play()
}
OnMessage(0x20, "WM_SETCURSOR")
Gui, Show
Return
GuiClose:
AnimateGif.Gifs := ""
ExitApp
PlayGif(hPic, currentFrameIdx, hBitmap) {
GuiControl,, % hPic, HBITMAP: %hBitmap%
}
OnClick(hPic) {
if AnimateGif.Gifs[hPic].playing
AnimateGif.Gifs[hPic].Pause()
Else
AnimateGif.Gifs[hPic].Play()
}
WM_SETCURSOR(wp) {
static hCursor, flags := (LR_DEFAULTSIZE := 0x40) | (LR_SHARED := 0x8000)
, params := [ "Ptr", 0, "UInt", OCR_HAND := 32649
, "UInt", IMAGE_CURSOR := 2
, "Int", 0, "Int", 0, "UInt", flags, "Ptr" ]
(!hCursor && hCursor := DllCall("LoadImage", params*))
if AnimateGif.Gifs.HasKey(wp)
Return DllCall("SetCursor", "Ptr", hCursor)
}
class AnimateGif
{
__New(gifFile, UserFunc := "", cycle := true) {
this.GDIp := new GDIplus
this.pBitmap := this.GDIp.CreateBitmapFromFile(gifFile)
this.GDIp.GetImageDimensions(this.pBitmap, width, height)
this.width := width
this.height := height
this.Frames := new this._FramesHandling(this.GDIp, this.pBitmap, width, height, UserFunc, cycle)
}
Play() { ; UserFunc will be called with two params: currentFrameIdx and hBitmap
this.playing := true ; user is responsible for deleting hBitmap
this.Frames.PlayFrames()
}
Pause() {
if this.playing {
this.playing := false
timer := this.Frames._PlayTimer
SetTimer, % timer, Delete
}
}
Stop() {
this.Pause()
this.ShowFrame(1)
}
Prev() {
this.ShowFrame("prev")
}
Next() {
this.ShowFrame("next")
}
ShowFrame(which) { ; 'which' can be "prev", "next" or "", or 1-based frame index
this.Pause()
(which = "prev" && this.Frames.currentFrame -= 2)
(which + 0 && this.Frames.currentFrame := which - 1)
this.Frames.PlayFrames()
}
GetFrameByIndex(idx) {
Return hBitmap := this.Frames.GetFrame(idx - 1)
}
playing[] {
get {
Return this.Frames.playing
}
set {
Return this.Frames.playing := value
}
}
framesCount[] {
get {
Return this.Frames.frameCount
}
}
__Delete() {
this.Frames.Clear()
this.GDIp.DisposeImage(this.pBitmap)
this.Delete("Frames")
this.GDIp.Release()
}
class _FramesHandling {
__New(GDIp, pBitmap, width, height, userFunc, cycle) {
this.GDIp := GDIp
this.pBitmap := pBitmap
this.hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
this.DC := new CompatibleDC(this.hDC, width, height)
this.G := this.GDIp.GraphicsFromHDC(this.DC.hCDC)
this.userFunc := userFunc
this.cycle := cycle
this.GetFrameCount()
this.GetFrameDelay()
this._PlayTimer := ObjBindMethod(this, "PlayFrames")
this._currentFrame := 1
}
currentFrame[] {
get {
Return this._currentFrame
}
set {
Return this._currentFrame := value < 1 ? this.frameCount + value : value > this.frameCount ? 1 : value
}
}
PlayFrames() {
Critical
frameIdx := ++this.currentFrame - 1
if ( this.playing && this.currentFrame != (this.cycle ? 0xFFFFFFFF : this.frameCount) ) {
timer := this._PlayTimer
SetTimer, % timer, % "-" this.frameDelay[frameIdx]
}
if userFunc := this.userFunc
%userFunc%(this.currentFrame, this.GetFrame(frameIdx))
}
GetFrameCount() {
this.frameCount := this.GDIp.GetFrameCount(this.pBitmap, dimensionIDs, size)
this.SetCapacity("dimensionIDs", size)
this.pDimensionIDs := this.GetAddress("dimensionIDs")
DllCall("RtlMoveMemory", "Ptr", this.pDimensionIDs, "Ptr", &dimensionIDs, "Ptr", size)
VarSetCapacity(dimensionIDs, 0), dimensionIDs := ""
this.currentFrame := 0
}
GetFrameDelay() {
this.GDIp.GetPropertyItem(this.pBitmap, PropertyTagFrameDelay := 0x5100, item)
len := NumGet(item, 4, "UInt")
val := NumGet(item, 8 + A_PtrSize, "UPtr")
this.frameDelay := []
Loop, % len//4 {
i := A_Index - 1
n := NumGet(val + i*4, "UInt") * 10
this.frameDelay[i] := n ? n : 100
}
}
GetFrame(idx) {
this.GDIp.ImageSelectActiveFrame(this.pBitmap, this.pDimensionIDs, idx)
DllCall("gdiplus\GdipCreateCachedBitmap", "Ptr", this.pBitmap, "Ptr", this.G, "PtrP", pCachedBitmap)
DllCall("gdiplus\GdipDrawCachedBitmap", "Ptr", this.G, "Ptr", pCachedBitmap, "Int", 0, "Int", 0)
DllCall("gdiplus\GdipDeleteCachedBitmap", "Ptr", pCachedBitmap)
Return this.DC.hCBM
}
Clear() {
this.playing := false
timer := this._PlayTimer
SetTimer, % timer, Delete
this.Delete("dimensionIDs")
this.GDIp.DeleteGraphics(this.G)
this.DC := ""
DllCall("ReleaseDC", this.hDC)
}
}
}
class CompatibleDC
{
__New(hDC, w, h) {
this.hCDC := DllCall("CreateCompatibleDC", Ptr, hDC, Ptr)
this.hCBM := DllCall("CreateCompatibleBitmap", Ptr, hDC, Int, w, Int, h, Ptr)
this.oBM := DllCall("SelectObject", Ptr, this.hCDC, Ptr, this.hCBM, Ptr)
}
__Delete() {
DllCall("SelectObject", Ptr, this.hCDC, Ptr, this.oBM, Ptr)
DllCall("DeleteDC", Ptr, this.hCDC)
DllCall("DeleteObject", Ptr, this.hCBM)
}
}
class GDIplus {
__New() {
static Instance := ""
if Instance.references {
++Instance.references
Return Instance
}
this.references := 1
if !DllCall("GetModuleHandle", "Str", "gdiplus", "Ptr")
DllCall("LoadLibrary", "Str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "UPtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
Return Instance := this
}
Release() {
if --this.references
Return
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
if hModule := DllCall("GetModuleHandle", "Str", "gdiplus", "Ptr")
DllCall("FreeLibrary", "Ptr", hModule)
}
CreateBitmapFromFile(sFile) {
DllCall("gdiplus\GdipCreateBitmapFromFile", "WStr", sFile, "PtrP", pBitmap)
Return pBitmap
}
GraphicsFromHDC(hdc) {
DllCall("gdiplus\GdipCreateFromHDC", "Ptr", hdc, "PtrP", pGraphics)
return pGraphics
}
CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff) {
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hbm, "Int", Background)
Return hbm
}
GetImageDimensions(pBitmap, ByRef Width, ByRef Height) {
DllCall("gdiplus\GdipGetImageWidth", "Ptr", pBitmap, "UIntP", Width)
DllCall("gdiplus\GdipGetImageHeight", "Ptr", pBitmap, "UIntP", Height)
}
GetFrameCount(pBitmap, ByRef dimensionIDs, ByRef size) {
DllCall("gdiplus\GdipImageGetFrameDimensionsCount", "Ptr", pBitmap, "UIntP", frameDimensions)
VarSetCapacity(dimensionIDs, size := 16*frameDimensions)
DllCall("gdiplus\GdipImageGetFrameDimensionsList", "Ptr", pBitmap, "Ptr", &dimensionIDs, "UInt", frameDimensions)
DllCall("gdiplus\GdipImageGetFrameCount", "Ptr", pBitmap, "Ptr", &dimensionIDs, "UIntP", count)
Return count
}
GetPropertyItem(pBitmap, tag, ByRef item) {
DllCall("gdiplus\GdipGetPropertyItemSize", "Ptr", pBitmap, "UInt", tag, "UIntP", size)
VarSetCapacity(item, size, 0)
DllCall("gdiplus\GdipGetPropertyItem", "Ptr", pBitmap, "UInt", tag, "UInt", size, "Ptr", &item)
Return size
}
ImageSelectActiveFrame(pBitmap, pDimensionIDs, idx) {
Return DllCall("gdiplus\GdipImageSelectActiveFrame", "Ptr", pBitmap, "Ptr", pDimensionIDs, "Int", idx)
}
DeleteGraphics(pGraphics) {
return DllCall("gdiplus\GdipDeleteGraphics", "Ptr", pGraphics)
}
DisposeImage(pBitmap) {
Return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}
}
Зато очень шустро рисует GdipDrawImageRectI, но не поддерживает WS_EX_COMPOSITED | WS_EX_LAYERED, и размазывает области с прозрачностью:
#NoEnv
SetBatchLines, -1
filePath := "D:\OneDrive\Scripts\GDI+\Gif\gif files\girl.gif"
AnimateGif.Gifs := {}
; exStyles := (WS_EX_COMPOSITED := 0x02000000) | (WS_EX_LAYERED := 0x80000)
; Gui, New, +E%exStyles%
Gui, Margin, 5, 5
GuiW := 12 + 5 ; borders + margin
Loop 20 {
if (A_Index > 1) {
GuiW += W + 5
if (GuiW < A_ScreenWidth)
x := "x+5", y := "yp"
else
x := "xm", y := "y+5", GuiW := 12 + 5 + W
}
Gui, Add, Pic, % "hwndhGif" . A_Index . " " . (A_Index = 1 ? "" : x . " " . y), % "HBITMAP:" . LoadPicture(filePath, "GDI+")
if (A_Index = 1) {
WinGetPos,,, W,, % "ahk_id" hGif%A_Index%
GuiW += W
}
handler := Func("OnClick").Bind(hGif%A_Index%)
GuiControl, +g, % hGif%A_Index%, % handler
AnimateGif.Gifs[hGif%A_Index%] := new AnimateGif(filePath, hGif%A_Index%)
AnimateGif.Gifs[hGif%A_Index%].Play()
}
OnMessage(0x20, "WM_SETCURSOR")
Gui, Show
Return
GuiClose:
AnimateGif.Gifs := ""
ExitApp
OnClick(hPic) {
if AnimateGif.Gifs[hPic].playing
AnimateGif.Gifs[hPic].Pause()
Else
AnimateGif.Gifs[hPic].Play()
}
WM_SETCURSOR(wp) {
static hCursor, flags := (LR_DEFAULTSIZE := 0x40) | (LR_SHARED := 0x8000)
, params := [ "Ptr", 0, "UInt", OCR_HAND := 32649
, "UInt", IMAGE_CURSOR := 2
, "Int", 0, "Int", 0, "UInt", flags, "Ptr" ]
(!hCursor && hCursor := DllCall("LoadImage", params*))
if AnimateGif.Gifs.HasKey(wp)
Return DllCall("SetCursor", "Ptr", hCursor)
}
class AnimateGif
{
__New(gifFile, hPic, cycle := true) {
this.GDIp := new GDIplus
this.pBitmap := this.GDIp.CreateBitmapFromFile(gifFile)
this.GDIp.GetImageDimensions(this.pBitmap, width, height)
this.width := width
this.height := height
this.Frames := new this._FramesHandling(this.GDIp, this.pBitmap, hPic, width, height, cycle)
}
Play() {
this.playing := true
this.Frames.PlayFrames()
}
Pause() {
if this.playing {
this.playing := false
timer := this.Frames._PlayTimer
SetTimer, % timer, Delete
}
}
Stop() {
this.Pause()
this.ShowFrame(1)
}
Prev() {
this.ShowFrame("prev")
}
Next() {
this.ShowFrame("next")
}
ShowFrame(which) { ; 'which' can be "prev", "next" or "", or 1-based frame index
this.Pause()
(which = "prev" && this.Frames.currentFrame -= 2)
(which + 0 && this.Frames.currentFrame := which - 1)
this.Frames.PlayFrames()
}
playing[] {
get {
Return this.Frames.playing
}
set {
Return this.Frames.playing := value
}
}
framesCount[] {
get {
Return this.Frames.frameCount
}
}
__Delete() {
this.Frames.Clear()
this.GDIp.DisposeImage(this.pBitmap)
this.Delete("Frames")
this.GDIp.Release()
}
class _FramesHandling {
__New(GDIp, pBitmap, hPic, width, height, cycle) {
this.GDIp := GDIp
this.pBitmap := pBitmap
this.G := this.GDIp.GraphicsFromHwnd(hPic)
this.width := width
this.height := height
this.cycle := cycle
this.GetFrameCount()
this.GetFrameDelay()
this._PlayTimer := ObjBindMethod(this, "PlayFrames")
this._currentFrame := 1
}
currentFrame[] {
get {
Return this._currentFrame
}
set {
Return this._currentFrame := value < 1 ? this.frameCount + value : value > this.frameCount ? 1 : value
}
}
PlayFrames() {
Critical
frameIdx := ++this.currentFrame - 1
if ( this.playing && this.currentFrame != (this.cycle ? 0xFFFFFFFF : this.frameCount) ) {
timer := this._PlayTimer
SetTimer, % timer, % "-" this.frameDelay[frameIdx]
}
this.DrawFrame(frameIdx)
}
GetFrameCount() {
this.frameCount := this.GDIp.GetFrameCount(this.pBitmap, dimensionIDs, size)
this.SetCapacity("dimensionIDs", size)
this.pDimensionIDs := this.GetAddress("dimensionIDs")
DllCall("RtlMoveMemory", "Ptr", this.pDimensionIDs, "Ptr", &dimensionIDs, "Ptr", size)
VarSetCapacity(dimensionIDs, 0), dimensionIDs := ""
this.currentFrame := 0
}
GetFrameDelay() {
this.GDIp.GetPropertyItem(this.pBitmap, PropertyTagFrameDelay := 0x5100, item)
len := NumGet(item, 4, "UInt")
val := NumGet(item, 8 + A_PtrSize, "UPtr")
this.frameDelay := []
Loop, % len//4 {
i := A_Index - 1
n := NumGet(val + i*4, "UInt") * 10
this.frameDelay[i] := n ? n : 100
}
}
DrawFrame(idx) {
this.GDIp.ImageSelectActiveFrame(this.pBitmap, this.pDimensionIDs, idx)
DllCall("gdiplus\GdipDrawImageRectI", "Ptr", this.G, "Ptr", this.pBitmap, "Int", 0, "Int", 0, "Int", this.width, "Int", this.height)
}
Clear() {
this.playing := false
timer := this._PlayTimer
SetTimer, % timer, Delete
this.Delete("dimensionIDs")
this.GDIp.DeleteGraphics(this.G)
}
}
}
class GDIplus {
__New() {
static Instance := ""
if Instance.references {
++Instance.references
Return Instance
}
this.references := 1
if !DllCall("GetModuleHandle", "Str", "gdiplus", "Ptr")
DllCall("LoadLibrary", "Str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "UPtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
Return Instance := this
}
Release() {
if --this.references
Return
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
if hModule := DllCall("GetModuleHandle", "Str", "gdiplus", "Ptr")
DllCall("FreeLibrary", "Ptr", hModule)
}
CreateBitmapFromFile(sFile) {
DllCall("gdiplus\GdipCreateBitmapFromFile", "WStr", sFile, "PtrP", pBitmap)
Return pBitmap
}
CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff) {
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hbm, "Int", Background)
Return hbm
}
GetImageDimensions(pBitmap, ByRef Width, ByRef Height) {
DllCall("gdiplus\GdipGetImageWidth", "Ptr", pBitmap, "UIntP", Width)
DllCall("gdiplus\GdipGetImageHeight", "Ptr", pBitmap, "UIntP", Height)
}
GetFrameCount(pBitmap, ByRef dimensionIDs, ByRef size) {
DllCall("gdiplus\GdipImageGetFrameDimensionsCount", "Ptr", pBitmap, "UIntP", frameDimensions)
VarSetCapacity(dimensionIDs, size := 16*frameDimensions)
DllCall("gdiplus\GdipImageGetFrameDimensionsList", "Ptr", pBitmap, "Ptr", &dimensionIDs, "UInt", frameDimensions)
DllCall("gdiplus\GdipImageGetFrameCount", "Ptr", pBitmap, "Ptr", &dimensionIDs, "UIntP", count)
Return count
}
GetPropertyItem(pBitmap, tag, ByRef item) {
DllCall("gdiplus\GdipGetPropertyItemSize", "Ptr", pBitmap, "UInt", tag, "UIntP", size)
VarSetCapacity(item, size, 0)
DllCall("gdiplus\GdipGetPropertyItem", "Ptr", pBitmap, "UInt", tag, "UInt", size, "Ptr", &item)
Return size
}
ImageSelectActiveFrame(pBitmap, pDimensionIDs, idx) {
Return DllCall("gdiplus\GdipImageSelectActiveFrame", "Ptr", pBitmap, "Ptr", pDimensionIDs, "Int", idx)
}
GraphicsFromHwnd(hwnd) {
DllCall("Gdiplus\GdipCreateFromHWND", "Ptr", hwnd, "PtrP", pGraphics)
Return pGraphics
}
DeleteGraphics(pGraphics) {
return DllCall("gdiplus\GdipDeleteGraphics", "Ptr", pGraphics)
}
DisposeImage(pBitmap) {
Return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}
}
Разработка AHK-скриптов:
e-mail
dfiveg@mail.ruTelegram
jollycoder