Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

GDI+ standard library 1.45 by tic


  • Please log in to reply
1385 replies to this topic
tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Hi jleslie48

If you can please change your images to be a bit smaller to help the loading of each page.

What more do you need to learn? I think tutorial 9 should cover a lot of what you are asking. Let me know if you need anything explaining

Thanks

kenn
  • Members
  • 407 posts
  • Last active: Jan 14 2015 08:16 PM
  • Joined: 11 Oct 2010
I think the most difficult part is to rotate the speedometer needle in the center by slider level. Button switching part looks easy, take a look at this <!-- m -->http://www.autohotke...topic59461.html<!-- m -->
Edit: I think we are hijacking Tic's Scripts & Functions thread, you can open new ask for help thread

jleslie48
  • Members
  • 145 posts
  • Last active: Sep 28 2017 07:13 PM
  • Joined: 29 Jun 2010

Hi jleslie48

If you can please change your images to be a bit smaller to help the loading of each page.

What more do you need to learn? I think tutorial 9 should cover a lot of what you are asking. Let me know if you need anything explaining

Thanks


I thought those were small opps. I've reduced then now down to 300 pixels, I hope that is good enough.

I looked at tutorial 9, I didn't associate that with loading an image. I will try and see if I can figure out how to either merge the image display from tutorial 10 into the internal gui of tutorial 9, or vice versa, take the display controls of the progress bar and use them in tutorial 10. All I can say is that from the perspective of someone new to autohotkey, and gdi, it is not obvious the atomic units of either. In other words, I can't tell what commands are part of setting up the display container (the second gui of tutorial 10 with its associated updatelayeredwindow command, vsi tutorial 9 which uses ~I can't figure it out~ to display some drawing stuff??) vs making up the image of the container.

The point is I deducing that this GDI interface works sorta like this

1) intialize stuff
2) set up a canvas of some type for some kind of graphic.
3) load or make up the graphic,
4) convert it to bitmap.
5) load it onto the canvas
6) at the end dispose of your stuff you used in 3)

I ~think~ that is the basic model of control of your gdi interface. In tutorial 9 you are using a "canvas" that is attached to a gui. In tutorial 10 and most of the others, the "canvas" is some invisible canvas that is always on top. Sometimes I'm able to move this this invisible canvas, sometimes not.

To surmise my ramblings, its this basic workflow that is not clear. I guess that is why I don't see that the tools shown in tutorial 9 apply to my application. From what I can gather from the other comments, this understanding is missing with others as well. I think that GDI is immensely powerful, and IS the best tool out there to get the job done.

- Jon

jleslie48
  • Members
  • 145 posts
  • Last active: Sep 28 2017 07:13 PM
  • Joined: 29 Jun 2010

I think the most difficult part is to rotate the speedometer needle in the center by slider level. Button switching part looks easy, take a look at this <!-- m -->http://www.autohotke...topic59461.html<!-- m -->
Edit: I think we are hijacking Tic's Scripts & Functions thread, you can open new ask for help thread


oh I have both of those solved already. my buttons work, and so does the rotating of the speedometer. you can try it out by downloading the the zip file of the project. I can rotate the speedometer needle just fine, I can't attach it to the gui.

The switches on and off is part of another project right now. It doesn't use gdi at all, but I'd like to redo it with gdi as it can handle png's with transparent colors. I just uploaded it to the directory:

http://jleslie48.com...es/speedometer/ as the zip file "switchbox". It's the ahk file "change_image.ahk". Along with working buttons, it has a working solution to turn on and off the mouse cursor for the gui (I plan on implementing on a touchscreen and I won't want the mouse cursor on for this app) and also a working model for a settings.ini file that remembers where you moved the gui to so that on a restart it starts up in the same location on the screen. If those functionalities are not clear just ask.

kenn
  • Members
  • 407 posts
  • Last active: Jan 14 2015 08:16 PM
  • Joined: 11 Oct 2010
Here is a gui, it can rotate the needle of the speedometer. It needs improvement, I don't know much about GUI, it's my poor attempt.
Note: Needle appears after you move the slider.
speedometer.zip

jleslie48
  • Members
  • 145 posts
  • Last active: Sep 28 2017 07:13 PM
  • Joined: 29 Jun 2010

