Multi GUI Image Refresh?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Olek1
Posts: 1
Joined: 19 Feb 2018, 19:44

Multi GUI Image Refresh?

19 Feb 2018, 22:01

I am trying to find out how to refresh a gui that uses a single updating image source. I am trying to display an updating image to an area of my screen. The image file has the same name and path but is overwritten about every 10-30ms. I got a working result with splash image as it would constantly refresh, but I could not display more than one splash image at once so I would get a flashy/stuttering image output. With the current code I have 2 guis that are in the same position but are alternately activated every 100ms when I press the "alt" key. I was hoping to get a "moving image" from the 2 guis because the image will be changing, but instead it displays an old image it was initialized with. I'm wondering if there is something that I can use to get the same effect as a moving image from 1 updating image source that is smooth and not flashy like with Splash image. I can technically save the image output as a different file each time, but then I worry about synchronization and disk space.
Code Below

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

Gui, g1: New
Gui, g1:Add, Picture, w900 h-1, C:\Users\user1\Desktop\Buff.jpg
Gui, g2:Add, Picture, w900 h-1, C:\Users\user1\Desktop\Buff.jpg

while (0 == 0){

GetKeyState, state, Alt
if state = D
{

Gui, g1:Show
Sleep, 100
Gui, g2:Show
Sleep, 100

}
}
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Multi GUI Image Refresh?

20 Feb 2018, 08:14

Code: Select all

SetTimer, iRefresh, % 1000 * 0.5   ; check ever 500ms
Return

iRefresh:
   GuiControl,, Image, C:\Users\user1\Desktop\Buff.jpg   ; for the Gui Picture control a variable parameter has to be set accordingly ("vImage")!
   Return
Not tested.
User avatar
noname
Posts: 515
Joined: 19 Nov 2013, 09:15

Re: Multi GUI Image Refresh?

20 Feb 2018, 12:35

If you want to fast update images without flickering you will need to draw direct on the device context .

code from Skan : https://autohotkey.com/board/topic/7344 ... e-flicker/

