I ended up coming up with the correct approach in the shower. Stores a cache of rendered device contexts.
Code: Select all
#Requires AutoHotkey v2.0
#include ImagePut.ahk
image := FileSelect(,, "Select an image:", "Images (*.bmp; *.dib; *.rle; *.jpg; *.jpeg; *.jpe; *.jfif; *.gif; *.emf; *.wmf; *.tif; *.tiff; *.png; *.ico; *.heic; *.hif; *.webp; *avif; *avifs)")
; Make the GUI resizable and not affected by DPI scaling.
app := Gui("-DPIScale +Resize")
; Sets the image filepath as the window title.
app.Title := image
; Create a dummy text control to repurpose for ImagePut's functionality.
display := app.Add("Text", "xm+0")
; Get the width and height.
width := ImageWidth(image)
height := ImageHeight(image)
; Must resize the viewable area of the control.
display.move(,, 9*width, 3*height) ; Note: Extend viewable width by 3!!!
; Use ImagePut to create a child window, and set the parent as the text control.
image_hwnd1 := ImageShow(image,, [0, 0, 3*width, 3*height], 0x40000000 | 0x10000000 | 0x8000000,, display.hwnd, False)
image_hwnd2 := ImageShow(image,, [3*width, 0, 3*width, 3*height], 0x40000000 | 0x10000000 | 0x8000000,, display.hwnd, False)
image_hwnd3 := ImageShow(image,, [6*width, 0, 3*width, 3*height], 0x40000000 | 0x10000000 | 0x8000000,, display.hwnd, False)
; Show the image
app.Show("xCenter y0 AutoSize")
; Some useful functions.
Play(hwnd) => PostMessage(0x8001,,,, hwnd)
Pause(hwnd) => PostMessage(0x8002,,,, hwnd)
Stop(hwnd) => PostMessage(0x8002, 1,,, hwnd)
; Use PostMessage to asynchronously start playback!
Play("ahk_id" image_hwnd1)
Play("ahk_id" image_hwnd2)
Play("ahk_id" image_hwnd3)