GDI+ Gui Pic Issue Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
TheDewd
Posts: 1513
Joined: 19 Dec 2013, 11:16
Location: USA

GDI+ Gui Pic Issue

27 Mar 2024, 14:40

I have some sample code below to help illustrate the problem I am currently facing.

I'm using GDI+ to draw to an empty picture control within my Gui.

It successfully updates the background color of the image to GREEN, however if I resize the Gui, move it off & on the screen, minimize/restore, etc it will go back to BLACK.

Any suggestions on how to keep the update from disappearing?

I'm thinking I need SendMessage or something like that...

Code: Select all

#SingleInstance Force
Persistent

If (!DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")) { ; Load GDI+ module
	Throw Error("Failed to load Gdiplus library")
}

GdiplusStartupInput := Buffer(A_PtrSize = 8 ? 24 : 16, 0) ; GdiplusStartupInput structure
NumPut("UInt", 1, GdiplusStartupInput) ; GdiplusVersion
DllCall("Gdiplus.dll\GdiplusStartup", "UPtr*", &pToken := 0, "UPtr", GdiplusStartupInput.Ptr, "UPtr", 0) ; Initialize GDI+

If (!pToken) {
	Throw Error("Failed to start Gdiplus")
}

; Create a Bitmap object
DllCall("Gdiplus.dll\GdipCreateBitmapFromScan0", "Int", 640, "Int", 480, "Int", 0, "Int", 0x26200A, "UPtr", 0, "UPtr*", &pBackgroundImage := 0)

; Create a Graphics object associated with pBackgroundImage
DllCall("Gdiplus.dll\GdipGetImageGraphicsContext", "UPtr", pBackgroundImage, "UPtr*", &pBackgroundGraphics := 0)

MyGui := Gui()

MyGui.MarginX := 0
MyGui.MarginY := 0

MyGui.Opt("+LastFound +DPIScale +Resize")
MyGui.Title := "Example"
MyGui.Name := "Example"
MyGui.BackColor := "000000"

hBackground := MyGui.Add("Picture", "x0 y0 w640 h480 +0xE")

; Get pointer to control graphics image
DllCall("Gdiplus.dll\GdipCreateFromHWND", "UPtr", hBackground.Hwnd, "UPtr*", &pControlGraphics := 0)

MyGui.Show("w640 h480")

DllCall("Gdiplus.dll\GdipGraphicsClear", "UPtr", pBackgroundGraphics, "Int", 0xFF00FF00)
DllCall("Gdiplus.dll\GdipDrawImage", "UPtr", pControlGraphics, "UPtr", pBackgroundImage, "Float", 0, "Float", 0)

return ; End automatic execution

F5::Reload
teadrinker
Posts: 4333
Joined: 29 Mar 2015, 09:41
Contact:

Re: GDI+ Gui Pic Issue  Topic is solved

27 Mar 2024, 17:27

It could be like this:

Code: Select all

#Requires AutoHotkey v2

wnd := Gui('Resize')
wnd.MarginX := wnd.MarginY := 0
wnd.AddPicture(, 'HBITMAP: ' . CreateBitmap(300, 300, 0xFFFFAA00))
wnd.Show()

CreateBitmap(w, h, colorARGB) {
    #DllLoad Gdiplus
    static PixelFormat32bppARGB := 0x26200A
    NumPut('Int', 1, GdiplusStartupInput := Buffer(8 + A_PtrSize * 2, 0))
    DllCall('Gdiplus\GdiplusStartup', 'Ptr*', &pToken := 0, 'Ptr', GdiplusStartupInput, 'Ptr', 0)
    DllCall('Gdiplus\GdipCreateBitmapFromScan0', 'Int', w, 'Int', h, 'Int', 0, 'Int', PixelFormat32bppARGB, 'Ptr', 0, 'Ptr*', &pBitmap := 0)
    DllCall('Gdiplus\GdipGetImageGraphicsContext', 'Ptr', pBitmap, 'Ptr*', &pGraphics := 0)
    DllCall('Gdiplus\GdipGraphicsClear', 'Ptr', pGraphics, 'UInt', colorARGB)
    DllCall('Gdiplus\GdipCreateHBITMAPFromBitmap', 'Ptr', pBitmap, 'Ptr*', &hBitmap := 0, 'Int', 0xFFFFFFFF)
    DllCall('Gdiplus\GdipDeleteGraphics', 'Ptr', pGraphics)
    DllCall('Gdiplus\GdipDisposeImage', 'Ptr', pBitmap)
    DllCall('Gdiplus\GdiplusShutdown', 'Ptr', pToken)
    return hBitmap
}
User avatar
TheDewd
Posts: 1513
Joined: 19 Dec 2013, 11:16
Location: USA

Re: GDI+ Gui Pic Issue

28 Mar 2024, 10:45

@teadrinker,

That's exactly what I needed! Thank you!