example without resizing the original image ( i would use Tic's Gdip library if resizing was needed)

Code: Select all

#SingleInstance, Force
SetWorkingDir %A_ScriptDir%


Gui +AlwaysOnTop +hwnd
Gui, Add, Picture, 0xE hwndhPic
Gui, Show,w350 h350
SetTimer, UpdateDisplay, 100
Return

UpdateDisplay:
while getkeystate("Alt","D"){
sfile=C:\Users\user1\Desktop\Buff.jpg
hBM := DllCall( "LoadImage", UInt,0, Str,sFile, UInt,0, Int,0, Int,0, UInt,0x2010 )
GDI_SetImageX( hBM, hPic)
sleep 100
}
Return


GuiClose:
GuiEscape:
ExitApp

GDI_SetImageX( hBM, hCtrl ) { ; By SKAN Created 10-Nov-2011
 ; SetImage without flicker :       www.autohotkey.com/forum/viewtopic.php?p=488784#488784
 hdcSrc  := DllCall( "CreateCompatibleDC", UInt,0 )
 hdcDst  := DllCall( "GetDC", UInt,hCtrl )
 VarSetCapacity( bm,24,0 ) ; BITMAP Structure
 DllCall( "GetObject", UInt,hbm, UInt,24, UInt,&bm )
 w := Numget( bm,4 ), h := Numget( bm,8 )
 hbmOld  := DllCall( "SelectObject", UInt,hdcSrc, UInt,hBM )
 hbmNew  := DllCall( "CreateBitmap", Int,w, Int,h, UInt,NumGet( bm,16,"UShort" )
                    , UInt,NumGet( bm,18,"UShort" ), Int,0 )
 hbmOld2 := DllCall( "SelectObject", UInt,hdcDst, UInt,hbmNew )
 DllCall( "BitBlt", UInt,hdcDst, Int,0, Int,0, Int,w, Int,h
                  , UInt,hdcSrc, Int,0, Int,0, UInt,0x00CC0020 )
 DllCall( "SelectObject", UInt,hdcSrc, UInt,hbmOld )
 DllCall( "DeleteDC",  UInt,hdcSrc ),   DllCall( "ReleaseDC", UInt,hCtrl, UInt,hdcDst )
 DllCall( "SendMessage", UInt,hCtrl, UInt,0x0B, UInt,0, UInt,0 )        ; WM_SETREDRAW OFF
 oBM := DllCall( "SendMessage", UInt,hCtrl, UInt,0x172, UInt,0, UInt,hBM ) ; STM_SETIMAGE
 DllCall( "SendMessage", UInt,hCtrl, UInt,0x0B, UInt,1, UInt,0 )        ; WM_SETREDRAW ON
 DllCall( "DeleteObject", UInt,oBM )
}
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Multi GUI Image Refresh?

21 Feb 2018, 06:14

noname wrote:If you want to fast update images without flickering you will need to draw direct on the device context .

code from Skan : https://autohotkey.com/board/topic/7344 ... e-flicker/

example without resizing the original image ( i would use Tic's Gdip library if resizing was needed)
Using your script I wasn't able to load/draw an image successfully within that GUI. Any idea? Filetype?? :shifty:
User avatar
noname
Posts: 515
Joined: 19 Nov 2013, 09:15

Re: Multi GUI Image Refresh?

21 Feb 2018, 07:50

You are absolutely right BoBo it only works with bmp filetypes , by coincidence i used a bmp to test it ......... :oops:

Using gdip you can use other filetypes but it makes a lot more code or you need to include Tic's gdip library.But i think it is worthwhile apart from using layered windows it is the only way i know of having flicker free rapid updates of images in standard GUI.

example with relevant part of Gdip_all library included , hope i did not mess up something else :?

Code: Select all


pToken := Gdip_Startup()

sfile=%A_ScriptDir%\demo.jpg

pBitmap := Gdip_CreateBitmapFromFile(sfile)
Gdip_GetImageDimensions(pBitmap, w,h)
Gdip_DisposeImage(pBitmap)

hbm := CreateDIBSection(w,h)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)


Gui, 1: Add, Picture, w%w% h%h% 0xE hwndpic
Gui, 1: Show, AutoSize, Example
ddc := GetDC(pic)
SetTimer, Update, 50
return

Update:
while getkeystate("Alt","D"){
Gdip_DrawImage(G, pBitmap := Gdip_CreateBitmapFromFile(sfile)) 
BitBlt(ddc, 0, 0, w, h, hdc, 0, 0)
Gdip_DisposeImage(pBitmap)
sleep 50
}
Return

GuiClose:
GuiEscape:
ExitApp



Gdip_Startup()
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	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)
	return pToken
}
Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize="")
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	, PtrA := A_PtrSize ? "UPtr*" : "UInt*"
	
	SplitPath, sFile,,, ext
	if ext in exe,dll
	{
		Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16
		BufSize := 16 + (2*(A_PtrSize ? A_PtrSize : 4))
		
		VarSetCapacity(buf, BufSize, 0)
		Loop, Parse, Sizes, |
		{
			DllCall("PrivateExtractIcons", "str", sFile, "int", IconNumber-1, "int", A_LoopField, "int", A_LoopField, PtrA, hIcon, PtrA, 0, "uint", 1, "uint", 0)
			
			if !hIcon
				continue

			if !DllCall("GetIconInfo", Ptr, hIcon, Ptr, &buf)
			{
				DestroyIcon(hIcon)
				continue
			}
			
			hbmMask  := NumGet(buf, 12 + ((A_PtrSize ? 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 !hIcon
			return -1

		Width := NumGet(buf, 4, "int"), Height := NumGet(buf, 8, "int")
		hbm := CreateDIBSection(Width, -Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
		if !DllCall("DrawIconEx", Ptr, hdc, "int", 0, "int", 0, Ptr, hIcon, "uint", Width, "uint", Height, "uint", 0, Ptr, 0, "uint", 3)
		{
			DestroyIcon(hIcon)
			return -2
		}
		
		VarSetCapacity(dib, 104)
		DllCall("GetObject", Ptr, hbm, "int", A_PtrSize = 8 ? 104 : 84, Ptr, &dib) ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize
		Stride := NumGet(dib, 12, "Int"), Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0)) ; padding
		DllCall("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)
		}
		else
			DllCall("gdiplus\GdipCreateBitmapFromFile", Ptr, &sFile, PtrA, pBitmap)
	}
	
	return pBitmap
}
DestroyIcon(hIcon)
{
	return DllCall("DestroyIcon", A_PtrSize ? "UPtr" : "UInt", hIcon)
}
CreateDIBSection(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 !hdc
		ReleaseDC(hdc2)
	return hbm
}
GetDC(hwnd=0)
{
	return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}
ReleaseDC(hdc, hwnd=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}
CreateCompatibleDC(hdc=0)
{
   return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
SelectObject(hdc, hgdiobj)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}
Gdip_CreateBitmap(Width, Height, Format=0x26200A)
{
    DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", 0, "int", Format, A_PtrSize ? "UPtr" : "UInt", 0, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
    Return pBitmap
}
Gdip_GraphicsFromImage(pBitmap)
{
	DllCall("gdiplus\GdipGetImageGraphicsContext", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)
	return pGraphics
}
Gdip_DrawImage(pGraphics, pBitmap, dx="", dy="", dw="", dh="", sx="", sy="", sw="", sh="", Matrix=1)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if (Matrix&1 = "")
		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 := 0
			sw := dw := Gdip_GetImageWidth(pBitmap)
			sh := dh := Gdip_GetImageHeight(pBitmap)
		}
		else
		{
			sx := sy := 0
			sw := 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
				, Ptr, 0
				, Ptr, 0)
	if ImageAttr
		Gdip_DisposeImageAttributes(ImageAttr)
	return E
}
Gdip_SetImageAttributesColorMatrix(Matrix)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	VarSetCapacity(ColourMatrix, 100, 0)
	Matrix := RegExReplace(RegExReplace(Matrix, "^[^\d-\.]+([\d\.])", "$1", "", 1), "[^\d-\.]+", "|")
	StringSplit, Matrix, Matrix, |
	Loop, 25
	{
		Matrix := (Matrix%A_Index% != "") ? Matrix%A_Index% : Mod(A_Index-1, 6) ? 0 : 1
		NumPut(Matrix, 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
}
Gdip_GetImageWidth(pBitmap)
{
   DllCall("gdiplus\GdipGetImageWidth", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Width)
   return Width
}
Gdip_GetImageHeight(pBitmap)
{
   DllCall("gdiplus\GdipGetImageHeight", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Height)
   return Height
}
Gdip_DisposeImageAttributes(ImageAttr)
{
	return DllCall("gdiplus\GdipDisposeImageAttributes", A_PtrSize ? "UPtr" : "UInt", ImageAttr)
}
DeleteObject(hObject)
{
   return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
}
DeleteDC(hdc)
{
   return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
Gdip_DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}
Gdip_DisposeImage(pBitmap)
{
   return DllCall("gdiplus\GdipDisposeImage", A_PtrSize ? "UPtr" : "UInt", pBitmap)
}
Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	DllCall("gdiplus\GdipGetImageWidth", Ptr, pBitmap, "uint*", Width)
	DllCall("gdiplus\GdipGetImageHeight", Ptr, pBitmap, "uint*", Height)
}
Gdip_GraphicsFromHDC(hdc)
{
    DllCall("gdiplus\GdipCreateFromHDC", A_PtrSize ? "UPtr" : "UInt", hdc, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)
    return pGraphics
}
BitBlt(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)
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], Rohwedder and 337 guests