Here is a gui, it can rotate the needle of the speedometer. I needs improvement, I don't know much about GUI, it's my poor attempt.
Note: Needle appears after you move the slider.
speedometer.zip


I don't see the difference between this and what I supplied. When you move the gui, the needle does not move with it. The needle is centered on the center of the monitor rather than a fixed point in the gui.

kenn
  • Members
  • 407 posts
  • Last active: Jan 14 2015 08:16 PM
  • Joined: 11 Oct 2010
sorry wrong link I posted. Check it out again

jleslie48
  • Members
  • 145 posts
  • Last active: Sep 28 2017 07:13 PM
  • Joined: 29 Jun 2010

sorry wrong link I posted. Check it out again


LOL!!! I'm checking out the RAR file now....


Ok, you've cleaned up the interrface a bit, but the needle is centered on
the center of the monitor rather than a fixed point in the gui. The needle
also doesn't move to the background with the gui, or move with the gui.

kenn
  • Members
  • 407 posts
  • Last active: Jan 14 2015 08:16 PM
  • Joined: 11 Oct 2010
I adjusted it according to my screen resolution, it looks ok in my comp, I ll think about it later.

jleslie48
  • Members
  • 145 posts
  • Last active: Sep 28 2017 07:13 PM
  • Joined: 29 Jun 2010

I adjusted it according to my screen resolution, it looks ok in my comp, I ll think about it later.



the point is, the needle needs to appear based on the gui position and not your screen reslolution. so the needle png file should be set relative the the scripts gui and not relative to the screen. Tutorial 9 does this perfectly with the gdi graphics package, but not with a imported png file. I'm not sure where the boundaries are between the positioning stuff of tutorial 9 and the drawing stuff of tutorial 9.

EiPhone
  • Guests
  • Last active:
  • Joined: --
I posted my problem already in the help section, but since its GDI related and most GDI specialists are here, i though it would be a good idea to bring it up here too. I hope its not rude of me.

To recap my problem:
Im trying to put bitmaps with semitransparency into a 32bit imagelist. The problem is: The bitmap that ends up in the imagelist has messed up colors in the semitransparent pixels. The alpha channel stays intact, but the semitransparent pixels got mixed together with an background color.

Link to the thread with example picture and code:
http://www.autohotke...topic81505.html

I'm sure its releated to
Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)
since the background color can be set there.

Is there a way to keep the original image transparency and color without multiplying it with an background color?

jleslie48
  • Members
  • 145 posts
  • Last active: Sep 28 2017 07:13 PM
  • Joined: 29 Jun 2010
Ok, I've tried to put the image display portion of tutorial 10 into tutorial 9 but the image speedometer-2.png is not showing up. Any idea why? the code I inserted is sandwiched between the statements:

;jl:: speedometer begin
...
;jl:: speedometer end

;
; AutoHotkey Version: 1.x
; Language:       English
; Platform:       Win9x/NT
; Author:         A.N.Other <[email protected]>
;
; Script Function:
;	Template script (you can customize this template by editing "ShellNew\Template.ahk" in your Windows folder)
;

#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.

;---------------------------------
; gdi+ ahk tutorial 9 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Example to create a progress bar in a standard gui

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip.ahk

; Start gdi+
If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}
OnExit, Exit

; Before we start there are some design elements we must consider.
; We can either make the script faster. Creating the bitmap 1st and just write the new progress bar onto it every time and updating it on the gui
; and dispose it all at the end/ This will use more RAM
; Or we can create the entire bitmap and write the information to it, display it and then delete it after every occurence
; This will be slower, but will use less RAM and will be modular (can all be put into a function)
; I will go with the 2nd option, but if more speed is a requirement then choose the 1st

; I am first creating a slider, just as a way to change the percentage on the progress bar
Gui, 1: Add, Slider, x10 y10 w300 Range0-100 vPercentage gSlider Tooltip, 50

; The progress bar needs to be added as a picture, as all we are doing is creating a gdi+ bitmap and setting it to this control
; Note we have set the 0xE style for it to accept an hBitmap later and also set a variable in order to reference it (could also use hwnd)
Gui, 1: Add, Picture, x10 y+30 w400 h50 0xE vProgressBar
; We will set the initial image on the control before showing the gui
GoSub, Slider
Gui, 1: Show, w600 h600, Example 9 - gdi+ progress bar
Return

;#######################################################################