I've fully commented the example code below for anyone else that find themselves with a similar question.

Code: Select all

; Prevent multiple instances of script from running
#SingleInstance Force

; Prevent script from exiting automatically
Persistent True

; Load GDI+ module
hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")

; GdiplusStartupInput structure
GdiplusStartupInput := Buffer(A_PtrSize = 8 ? 24 : 16, 0)

; GdiplusVersion
NumPut("UInt", 1, GdiplusStartupInput)

; Initialize GDI+
DllCall("Gdiplus.dll\GdiplusStartup", "UPtr*", &pToken := 0, "UPtr", GdiplusStartupInput.Ptr, "UPtr", 0)

; Create new window
oGui := Gui()

; Set options for window
oGui.Opt("+LastFound +DPIScale -Resize")

; Set title of window
oGui.Title := "Example"

; Set background color of window
oGui.BackColor := "000000"

; Set horizontal margins of window
oGui.MarginX := 0

; Set vertical margins of window
oGui.MarginY := 0

; Create picture control
hCanvas := oGui.Add("Picture", "x0 y0 w640 h480 +0xE") ; SS_BITMAP

; Show window
oGui.Show("w640 h480")

; Create Bitmap object
DllCall("Gdiplus.dll\GdipCreateBitmapFromScan0", "Int", 640, "Int", 480, "Int", 0, "Int", 0x26200A, "UPtr", 0, "UPtr*", &pBitmap := 0)

; Create Graphics object associated with Bitmap object
DllCall("Gdiplus.dll\GdipGetImageGraphicsContext", "UPtr", pBitmap, "UPtr*", &pGraphics := 0)

; Set rendering quality of Graphics object
DllCall("Gdiplus.dll\GdipSetSmoothingMode", "UPtr", pGraphics, "Int", 3) ; None

; Set interpolation mode of Graphics object
DllCall("Gdiplus.dll\GdipSetInterpolationMode", "UPtr", pGraphics, "Int", 5) ; NearestNeighbor

; Clear Graphics object to specified color
DllCall("Gdiplus.dll\GdipGraphicsClear", "UPtr", pGraphics, "Int", 0xFF00FF00)

; Create GDI bitmap from Bitmap object
DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "UPtr", pBitmap, "UPtr*", &hBitmap := 0, "Int", 0xFFFFFFFF)

; Delete Graphics object
DllCall("Gdiplus.dll\GdipDeleteGraphics", "UPtr", pGraphics)

; Release resources used by Image object
DllCall("Gdiplus.dll\GdipDisposeImage", "UPtr", pBitmap)

; Clean up resources used by GDI+
DllCall("Gdiplus.dll\GdiplusShutdown", "UPtr", pToken)

; Free module from memory
DllCall("Kernel32.dll\FreeLibrary", "UPtr", hGdip)

; Update picture control
hCanvas.Value := "HBITMAP: " hBitmap
just me
Posts: 9466
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GDI+ Gui Pic Issue

29 Mar 2024, 04:52

Hi @TheDewd,

if you only want to set one RGB color as a static control's (Text/Pic) background, the following will do it in v2:

Code: Select all

; Create picture control
hCanvas := oGui.Add("Picture", "x0 y0 w640 h480 +0xE +Background00FF00") ; SS_BITMAP
If you want a uni-colored bitmap you can try this code by SKAN (on Win 8 and later).
User avatar
TheDewd
Posts: 1513
Joined: 19 Dec 2013, 11:16
Location: USA

Re: GDI+ Gui Pic Issue

29 Mar 2024, 07:59

@just me
Thanks! That's good information to know.

The code was just a demonstration. I'm actually recreating my sokoban game in v2, but I'm reworking everything to be better this time around. I will be drawing images to the picture control -- not doing a single one-time background color update. :-) I just wanted to get an understanding of how to do the update first. Now I know what I need.
teadrinker
Posts: 4333
Joined: 29 Mar 2015, 09:41
Contact:

Re: GDI+ Gui Pic Issue

29 Mar 2024, 11:42

I too assumed that in a real BITMAP example, it would be more complicated. :)
just me wrote: SS_BITMAP
No, it's not necessary in this case:

Code: Select all

wnd := Gui()
wnd.MarginX := wnd.MarginY := 0
wnd.AddText('w300 h200 BackgroundFF8100')
wnd.AddPicture('yp wp hp Background057D9F')
wnd.Show()
just me
Posts: 9466
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GDI+ Gui Pic Issue

29 Mar 2024, 17:48

teadrinker wrote:No, it's not necessary in this case:
I know.

TheDewd wrote:
28 Mar 2024, 10:45

Code: Select all

...
; Create picture control
hCanvas := oGui.Add("Picture", "x0 y0 w640 h480 +0xE") ; SS_BITMAP
...

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: Dav22, Draken, Google [Bot], loek6000, vmech and 95 guests