; This subroutine is activated every time we move the slider as I used gSlider in the options of the slider
Slider:
Gui, 1: Default
Gui, 1: Submit, NoHide
Gdip_SetProgress(ProgressBar, Percentage, 0xff0993ea, 0xffbde5ff, Percentage "`%")
Return

;#######################################################################

Gdip_SetProgress(ByRef Variable, Percentage, Foreground, Background=0x00000000, Text="", TextOptions="x0p y15p s60p Center cff000000 r4 Bold", Font="Arial")
{
	; We first want the hwnd (handle to the picture control) so that we know where to put the bitmap we create
	; We also want to width and height (posw and Posh)
	GuiControlGet, Pos, Pos, Variable
	GuiControlGet, hwnd, hwnd, Variable

	; Create 2 brushes, one for the background and one for the foreground. Remember this is in ARGB
	pBrushFront := Gdip_BrushCreateSolid(Foreground), pBrushBack := Gdip_BrushCreateSolid(Background)
	
	; Create a gdi+ bitmap the width and height that we found the picture control to be
	; We will then get a reference to the graphics of this bitmap
	; We will also set the smoothing mode of the graphics to 4 (Antialias) to make the shapes we use smooth
	pBitmap := Gdip_CreateBitmap(Posw, Posh), G := Gdip_GraphicsFromImage(pBitmap), Gdip_SetSmoothingMode(G, 4)
	
	; We will fill the background colour with out background brush
	; x = 0, y = 0, w = Posw, h = Posh
	Gdip_FillRectangle(G, pBrushBack, 0, 0, Posw, Posh)
	
	; We will then fill a rounded rectangle with our other brush, starting at x = 4 and y = 4
	; The total width is now Posw-8 as we have slightly indented the actual progress bar
	; The last parameter which is the amount the corners will be rounded by in pixels has been made to be 3 pixels...
	; ...however I have made it so that they are smaller if the percentage is too small as it cannot be rounded by that much
	Gdip_FillRoundedRectangle(G, pBrushFront, 4, 4, (Posw-8)*(Percentage/100), Posh-8, (Percentage >= 3) ? 3 : Percentage)
	
	; As mentioned in previous examples, we will provide Gdip_TextToGraphics with the width and height of the graphics
	; We will then write the percentage centred onto the graphics (Look at previous examples to understand all options)
	; I added an optional text parameter at the top of this function, to make it so you could write an indication onto the progress bar
	; such as "Finished!" or whatever, otherwise it will write the percentage to it
	Gdip_TextToGraphics(G, (Text != "") ? Text : Round(Percentage) "`%", TextOptions, Font, Posw, Posh)
	
	; We then get a gdi bitmap from the gdi+ one we've been working with...
	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	; ... and set it to the hwnd we found for the picture control
	SetImage(hwnd, hBitmap)

        ; jl:: speedometer begin
        file = speedometer-2.png
        If !pimageBitmap := Gdip_CreateBitmapFromFile(File)
        Return


        ; We should get the width and height of the image, in case it is too big for the screen then we can resize it to fit nicely
        OriginalWidth := Gdip_GetImageWidth(pimageBitmap), OriginalHeight := Gdip_GetImageHeight(pimageBitmap)
        Ratio := OriginalWidth/OriginalHeight

        ; msgbox, jl::past origwidth =%originalwidth% originalheight = %originalheight% ratio= %ratio%   ;this passes. 

        ; If the image has a width larger than 1/2 of the width of the screen or height larger than 1/2 the screen, then we will resize it to be half of the screen
        If (OriginalWidth >= A_ScreenWidth//2) || (OriginalHeight >= A_ScreenHeight//2)
        {
	        If (OriginalWidth >= OriginalHeight)
	        Width := A_ScreenWidth//2, Height := Width*(1/Ratio)
	        Else
	        Height := A_ScreenHeight//2, Width := Height*Ratio
                }
        Else
                Width := OriginalWidth, Height := OriginalHeight

        ; Width and Height now contain the new dimensions the image on screen will be

        ; When rotating a square image, then the bitmap or canvas will need to be bigger as you can imagine that once rotated then a triangle will be wider than a square
        ; We need to know the new dimensions of the image
        ; With Gdip_GetRotatedDimensions we can plug in the width and height of the image, and the angle it is to be rotated by
        ; The last 2 parameters are the variables in which tio store the new width and height of the rotated image
        ; RWidth and RHeight now contain the dimensions of the rotated image
        Gdip_GetRotatedDimensions(Width, Height, Angle, RWidth, RHeight)

        msgbox, jl::past width =%width% height = %height%  angle=%angle% Rwidth=%rwidth% rheight=%rheight%  

        ; We rotate an image about the top left corner of the image, however this will result in the image moving off the canvas
        ; We can use Gdip_GetRotatedTranslation to find how much the image should be 'shifted' by in the x and y coordinates in order for it to be back on the canvas
        ; As with the above function, we plug in the width, height and angle to rotate by
        ; The function will then make the last 2 parameters the x and y translation (this is the distance in pixels the image must be shifted by)
        ; xTranslation and yTranslation now contain the distance to shift the image by
        Gdip_GetRotatedTranslation(Width, Height, Angle, xTranslation, yTranslation)

        ; We will now create a gdi bitmap to display the rotated image on the screen (as mentioned previously we must use a gdi bitmap to display things on the screen)
        hbm := CreateDIBSection(RWidth, RHeight)

        ; Get a device context compatible with the screen
        hdc := CreateCompatibleDC()

        ; Select the bitmap into the device context
        obm := SelectObject(hdc, hbm)

        ; Get a pointer to the graphics of the bitmap, for use with drawing functions,
        ; and set the InterpolationMode to HighQualityBicubic = 7 so that when resizing the image still looks good
        Gletter := Gdip_GraphicsFromHDC(hdc), Gdip_SetInterpolationMode(Gletter, 7)

        ; We can now shift our graphics or 'canvas' using the values found with Gdip_GetRotatedTranslation so that the image will be drawn on the canvas
        Gdip_TranslateWorldTransform(Gletter, xTranslation, yTranslation)

        ; We can also rotate the graphics by the angle we desire
        Gdip_RotateWorldTransform(Gletter, Angle)

          msgbox, jl:: Gletter = %Gletter%,  Angle=%Angle% 

        ; If we wish to flip the image horizontally, then we supply Gdip_ScaleWorldTransform(Gletter, x, y) with a negative x transform
        ; We multiply the image by the x and y transform. So multiplying a direction by -1 will flip it in that direction and 1 will do nothing
        ; We must then shift the graphics again to ensure the image will be within the 'canvas'
        ; You can see that if we wish to flip vertically we supply a negative y transform
        If Horizontal
                Gdip_ScaleWorldTransform(Gletter, -1, 1), Gdip_TranslateWorldTransform(Gletter, -Width, 0)
        If Vertical
                Gdip_ScaleWorldTransform(Gletter, 1, -1), Gdip_TranslateWorldTransform(Gletter, 0, -Height)


        ; As you will already know....we must draw the image onto the graphics. We want to draw from the top 
        ; left coordinates of the image (0, 0) to the top left of the graphics (0, 0)
        ; We are drawing from the orginal image size to the new size (this may not be different if the image was not larger than half the screen)
        Gdip_DrawImage(Gletter, pimageBitmap, 0, 0, Width, Height, 0, 0, OriginalWidth, OriginalHeight)

        ; Even though this is not necessary in this scenario, you should always reset the transforms set on the graphics. This will remove any of the rotations
        Gdip_ResetWorldTransform(Gletter)

        ; We will update the hwnd  with the hdc of our gdi bitmap. We are drawing it at the new width and height and in the centre of the screen
        UpdateLayeredWindow(hwnd2, hdc, (A_ScreenWidth-RWidth)//2, (A_ScreenHeight-RHeight)//2, RWidth, RHeight)
        ; jl:: speedometer end



	
	; We then must delete everything we created
	; So the 2 brushes must be deleted
	; Then we can delete the graphics, our gdi+ bitmap and the gdi bitmap
	Gdip_DeleteBrush(pBrushFront), Gdip_DeleteBrush(pBrushBack)
	Gdip_DeleteGraphics(Gletter), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
	Return, 0
}

;#######################################################################

GuiClose:
Exit:
; gdi+ may now be shutdown
Gdip_Shutdown(pToken)
ExitApp
Return

I've added a few msgbox'es to see what was going on, but all seems in order to me. Just no image at all let alone attached to the window.

- Jon

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
You use a lot of things that aren't related to setting a bitmap onto a standard window. You do not need UpdateLayeredWindow, as you are not dealing with layered windows. The most basic example of how to take an image from disk and place it onto a standard control is below

pToken := Gdip_Startup()
File = myimage.png
pBitmap := Gdip_CreateBitmapFromFile(File)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
Gdip_GetImageDimensions(pBitmap, Width, Height)

Gui, 1: Add, Picture, x10 y10 w%Width% h%Height% 0xE hwndMyPic
SetImage(MyPic, hBitmap)
Gui, 1: Show, AutoSize, gdi+ Example

Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
Gdip_Shutdown(pToken)
return

If you plan on doing this many times then you could wrap some of it into a function

Gdip_CreateHBITMAPFromFile(sFile)
{
	pBitmap := Gdip_CreateBitmapFromFile(sFile)
	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	Gdip_DisposeImage(pBitmap)
	return hBitmap
}

Cleaner versions of this are not included natively in the gdi+ library as it supposed to mostly target gdi+ rather than gdi.
Also note that SetImage is not a good choice if you will be updating the screen many times a second. BitBlt would be a better choice

jleslie48
  • Members
  • 145 posts
  • Last active: Sep 28 2017 07:13 PM
  • Joined: 29 Jun 2010

You use a lot of things that aren't related to setting a bitmap onto a standard window. ... The most basic example of how to take an image from disk and place it onto a standard control is below


Tic thank you very much. Your example works right out of the box. I am going to work with it and see how far I can develop it within the bounds of my project. I will read up on BitBit as well.

As I tried to state before I am sure I used lots of things that aren't related to setting a bitmap onto a standard window. I am not clear on where the boundaries are between displaying a bitmap and other elements of the gdi suite. Hopefully by the end of this excercise I will understand it fully and it will be well demonstrated for others. Thanks again for both your help and patience.

- Jon

jleslie48
  • Members
  • 145 posts
  • Last active: Sep 28 2017 07:13 PM
  • Joined: 29 Jun 2010
tic,

I've tried to insert your example into tutorial 9 and I do indeed get the transparent png to show up. However, if I put an image behind it (speedometer-0.png) then the transparency of the new image is lost and the second image (speedometer-2.png) covers up the first image. In this example I"ve offset the images a little to demonstrate the effect. speedometer-0.png is 400x300 pixels, so when I put up speedometer-2.png 200 pixels lower than speedometer-1.png the bottom 1/3 of the speedometer-0.png should be underneath speedometer-2.png but visible since speedometer-2.png is mostly invisible. However what is shown it the background under that 1/3 overlap rather than the underlying image.

added code in red:

;
; AutoHotkey Version: 1.x
; Language:       English
; Platform:       Win9x/NT
; Author:         A.N.Other <[email protected]>
;
; Script Function:
;	Template script (you can customize this template by editing "ShellNew\Template.ahk" in your Windows folder)
;

#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.

;---------------------------------
; gdi+ ahk tutorial 9 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Example to create a progress bar in a standard gui

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip.ahk

; Start gdi+
If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}
OnExit, Exit

; Before we start there are some design elements we must consider.
; We can either make the script faster. Creating the bitmap 1st and just write the new progress bar onto it every time and updating it on the gui
; and dispose it all at the end/ This will use more RAM
; Or we can create the entire bitmap and write the information to it, display it and then delete it after every occurence
; This will be slower, but will use less RAM and will be modular (can all be put into a function)
; I will go with the 2nd option, but if more speed is a requirement then choose the 1st

; I am first creating a slider, just as a way to change the percentage on the progress bar
Gui, 1: Add, Slider, x10 y10 w300 Range0-100 vPercentage gSlider Tooltip, 50

; The progress bar needs to be added as a picture, as all we are doing is creating a gdi+ bitmap and setting it to this control
; Note we have set the 0xE style for it to accept an hBitmap later and also set a variable in order to reference it (could also use hwnd)
Gui, 1: Add, Picture, x10 y+30 w400 h50 0xE vProgressBar

[color=red]
; JL:: speedometer 02 begin
;Gui, 1: Add, Picture, x10 yp+60 , speedometer-0.png
imgFile = speedometer-0.png
pimgBitmap := Gdip_CreateBitmapFromFile(imgFile)
himgBitmap := Gdip_CreateHBITMAPFromBitmap(pimgBitmap)
Gdip_GetImageDimensions(pimgBitmap, imgWidth, imgHeight)
Gui, 1: Add, Picture, x10 yp+60 w%imgWidth% h%imgHeight% 0xE hwndimgMyPic
SetImage(imgMyPic, himgBitmap)

imgFile = speedometer-2.png
pimgBitmap := Gdip_CreateBitmapFromFile(imgFile)
himgBitmap := Gdip_CreateHBITMAPFromBitmap(pimgBitmap)
Gdip_GetImageDimensions(pimgBitmap, imgWidth, imgHeight)

; lets put it so it overlaps the background a bit.  we see that it has lost its transparency. 
Gui, 1: Add, Picture, x10 yp+200 w%imgWidth% h%imgHeight% 0xE hwndimgMyPic
SetImage(imgMyPic, himgBitmap)
; JL:: speedometer 02 end
[/color]
GoSub, Slider
;Gui, 1: Show, w600 h600, Example 9 - gdi+ progress bar
Gui, 1: Show, autosize, Example 9 - gdi+ progress bar
Return

;#######################################################################

; This subroutine is activated every time we move the slider as I used gSlider in the options of the slider
Slider:
Gui, 1: Default
Gui, 1: Submit, NoHide
Gdip_SetProgress(ProgressBar, Percentage, 0xff0993ea, 0xffbde5ff, Percentage "`%")
Return

;#######################################################################

Gdip_SetProgress(ByRef Variable, Percentage, Foreground, Background=0x00000000, Text="", TextOptions="x0p y15p s60p Center cff000000 r4 Bold", Font="Arial")
{
	; We first want the hwnd (handle to the picture control) so that we know where to put the bitmap we create
	; We also want to width and height (posw and Posh)
	GuiControlGet, Pos, Pos, Variable
	GuiControlGet, hwnd, hwnd, Variable

	; Create 2 brushes, one for the background and one for the foreground. Remember this is in ARGB
	pBrushFront := Gdip_BrushCreateSolid(Foreground), pBrushBack := Gdip_BrushCreateSolid(Background)
	
	; Create a gdi+ bitmap the width and height that we found the picture control to be
	; We will then get a reference to the graphics of this bitmap
	; We will also set the smoothing mode of the graphics to 4 (Antialias) to make the shapes we use smooth
	pBitmap := Gdip_CreateBitmap(Posw, Posh), G := Gdip_GraphicsFromImage(pBitmap), Gdip_SetSmoothingMode(G, 4)
	
	; We will fill the background colour with out background brush
	; x = 0, y = 0, w = Posw, h = Posh
	Gdip_FillRectangle(G, pBrushBack, 0, 0, Posw, Posh)
	
	; We will then fill a rounded rectangle with our other brush, starting at x = 4 and y = 4
	; The total width is now Posw-8 as we have slightly indented the actual progress bar
	; The last parameter which is the amount the corners will be rounded by in pixels has been made to be 3 pixels...
	; ...however I have made it so that they are smaller if the percentage is too small as it cannot be rounded by that much
	Gdip_FillRoundedRectangle(G, pBrushFront, 4, 4, (Posw-8)*(Percentage/100), Posh-8, (Percentage >= 3) ? 3 : Percentage)
	
	; As mentioned in previous examples, we will provide Gdip_TextToGraphics with the width and height of the graphics
	; We will then write the percentage centred onto the graphics (Look at previous examples to understand all options)
	; I added an optional text parameter at the top of this function, to make it so you could write an indication onto the progress bar
	; such as "Finished!" or whatever, otherwise it will write the percentage to it
	Gdip_TextToGraphics(G, (Text != "") ? Text : Round(Percentage) "`%", TextOptions, Font, Posw, Posh)
	
	; We then get a gdi bitmap from the gdi+ one we've been working with...
	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	; ... and set it to the hwnd we found for the picture control
	SetImage(hwnd, hBitmap)
	
	; We then must delete everything we created
	; So the 2 brushes must be deleted
	; Then we can delete the graphics, our gdi+ bitmap and the gdi bitmap
	Gdip_DeleteBrush(pBrushFront), Gdip_DeleteBrush(pBrushBack)
	Gdip_DeleteGraphics(Gletter), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
	Return, 0
}

;#######################################################################

GuiClose:
Exit:
; gdi+ may now be shutdown
Gdip_Shutdown(pToken)
ExitApp
Return