├── Examples ├── MJ.jpg ├── needle.png ├── background.png ├── Gdip.tutorial.file-fish.bra ├── Gdip.Tutorial.6-Image.Editing.ahk ├── Gdip.Tutorial.1-Draw.Shapes.ahk ├── Gdip.Tutorial.5-Create.Bitmap.ahk ├── Gdip.Tutorial.4-Draw.Circles.ahk ├── Gdip.Tutorial.2-Draw.Outlined.Shapes.ahk ├── Gdip.Tutorial.12-Pixelate.a.bitmap.using.machine.code.ahk ├── Gdip.Tutorial.7-Draw.draggable.rounded.rectangle.ahk ├── Gdip.Tutorial.3-Create.Gui.From.Image.ahk ├── Gdip.Tutorial.9-Create.a.progress.bar.on.standard.gui.ahk ├── Gdip.Tutorial.8-Write.text.onto.a.gui.ahk ├── Gdip.Tutorial.10-Rotate.Flip.or.Mirror.an.image.ahk └── Gdip.Tutorial.11-Using.BRAs.to.perform.animations.ahk ├── Gdip_Toolbox-usage_example.ahk ├── CHANGE.log ├── README.md ├── Gdip_Toolbox.ahk └── Gdip_All.ahk /Examples/MJ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buliasz/AHKv2-Gdip/HEAD/Examples/MJ.jpg -------------------------------------------------------------------------------- /Examples/needle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buliasz/AHKv2-Gdip/HEAD/Examples/needle.png -------------------------------------------------------------------------------- /Examples/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buliasz/AHKv2-Gdip/HEAD/Examples/background.png -------------------------------------------------------------------------------- /Examples/Gdip.tutorial.file-fish.bra: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buliasz/AHKv2-Gdip/HEAD/Examples/Gdip.tutorial.file-fish.bra -------------------------------------------------------------------------------- /Gdip_Toolbox-usage_example.ahk: -------------------------------------------------------------------------------- 1 | #include Gdip_Toolbox.ahk 2 | 3 | color := GetPixelColorBuffered(120,130) 4 | MsgBox("Color of pixel at 120x130 (BGR): " Format("0x{:06X}", color)) 5 | 6 | rect := DrawRectangle(120, 130, 222, 333, 12345678, 0.5) 7 | MsgBox("Click ok to destroy rectangle") 8 | rect.Destroy() 9 | -------------------------------------------------------------------------------- /CHANGE.log: -------------------------------------------------------------------------------- 1 | 2023-07-01 v1.57-60 - bug fixes 2 | 2023-04-19 v1.56 - compatible with AHK v2.0.2, Gdip_DrawLines fixed, gdip_toolbox improved, separated changelog 3 | 2021-12-19 v1.55 - compatibility with AHK v1 dropped, fixed compatibility with v2.0beta3 by buliasz 4 | 2017-11-15 v1.54 - compatibility with both AHK v2 and v1, restored by nnnik 5 | 2017-06-19 v1.53 - fixed few bugs from old syntax by buliasz 6 | 2017-06-11 v1.52 - made code compatible with new AHK v2.0-a079-be5df98 by buliasz 7 | 2017-01-27 v1.51 - fixed some bugs and made #Warn All compatible by buliasz 8 | 2016-11-20 v1.50 - fixed Gdip_BitmapFromBRA() by 'just me' 9 | 2016-11-18 - backward compatible support for both AHK v1.1 and AHK v2 10 | 2016-11-15 - initial AHK v2 support by guest3456 11 | 2014-02-20 - fixed Gdip_CreateRegion() and Gdip_GetClipRegion() on AHK Unicode x86 12 | 2013-05-13 - fixed Gdip_SetBitmapToClipboard() on AHK Unicode x64 13 | 2013-05-01 - modifed by Rseding91 using fincs 64 bit compatible Gdip library 14 | 2011-07-09 v1.45 by tic (Tariq Porter) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AHKv2-Gdip 2 | This repository contains the GDI+ library (Gdip_All.ahk) compatible with the current [AutoHotKey v2](https://autohotkey.com/v2/). 3 | 4 | Support for AHK v1 is dropped (find the original `Gdip_All.ahk` library if you need it). 5 | 6 | See the [commit history](https://github.com/buliasz/AHKv2-Gdip/commits/master) to see the changes made and [changelog](https://github.com/buliasz/AHKv2-Gdip/blob/master/CHANGE.log). 7 | 8 | # Examples 9 | See the appropriate Examples folder for usage examples 10 | 11 | # Usage 12 | All of the Gdip_*() functions use the same syntax as before, so no changes should be required, with one exception: 13 | 14 | The `Gdip_BitmapFromBRA()` function requires you to read the .bra file witih `FileObj.RawRead()` instead of the `FileRead` command. See the Tutorial.11 file in the Examples folder 15 | 16 | # History 17 | - @tic Created the original [Gdip.ahk](https://github.com/tariqporter/Gdip/) library. 18 | - @Rseding91 Updated it to make it compatible with unicode and x64 AHK versions and renamed the file `Gdip_All.ahk`. 19 | - @mmikeww Repository updates @Rseding91's `Gdip_All.ahk` to fix bugs and make it compatible with AHK v2. 20 | - @buliasz Fork of mmikeww repository: updates for the current version of AHK v2 (dropping AHK v1 backward compatibility). 21 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.6-Image.Editing.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 6 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Example to take files from disk, load them onto a background and save back to disk 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Specify both of the files we are going to use 14 | File1 := "needle.png" 15 | File2 := "background.png" 16 | 17 | ; Start gdi+ 18 | If !pToken := Gdip_Startup() 19 | { 20 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 21 | ExitApp 22 | } 23 | 24 | ; If the images we want to work with do not exist on disk, then download them... 25 | If !(FileExist(File1) && FileExist(File2)) 26 | { 27 | MsgBox "Cannot find files 'needle.png' and 'background.png' in this same directory" 28 | ExitApp 29 | } 30 | 31 | 32 | ; Create a 500x500 pixel gdi+ bitmap (this will be the entire drawing area we have to play with) 33 | pBitmap := Gdip_CreateBitmap(600, 600) 34 | 35 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions 36 | G := Gdip_GraphicsFromImage(pBitmap) 37 | 38 | ; Create a green brush (this will be used to fill the background with green). The brush is fully opaque (ARGB) 39 | pBrush := Gdip_BrushCreateSolid(0xff00ff00) 40 | 41 | ; Filll the entire graphics of the bitmap with the green brush (this will be out background colour) 42 | Gdip_FillRectangle(G, pBrush, 0, 0, 600, 600) 43 | 44 | ; Delete the brush created to save memory as we don't need the same brush anymore 45 | Gdip_DeleteBrush(pBrush) 46 | 47 | 48 | ; Get bitmaps for both the files we are going to be working with 49 | pBitmapFile1 := Gdip_CreateBitmapFromFile(File1), pBitmapFile2 := Gdip_CreateBitmapFromFile(File2) 50 | 51 | ; Get the width and height of the 1st bitmap 52 | Width := Gdip_GetImageWidth(pBitmapFile1), Height := Gdip_GetImageHeight(pBitmapFile1) 53 | 54 | ; Draw the 1st bitmap (1st image) onto our "canvas" (the graphics of the original bitmap we created) with the same height and same width 55 | ; at coordinates (25,30).....We will be ignoring the matrix parameter for now. This can be used to change opacity and colours when drawing 56 | Gdip_DrawImage(G, pBitmapFile1, 25, 30, Width, Height, 0, 0, Width, Height) 57 | 58 | 59 | ; Do the same again for the 2nd file, but change the coordinates to (250,260)..... 60 | 61 | Width := Gdip_GetImageWidth(pBitmapFile2), Height := Gdip_GetImageHeight(pBitmapFile2) 62 | Gdip_DrawImage(G, pBitmapFile2, 250, 260, Width, Height, 0, 0, Width, Height) 63 | 64 | ; Dispose of both of these bitmaps we created from the images on disk, as they are now been used...They are on 65 | ; the graphics of the bitmap of our created "canvas" 66 | Gdip_DisposeImage(pBitmapFile1), Gdip_DisposeImage(pBitmapFile2) 67 | 68 | 69 | ; Save the bitmap to file "File.png" (extension can be .png,.bmp,.jpg,.tiff,.gif) 70 | ; Bear in mind transparencies may be lost with some image formats and will appear black 71 | Gdip_SaveBitmapToFile(pBitmap, "FinalImage.png") 72 | 73 | MsgBox "Image saved as 'FinalImage.png' " 74 | 75 | ; The bitmap can be deleted 76 | Gdip_DisposeImage(pBitmap) 77 | 78 | ; The graphics may now be deleted 79 | Gdip_DeleteGraphics(G) 80 | 81 | ; ...and gdi+ may now be shutdown 82 | Gdip_Shutdown(pToken) 83 | ExitApp 84 | Return 85 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.1-Draw.Shapes.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 1 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to draw a single ellipse and rectangle to the screen 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | OnExit ExitFunc 20 | 21 | ; Set the width and height we want as our drawing area, to draw everything in. This will be the dimensions of our bitmap 22 | Width :=1400, Height := 1050 23 | 24 | ; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption 25 | ;AHK v1 26 | ;Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs 27 | ;Gui, 1: Show, NA 28 | Gui1 := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 29 | Gui1.Show("NA") 30 | 31 | ; Get a handle to this window we have created in order to update it later 32 | hwnd1 := WinExist() 33 | 34 | ; Create a gdi bitmap with width and height of what we are going to draw into it. This is the entire drawing area for everything 35 | hbm := CreateDIBSection(Width, Height) 36 | 37 | ; Get a device context compatible with the screen 38 | hdc := CreateCompatibleDC() 39 | 40 | ; Select the bitmap into the device context 41 | obm := SelectObject(hdc, hbm) 42 | 43 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions 44 | G := Gdip_GraphicsFromHDC(hdc) 45 | 46 | ; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling) 47 | Gdip_SetSmoothingMode(G, 4) 48 | 49 | ; Create a fully opaque red brush (ARGB = Transparency, red, green, blue) to draw a circle 50 | pBrush := Gdip_BrushCreateSolid(0xffff0000) 51 | 52 | ; Fill the graphics of the bitmap with an ellipse using the brush created 53 | ; Filling from coordinates (100,50) an ellipse of 200x300 54 | Gdip_FillEllipse(G, pBrush, 100, 500, 200, 300) 55 | 56 | ; Delete the brush as it is no longer needed and wastes memory 57 | Gdip_DeleteBrush(pBrush) 58 | 59 | ; Create a slightly transparent (66) blue brush (ARGB = Transparency, red, green, blue) to draw a rectangle 60 | pBrush := Gdip_BrushCreateSolid(0x660000ff) 61 | 62 | ; Fill the graphics of the bitmap with a rectangle using the brush created 63 | ; Filling from coordinates (250,80) a rectangle of 300x200 64 | Gdip_FillRectangle(G, pBrush, 250, 80, 300, 200) 65 | 66 | ; Delete the brush as it is no longer needed and wastes memory 67 | Gdip_DeleteBrush(pBrush) 68 | 69 | 70 | ; Update the specified window we have created (hwnd1) with a handle to our bitmap (hdc), specifying the x,y,w,h we want it positioned on our screen 71 | ; So this will position our gui at (0,0) with the Width and Height specified earlier 72 | UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height) 73 | 74 | 75 | ; Select the object back into the hdc 76 | SelectObject(hdc, obm) 77 | 78 | ; Now the bitmap may be deleted 79 | DeleteObject(hbm) 80 | 81 | ; Also the device context related to the bitmap may be deleted 82 | DeleteDC(hdc) 83 | 84 | ; The graphics may now be deleted 85 | Gdip_DeleteGraphics(G) 86 | Return 87 | 88 | ;####################################################################### 89 | 90 | ExitFunc(ExitReason, ExitCode) 91 | { 92 | global 93 | ; gdi+ may now be shutdown on exiting the program 94 | Gdip_Shutdown(pToken) 95 | } 96 | 97 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.5-Create.Bitmap.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 5 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Example to create a bitmap, fill it with some shapes and save to file 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | 20 | ; Create a 400x400 pixel gdi+ bitmap 21 | pBitmap := Gdip_CreateBitmap(400, 400) 22 | 23 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions 24 | G := Gdip_GraphicsFromImage(pBitmap) 25 | 26 | ; Set the smoothing mode to antialias = 4 to make shapes appear smoother (only used for vector drawing and filling) 27 | Gdip_SetSmoothingMode(G, 4) 28 | 29 | ; Create a hatched brush with background and foreground colours specified (HatchStyleBackwardDiagonal = 3) 30 | pBrush := Gdip_BrushCreateHatch(0xff553323, 0xffc09e8e, 31) 31 | ; Draw into the graphics of the bitmap from coordinates (100,80) a filled rectangle with 200 width and 250 height using the brush created 32 | Gdip_FillRectangle(G, pBrush, (400-200)//2, (400-250)//2, 200, 250) 33 | ; Delete the brush created to save memory as we don't need the same brush anymore 34 | Gdip_DeleteBrush(pBrush) 35 | 36 | ; Create a hatched brush with background and foreground colours specified (HatchStyleBackwardDiagonal = 3) 37 | pBrush := Gdip_BrushCreateHatch(0xff000000, 0xff4d3538, 31) 38 | ; Draw an ellipse into the graphics with the brush we just created. 40 degree sweep angle starting at 250 degrees (0 degrees from right horizontal) 39 | Gdip_FillPie(G, pBrush, (400-80)//2, (400-80)//2, 80, 80, 250, 40) 40 | ; Delete the brush created to save memory as we don't need the same brush anymore 41 | Gdip_DeleteBrush(pBrush) 42 | 43 | ; Create a white brush 44 | pBrushWhite := Gdip_BrushCreateSolid(0xffffffff) 45 | ; Create a black brush 46 | pBrushBlack := Gdip_BrushCreateSolid(0xff000000) 47 | 48 | ; Loop to draw 2 ellipses filling them with white then black in the centre of each 49 | Loop 2 50 | { 51 | x := (A_Index = 1) ? 120 : 220, y := 100 52 | Gdip_FillEllipse(G, pBrushWhite, x, y, 60, 60) 53 | x += 15, y+=15 54 | Gdip_FillEllipse(G, pBrushBlack, x, y, 30, 30) 55 | } 56 | ; Delete both brushes 57 | Gdip_DeleteBrush(pBrushWhite), Gdip_DeleteBrush(pBrushBlack) 58 | 59 | ; Create a hatched brush with background and foreground colours specified (HatchStyle30Percent = 10) 60 | pBrush := Gdip_BrushCreateHatch(0xfff22231, 0xffa10f19, 10) 61 | ; Again draw another ellipse into the graphics with the specified brush 62 | Gdip_FillPie(G, pBrush, 150, 200, 100, 80, 0, 180) 63 | ; Delete the brush 64 | Gdip_DeleteBrush(pBrush) 65 | 66 | ; Create a 3 pixel wide slightly transparent black pen 67 | pPen := Gdip_CreatePen(0xbb000000, 3) 68 | 69 | ; Create some coordinates for the lines in format x1,y1,x2,y2 then loop and draw all the lines 70 | Lines := "180,200,130,220|180,190,130,195|220,200,270,220|220,190,270,195" 71 | for k,v in StrSplit(Lines, "|") 72 | { 73 | Pos := StrSplit(v, ",") 74 | Gdip_DrawLine(G, pPen, Pos[1], Pos[2], Pos[3], Pos[4]) 75 | } 76 | ; Delete the pen 77 | Gdip_DeletePen(pPen) 78 | 79 | 80 | ; Save the bitmap to file "File.png" (extension can be .png,.bmp,.jpg,.tiff,.gif) 81 | ; Bear in mind transparencies may be lost with some image formats and will appear black 82 | Gdip_SaveBitmapToFile(pBitmap, "File.png") 83 | 84 | MsgBox "Bitmap saved as 'File.png' " 85 | 86 | ; The bitmap can be deleted 87 | Gdip_DisposeImage(pBitmap) 88 | 89 | ; The graphics may now be deleted 90 | Gdip_DeleteGraphics(G) 91 | 92 | ; ...and gdi+ may now be shutdown 93 | Gdip_Shutdown(pToken) 94 | ExitApp 95 | Return 96 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.4-Draw.Circles.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 4 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to fill the screen with randomly hatched ellipses 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | OnExit ExitFunc 20 | 21 | ; Get the dimensions of the primary monitor 22 | ; these funcs are based off MDMF lib and are now included in the Gdip_All library 23 | MonitorPrimary := GetPrimaryMonitor() 24 | M := GetMonitorInfo(MonitorPrimary) 25 | WALeft := M.WALeft 26 | WATop := M.WATop 27 | WARight := M.WARight 28 | WABottom := M.WABottom 29 | WAWidth := M.WARight-M.WALeft 30 | WAHeight := M.WABottom-M.WATop 31 | 32 | ; Create a layered window (+E0x80000) that is always on top (+AlwaysOnTop), has no taskbar entry or caption 33 | ;AHK v1 34 | ;Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs 35 | ;Gui, 1: Show, NA 36 | Gui1 := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 37 | Gui1.Show("NA") 38 | 39 | ; Get a handle to this window we have created in order to update it later 40 | hwnd1 := WinExist() 41 | 42 | ; Create a gdi bitmap with width and height of the work area 43 | hbm := CreateDIBSection(WAWidth, WAHeight) 44 | 45 | ; Get a device context compatible with the screen 46 | hdc := CreateCompatibleDC() 47 | 48 | ; Select the bitmap into the device context 49 | obm := SelectObject(hdc, hbm) 50 | 51 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions 52 | G := Gdip_GraphicsFromHDC(hdc) 53 | 54 | ; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling) 55 | Gdip_SetSmoothingMode(G, 4) 56 | 57 | ; Set a timer to draw a new ellipse every 200ms 58 | SetTimer DrawCircle, 200 59 | Return 60 | 61 | ;####################################################################### 62 | 63 | DrawCircle() 64 | { 65 | global 66 | DrawCircle: 67 | ; Get a random colour for the background and foreground of hatch style used to fill the ellipse, 68 | ; as well as random brush style, x and y coordinates and width/height 69 | RandBackColour := Random(0.0, 0xffffffff) 70 | RandForeColour := Random(0.0, 0xffffffff) 71 | RandBrush := Random(0, 53) 72 | RandElipseWidth := Random(1, 200) 73 | RandElipseHeight := Random(1, 200) 74 | RandElipsexPos := Random(WALeft, WAWidth-RandElipseWidth) 75 | RandElipseyPos := Random(WATop, WAHeight-RandElipseHeight) 76 | 77 | ; Create the random brush 78 | pBrush := Gdip_BrushCreateHatch(RandBackColour, RandForeColour, RandBrush) 79 | 80 | ; Fill the graphics of the bitmap with an ellipse using the brush created 81 | Gdip_FillEllipse(G, pBrush, RandElipsexPos, RandElipseyPos, RandElipseWidth, RandElipseHeight) 82 | 83 | ; Update the specified window 84 | UpdateLayeredWindow(hwnd1, hdc, WALeft, WATop, WAWidth, WAHeight) 85 | 86 | ; Delete the brush as it is no longer needed and wastes memory 87 | Gdip_DeleteBrush(pBrush) 88 | Return 89 | } 90 | 91 | ;####################################################################### 92 | 93 | ExitFunc(ExitReason, ExitCode) 94 | { 95 | global 96 | ; Select the object back into the hdc 97 | SelectObject(hdc, obm) 98 | 99 | ; Now the bitmap may be deleted 100 | DeleteObject(hbm) 101 | 102 | ; Also the device context related to the bitmap may be deleted 103 | DeleteDC(hdc) 104 | 105 | ; The graphics may now be deleted 106 | Gdip_DeleteGraphics(G) 107 | 108 | ; ...and gdi+ may now be shutdown 109 | Gdip_Shutdown(pToken) 110 | } 111 | 112 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.2-Draw.Outlined.Shapes.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 2 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to draw a single ellipse and rectangle to the screen, but just the outlines of these shapes 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | OnExit ExitFunc 20 | 21 | ; Set the width and height we want as our drawing area, to draw everything in. This will be the dimensions of our bitmap 22 | Width := 600, Height := 400 23 | 24 | ; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption 25 | ;AHK v1 26 | ;Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs 27 | ;Gui, 1: Show, NA 28 | Gui1 := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 29 | Gui1.Show("NA") 30 | 31 | ; Get a handle to this window we have created in order to update it later 32 | hwnd1 := WinExist() 33 | 34 | ; Create a gdi bitmap with width and height of what we are going to draw into it. This is the entire drawing area for everything 35 | hbm := CreateDIBSection(Width, Height) 36 | 37 | ; Get a device context compatible with the screen 38 | hdc := CreateCompatibleDC() 39 | 40 | ; Select the bitmap into the device context 41 | obm := SelectObject(hdc, hbm) 42 | 43 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions 44 | G := Gdip_GraphicsFromHDC(hdc) 45 | 46 | ; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling) 47 | Gdip_SetSmoothingMode(G, 4) 48 | 49 | ; Create a fully opaque red pen (ARGB = Transparency, red, green, blue) of width 3 (the thickness the pen will draw at) to draw a circle 50 | pPen := Gdip_CreatePen(0xffff0000, 3) 51 | 52 | ; Draw an ellipse into the graphics of the bitmap (this being only the outline of the shape) using the pen created 53 | ; This pen has a width of 3, and is drawing from coordinates (100,50) an ellipse of 200x300 54 | Gdip_DrawEllipse(G, pPen, 100, 50, 200, 300) 55 | 56 | ; Delete the pen as it is no longer needed and wastes memory 57 | Gdip_DeletePen(pPen) 58 | 59 | ; Create a slightly transparent (66) blue pen (ARGB = Transparency, red, green, blue) to draw a rectangle 60 | ; This pen is wider than the last one, with a thickness of 10 61 | pPen := Gdip_CreatePen(0x660000ff, 10) 62 | 63 | ; Draw a rectangle onto the graphics of the bitmap using the pen just created 64 | ; Draws the rectangle from coordinates (250,80) a rectangle of 300x200 and outline width of 10 (specified when creating the pen) 65 | Gdip_DrawRectangle(G, pPen, 250, 80, 300, 200) 66 | 67 | ; Delete the brush as it is no longer needed and wastes memory 68 | Gdip_DeletePen(pPen) 69 | 70 | ; Update the specified window we have created (hwnd1) with a handle to our bitmap (hdc), specifying the x,y,w,h we want it positioned on our screen 71 | ; So this will position our gui at (0,0) with the Width and Height specified earlier 72 | UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height) 73 | 74 | 75 | ; Select the object back into the hdc 76 | SelectObject(hdc, obm) 77 | 78 | ; Now the bitmap may be deleted 79 | DeleteObject(hbm) 80 | 81 | ; Also the device context related to the bitmap may be deleted 82 | DeleteDC(hdc) 83 | 84 | ; The graphics may now be deleted 85 | Gdip_DeleteGraphics(G) 86 | Return 87 | 88 | ;####################################################################### 89 | 90 | ExitFunc(ExitReason, ExitCode) 91 | { 92 | global 93 | ; gdi+ may now be shutdown on exiting the program 94 | Gdip_Shutdown(pToken) 95 | } 96 | 97 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.12-Pixelate.a.bitmap.using.machine.code.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 12 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to pixelate a bitmap using machine code 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | OnExit ExitFunc 20 | 21 | ; Create a layered window that is always on top as usual and get a handle to the window 22 | ;AHK v1 23 | ;Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop 24 | ;Gui, 1: Show, NA 25 | Gui1 := Gui("-Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop") 26 | Gui1.Show("NA") 27 | hwnd1 := WinExist() 28 | 29 | ; Get a bitmap from the image 30 | If FileExist("MJ.jpg") 31 | pBitmap := Gdip_CreateBitmapFromFile("MJ.jpg") 32 | ;pBitmap := Gdip_BitmapFromScreen() 33 | If !pBitmap 34 | { 35 | MsgBox "Could not load the image 'MJ.jpg' " 36 | ExitApp 37 | } 38 | ; Get the width and height of the bitmap we have just created from the file 39 | Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap) 40 | 41 | ; We also need to create 42 | pBitmapOut := Gdip_CreateBitmap(Width, Height) 43 | 44 | ; As normal create a gdi bitmap and get the graphics for it to draw into 45 | hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm) 46 | G := Gdip_GraphicsFromHDC(hdc) 47 | 48 | ; Call WM_LBUTTONDOWN every time the gui is clicked, to allow it to be dragged 49 | OnMessage(0x201, WM_LBUTTONDOWN) 50 | 51 | ; Update the window with the hdc so that it has a position and dimension for future calls to not 52 | ; have to explicitly pass them 53 | UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height) 54 | 55 | ; Set a timer to update the gui with our pixelated bitmap 56 | SetTimer Update, 50 57 | return 58 | 59 | ;####################################################################### 60 | 61 | Update() 62 | { 63 | global 64 | Update: 65 | 66 | static v := 0 67 | static dir := 0 68 | ; Some simple checks to see if we are increasing or decreasing the pixelation 69 | ; v is the block size of the pixelation and dir is the direction (inc/decreasing) 70 | if (v <= 1) 71 | v := 1, dir := !dir 72 | else if (v >= 30) 73 | v := 30, dir := !dir 74 | 75 | ; Call Gdip_PixelateBitmap with the bitmap we retrieved earlier and the block size of the pixels 76 | ; The function returns the pixelated bitmap, and doesn't dispose of the original bitmap 77 | Gdip_PixelateBitmap(pBitmap, &pBitmapOut, dir ? ++v : --v) 78 | 79 | ; We can optionally clear the graphics we will be drawing to, but if we know there will be no transparencies then 80 | ; it doesn't matter 81 | ;Gdip_GraphicsClear(G) 82 | 83 | ; We then draw our pixelated bitmap into our graphics and dispose of the pixelated bitmap 84 | Gdip_DrawImage(G, pBitmapOut, 0, 0, Width, Height, 0, 0, Width, Height) 85 | 86 | ; We can now update our window, and don't need to provide a position or dimensions as we don't want them to change 87 | UpdateLayeredWindow(hwnd1, hdc) 88 | return 89 | } 90 | 91 | ;####################################################################### 92 | 93 | ; This is called on left click to allow to drag 94 | WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) 95 | { 96 | PostMessage 0xA1, 2 97 | } 98 | 99 | ;####################################################################### 100 | 101 | ; On exit, dispose of everything created 102 | Esc::ExitApp 103 | 104 | ExitFunc(ExitReason, ExitCode) 105 | { 106 | global 107 | Gdip_DisposeImage(pBitmapOut), Gdip_DisposeImage(pBitmap) 108 | SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc) 109 | Gdip_DeleteGraphics(G) 110 | Gdip_Shutdown(pToken) 111 | } 112 | 113 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.7-Draw.draggable.rounded.rectangle.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 7 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to draw a rounded rectangle as a gui that you can drag 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | OnExit ExitFunc 20 | 21 | ; Set the width and height we want as our drawing area, to draw everything in. This will be the dimensions of our bitmap 22 | Width := 300, Height := 200 23 | 24 | ; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption 25 | ;AHK v1 26 | ;Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs 27 | ;Gui, 1: Show, NA 28 | Gui1 := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 29 | Gui1.Show("NA") 30 | 31 | ; Get a handle to this window we have created in order to update it later 32 | hwnd1 := WinExist() 33 | 34 | ; Create a gdi bitmap with width and height of what we are going to draw into it. This is the entire drawing area for everything 35 | hbm := CreateDIBSection(Width, Height) 36 | 37 | ; Get a device context compatible with the screen 38 | hdc := CreateCompatibleDC() 39 | 40 | ; Select the bitmap into the device context 41 | obm := SelectObject(hdc, hbm) 42 | 43 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions 44 | G := Gdip_GraphicsFromHDC(hdc) 45 | 46 | ; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling) 47 | Gdip_SetSmoothingMode(G, 4) 48 | 49 | ; Create a partially transparent, black brush (ARGB = Transparency, red, green, blue) to draw a rounded rectangle with 50 | pBrush := Gdip_BrushCreateSolid(0x77000000) 51 | 52 | ; Fill the graphics of the bitmap with a rounded rectangle using the brush created 53 | ; Filling the entire graphics - from coordinates (0, 0) the entire width and height 54 | ; The last parameter (20) is the radius of the circles used for the rounded corners 55 | Gdip_FillRoundedRectangle(G, pBrush, 0, 0, Width, Height, 20) 56 | 57 | ; Delete the brush as it is no longer needed and wastes memory 58 | Gdip_DeleteBrush(pBrush) 59 | 60 | 61 | ; Update the specified window we have created (hwnd1) with a handle to our bitmap (hdc), specifying the x,y,w,h we want it positioned on our screen 62 | ; With some simple maths we can place the gui in the centre of our primary monitor horizontally and vertically at the specified heigth and width 63 | UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height) 64 | 65 | ; By placing this OnMessage here. The function WM_LBUTTONDOWN will be called every time the user left clicks on the gui 66 | OnMessage(0x201, WM_LBUTTONDOWN) 67 | 68 | 69 | ; Select the object back into the hdc 70 | SelectObject(hdc, obm) 71 | 72 | ; Now the bitmap may be deleted 73 | DeleteObject(hbm) 74 | 75 | ; Also the device context related to the bitmap may be deleted 76 | DeleteDC(hdc) 77 | 78 | ; The graphics may now be deleted 79 | Gdip_DeleteGraphics(G) 80 | Return 81 | 82 | ;####################################################################### 83 | 84 | ; This function is called every time the user clicks on the gui 85 | ; The PostMessage will act on the last found window (this being the gui that launched the subroutine, hence the last parameter not being needed) 86 | WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) 87 | { 88 | PostMessage 0xA1, 2 89 | } 90 | 91 | ;####################################################################### 92 | 93 | ExitFunc(ExitReason, ExitCode) 94 | { 95 | global 96 | ; gdi+ may now be shutdown on exiting the program 97 | Gdip_Shutdown(pToken) 98 | } 99 | 100 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.3-Create.Gui.From.Image.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 3 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to take make a gui from an existing image on disk 5 | ; For the example we will use png as it can handle transparencies. The image will also be halved in size 6 | 7 | #SingleInstance Force 8 | ;#NoEnv 9 | ;SetBatchLines -1 10 | 11 | ; Uncomment if Gdip.ahk is not in your standard library 12 | #Include ../Gdip_All.ahk 13 | 14 | ; Start gdi+ 15 | If !pToken := Gdip_Startup() 16 | { 17 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 18 | ExitApp 19 | } 20 | OnExit ExitFunc 21 | 22 | ; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption 23 | ;AHK v1 24 | ;Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs 25 | ;Gui, 1: Show, NA 26 | Gui1 := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 27 | Gui1.Show("NA") 28 | 29 | ; Get a handle to this window we have created in order to update it later 30 | hwnd1 := WinExist() 31 | 32 | ; Get a bitmap from the image 33 | pBitmap := Gdip_CreateBitmapFromFile("background.png") 34 | 35 | ; Check to ensure we actually got a bitmap from the file, in case the file was corrupt or some other error occured 36 | If !pBitmap 37 | { 38 | MsgBox "Could not load 'background.png'" 39 | ExitApp 40 | } 41 | 42 | ; Get the width and height of the bitmap we have just created from the file 43 | ; This will be the dimensions that the file is 44 | Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap) 45 | 46 | ; Create a gdi bitmap with width and height of what we are going to draw into it. This is the entire drawing area for everything 47 | ; We are creating this "canvas" at half the size of the actual image 48 | ; We are halving it because we want the image to show in a gui on the screen at half its dimensions 49 | hbm := CreateDIBSection(Width//2, Height//2) 50 | 51 | ; Get a device context compatible with the screen 52 | hdc := CreateCompatibleDC() 53 | 54 | ; Select the bitmap into the device context 55 | obm := SelectObject(hdc, hbm) 56 | 57 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions 58 | G := Gdip_GraphicsFromHDC(hdc) 59 | 60 | ; We do not need SmoothingMode as we did in previous examples for drawing an image 61 | ; Instead we must set InterpolationMode. This specifies how a file will be resized (the quality of the resize) 62 | ; Interpolation mode has been set to HighQualityBicubic = 7 63 | Gdip_SetInterpolationMode(G, 7) 64 | 65 | ; DrawImage will draw the bitmap we took from the file into the graphics of the bitmap we created 66 | ; We are wanting to draw the entire image, but at half its size 67 | ; Coordinates are therefore taken from (0,0) of the source bitmap and also into the destination bitmap 68 | ; The source height and width are specified, and also the destination width and height (half the original) 69 | ; Gdip_DrawImage(pGraphics, pBitmap, dx, dy, dw, dh, sx, sy, sw, sh, Matrix) 70 | ; d is for destination and s is for source. We will not talk about the matrix yet (this is for changing colours when drawing) 71 | Gdip_DrawImage(G, pBitmap, 0, 0, Width//2, Height//2, 0, 0, Width, Height) 72 | 73 | ; Update the specified window we have created (hwnd1) with a handle to our bitmap (hdc), specifying the x,y,w,h we want it positioned on our screen 74 | ; So this will position our gui at (0,0) with the Width and Height specified earlier (half of the original image) 75 | UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width//2, Height//2) 76 | 77 | 78 | ; Select the object back into the hdc 79 | SelectObject(hdc, obm) 80 | 81 | ; Now the bitmap may be deleted 82 | DeleteObject(hbm) 83 | 84 | ; Also the device context related to the bitmap may be deleted 85 | DeleteDC(hdc) 86 | 87 | ; The graphics may now be deleted 88 | Gdip_DeleteGraphics(G) 89 | 90 | ; The bitmap we made from the image may be deleted 91 | Gdip_DisposeImage(pBitmap) 92 | Return 93 | 94 | ;####################################################################### 95 | 96 | ExitFunc(ExitReason, ExitCode) 97 | { 98 | global 99 | ; gdi+ may now be shutdown on exiting the program 100 | Gdip_Shutdown(pToken) 101 | } 102 | 103 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.9-Create.a.progress.bar.on.standard.gui.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 9 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Example to create a progress bar in a standard gui 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | OnExit ExitFunc 20 | 21 | ; Before we start there are some design elements we must consider. 22 | ; 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 23 | ; and dispose it all at the end/ This will use more RAM 24 | ; Or we can create the entire bitmap and write the information to it, display it and then delete it after every occurence 25 | ; This will be slower, but will use less RAM and will be modular (can all be put into a function) 26 | ; I will go with the 2nd option, but if more speed is a requirement then choose the 1st 27 | 28 | ; I am first creating a slider, just as a way to change the percentage on the progress bar 29 | ; 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 30 | ; 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) 31 | ; We will set the initial image on the control before showing the gui 32 | 33 | ;AHK v1 34 | ;Gui, 1: -DPIScale 35 | ;Gui, 1: Add, Slider, x10 y10 w400 Range0-100 vPercentage gSlider Tooltip, 50 36 | ;Gui, 1: Add, Picture, x10 y+30 w400 h50 0xE vProgressBar 37 | ;GoSub Slider 38 | ;Gui, 1: Show, AutoSize, Example 9 - gdi+ progress bar 39 | 40 | Gui1 := Gui("-DPIScale") 41 | Gui1.OnEvent("Close", Gui_Close) 42 | SliderObj := Gui1.Add("Slider", "x10 y10 w400 Range0-100 vPercentage Tooltip", 50) 43 | SliderObj.OnEvent("Change", Slider_Change) 44 | PictureObj := Gui1.Add("Picture", "x10 y+30 w400 h50 0xE vProgressBar") 45 | Gdip_SetProgress(PictureObj, 50, 0xff0993ea, 0xffbde5ff, "50`%") 46 | Gui1.Title := "Example 9 - gdi+ progress bar" 47 | Gui1.Show("AutoSize") 48 | Return 49 | 50 | ;####################################################################### 51 | 52 | ; This subroutine is activated every time we move the slider as I used gSlider in the options of the slider 53 | Slider_Change(GuiCtrlObj, Info) 54 | { 55 | Gdip_SetProgress(GuiCtrlObj.Gui["ProgressBar"], GuiCtrlObj.Value, 0xff0993ea, 0xffbde5ff, GuiCtrlObj.Value "`%") 56 | } 57 | 58 | ;####################################################################### 59 | 60 | Gdip_SetProgress(GuiCtrl, Percentage, Foreground, Background:=0x00000000, Text:="", TextOptions:="x0p y15p s60p Center cff000000 r4 Bold", Font:="Arial") 61 | { 62 | ; We first want the hwnd (handle to the picture control) so that we know where to put the bitmap we create 63 | ; We also want to width and height (posw and Posh) 64 | GuiCtrl.GetPos(&X, &Y, &Posw, &Posh) 65 | hwnd := GuiCtrl.Hwnd 66 | 67 | ; Create 2 brushes, one for the background and one for the foreground. Remember this is in ARGB 68 | pBrushFront := Gdip_BrushCreateSolid(Foreground), pBrushBack := Gdip_BrushCreateSolid(Background) 69 | ; Create a gdi+ bitmap the width and height that we found the picture control to be 70 | ; We will then get a reference to the graphics of this bitmap 71 | ; We will also set the smoothing mode of the graphics to 4 (Antialias) to make the shapes we use smooth 72 | pBitmap := Gdip_CreateBitmap(Posw, Posh), G := Gdip_GraphicsFromImage(pBitmap), Gdip_SetSmoothingMode(G, 4) 73 | 74 | ; We will fill the background colour with out background brush 75 | ; x = 0, y = 0, w = Posw, h = Posh 76 | Gdip_FillRectangle(G, pBrushBack, 0, 0, Posw, Posh) 77 | 78 | ; We will then fill a rounded rectangle with our other brush, starting at x = 4 and y = 4 79 | ; The total width is now Posw-8 as we have slightly indented the actual progress bar 80 | ; The last parameter which is the amount the corners will be rounded by in pixels has been made to be 3 pixels... 81 | ; ...however I have made it so that they are smaller if the percentage is too small as it cannot be rounded by that much 82 | Gdip_FillRoundedRectangle(G, pBrushFront, 4, 4, (Posw-8)*(Percentage/100), Posh-8, (Percentage >= 3) ? 3 : Percentage) 83 | 84 | ; As mentioned in previous examples, we will provide Gdip_TextToGraphics with the width and height of the graphics 85 | ; We will then write the percentage centred onto the graphics (Look at previous examples to understand all options) 86 | ; 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 87 | ; such as "Finished!" or whatever, otherwise it will write the percentage to it 88 | Gdip_TextToGraphics(G, (Text != "") ? Text : Round(Percentage) "`%", TextOptions, Font, Posw, Posh) 89 | 90 | ; We then get a gdi bitmap from the gdi+ one we've been working with... 91 | hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap) 92 | ; ... and set it to the hwnd we found for the picture control 93 | SetImage(hwnd, hBitmap) 94 | 95 | ; We then must delete everything we created 96 | ; So the 2 brushes must be deleted 97 | ; Then we can delete the graphics, our gdi+ bitmap and the gdi bitmap 98 | Gdip_DeleteBrush(pBrushFront), Gdip_DeleteBrush(pBrushBack) 99 | Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap) 100 | Return 0 101 | } 102 | 103 | ;####################################################################### 104 | 105 | Gui_Close(GuiObj) { 106 | GuiClose: 107 | ExitApp 108 | return 109 | } 110 | 111 | ExitFunc(ExitReason, ExitCode) 112 | { 113 | global 114 | ; gdi+ may now be shutdown 115 | Gdip_Shutdown(pToken) 116 | } 117 | 118 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.8-Write.text.onto.a.gui.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 8 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to write text onto a gui 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | OnExit ExitFunc 20 | 21 | ; Set the width and height we want as our drawing area, to draw everything in. This will be the dimensions of our bitmap 22 | Width := 300, Height := 200 23 | 24 | ; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption 25 | ;AHK v1 26 | ;Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs 27 | ;Gui, 1: Add, Edit, w%Width% h20 y300 vMeEdit 28 | ;Gui, 1: Show, NA 29 | Gui1 := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 30 | Gui1.Add("Edit", "w" Width " h20 y300 vMeEdit", "") 31 | Gui1.Show("NA") 32 | 33 | ; Get a handle to this window we have created in order to update it later 34 | hwnd1 := WinExist() 35 | 36 | ; Create a gdi bitmap with width and height of what we are going to draw into it. This is the entire drawing area for everything 37 | hbm := CreateDIBSection(Width, Height) 38 | 39 | ; Get a device context compatible with the screen 40 | hdc := CreateCompatibleDC() 41 | 42 | ; Select the bitmap into the device context 43 | obm := SelectObject(hdc, hbm) 44 | 45 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions 46 | G := Gdip_GraphicsFromHDC(hdc) 47 | 48 | ; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling) 49 | Gdip_SetSmoothingMode(G, 4) 50 | 51 | ; Create a partially transparent, black brush (ARGB = Transparency, red, green, blue) to draw a rounded rectangle with 52 | pBrush := Gdip_BrushCreateSolid(0xaa000000) 53 | 54 | ; Fill the graphics of the bitmap with a rounded rectangle using the brush created 55 | ; Filling the entire graphics - from coordinates (0, 0) the entire width and height 56 | ; The last parameter (20) is the radius of the circles used for the rounded corners 57 | Gdip_FillRoundedRectangle(G, pBrush, 0, 0, Width, Height, 20) 58 | 59 | ; Delete the brush as it is no longer needed and wastes memory 60 | Gdip_DeleteBrush(pBrush) 61 | 62 | ; We can specify the font to use. Here we use Arial as most systems should have this installed 63 | Font := "Arial" 64 | ; Next we can check that the user actually has the font that we wish them to use 65 | ; If they do not then we can do something about it. I choose to give a wraning and exit! 66 | If !Gdip_FontFamilyCreate(Font) 67 | { 68 | MsgBox "The font you have specified does not exist on the system" 69 | ExitApp 70 | } 71 | 72 | ; There are a lot of things to cover with the function Gdip_TextToGraphics 73 | 74 | ; The 1st parameter is the graphics we wish to use (our canvas) 75 | 76 | ; The 2nd parameter is the text we wish to write. It can include new lines `n 77 | 78 | ; The 3rd parameter, the options are where all the action takes place... 79 | ; You can write literal x and y coordinates such as x20 y50 which would place the text at that position in pixels 80 | ; or you can include the last 2 parameters (Width and Height of the Graphics we will use) and then you can use x10p 81 | ; which will place the text at 10% of the width and y30p which is 30% of the height 82 | ; The same percentage marker may be used for width and height also, so w80p makes the bounding box of the rectangle the text 83 | ; will be written to 80% of the width of the graphics. If either is missed (as I have missed height) then the height of the bounding 84 | ; box will be made to be the height of the graphics, so 100% 85 | 86 | ; Any of the following words may be used also: Regular,Bold,Italic,BoldItalic,Underline,Strikeout to perform their associated action 87 | 88 | ; To justify the text any of the following may be used: Near,Left,Centre,Center,Far,Right with different spelling of words for convenience 89 | 90 | ; The rendering hint (the quality of the antialiasing of the text) can be specified with r, whose values may be: 91 | ; SystemDefault = 0 92 | ; SingleBitPerPixelGridFit = 1 93 | ; SingleBitPerPixel = 2 94 | ; AntiAliasGridFit = 3 95 | ; AntiAlias = 4 96 | 97 | ; The size can simply be specified with s 98 | 99 | ; The colour and opacity can be specified for the text also by specifying the ARGB as demonstrated with other functions such as the brush 100 | ; So cffff0000 would make a fully opaque red brush, so it is: cARGB (the literal letter c, follwed by the ARGB) 101 | 102 | ; The 4th parameter is the name of the font you wish to use 103 | 104 | ; As mentioned previously, you don not need to specify the last 2 parameters, the width and height, unless 105 | ; you are planning on using the p option with the x,y,w,h to use the percentage 106 | Options := "x10p y30p w80p Centre cbbffffff r4 s20 Underline Italic" 107 | Gdip_TextToGraphics(G, "Tutorial 8`n`nThank you for trying this example", Options, Font, Width, Height) 108 | 109 | 110 | ; Update the specified window we have created (hwnd1) with a handle to our bitmap (hdc), specifying the x,y,w,h we want it positioned on our screen 111 | ; With some simple maths we can place the gui in the centre of our primary monitor horizontally and vertically at the specified heigth and width 112 | UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height) 113 | 114 | ; By placing this OnMessage here. The function WM_LBUTTONDOWN will be called every time the user left clicks on the gui 115 | OnMessage(0x201, WM_LBUTTONDOWN) 116 | 117 | 118 | ; Select the object back into the hdc 119 | SelectObject(hdc, obm) 120 | 121 | ; Now the bitmap may be deleted 122 | DeleteObject(hbm) 123 | 124 | ; Also the device context related to the bitmap may be deleted 125 | DeleteDC(hdc) 126 | 127 | ; The graphics may now be deleted 128 | Gdip_DeleteGraphics(G) 129 | Return 130 | 131 | ;####################################################################### 132 | 133 | ; This function is called every time the user clicks on the gui 134 | ; The PostMessage will act on the last found window (this being the gui that launched the subroutine, hence the last parameter not being needed) 135 | WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) 136 | { 137 | PostMessage 0xA1, 2 138 | } 139 | 140 | ;####################################################################### 141 | 142 | ExitFunc(ExitReason, ExitCode) 143 | { 144 | global 145 | ; gdi+ may now be shutdown on exiting the program 146 | Gdip_Shutdown(pToken) 147 | } 148 | 149 | -------------------------------------------------------------------------------- /Gdip_Toolbox.ahk: -------------------------------------------------------------------------------- 1 | #include Gdip_All.ahk 2 | 3 | ; Creates always on top window with current screen making impression as if screen froze 4 | ; Argument 'shouldFreeze' value 1: freeze, 0: unfreeze, -1: unfreeze all (if frozen more than once) 5 | ScreenFreeze(shouldFreeze:=1) { 6 | static freezeCounter:=0, frozenWindow:="" 7 | static raster := 0x40000000 + 0x00CC0020 ; to capture layered windows too 8 | 9 | switch shouldFreeze { 10 | case -2: ; Unfreeze everything 11 | if (freezeCounter > 0) { 12 | frozenWindow.Hide() 13 | } 14 | freezeCounter := 0 15 | return 16 | 17 | case -1: ; Refresh frozen picture 18 | if (freezeCounter < 1) { 19 | return 20 | } 21 | frozenWindow.Hide() 22 | 23 | case 0: ; Unfreeze one level 24 | if (freezeCounter < 1) { 25 | return 26 | } 27 | freezeCounter -= 1 28 | if (freezeCounter < 1) { 29 | frozenWindow.Hide() 30 | } 31 | return 32 | 33 | case 1: ; Increase freeze level 34 | freezeCounter += 1 35 | if (freezeCounter > 1) { 36 | return 37 | } 38 | 39 | default: 40 | throw Error("Wrong argument value: " shouldFreeze) 41 | } 42 | 43 | pToken := Gdip_Startup() 44 | pBitmap := Gdip_BitmapFromScreen(0 "|" 0 "|" A_ScreenWidth "|" A_ScreenHeight, raster) 45 | 46 | if (!frozenWindow) { 47 | frozenWindow := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 48 | } 49 | 50 | 51 | hbm := Gdip_CreateHBITMAPFromBitmap(pBitmap) 52 | Gdip_DisposeImage(pBitmap) 53 | hdc := CreateCompatibleDC() 54 | obm := SelectObject(hdc, hbm) 55 | frozenWindow.Show("NA") 56 | UpdateLayeredWindow(frozenWindow.hwnd, hdc, 0, 0, A_ScreenWidth, A_ScreenHeight) 57 | 58 | SelectObject(hdc, obm) 59 | 60 | DeleteObject(hbm) 61 | DeleteDC(hdc) 62 | Gdip_Shutdown(pToken) 63 | 64 | frozenWindow.Opt("+OwnDialogs") 65 | return frozenWindow 66 | } 67 | 68 | ScreenUnfreeze(shouldFreeze:=0) { 69 | return ScreenFreeze(shouldFreeze) 70 | } 71 | 72 | ; Draws colored rectangle (with optional transparency) 73 | ; Use `returnValue.Destroy()` to destroy the rectangle (AHK Gui object) 74 | DrawRectangle(x1, y1, x2, y2, color, alpha:=1, &parentWindow:="") { 75 | if (parentWindow && !parentWindow.HasProp("hwnd")) { 76 | throw Error("The 'parentWindow' argument needs to have proper 'hwnd' property (for example a Gui object has it). Skip this value to create one.") 77 | } 78 | 79 | pToken := Gdip_Startup() 80 | 81 | w := x2 - x1 + 1 82 | h := y2 - y1 + 1 83 | 84 | if (!parentWindow) { 85 | parentWindow := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 86 | parentWindow.Show("NA") 87 | } 88 | 89 | hdc := CreateCompatibleDC() 90 | hbm := CreateDIBSection(w, h) 91 | obm := SelectObject(hdc, hbm) 92 | G := Gdip_GraphicsFromHDC(hdc) 93 | pBrush := Gdip_BrushCreateSolid((floor(alpha * 0xFF) << 24) | color) 94 | Gdip_FillRectangle(G, pBrush, 0, 0, w, h) 95 | Gdip_DeleteBrush(pBrush) 96 | 97 | UpdateLayeredWindow(parentWindow.hwnd, hdc, x1, y1, w, h) 98 | SelectObject(hdc, obm) 99 | 100 | DeleteObject(hbm) 101 | DeleteDC(hdc) 102 | Gdip_DeleteGraphics(G) 103 | 104 | Gdip_Shutdown(pToken) 105 | 106 | return parentWindow 107 | } 108 | 109 | ; Draws colored rectangle (with optional transparency) 110 | ; Use `returnValue.Destroy()` to destroy the rectangle (AHK Gui object) 111 | DrawCircle(x, y, radius, color, alpha:=1, &parentWindow:="") { 112 | if (parentWindow && !parentWindow.HasProp("hwnd")) { 113 | throw Error("The 'parentWindow' argument needs to have proper 'hwnd' property (for example a Gui object has it). Skip this value to create one.") 114 | } 115 | 116 | pToken := Gdip_Startup() 117 | x1 := x - radius + 1 118 | y1 := y - radius + 1 119 | 120 | w := radius * 2 - 1 121 | h := radius * 2 - 1 122 | 123 | if (!parentWindow) { 124 | parentWindow := Gui("-Caption +Disabled +E0x80000 -LastFound +AlwaysOnTop +ToolWindow -OwnDialogs") 125 | parentWindow.Show("NA") 126 | } 127 | 128 | hdc := CreateCompatibleDC() 129 | hbm := CreateDIBSection(w, h) 130 | obm := SelectObject(hdc, hbm) 131 | G := Gdip_GraphicsFromHDC(hdc) 132 | pBrush := Gdip_BrushCreateSolid((floor(alpha * 0xFF) << 24) | color) 133 | ; pBrush := Gdip_BrushCreateHatch((floor(alpha * 0xFF) << 24) | color, 0x7F1155FF, 4) ; Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle:=0) 134 | Gdip_FillEllipse(G, pBrush, 0, 0, w, h) 135 | ; Gdip_FillRectangle(G, pBrush, 0, 0, w, h) 136 | Gdip_DeleteBrush(pBrush) 137 | 138 | UpdateLayeredWindow(parentWindow.hwnd, hdc, x1, y1, w, h) 139 | SelectObject(hdc, obm) 140 | 141 | DeleteObject(hbm) 142 | DeleteDC(hdc) 143 | Gdip_DeleteGraphics(G) 144 | 145 | Gdip_Shutdown(pToken) 146 | 147 | return parentWindow 148 | } 149 | 150 | DrawTemporaryCircle(x, y, radius, color, alpha, time) { 151 | circleWindow := DrawCircle(x, y, radius, color, alpha) 152 | SetTimer(DestroyCircle, -time) 153 | 154 | DestroyCircle() { 155 | circleWindow.Destroy() 156 | } 157 | } 158 | 159 | 160 | ; Draws colored rectangle (with optional transparency), a slow version without Gdip use 161 | ; Use `returnValue.Destroy()` to destroy the rectangle (AHK Gui object) 162 | DrawRectangleSlow(x1, y1, x2, y2, color, alpha:=1) { 163 | global CoordText 164 | 165 | w := x2 - x1 + 1 166 | h := y2 - y1 + 1 167 | myGui := Gui("-Caption +E0x80000 +AlwaysOnTop +ToolWindow -DPIScale +LastFound +OwnDialogs") 168 | myGui.BackColor := color 169 | WinSetTransparent(round(255*alpha), myGui) 170 | myGui.Show() 171 | myGui.Move(x1, y1, w, h) 172 | 173 | return myGui 174 | } 175 | 176 | ; Gets pixel color using screen buffer which refreshes on specified time period (150 ms by default) 177 | GetPixelColorBuffered(x, y, refreshRate:=150, waitForUpdate:=false) { 178 | static isBufferReady:=false, myDC:=0, screenX, screenY 179 | static lastUpdateTick := 0 180 | 181 | timeRemaining := lastUpdateTick + refreshRate - A_TickCount 182 | 183 | if (timeRemaining <= 0 || waitForUpdate) { 184 | if (waitForUpdate && timeRemaining > 0) { 185 | sleep timeRemaining 186 | } 187 | UpdateScreenBuffer(0) 188 | lastUpdateTick := A_TickCount 189 | } 190 | 191 | return GetPixelColorFromBuffer() 192 | 193 | GetPixelColorFromBuffer() { 194 | if (!IsInteger(x) || !IsInteger(y)) { 195 | throw Error("Wrong parameter types: x=" x ", y=" y) 196 | } 197 | 198 | ; check if there is a valid data buffer 199 | if (!isBufferReady) { 200 | Start := A_TickCount 201 | while (!isBufferReady) { 202 | Sleep 10 203 | if (A_TickCount - Start > 5000) { ; time out if data is not ready after 5 seconds 204 | return -3 205 | } 206 | } 207 | } 208 | return DllCall("GetPixel", "Uint", myDC, "int", x - screenX, "int", y - screenY) 209 | } 210 | 211 | ; Default window handle is NULL (entire screen) 212 | UpdateScreenBuffer(windowHandle:=0) { 213 | static oldObject := 0, hBuffer := 0 214 | static screenWOld := 0, screenHOld := 0 215 | 216 | ; get screen dimensions 217 | screenX := SysGet(76) 218 | screenY := SysGet(77) 219 | screenW := SysGet(78) 220 | screenH := SysGet(79) 221 | isBufferReady := 0 222 | 223 | ; determine whether the old buffer can be reused 224 | bufferInvalid := screenW != screenWOld || screenH != screenHOld || myDC == 0 || hBuffer == 0 225 | screenWOld := screenW 226 | screenHOld := screenH 227 | if (bufferInvalid) { 228 | ; cleanly discard the old buffer 229 | DllCall("SelectObject", "Uint", myDC, "Uint", oldObject) 230 | DllCall("DeleteDC", "Uint", myDC) 231 | DllCall("DeleteObject", "Uint", hBuffer) 232 | 233 | ; create a new empty buffer 234 | myDC := CreateCompatibleDC(0) 235 | hBuffer := CreateDIBSection(screenW, screenH, myDC) 236 | oldObject := DllCall("SelectObject", "Uint", myDC, "Uint", hBuffer) 237 | } 238 | screenDC := DllCall("GetDC", "Uint", windowHandle) 239 | 240 | ; retrieve the whole screen into the newly created buffer 241 | DllCall("BitBlt", "Uint", myDC, "int", 0, "int", 0, "int", screenW, "int", screenH, "Uint", screenDC, "int", screenX, "int", screenY, "Uint", 0x40000000 | 0x00CC0020) 242 | 243 | ; important: release the DC of the screen 244 | DllCall("ReleaseDC", "Uint", windowHandle, "Uint", screenDC) 245 | isBufferReady := 1 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.10-Rotate.Flip.or.Mirror.an.image.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 10 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to rotate, flip or mirror an image 5 | 6 | #SingleInstance Force 7 | ;#NoEnv 8 | ;SetBatchLines -1 9 | 10 | ; Uncomment if Gdip.ahk is not in your standard library 11 | #Include ../Gdip_All.ahk 12 | 13 | ; Start gdi+ 14 | If !pToken := Gdip_Startup() 15 | { 16 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 17 | ExitApp 18 | } 19 | OnExit ExitFunc 20 | 21 | ; Gui 1 22 | ; Create a gui where we can select the file we want to rotate, the angle to rotate it by and whether we want to flip it 23 | ; Here is the slider allowing rotation between 0 and 360 degrees 24 | ; Create 2 checkboxes, to select whether we want to flip it horizontally or vertically 25 | ; Gui 2 26 | ; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption 27 | ; This will be used as the 2nd gui so that we can show our image on it 28 | 29 | ;AHK v1 30 | ;Gui, 1: +ToolWindow +AlwaysOnTop 31 | ;Gui, 1: Add, Edit, x10 y10 w300 r1 vFile, %A_ScriptDir%\MJ.jpg 32 | ;Gui, 1: Add, Button, x+10 yp+0 w75 gGo Default, &Go 33 | ;Gui, 1: Add, Slider, x10 y+10 w300 Tooltip vAngle Range0-360, 0 34 | ;Gui, 1: Add, CheckBox, x+10 yp+0 vHorizontal, Flip horizontally 35 | ;Gui, 1: Add, CheckBox, x+10 yp+0 vVertical, Flip vertically 36 | ;Gui, 1: Show, x0 y0 AutoSize 37 | ;Gui, 2: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs 38 | ;Gui, 2: Show, NA 39 | 40 | Gui1 := Gui("+ToolWindow +AlwaysOnTop") 41 | Gui1.OnEvent("Close", Gui_Close) 42 | Gui1.Add("Edit", "x10 y10 w300 r1 vFile", A_ScriptDir "\MJ.jpg") 43 | ButtonObj := Gui1.Add("Button", "x+10 yp+0 w75 Default", "Go") 44 | ButtonObj.OnEvent("Click", ButtonGo_Click) 45 | Gui1.Add("Slider", "x10 y+10 w300 Tooltip vAngle Range0-360", 0) 46 | Gui1.Add("CheckBox", "x+10 yp+0 vHorizontal", "Flip horizontally") 47 | Gui1.Add("CheckBox", "x+10 yp+0 vVertical", "Flip vertically") 48 | Gui1.Show("x0 y0 AutoSize") 49 | Gui2 := Gui("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs") 50 | Gui2.Name := "Holder" 51 | Gui2.Show("NA") 52 | 53 | ; Get a handle to this window we have created in order to update it later 54 | global hwnd2 := WinExist() 55 | 56 | ; By placing this OnMessage here. The function WM_LBUTTONDOWN will be called every time the user left clicks on the gui. This can be used for dragging the image 57 | OnMessage(0x201, WM_LBUTTONDOWN) 58 | Return 59 | 60 | ;##################################################################### 61 | 62 | ButtonGo_Click(GuiCtrlObj, Info) 63 | { 64 | ; Submit the variables to see the degress to rotate by and whether to flip the image 65 | ;AHK v1 66 | ;global File, Angle, Horizontal, Vertical 67 | ;Go: ; this label is ok inside the func as long as the vars above are global 68 | ;Gui, 1: +OwnDialogs 69 | ;Gui, 1: Submit, NoHide 70 | GuiCtrlObj.Gui.Opt("+OwnDialogs") 71 | GuiCtrlObj.Gui.Submit(false) 72 | File := GuiCtrlObj.Gui["File"].Value 73 | Angle := GuiCtrlObj.Gui["Angle"].Value 74 | Horizontal := GuiCtrlObj.Gui["Horizontal"].Value 75 | Vertical := GuiCtrlObj.Gui["Vertical"].Value 76 | 77 | ; If the file in the edit field is not a valid image then return 78 | If !pBitmap := Gdip_CreateBitmapFromFile(File) 79 | Return 80 | 81 | ; 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 82 | OriginalWidth := Gdip_GetImageWidth(pBitmap), OriginalHeight := Gdip_GetImageHeight(pBitmap) 83 | Ratio := OriginalWidth/OriginalHeight 84 | 85 | ; 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 86 | If (OriginalWidth >= A_ScreenWidth//2) || (OriginalHeight >= A_ScreenHeight//2) 87 | { 88 | If (OriginalWidth >= OriginalHeight) 89 | Width := A_ScreenWidth//2, Height := Width*(1/Ratio) 90 | Else 91 | Height := A_ScreenHeight//2, Width := Height*Ratio 92 | } 93 | Else 94 | Width := OriginalWidth, Height := OriginalHeight 95 | 96 | ; Width and Height now contain the new dimensions the image on screen will be 97 | 98 | ; 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 99 | ; We need to know the new dimensions of the image 100 | ; With Gdip_GetRotatedDimensions we can plug in the width and height of the image, and the angle it is to be rotated by 101 | ; The last 2 parameters are the variables in which tio store the new width and height of the rotated image 102 | ; RWidth and RHeight now contain the dimensions of the rotated image 103 | Gdip_GetRotatedDimensions(Width, Height, Angle, &RWidth, &RHeight) 104 | 105 | ; We rotate an image about the top left corner of the image, however this will result in the image moving off the canvas 106 | ; 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 107 | ; As with the above function, we plug in the width, height and angle to rotate by 108 | ; 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) 109 | ; xTranslation and yTranslation now contain the distance to shift the image by 110 | Gdip_GetRotatedTranslation(Width, Height, Angle, &xTranslation, &yTranslation) 111 | 112 | ; 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) 113 | hbm := CreateDIBSection(RWidth, RHeight) 114 | 115 | ; Get a device context compatible with the screen 116 | hdc := CreateCompatibleDC() 117 | 118 | ; Select the bitmap into the device context 119 | obm := SelectObject(hdc, hbm) 120 | 121 | ; Get a pointer to the graphics of the bitmap, for use with drawing functions, 122 | ; and set the InterpolationMode to HighQualityBicubic = 7 so that when resizing the image still looks good 123 | G := Gdip_GraphicsFromHDC(hdc), Gdip_SetInterpolationMode(G, 7) 124 | 125 | ; 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 126 | Gdip_TranslateWorldTransform(G, xTranslation, yTranslation) 127 | 128 | ; We can also rotate the graphics by the angle we desire 129 | Gdip_RotateWorldTransform(G, Angle) 130 | 131 | ; If we wish to flip the image horizontally, then we supply Gdip_ScaleWorldTransform(G, x, y) with a negative x transform 132 | ; 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 133 | ; We must then shift the graphics again to ensure the image will be within the 'canvas' 134 | ; You can see that if we wish to flip vertically we supply a negative y transform 135 | If Horizontal 136 | Gdip_ScaleWorldTransform(G, -1, 1), Gdip_TranslateWorldTransform(G, -Width, 0) 137 | If Vertical 138 | Gdip_ScaleWorldTransform(G, 1, -1), Gdip_TranslateWorldTransform(G, 0, -Height) 139 | 140 | 141 | ; 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) 142 | ; 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) 143 | Gdip_DrawImage(G, pBitmap, 0, 0, Width, Height, 0, 0, OriginalWidth, OriginalHeight) 144 | 145 | ; 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 146 | Gdip_ResetWorldTransform(G) 147 | 148 | ; 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 149 | UpdateLayeredWindow(hwnd2, hdc, (A_ScreenWidth-RWidth)//2, (A_ScreenHeight-RHeight)//2, RWidth, RHeight) 150 | 151 | ; As always we will dispose of everything we created 152 | ; So we select the object back into the hdc, the delete the bitmap and hdc 153 | SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc) 154 | ; We will then dispose of the graphics and bitmap we created 155 | Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap) 156 | Return 157 | } 158 | 159 | ;##################################################################### 160 | 161 | ; This is the function to allow the user to drag the image drawn on the screen (this being gui 2) 162 | WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) 163 | { 164 | ;AHK v1 165 | ;If (A_Gui = 2) 166 | ;PostMessage 0xA1, 2 167 | 168 | Gui := GuiFromHwnd(hwnd) 169 | GuiControl := GuiCtrlFromHwnd(hwnd) 170 | if GuiControl 171 | Gui := GuiControl.Gui 172 | If (Gui.Name = "Holder") 173 | PostMessage 0xA1, 2 174 | } 175 | 176 | ;##################################################################### 177 | 178 | ; If the user closes the gui or closes the program then we want to shut down gdi+ and exit the application 179 | Gui_Close(GuiObj) { 180 | GuiClose: 181 | ExitApp 182 | return 183 | } 184 | 185 | ExitFunc(ExitReason, ExitCode) 186 | { 187 | global 188 | Gdip_Shutdown(pToken) 189 | } 190 | 191 | -------------------------------------------------------------------------------- /Examples/Gdip.Tutorial.11-Using.BRAs.to.perform.animations.ahk: -------------------------------------------------------------------------------- 1 | ; gdi+ ahk tutorial 11 written by tic (Tariq Porter) 2 | ; Requires Gdip.ahk either in your Lib folder as standard library or using #Include 3 | ; 4 | ; Tutorial to demonstrate how to use BRA files, in this instance for animation 5 | 6 | #SingleInstance Force 7 | ; #NoEnv 8 | 9 | ; Uncomment if Gdip.ahk is not in your standard library 10 | #Include ../Gdip_All.ahk 11 | 12 | ; Start gdi+ 13 | If !pToken := Gdip_Startup() 14 | { 15 | MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system" 16 | ExitApp 17 | } 18 | ; On exiting the program we will go to Exit subroutine to clean up any resources 19 | ; OnExit, Exit 20 | OnExit AppExit 21 | 22 | ; I've added a simple new function here, just to ensure if anyone is having any problems then to make sure they are using the correct library version 23 | if (Gdip_LibrarySubVersion() < 1.50) 24 | { 25 | MsgBox "This example requires v1.50 of the Gdip library" 26 | ExitApp 27 | } 28 | 29 | ; Get the dimensions of the work area of the primary monitor 30 | MonInfo := GetMonitorInfo(GetPrimaryMonitor()) 31 | WALeft := MonInfo.WALeft 32 | WATop := MonInfo.WATop 33 | WARight := MonInfo.WARight 34 | WABottom := MonInfo.WABottom 35 | WAWidth := WARight - WALeft 36 | WAHeight := WABottom- WATop 37 | 38 | ; Create our gui with WS_EX_LAYERED style = 0x80000 39 | ;AHK v1 40 | ;Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner 41 | ;Gui, 1: Show, NA 42 | Gui1 := Gui("-Caption +E0x80000 +LastFound +OwnDialogs +Owner") 43 | Gui1.Show("NA") 44 | 45 | ; Get a handle to this window 46 | hwnd1 := WinExist() 47 | 48 | ; A BRA File is a collection of files packed into one Binary Resource Archive 49 | ; There are a number of functions for use with BRA files. You must download the BRA Standard Library and either put it in your Lib folder or use #Include 50 | ; The advantages over using the separate files are: 51 | ; - One BRA file is cleaner to transport with your script than several other files 52 | ; - It is easier to cleanup 1 BRA after use if needed 53 | ; - A BRA file can be read once into memory using FileRead and is no longer needed 54 | ; - A BRA file is better for your disk (especially flash disks) as it only uses 1 read operation. Flash disks have a finite number of read/writes 55 | ; - BRA files are quicker to access as they are read from RAM and not from disk 56 | ; - It is easier to use BRA files as the library provides all the functions needed 57 | 58 | ; If the image we want to work with does not exist on disk, then download it... 59 | If !FileExist("Gdip.tutorial.file-fish.bra") 60 | { 61 | MsgBox "Could not read file 'Gdip.tutorial.file-fish.bra' in the current directory" 62 | ExitApp 63 | } 64 | ; UrlDownloadToFile, http://www.autohotkey.net/~tic/Gdip.tutorial.file-fish.bra, Gdip.tutorial.file-fish.bra 65 | 66 | ; First you will need to read the BRA into a variable. It is now stored in the variable BRA 67 | If !(FileObject := FileOpen("Gdip.tutorial.file-fish.bra", "r")) { 68 | MsgBox "Error opening Gdip.tutorial.file-fish.bra for reading" 69 | ExitApp 70 | } 71 | BRA := Buffer(FileObject.Length) 72 | FileObject.RawRead(BRA) 73 | FileObject.Close() 74 | 75 | ; Get a count of the number of files contained in the BRA 76 | ImageCount := BRA_GetCount(BRA) 77 | 78 | ; Built into the Gdip library is the ability to directly get a pointer to a bitmap from a BRA 79 | ; Gdip_BitmapFromBRA(&BRAFromMemIn, File, Alternate=0) 80 | ; The 1st parameter is the BRA in memory from FileObject.RawRead() 81 | ; The 2nd parameter is the name of the file you wish to get a bitmap for 82 | ; If the 3rd parameter is true (as it is here) then the name (2nd parameter) doesn't go by file name, but instead by file number 83 | ; So we take a pointer to the bitmap of the 1st file 84 | ; I am doing this to get the dimensions of an image. We could have taken any file as they are all the same dimension in this particular BRA 85 | pBitmap := Gdip_BitmapFromBRA(BRA, 1, 1) 86 | 87 | ; PLEASE TAKE NOTE 88 | ; To check if the handle to the bitmap is not actually a bitmap you must check whether the pointer is either 0 or negative 89 | ; You can do this by checking if pBitmap < 1. Normally you would have checked if it was just 0 90 | ; 0 would mean you have a blank pointer 91 | ; a negative number means that the function has returned an error 92 | If (pBitmap < 1) 93 | { 94 | MsgBox "Could not load the image specified! Error: " pBitmap 95 | ExitApp 96 | } 97 | 98 | ; Calculate the dimensions of the gui. I advise you always work on fractions of the screen dimensions to ensure it will look similar on other screens 99 | ; If you feel like it, you could go further and change the dimensions based on 16:9 or 4:3 100 | WinWidth := Floor(WAWidth/2.5) 101 | WinHeight := Round(WinWidth//4) 102 | 103 | ; Get the width and height of a single bitmap. This bitmap is the fish banner 104 | Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap) 105 | 106 | ; Calculate the dimensions the fish banner will be resized to, to fit nicely on the gui 107 | NewWidth := 0.9*WinWidth 108 | NewHeight := (NewWidth/Width)*Height 109 | NewMargin := (WinWidth-NewWidth)/2 110 | 111 | ; This is standard for all guis. Create a gdi bitmap and get a graphics context to draw into 112 | ; The bitmap will be out entire drawing area, so will be the same size as the gui 113 | hbm := CreateDIBSection(WinWidth, WinHeight), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm) 114 | G := Gdip_GraphicsFromHDC(hdc) 115 | 116 | ; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling) 117 | Gdip_SetSmoothingMode(G, 4) 118 | ; Gdip_SetInterpolationMode of 7 is used to ensure images are resized using HighQualityBicubic so that when the fish banner is redrawn it looks as good as possible 119 | ; I have commented it as it uses slightly more of the processor 120 | ;Gdip_SetInterpolationMode(G, 7) 121 | 122 | ; This brush has not been covered previously in my tutorials. Gdip_CreateLineBrushFromRect will create a fading brush 123 | ; Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode=1, WrapMode=1) 124 | ; You can see that it fades from 0xee000000 (mostly opaque black) to 0x77000000 (partially transparent black) 125 | ; You have 2 more optional parameters: 126 | ; LinearGradientMode specifies the direction of fill. Horizontal, vertical, diagonal, etc 127 | ; WrapMode specifies how to fill if the rectangle does not fit the area it is trying to fill. So for example it could tile the brush 128 | pBrush := Gdip_CreateLineBrushFromRect(0, 0, WinWidth, WinHeight, 0xee000000, 0x77000000) 129 | 130 | ; Standard rounded rectangle to be used with the gradient brush for the background of our gui 131 | Gdip_FillRoundedRectangle(G, pBrush, 0, 0, WinWidth, WinHeight, 20) 132 | 133 | ; We can specify the font to use. Here we use Arial as most systems should have this installed 134 | Font := "Arial" 135 | ; Next we can check that the user actually has the font that we wish them to use 136 | ; If they do not then we can do something about it. I choose to give a wraning and exit! 137 | If !(hFamily := Gdip_FontFamilyCreate(Font)) 138 | { 139 | MsgBox "The font you have specified does not exist on the system" 140 | ExitApp 141 | } 142 | ; Delete font family as we now know the font does exist 143 | Gdip_DeleteFontFamily(hFamily) 144 | 145 | ; There are 2 new additions to Gdip_TextToGraphics 146 | ; The first additoon is shown below 147 | ; You should have already used Gdip_TextToGraphics so I wont go through all the options 148 | ; We are going to get the height of the text we want to draw so that we can create gradient brush for future use 149 | ; I put all the same options that I will use later, except I just put an arbitrary colour in and also just wrote the letter T as that will be the tallest letter 150 | ; Most importantly is the last parameter that is new. It is the measure parameter 151 | ; If specified then it will still get you the dimensions of the text, but will not actually draw it 152 | Options := "x10p y60p w80p Centre cff000000 r4 s18p Bold" 153 | RC := Gdip_TextToGraphics(G, "T", Options, Font, WinWidth, WinHeight, 1) 154 | ; StringSplit RC to get the dimensions of the text. The width is not important to me, just the starting y and height 155 | ; x = RC1, y = RC2, width = RC3, height = RC4, number of characters = RC5, number of lines = RC6 156 | RC := StrSplit(RC, "|") 157 | 158 | ; I can now create a gradient brush for the text (to be used with another new addition to Gdip_TextToGraphics 159 | ; I am going to create it using the y and height we just got. The width doesnt matter as I will make the brush the same width as the gui 160 | ; so no matter how wide the writing it will still be within the brushes width 161 | pTextBrush := Gdip_CreateLineBrushFromRect(0, RC[2], WinWidth, RC[4], 0xffDDF7F7, 0x774549DF) 162 | 163 | ; In the options for Gdip_TextToGraphics we can now specify the brush we just created rather than just specifying the argb as we normally do 164 | ; We literally pass the pointer to the brush (so our brush variable) after the c 165 | ; These options will be used for the duration of the program now for writing text 166 | Options := "x10p y60p w80p Centre c" . pTextBrush . " r4 s18p Bold" 167 | 168 | ; We can dispose of the bitmap we got from the bra. We just needed it for its dimensions 169 | Gdip_DisposeImage(pBitmap) 170 | 171 | ; We will keep a variable to count which fish image we are currently showing and incremeent it for the appearance of a video 172 | Index := 0 173 | 174 | ; Same as always. On LBUTTONDOWN then run the function to allow dragging of the gui 175 | OnMessage(0x201, WM_LBUTTONDOWN) 176 | 177 | ; Update this all onto the window so that it has a postion on screen 178 | ; In future we wont need to supply x,y,w,h any more 179 | UpdateLayeredWindow(hwnd1, hdc, (WAWidth-WinWidth)//2, (WAHeight-WinHeight)//2, WinWidth, WinHeight) 180 | 181 | ; Set the timers 182 | ; UpdateTime to draw the time onto the gui 183 | ; Play to change the image for the fish video 184 | UpdateTime() 185 | SetTimer UpdateTime, 950 186 | SetTimer Play, 70 187 | return 188 | 189 | ;###################################################################### 190 | 191 | UpdateTime() 192 | { 193 | static OldTime := 0 194 | 195 | ; We should probably put critical here so that it isnt interrupted, but the subroutines are so quick that its very unlikely 196 | 197 | ; Get the time in the format of 16:05 06 January 2010 (oops...caught me commenting this at work!) 198 | Time := FormatTime() 199 | 200 | if (Time = OldTime) 201 | return 202 | 203 | ; We are going to get the dimensions of the text for the time 204 | RC := Gdip_TextToGraphics(G, Time, Options, Font, WinWidth, WinHeight, 1) 205 | RC := StrSplit(RC, "|") 206 | 207 | ; We can then clip a rectangle so that we only need to redraw what is contained within it 208 | Gdip_SetClipRect(G, RC[1], RC[2], RC[3], RC[4]) 209 | 210 | ; Gdip_SetCompositingMode to 1, which overwrites anything inside the rectangle 211 | Gdip_SetCompositingMode(G, 1) 212 | ; We fill the background up again 213 | Gdip_FillRectangle(G, pBrush, 0, 0, WinWidth, WinHeight) 214 | ; And Gdip_SetCompositingMode back to 0 so that anything new that is drawn will be blended on top 215 | Gdip_SetCompositingMode(G, 0) 216 | 217 | ; We now write the time onto our gui 218 | ; We are using the options before which uses our white-purple fading brush 219 | ; When actually passing a pBrush to the function as we have done, then it will not dispose of it. You are responsible for disposing of it 220 | Gdip_TextToGraphics(G, Time, Options, Font, WinWidth, WinHeight) 221 | 222 | ; As we do not need to change the x,y,w,h then we dont need to specify those parameters. Just pass the hdc to update our gui 223 | UpdateLayeredWindow(hwnd1, hdc) 224 | 225 | ; Reset the clipping area so that it is not just limited to drawing in the rectangle we just specified 226 | Gdip_ResetClip(G) 227 | 228 | ; Save the time so that we dont redraw until the time changes 229 | OldTime := Time 230 | return 231 | } 232 | 233 | ;###################################################################### 234 | 235 | BRA_GetCount(BRAFromMemIn) { 236 | If !(BRAFromMemIn) 237 | Return -1 238 | Headers := StrSplit(StrGet(BRAFromMemIn, 256, "CP0"), "`n") 239 | Header := StrSplit(Headers[1], "|") 240 | If (Header.Length != 4) || (Header[2] != "BRA!") 241 | Return -2 242 | Info := StrSplit(Headers[2], "|") 243 | If Info.Length != 3 244 | Return -3 245 | Return (Info[1] + 0) 246 | } 247 | 248 | ;###################################################################### 249 | 250 | ; I know it's dirty to have global functions, but this is just really a subroutine, but is also useful to have a single parameter passed 251 | Fade(InOut) 252 | { 253 | global 254 | 255 | ; We will create a simple fade effect when starting or ending the video 256 | ; We need to know whether it will start opaque or transparent 257 | Trans := (InOut = "In") ? 0 : 0.8 258 | 259 | ; Loop the number of times until it is at the specified opacity 260 | numLoops := 0.8/0.05 261 | N := "numLoops" 262 | Loop %N% 263 | { 264 | ; Clip to the area we are drawing for the fish, so that only this rectangle gets drawn to 265 | ; We could do this once at the top of this function, but it is safer to do it each loop so that nothing else can modify it during the sleep 266 | Gdip_SetClipRect(G, NewMargin, NewMargin, NewWidth, NewHeight) 267 | ; Gdip_SetCompositingMode to 1 so that it will erase anything that is currently there 268 | Gdip_SetCompositingMode(G, 1) 269 | ; Fill the background 270 | Gdip_FillRectangle(G, pBrush, 0, 0, WinWidth, WinHeight) 271 | ; Gdip_SetCompositingMode back to 0 so that the fish are drawn onto the background and dont erase it 272 | Gdip_SetCompositingMode(G, 0) 273 | 274 | ; Increment index by 1 so that we get the next image in the sequence 275 | Index++ 276 | ; Again use alternate mode so that we only specify the file number and get a pBitmap for it 277 | pBitmap := Gdip_BitmapFromBRA(BRA, Index, 1) 278 | 279 | ; Draw this image onto our graphics context for the gui (this being our canvas) with the current transparency 280 | Gdip_DrawImage(G, pBitmap, NewMargin, NewMargin, NewWidth, NewHeight, 0, 0, Width, Height, Trans) 281 | 282 | ; Now update the window with the dc as usual 283 | UpdateLayeredWindow(hwnd1, hdc) 284 | 285 | ; We can dispose of the fish bitmap we just retrieved now that it is drawn 286 | Gdip_DisposeImage(pBitmap) 287 | 288 | ; Increase or decrease opacity depending on whether we are fading in or out 289 | Trans := (InOut = "In") ? Trans+0.05 : Trans-0.05 290 | 291 | ; Reset the clipping region so that another function if called can still update the window 292 | Gdip_ResetClip(G) 293 | 294 | ; A sleep to match the length of the Play timer 295 | Sleep 70 296 | } 297 | 298 | ; If we have reached the end of the video then put it back to the beginning after the fade 299 | Index := (Index >= ImageCount) ? 0 : Index 300 | return 301 | } 302 | 303 | ;####################################################################### 304 | 305 | Play() 306 | { 307 | global 308 | Play: 309 | ; Check if we need to fade in or whether we are close enough to the end to have to fade out 310 | if (Index = 0) 311 | Fade("In") 312 | else if (Index = ImageCount-(0.8/0.05)) 313 | Fade("Out") 314 | else 315 | { 316 | ; If we are doing no fading and we are just playing the video.... 317 | 318 | ; We do the same here as we did inside the function 319 | ; We are setting a clipping area for just the fish, then filling the background in (overwiting anything that was there) 320 | ; We set Gdip_SetCompositingMode back to 0 and then get a bitmap for the next fish image and draw it over our background 321 | ; Dispose the image and reset the clipping region 322 | Gdip_SetClipRect(G, NewMargin, NewMargin, NewWidth, NewHeight) 323 | Gdip_SetCompositingMode(G, 1) 324 | Gdip_FillRectangle(G, pBrush, 0, 0, WinWidth, WinHeight) 325 | Gdip_SetCompositingMode(G, 0) 326 | 327 | Index++ 328 | pBitmap := Gdip_BitmapFromBRA(BRA, Index, 1) 329 | Gdip_DrawImage(G, pBitmap, NewMargin, NewMargin, NewWidth, NewHeight, 0, 0, Width, Height, 0.8) 330 | UpdateLayeredWindow(hwnd1, hdc) 331 | Gdip_DisposeImage(pBitmap) 332 | Gdip_ResetClip(G) 333 | } 334 | return 335 | } 336 | 337 | ;####################################################################### 338 | 339 | ; Our function for WM_LBUTTONDOWN allowing us to drag. works on last found window 340 | WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) 341 | { 342 | PostMessage 0xA1, 2 343 | } 344 | 345 | ;####################################################################### 346 | 347 | ; On Exit clean up resources 348 | AppExit(ExitReason, ExitCode) { 349 | global 350 | ; Select the object back into the hdc 351 | SelectObject(hdc, obm) 352 | 353 | ; Now the bitmap may be deleted 354 | DeleteObject(hbm) 355 | 356 | ; Also the device context related to the bitmap may be deleted 357 | DeleteDC(hdc) 358 | 359 | ; The graphics may now be deleted 360 | Gdip_DeleteGraphics(G) 361 | 362 | ; Also delete the 2 brushes we created 363 | Gdip_DeleteBrush(pBrush), Gdip_DeleteBrush(pTextBrush) 364 | Gdip_Shutdown(pToken) 365 | Return 0 366 | } 367 | -------------------------------------------------------------------------------- /Gdip_All.ahk: -------------------------------------------------------------------------------- 1 | ; v1.62 2 | ; 3 | ;##################################################################################### 4 | ;##################################################################################### 5 | ; STATUS ENUMERATION 6 | ; Return values for functions specified to have status enumerated return type 7 | ;##################################################################################### 8 | ; 9 | ; Ok = 0 10 | ; GenericError = 1 11 | ; InvalidParameter = 2 12 | ; OutOfMemory = 3 13 | ; ObjectBusy = 4 14 | ; InsufficientBuffer = 5 15 | ; NotImplemented = 6 16 | ; Win32Error = 7 17 | ; WrongState = 8 18 | ; Aborted = 9 19 | ; FileNotFound = 10 20 | ; ValueOverflow = 11 21 | ; AccessDenied = 12 22 | ; UnknownImageFormat = 13 23 | ; FontFamilyNotFound = 14 24 | ; FontStyleNotFound = 15 25 | ; NotTrueTypeFont = 16 26 | ; UnsupportedGdiplusVersion = 17 27 | ; GdiplusNotInitialized = 18 28 | ; PropertyNotFound = 19 29 | ; PropertyNotSupported = 20 30 | ; ProfileNotFound = 21 31 | ; 32 | ;##################################################################################### 33 | ;##################################################################################### 34 | ; FUNCTIONS 35 | ;##################################################################################### 36 | ; 37 | ; UpdateLayeredWindow(hwnd, hdc, x:="", y:="", w:="", h:="", Alpha:=255) 38 | ; BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster:="") 39 | ; StretchBlt(dDC, dx, dy, dw, dh, sDC, sx, sy, sw, sh, Raster:="") 40 | ; SetImage(hwnd, hBitmap) 41 | ; Gdip_BitmapFromScreen(Screen:=0, Raster:="") 42 | ; CreateRectF(&RectF, x, y, w, h) 43 | ; CreateSizeF(&SizeF, w, h) 44 | ; CreateDIBSection 45 | ; 46 | ;##################################################################################### 47 | 48 | ; Function: UpdateLayeredWindow 49 | ; Description: Updates a layered window with the handle to the DC of a gdi bitmap 50 | ; 51 | ; hwnd Handle of the layered window to update 52 | ; hdc Handle to the DC of the GDI bitmap to update the window with 53 | ; Layeredx x position to place the window 54 | ; Layeredy y position to place the window 55 | ; Layeredw Width of the window 56 | ; Layeredh Height of the window 57 | ; Alpha Default = 255 : The transparency (0-255) to set the window transparency 58 | ; 59 | ; return if the function succeeds, the return value is nonzero 60 | ; 61 | ; notes if x or y omitted, then layered window will use its current coordinates 62 | ; if w or h omitted then current width and height will be used 63 | 64 | UpdateLayeredWindow(hwnd, hdc, x:="", y:="", w:="", h:="", Alpha:=255) 65 | { 66 | if ((x != "") && (y != "")) { 67 | pt := Buffer(8) 68 | NumPut("UInt", x, "UInt", y, pt) 69 | } 70 | 71 | if (w = "") || (h = "") { 72 | WinGetRect(hwnd,,, &w, &h) 73 | } 74 | 75 | return DllCall("UpdateLayeredWindow" 76 | , "UPtr", hwnd 77 | , "UPtr", 0 78 | , "UPtr", ((x = "") && (y = "")) ? 0 : pt.Ptr 79 | , "Int64*", w|h<<32 80 | , "UPtr", hdc 81 | , "Int64*", 0 82 | , "UInt", 0 83 | , "UInt*", Alpha<<16|1<<24 84 | , "UInt", 2) 85 | } 86 | 87 | ;##################################################################################### 88 | 89 | ; Function BitBlt 90 | ; Description The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle 91 | ; of pixels from the specified source device context into a destination device context. 92 | ; 93 | ; dDC handle to destination DC 94 | ; dx x-coord of destination upper-left corner 95 | ; dy y-coord of destination upper-left corner 96 | ; dw width of the area to copy 97 | ; dh height of the area to copy 98 | ; sDC handle to source DC 99 | ; sx x-coordinate of source upper-left corner 100 | ; sy y-coordinate of source upper-left corner 101 | ; Raster raster operation code 102 | ; 103 | ; return if the function succeeds, the return value is nonzero 104 | ; 105 | ; notes if no raster operation is specified, then SRCCOPY is used, which copies the source directly to the destination rectangle 106 | ; 107 | ; BLACKNESS = 0x00000042 108 | ; NOTSRCERASE = 0x001100A6 109 | ; NOTSRCCOPY = 0x00330008 110 | ; SRCERASE = 0x00440328 111 | ; DSTINVERT = 0x00550009 112 | ; PATINVERT = 0x005A0049 113 | ; SRCINVERT = 0x00660046 114 | ; SRCAND = 0x008800C6 115 | ; MERGEPAINT = 0x00BB0226 116 | ; MERGECOPY = 0x00C000CA 117 | ; SRCCOPY = 0x00CC0020 118 | ; SRCPAINT = 0x00EE0086 119 | ; PATCOPY = 0x00F00021 120 | ; PATPAINT = 0x00FB0A09 121 | ; WHITENESS = 0x00FF0062 122 | ; CAPTUREBLT = 0x40000000 123 | ; NOMIRRORBITMAP = 0x80000000 124 | 125 | BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster:="") 126 | { 127 | return DllCall("gdi32\BitBlt" 128 | , "UPtr", dDC 129 | , "Int", dx 130 | , "Int", dy 131 | , "Int", dw 132 | , "Int", dh 133 | , "UPtr", sDC 134 | , "Int", sx 135 | , "Int", sy 136 | , "UInt", Raster ? Raster : 0x00CC0020) 137 | } 138 | 139 | ;##################################################################################### 140 | 141 | ; Function StretchBlt 142 | ; Description The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle, 143 | ; stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary. 144 | ; The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context. 145 | ; 146 | ; ddc handle to destination DC 147 | ; dx x-coord of destination upper-left corner 148 | ; dy y-coord of destination upper-left corner 149 | ; dw width of destination rectangle 150 | ; dh height of destination rectangle 151 | ; sdc handle to source DC 152 | ; sx x-coordinate of source upper-left corner 153 | ; sy y-coordinate of source upper-left corner 154 | ; sw width of source rectangle 155 | ; sh height of source rectangle 156 | ; Raster raster operation code 157 | ; 158 | ; return if the function succeeds, the return value is nonzero 159 | ; 160 | ; notes if no raster operation is specified, then SRCCOPY is used. It uses the same raster operations as BitBlt 161 | 162 | StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster:="") 163 | { 164 | return DllCall("gdi32\StretchBlt" 165 | , "UPtr", ddc 166 | , "Int", dx 167 | , "Int", dy 168 | , "Int", dw 169 | , "Int", dh 170 | , "UPtr", sdc 171 | , "Int", sx 172 | , "Int", sy 173 | , "Int", sw 174 | , "Int", sh 175 | , "UInt", Raster ? Raster : 0x00CC0020) 176 | } 177 | 178 | ;##################################################################################### 179 | 180 | ; Function SetStretchBltMode 181 | ; Description The SetStretchBltMode function sets the bitmap stretching mode in the specified device context 182 | ; 183 | ; hdc handle to the DC 184 | ; iStretchMode The stretching mode, describing how the target will be stretched 185 | ; 186 | ; return if the function succeeds, the return value is the previous stretching mode. If it fails it will return 0 187 | ; 188 | ; STRETCH_ANDSCANS = 0x01 189 | ; STRETCH_ORSCANS = 0x02 190 | ; STRETCH_DELETESCANS = 0x03 191 | ; STRETCH_HALFTONE = 0x04 192 | 193 | SetStretchBltMode(hdc, iStretchMode:=4) 194 | { 195 | return DllCall("gdi32\SetStretchBltMode" 196 | , "UPtr", hdc 197 | , "Int", iStretchMode) 198 | } 199 | 200 | ;##################################################################################### 201 | 202 | ; Function SetImage 203 | ; Description Associates a new image with a static control 204 | ; 205 | ; hwnd handle of the control to update 206 | ; hBitmap a gdi bitmap to associate the static control with 207 | ; 208 | ; return if the function succeeds, the return value is nonzero 209 | 210 | SetImage(hwnd, hBitmap) 211 | { 212 | _E := DllCall( "SendMessage", "UPtr", hwnd, "UInt", 0x172, "UInt", 0x0, "UPtr", hBitmap ) 213 | DeleteObject(_E) 214 | return _E 215 | } 216 | 217 | ;##################################################################################### 218 | 219 | ; Function SetSysColorToControl 220 | ; Description Sets a solid colour to a control 221 | ; 222 | ; hwnd handle of the control to update 223 | ; SysColor A system colour to set to the control 224 | ; 225 | ; return if the function succeeds, the return value is zero 226 | ; 227 | ; notes A control must have the 0xE style set to it so it is recognised as a bitmap 228 | ; By default SysColor=15 is used which is COLOR_3DFACE. This is the standard background for a control 229 | ; 230 | ; COLOR_3DDKSHADOW = 21 231 | ; COLOR_3DFACE = 15 232 | ; COLOR_3DHIGHLIGHT = 20 233 | ; COLOR_3DHILIGHT = 20 234 | ; COLOR_3DLIGHT = 22 235 | ; COLOR_3DSHADOW = 16 236 | ; COLOR_ACTIVEBORDER = 10 237 | ; COLOR_ACTIVECAPTION = 2 238 | ; COLOR_APPWORKSPACE = 12 239 | ; COLOR_BACKGROUND = 1 240 | ; COLOR_BTNFACE = 15 241 | ; COLOR_BTNHIGHLIGHT = 20 242 | ; COLOR_BTNHILIGHT = 20 243 | ; COLOR_BTNSHADOW = 16 244 | ; COLOR_BTNTEXT = 18 245 | ; COLOR_CAPTIONTEXT = 9 246 | ; COLOR_DESKTOP = 1 247 | ; COLOR_GRADIENTACTIVECAPTION = 27 248 | ; COLOR_GRADIENTINACTIVECAPTION = 28 249 | ; COLOR_GRAYTEXT = 17 250 | ; COLOR_HIGHLIGHT = 13 251 | ; COLOR_HIGHLIGHTTEXT = 14 252 | ; COLOR_HOTLIGHT = 26 253 | ; COLOR_INACTIVEBORDER = 11 254 | ; COLOR_INACTIVECAPTION = 3 255 | ; COLOR_INACTIVECAPTIONTEXT = 19 256 | ; COLOR_INFOBK = 24 257 | ; COLOR_INFOTEXT = 23 258 | ; COLOR_MENU = 4 259 | ; COLOR_MENUHILIGHT = 29 260 | ; COLOR_MENUBAR = 30 261 | ; COLOR_MENUTEXT = 7 262 | ; COLOR_SCROLLBAR = 0 263 | ; COLOR_WINDOW = 5 264 | ; COLOR_WINDOWFRAME = 6 265 | ; COLOR_WINDOWTEXT = 8 266 | 267 | SetSysColorToControl(hwnd, SysColor:=15) 268 | { 269 | WinGetRect(hwnd,,, &w, &h) 270 | bc := DllCall("GetSysColor", "Int", SysColor, "UInt") 271 | pBrushClear := Gdip_BrushCreateSolid(0xff000000 | (bc >> 16 | bc & 0xff00 | (bc & 0xff) << 16)) 272 | pBitmap := Gdip_CreateBitmap(w, h), G := Gdip_GraphicsFromImage(pBitmap) 273 | Gdip_FillRectangle(G, pBrushClear, 0, 0, w, h) 274 | hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap) 275 | SetImage(hwnd, hBitmap) 276 | Gdip_DeleteBrush(pBrushClear) 277 | Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap) 278 | return 0 279 | } 280 | 281 | ;##################################################################################### 282 | 283 | ; Function Gdip_BitmapFromScreen 284 | ; Description Gets a gdi+ bitmap from the screen 285 | ; 286 | ; Screen 0 = All screens 287 | ; Any numerical value = Just that screen 288 | ; x|y|w|h = Take specific coordinates with a width and height 289 | ; Raster raster operation code 290 | ; 291 | ; return if the function succeeds, the return value is a pointer to a gdi+ bitmap 292 | ; -1: one or more of x,y,w,h not passed properly 293 | ; 294 | ; notes if no raster operation is specified, then SRCCOPY is used to the returned bitmap 295 | 296 | Gdip_BitmapFromScreen(Screen:=0, Raster:="") 297 | { 298 | hhdc := 0 299 | if (Screen = 0) { 300 | _x := DllCall( "GetSystemMetrics", "Int", 76 ) 301 | _y := DllCall( "GetSystemMetrics", "Int", 77 ) 302 | _w := DllCall( "GetSystemMetrics", "Int", 78 ) 303 | _h := DllCall( "GetSystemMetrics", "Int", 79 ) 304 | } 305 | else if (SubStr(Screen, 1, 5) = "hwnd:") { 306 | Screen := SubStr(Screen, 6) 307 | if !WinExist("ahk_id " Screen) { 308 | return -2 309 | } 310 | WinGetRect(Screen,,, &_w, &_h) 311 | _x := _y := 0 312 | hhdc := GetDCEx(Screen, 3) 313 | } 314 | else if IsInteger(Screen) { 315 | M := GetMonitorInfo(Screen) 316 | _x := M.Left, _y := M.Top, _w := M.Right-M.Left, _h := M.Bottom-M.Top 317 | } 318 | else { 319 | S := StrSplit(Screen, "|") 320 | _x := S[1], _y := S[2], _w := S[3], _h := S[4] 321 | } 322 | 323 | if (_x = "") || (_y = "") || (_w = "") || (_h = "") { 324 | return -1 325 | } 326 | 327 | chdc := CreateCompatibleDC() 328 | hbm := CreateDIBSection(_w, _h, chdc) 329 | obm := SelectObject(chdc, hbm) 330 | hhdc := hhdc ? hhdc : GetDC() 331 | BitBlt(chdc, 0, 0, _w, _h, hhdc, _x, _y, Raster) 332 | ReleaseDC(hhdc) 333 | 334 | pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm) 335 | 336 | SelectObject(chdc, obm) 337 | DeleteObject(hbm) 338 | DeleteDC(hhdc) 339 | DeleteDC(chdc) 340 | return pBitmap 341 | } 342 | 343 | ;##################################################################################### 344 | 345 | ; Function Gdip_BitmapFromHWND 346 | ; Description Uses PrintWindow to get a handle to the specified window and return a bitmap from it 347 | ; 348 | ; hwnd handle to the window to get a bitmap from 349 | ; 350 | ; return if the function succeeds, the return value is a pointer to a gdi+ bitmap 351 | ; 352 | ; notes Window must not be not minimised in order to get a handle to it's client area 353 | 354 | Gdip_BitmapFromHWND(hwnd) 355 | { 356 | WinGetRect(hwnd,,, &Width, &Height) 357 | hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm) 358 | PrintWindow(hwnd, hdc) 359 | pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm) 360 | SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc) 361 | return pBitmap 362 | } 363 | 364 | ;##################################################################################### 365 | 366 | ; Function CreateRectF 367 | ; Description Creates a RectF object, containing a the coordinates and dimensions of a rectangle 368 | ; 369 | ; RectF Name to call the RectF object 370 | ; x x-coordinate of the upper left corner of the rectangle 371 | ; y y-coordinate of the upper left corner of the rectangle 372 | ; w Width of the rectangle 373 | ; h Height of the rectangle 374 | ; 375 | ; return No return value 376 | 377 | CreateRectF(&RectF, x, y, w, h) 378 | { 379 | RectF := Buffer(16) 380 | NumPut( 381 | "Float", x, 382 | "Float", y, 383 | "Float", w, 384 | "Float", h, 385 | RectF) 386 | } 387 | 388 | ;##################################################################################### 389 | 390 | ; Function CreateRect 391 | ; Description Creates a Rect object, containing a the coordinates and dimensions of a rectangle 392 | ; 393 | ; RectF Name to call the RectF object 394 | ; x x-coordinate of the upper left corner of the rectangle 395 | ; y y-coordinate of the upper left corner of the rectangle 396 | ; w Width of the rectangle 397 | ; h Height of the rectangle 398 | ; 399 | ; return No return value 400 | CreateRect(&Rect, x, y, w, h) 401 | { 402 | Rect := Buffer(16) 403 | NumPut("UInt", x, "UInt", y, "UInt", w, "UInt", h, Rect) 404 | } 405 | ;##################################################################################### 406 | 407 | ; Function CreateSizeF 408 | ; Description Creates a SizeF object, containing an 2 values 409 | ; 410 | ; SizeF Name to call the SizeF object 411 | ; w w-value for the SizeF object 412 | ; h h-value for the SizeF object 413 | ; 414 | ; return No Return value 415 | 416 | CreateSizeF(&SizeF, w, h) 417 | { 418 | SizeF := Buffer(8) 419 | NumPut("Float", w, "Float", h, SizeF) 420 | } 421 | ;##################################################################################### 422 | 423 | ; Function CreatePointF 424 | ; Description Creates a SizeF object, containing an 2 values 425 | ; 426 | ; SizeF Name to call the SizeF object 427 | ; w w-value for the SizeF object 428 | ; h h-value for the SizeF object 429 | ; 430 | ; return No Return value 431 | 432 | CreatePointF(&PointF, x, y) 433 | { 434 | PointF := Buffer(8) 435 | NumPut("Float", x, "Float", y, PointF) 436 | } 437 | ;##################################################################################### 438 | 439 | ; Function CreateDIBSection 440 | ; Description The CreateDIBSection function creates a DIB (Device Independent Bitmap) that applications can write to directly 441 | ; 442 | ; w width of the bitmap to create 443 | ; h height of the bitmap to create 444 | ; hdc a handle to the device context to use the palette from 445 | ; bpp bits per pixel (32 = ARGB) 446 | ; ppvBits A pointer to a variable that receives a pointer to the location of the DIB bit values 447 | ; 448 | ; return returns a DIB. A gdi bitmap 449 | ; 450 | ; notes ppvBits will receive the location of the pixels in the DIB 451 | 452 | CreateDIBSection(w, h, hdc:="", bpp:=32, &ppvBits:=0) 453 | { 454 | hdc2 := hdc ? hdc : GetDC() 455 | bi := Buffer(40, 0) 456 | 457 | NumPut("UInt", 40, "UInt", w, "UInt", h, "ushort", 1, "ushort", bpp, "UInt", 0, bi) 458 | 459 | hbm := DllCall("CreateDIBSection" 460 | , "UPtr", hdc2 461 | , "UPtr", bi.Ptr 462 | , "UInt", 0 463 | , "UPtr*", &ppvBits 464 | , "UPtr", 0 465 | , "UInt", 0, "UPtr") 466 | 467 | if (!hdc) { 468 | ReleaseDC(hdc2) 469 | } 470 | return hbm 471 | } 472 | 473 | ;##################################################################################### 474 | 475 | ; Function PrintWindow 476 | ; Description The PrintWindow function copies a visual window into the specified device context (DC), typically a printer DC 477 | ; 478 | ; hwnd A handle to the window that will be copied 479 | ; hdc A handle to the device context 480 | ; Flags Drawing options 481 | ; 482 | ; return if the function succeeds, it returns a nonzero value 483 | ; 484 | ; PW_CLIENTONLY = 1 485 | 486 | PrintWindow(hwnd, hdc, Flags:=0) 487 | { 488 | return DllCall("PrintWindow", "UPtr", hwnd, "UPtr", hdc, "UInt", Flags) 489 | } 490 | 491 | ;##################################################################################### 492 | 493 | ; Function DestroyIcon 494 | ; Description Destroys an icon and frees any memory the icon occupied 495 | ; 496 | ; hIcon Handle to the icon to be destroyed. The icon must not be in use 497 | ; 498 | ; return if the function succeeds, the return value is nonzero 499 | 500 | DestroyIcon(hIcon) 501 | { 502 | return DllCall("DestroyIcon", "UPtr", hIcon) 503 | } 504 | 505 | ;##################################################################################### 506 | 507 | ; Function: GetIconDimensions 508 | ; Description: Retrieves a given icon/cursor's width and height 509 | ; 510 | ; hIcon Pointer to an icon or cursor 511 | ; Width ByRef variable. This variable is set to the icon's width 512 | ; Height ByRef variable. This variable is set to the icon's height 513 | ; 514 | ; return if the function succeeds, the return value is zero, otherwise: 515 | ; -1 = Could not retrieve the icon's info. Check A_LastError for extended information 516 | ; -2 = Could not delete the icon's bitmask bitmap 517 | ; -3 = Could not delete the icon's color bitmap 518 | 519 | GetIconDimensions(hIcon, &Width:=0, &Height:=0) { 520 | ICONINFO := Buffer(size := 16 + 2 * A_PtrSize, 0) 521 | 522 | if !DllCall("user32\GetIconInfo", "UPtr", hIcon, "UPtr", ICONINFO.Ptr) { 523 | return -1 524 | } 525 | 526 | hbmMask := NumGet(ICONINFO.Ptr, 16, "UPtr") 527 | hbmColor := NumGet(ICONINFO.Ptr, 16 + A_PtrSize, "UPtr") 528 | BITMAP := Buffer(size, 0) 529 | 530 | if DllCall("gdi32\GetObject", "UPtr", hbmColor, "Int", size, "UPtr", BITMAP.Ptr) { 531 | Width := NumGet(BITMAP.Ptr, 4, "Int") 532 | Height := NumGet(BITMAP.Ptr, 8, "Int") 533 | } 534 | 535 | if !DllCall("gdi32\DeleteObject", "UPtr", hbmMask) { 536 | return -2 537 | } 538 | 539 | if !DllCall("gdi32\DeleteObject", "UPtr", hbmColor) { 540 | return -3 541 | } 542 | 543 | return 0 544 | } 545 | 546 | ;##################################################################################### 547 | 548 | PaintDesktop(hdc) 549 | { 550 | return DllCall("PaintDesktop", "UPtr", hdc) 551 | } 552 | 553 | ;##################################################################################### 554 | 555 | CreateCompatibleBitmap(hdc, w, h) 556 | { 557 | return DllCall("gdi32\CreateCompatibleBitmap", "UPtr", hdc, "Int", w, "Int", h) 558 | } 559 | 560 | ;##################################################################################### 561 | 562 | ; Function CreateCompatibleDC 563 | ; Description This function creates a memory device context (DC) compatible with the specified device 564 | ; 565 | ; hdc Handle to an existing device context 566 | ; 567 | ; return returns the handle to a device context or 0 on failure 568 | ; 569 | ; notes if this handle is 0 (by default), the function creates a memory device context compatible with the application's current screen 570 | 571 | CreateCompatibleDC(hdc:=0) 572 | { 573 | return DllCall("CreateCompatibleDC", "UPtr", hdc) 574 | } 575 | 576 | ;##################################################################################### 577 | 578 | ; Function SelectObject 579 | ; Description The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type 580 | ; 581 | ; hdc Handle to a DC 582 | ; hgdiobj A handle to the object to be selected into the DC 583 | ; 584 | ; return if the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced 585 | ; 586 | ; notes The specified object must have been created by using one of the following functions 587 | ; Bitmap - CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBSection (A single bitmap cannot be selected into more than one DC at the same time) 588 | ; Brush - CreateBrushIndirect, CreateDIBPatternBrush, CreateDIBPatternBrushPt, CreateHatchBrush, CreatePatternBrush, CreateSolidBrush 589 | ; Font - CreateFont, CreateFontIndirect 590 | ; Pen - CreatePen, CreatePenIndirect 591 | ; Region - CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect 592 | ; 593 | ; notes if the selected object is a region and the function succeeds, the return value is one of the following value 594 | ; 595 | ; SIMPLEREGION = 2 Region consists of a single rectangle 596 | ; COMPLEXREGION = 3 Region consists of more than one rectangle 597 | ; NULLREGION = 1 Region is empty 598 | 599 | SelectObject(hdc, hgdiobj) 600 | { 601 | return DllCall("SelectObject", "UPtr", hdc, "UPtr", hgdiobj) 602 | } 603 | 604 | ;##################################################################################### 605 | 606 | ; Function DeleteObject 607 | ; Description This function deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object 608 | ; After the object is deleted, the specified handle is no longer valid 609 | ; 610 | ; hObject Handle to a logical pen, brush, font, bitmap, region, or palette to delete 611 | ; 612 | ; return Nonzero indicates success. Zero indicates that the specified handle is not valid or that the handle is currently selected into a device context 613 | 614 | DeleteObject(hObject) 615 | { 616 | return DllCall("DeleteObject", "UPtr", hObject) 617 | } 618 | 619 | ;##################################################################################### 620 | 621 | ; Function GetDC 622 | ; Description This function retrieves a handle to a display device context (DC) for the client area of the specified window. 623 | ; The display device context can be used in subsequent graphics display interface (GDI) functions to draw in the client area of the window. 624 | ; 625 | ; hwnd Handle to the window whose device context is to be retrieved. If this value is NULL, GetDC retrieves the device context for the entire screen 626 | ; 627 | ; return The handle the device context for the specified window's client area indicates success. NULL indicates failure 628 | 629 | GetDC(hwnd:=0) 630 | { 631 | return DllCall("GetDC", "UPtr", hwnd) 632 | } 633 | 634 | ;##################################################################################### 635 | 636 | ; DCX_CACHE = 0x2 637 | ; DCX_CLIPCHILDREN = 0x8 638 | ; DCX_CLIPSIBLINGS = 0x10 639 | ; DCX_EXCLUDERGN = 0x40 640 | ; DCX_EXCLUDEUPDATE = 0x100 641 | ; DCX_INTERSECTRGN = 0x80 642 | ; DCX_INTERSECTUPDATE = 0x200 643 | ; DCX_LOCKWINDOWUPDATE = 0x400 644 | ; DCX_NORECOMPUTE = 0x100000 645 | ; DCX_NORESETATTRS = 0x4 646 | ; DCX_PARENTCLIP = 0x20 647 | ; DCX_VALIDATE = 0x200000 648 | ; DCX_WINDOW = 0x1 649 | 650 | GetDCEx(hwnd, flags:=0, hrgnClip:=0) 651 | { 652 | return DllCall("GetDCEx", "UPtr", hwnd, "UPtr", hrgnClip, "Int", flags) 653 | } 654 | 655 | ;##################################################################################### 656 | 657 | ; Function ReleaseDC 658 | ; Description This function releases a device context (DC), freeing it for use by other applications. The effect of ReleaseDC depends on the type of device context 659 | ; 660 | ; hdc Handle to the device context to be released 661 | ; hwnd Handle to the window whose device context is to be released 662 | ; 663 | ; return 1 = released 664 | ; 0 = not released 665 | ; 666 | ; notes The application must call the ReleaseDC function for each call to the GetWindowDC function and for each call to the GetDC function that retrieves a common device context 667 | ; An application cannot use the ReleaseDC function to release a device context that was created by calling the CreateDC function; instead, it must use the DeleteDC function. 668 | 669 | ReleaseDC(hdc, hwnd:=0) 670 | { 671 | return DllCall("ReleaseDC", "UPtr", hwnd, "UPtr", hdc) 672 | } 673 | 674 | ;##################################################################################### 675 | 676 | ; Function DeleteDC 677 | ; Description The DeleteDC function deletes the specified device context (DC) 678 | ; 679 | ; hdc A handle to the device context 680 | ; 681 | ; return if the function succeeds, the return value is nonzero 682 | ; 683 | ; notes An application must not delete a DC whose handle was obtained by calling the GetDC function. Instead, it must call the ReleaseDC function to free the DC 684 | 685 | DeleteDC(hdc) 686 | { 687 | return DllCall("DeleteDC", "UPtr", hdc) 688 | } 689 | ;##################################################################################### 690 | 691 | ; Function Gdip_LibraryVersion 692 | ; Description Get the current library version 693 | ; 694 | ; return the library version 695 | ; 696 | ; notes This is useful for non compiled programs to ensure that a person doesn't run an old version when testing your scripts 697 | 698 | Gdip_LibraryVersion() 699 | { 700 | return 1.45 701 | } 702 | 703 | ;##################################################################################### 704 | 705 | ; Function Gdip_LibrarySubVersion 706 | ; Description Get the current library sub version 707 | ; 708 | ; return the library sub version 709 | ; 710 | ; notes This is the sub-version currently maintained by Rseding91 711 | ; Updated by guest3456 preliminary AHK v2 support 712 | Gdip_LibrarySubVersion() 713 | { 714 | return 1.54 715 | } 716 | 717 | ;##################################################################################### 718 | 719 | ; Function: Gdip_BitmapFromBRA 720 | ; Description: Gets a pointer to a gdi+ bitmap from a BRA file 721 | ; 722 | ; BRAFromMemIn The variable for a BRA file read to memory 723 | ; File The name of the file, or its number that you would like (This depends on alternate parameter) 724 | ; Alternate Changes whether the File parameter is the file name or its number 725 | ; 726 | ; return if the function succeeds, the return value is a pointer to a gdi+ bitmap 727 | ; -1 = The BRA variable is empty 728 | ; -2 = The BRA has an incorrect header 729 | ; -3 = The BRA has information missing 730 | ; -4 = Could not find file inside the BRA 731 | 732 | Gdip_BitmapFromBRA(BRAFromMemIn, File, Alternate := 0) { 733 | if (!BRAFromMemIn) { 734 | return -1 735 | } 736 | 737 | Headers := StrSplit(StrGet(BRAFromMemIn.Ptr, 256, "CP0"), "`n") 738 | Header := StrSplit(Headers[1], "|") 739 | HeaderLength := Header.Length 740 | 741 | if (HeaderLength != 4) || (Header[2] != "BRA!") { 742 | return -2 743 | } 744 | 745 | _Info := StrSplit(Headers[2], "|") 746 | _InfoLength := _Info.Length 747 | 748 | if (_InfoLength != 3) { 749 | return -3 750 | } 751 | 752 | OffsetTOC := StrPut(Headers[1], "CP0") + StrPut(Headers[2], "CP0") ; + 2 753 | OffsetData := _Info[2] 754 | SearchIndex := Alternate ? 1 : 2 755 | TOC := StrGet(BRAFromMemIn.Ptr + OffsetTOC, OffsetData - OffsetTOC - 1, "CP0") 756 | RX1 := "mi`n)^" 757 | Offset := Size := 0 758 | 759 | if RegExMatch(TOC, RX1 . (Alternate ? File "\|.+?" : "\d+\|" . File) . "\|(\d+)\|(\d+)$", &FileInfo:="") { 760 | Offset := OffsetData + FileInfo[1] 761 | Size := FileInfo[2] 762 | } 763 | 764 | if (Size = 0) { 765 | return -4 766 | } 767 | 768 | hData := DllCall("GlobalAlloc", "UInt", 2, "UInt", Size, "UPtr") 769 | pData := DllCall("GlobalLock", "Ptr", hData, "UPtr") 770 | DllCall("RtlMoveMemory", "Ptr", pData, "Ptr", BRAFromMemIn.Ptr + Offset, "Ptr", Size) 771 | DllCall("GlobalUnlock", "Ptr", hData) 772 | DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", 1, "Ptr*", &pStream:=0) 773 | DllCall("Gdiplus.dll\GdipCreateBitmapFromStream", "Ptr", pStream, "Ptr*", &pBitmap:=0) 774 | ObjRelease(pStream) 775 | 776 | return pBitmap 777 | } 778 | 779 | ;##################################################################################### 780 | 781 | ; Function: Gdip_BitmapFromBase64 782 | ; Description: Creates a bitmap from a Base64 encoded string 783 | ; 784 | ; Base64 ByRef variable. Base64 encoded string. Immutable, ByRef to avoid performance overhead of passing long strings. 785 | ; 786 | ; return if the function succeeds, the return value is a pointer to a bitmap, otherwise: 787 | ; -1 = Could not calculate the length of the required buffer 788 | ; -2 = Could not decode the Base64 encoded string 789 | ; -3 = Could not create a memory stream 790 | 791 | Gdip_BitmapFromBase64(&Base64) 792 | { 793 | ; calculate the length of the buffer needed 794 | if !(DllCall("crypt32\CryptStringToBinary", "UPtr", StrPtr(Base64), "UInt", 0, "UInt", 0x01, "UPtr", 0, "UInt*", &DecLen:=0, "UPtr", 0, "UPtr", 0)) { 795 | return -1 796 | } 797 | 798 | Dec := Buffer(DecLen, 0) 799 | 800 | ; decode the Base64 encoded string 801 | if !(DllCall("crypt32\CryptStringToBinary", "UPtr", StrPtr(Base64), "UInt", 0, "UInt", 0x01, "UPtr", Dec.Ptr, "UInt*", &DecLen, "UPtr", 0, "UPtr", 0)) { 802 | return -2 803 | } 804 | 805 | ; create a memory stream 806 | if !(pStream := DllCall("shlwapi\SHCreateMemStream", "UPtr", Dec.Ptr, "UInt", DecLen, "UPtr")) { 807 | return -3 808 | } 809 | 810 | DllCall("gdiplus\GdipCreateBitmapFromStreamICM", "UPtr", pStream, "Ptr*", &pBitmap:=0) 811 | ObjRelease(pStream) 812 | 813 | return pBitmap 814 | } 815 | 816 | ;##################################################################################### 817 | 818 | ; Function: Gdip_EncodeBitmapTo64string 819 | ; Description: Encode a bitmap to a Base64 encoded string 820 | ; 821 | ; pBitmap Pointer to a bitmap 822 | ; sOutput The name of the file that the bitmap will be saved to. Supported extensions are: .BMP,.DIB,.RLE,.JPG,.JPEG,.JPE,.JFIF,.GIF,.TIF,.TIFF,.PNG 823 | ; Quality if saving as jpg (.JPG,.JPEG,.JPE,.JFIF) then quality can be 1-100 with default at maximum quality 824 | ; 825 | ; return if the function succeeds, the return value is a Base64 encoded string of the pBitmap 826 | 827 | Gdip_EncodeBitmapTo64string(pBitmap, extension := "png", quality := "") { 828 | 829 | ; Fill a buffer with the available image codec info. 830 | DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", &count:=0, "uint*", &size:=0) 831 | DllCall("gdiplus\GdipGetImageEncoders", "uint", count, "uint", size, "ptr", ci := Buffer(size)) 832 | 833 | ; struct ImageCodecInfo - http://www.jose.it-berater.org/gdiplus/reference/structures/imagecodecinfo.htm 834 | loop { 835 | if (A_Index > count) 836 | throw Error("Could not find a matching encoder for the specified file format.") 837 | 838 | idx := (48+7*A_PtrSize)*(A_Index-1) 839 | } until InStr(StrGet(NumGet(ci, idx+32+3*A_PtrSize, "ptr"), "UTF-16"), extension) ; FilenameExtension 840 | 841 | ; Get the pointer to the clsid of the matching encoder. 842 | pCodec := ci.ptr + idx ; ClassID 843 | 844 | ; JPEG default quality is 75. Otherwise set a quality value from [0-100]. 845 | if (quality ~= "^-?\d+$") and ("image/jpeg" = StrGet(NumGet(ci, idx+32+4*A_PtrSize, "ptr"), "UTF-16")) { ; MimeType 846 | ; Use a separate buffer to store the quality as ValueTypeLong (4). 847 | v := Buffer(4) 848 | NumPut("uint", quality, v) 849 | 850 | ; struct EncoderParameter - http://www.jose.it-berater.org/gdiplus/reference/structures/encoderparameter.htm 851 | ; enum ValueType - https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.encoderparametervaluetype 852 | ; clsid Image Encoder Constants - http://www.jose.it-berater.org/gdiplus/reference/constants/gdipimageencoderconstants.htm 853 | ep := Buffer(24+2*A_PtrSize) ; sizeof(EncoderParameter) = ptr + n*(28, 32) 854 | NumPut( "uptr", 1, ep, 0) ; Count 855 | DllCall("ole32\CLSIDFromString", "wstr", "{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}", "ptr", ep.ptr+A_PtrSize, "HRESULT") 856 | NumPut( "uint", 1, ep, 16+A_PtrSize) ; Number of Values 857 | NumPut( "uint", 4, ep, 20+A_PtrSize) ; Type 858 | NumPut( "ptr", v.ptr, ep, 24+A_PtrSize) ; Value 859 | } 860 | 861 | ; Create a Stream. 862 | DllCall("ole32\CreateStreamOnHGlobal", "ptr", 0, "int", True, "ptr*", &pStream:=0, "HRESULT") 863 | DllCall("gdiplus\GdipSaveImageToStream", "ptr", pBitmap, "ptr", pStream, "ptr", pCodec, "ptr", IsSet(ep) ? ep : 0) 864 | 865 | ; Get a pointer to binary data. 866 | DllCall("ole32\GetHGlobalFromStream", "ptr", pStream, "ptr*", &hbin:=0, "HRESULT") 867 | bin := DllCall("GlobalLock", "ptr", hbin, "ptr") 868 | size := DllCall("GlobalSize", "uint", bin, "uptr") 869 | 870 | ; Calculate the length of the base64 string. 871 | flags := 0x40000001 ; CRYPT_STRING_NOCRLF | CRYPT_STRING_BASE64 872 | length := 4 * Ceil(size/3) + 1 ; An extra byte of padding is required. 873 | str := Buffer(length) 874 | 875 | ; Using CryptBinaryToStringA saves about 2MB in memory. 876 | DllCall("crypt32\CryptBinaryToStringA", "ptr", bin, "uint", size, "uint", flags, "ptr", str, "uint*", &length) 877 | 878 | ; Release binary data and stream. 879 | DllCall("GlobalUnlock", "ptr", hbin) 880 | ObjRelease(pStream) 881 | 882 | ; Return encoded string length minus 1. 883 | return StrGet(str, length, "CP0") 884 | } 885 | 886 | ;##################################################################################### 887 | 888 | ; Function Gdip_DrawRectangle 889 | ; Description This function uses a pen to draw the outline of a rectangle into the Graphics of a bitmap 890 | ; 891 | ; pGraphics Pointer to the Graphics of a bitmap 892 | ; pPen Pointer to a pen 893 | ; x x-coordinate of the top left of the rectangle 894 | ; y y-coordinate of the top left of the rectangle 895 | ; w width of the rectanlge 896 | ; h height of the rectangle 897 | ; 898 | ; return status enumeration. 0 = success 899 | ; 900 | ; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width 901 | 902 | Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h) 903 | { 904 | return DllCall("gdiplus\GdipDrawRectangle", "UPtr", pGraphics, "UPtr", pPen, "Float", x, "Float", y, "Float", w, "Float", h) 905 | } 906 | 907 | ;##################################################################################### 908 | 909 | ; Function Gdip_DrawRoundedRectangle 910 | ; Description This function uses a pen to draw the outline of a rounded rectangle into the Graphics of a bitmap 911 | ; 912 | ; pGraphics Pointer to the Graphics of a bitmap 913 | ; pPen Pointer to a pen 914 | ; x x-coordinate of the top left of the rounded rectangle 915 | ; y y-coordinate of the top left of the rounded rectangle 916 | ; w width of the rectanlge 917 | ; h height of the rectangle 918 | ; r radius of the rounded corners 919 | ; 920 | ; return status enumeration. 0 = success 921 | ; 922 | ; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width 923 | 924 | Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r) 925 | { 926 | Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4) 927 | Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4) 928 | Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4) 929 | Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4) 930 | _E := Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h) 931 | Gdip_ResetClip(pGraphics) 932 | Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4) 933 | Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4) 934 | Gdip_DrawEllipse(pGraphics, pPen, x, y, 2*r, 2*r) 935 | Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y, 2*r, 2*r) 936 | Gdip_DrawEllipse(pGraphics, pPen, x, y+h-(2*r), 2*r, 2*r) 937 | Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y+h-(2*r), 2*r, 2*r) 938 | Gdip_ResetClip(pGraphics) 939 | return _E 940 | } 941 | 942 | ;##################################################################################### 943 | 944 | ; Function Gdip_DrawEllipse 945 | ; Description This function uses a pen to draw the outline of an ellipse into the Graphics of a bitmap 946 | ; 947 | ; pGraphics Pointer to the Graphics of a bitmap 948 | ; pPen Pointer to a pen 949 | ; x x-coordinate of the top left of the rectangle the ellipse will be drawn into 950 | ; y y-coordinate of the top left of the rectangle the ellipse will be drawn into 951 | ; w width of the ellipse 952 | ; h height of the ellipse 953 | ; 954 | ; return status enumeration. 0 = success 955 | ; 956 | ; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width 957 | 958 | Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h) 959 | { 960 | return DllCall("gdiplus\GdipDrawEllipse", "UPtr", pGraphics, "UPtr", pPen, "Float", x, "Float", y, "Float", w, "Float", h) 961 | } 962 | 963 | ;##################################################################################### 964 | 965 | ; Function Gdip_DrawBezier 966 | ; Description This function uses a pen to draw the outline of a bezier (a weighted curve) into the Graphics of a bitmap 967 | ; 968 | ; pGraphics Pointer to the Graphics of a bitmap 969 | ; pPen Pointer to a pen 970 | ; x1 x-coordinate of the start of the bezier 971 | ; y1 y-coordinate of the start of the bezier 972 | ; x2 x-coordinate of the first arc of the bezier 973 | ; y2 y-coordinate of the first arc of the bezier 974 | ; x3 x-coordinate of the second arc of the bezier 975 | ; y3 y-coordinate of the second arc of the bezier 976 | ; x4 x-coordinate of the end of the bezier 977 | ; y4 y-coordinate of the end of the bezier 978 | ; 979 | ; return status enumeration. 0 = success 980 | ; 981 | ; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width 982 | 983 | Gdip_DrawBezier(pGraphics, pPen, x1, y1, x2, y2, x3, y3, x4, y4) 984 | { 985 | return DllCall("gdiplus\GdipDrawBezier" 986 | , "UPtr", pgraphics 987 | , "UPtr", pPen 988 | , "Float", x1 989 | , "Float", y1 990 | , "Float", x2 991 | , "Float", y2 992 | , "Float", x3 993 | , "Float", y3 994 | , "Float", x4 995 | , "Float", y4) 996 | } 997 | 998 | ;##################################################################################### 999 | 1000 | ; Function Gdip_DrawArc 1001 | ; Description This function uses a pen to draw the outline of an arc into the Graphics of a bitmap 1002 | ; 1003 | ; pGraphics Pointer to the Graphics of a bitmap 1004 | ; pPen Pointer to a pen 1005 | ; x x-coordinate of the start of the arc 1006 | ; y y-coordinate of the start of the arc 1007 | ; w width of the arc 1008 | ; h height of the arc 1009 | ; StartAngle specifies the angle between the x-axis and the starting point of the arc 1010 | ; SweepAngle specifies the angle between the starting and ending points of the arc 1011 | ; 1012 | ; return status enumeration. 0 = success 1013 | ; 1014 | ; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width 1015 | 1016 | Gdip_DrawArc(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle) 1017 | { 1018 | return DllCall("gdiplus\GdipDrawArc" 1019 | , "UPtr", pGraphics 1020 | , "UPtr", pPen 1021 | , "Float", x 1022 | , "Float", y 1023 | , "Float", w 1024 | , "Float", h 1025 | , "Float", StartAngle 1026 | , "Float", SweepAngle) 1027 | } 1028 | 1029 | ;##################################################################################### 1030 | 1031 | ; Function Gdip_DrawPie 1032 | ; Description This function uses a pen to draw the outline of a pie into the Graphics of a bitmap 1033 | ; 1034 | ; pGraphics Pointer to the Graphics of a bitmap 1035 | ; pPen Pointer to a pen 1036 | ; x x-coordinate of the start of the pie 1037 | ; y y-coordinate of the start of the pie 1038 | ; w width of the pie 1039 | ; h height of the pie 1040 | ; StartAngle specifies the angle between the x-axis and the starting point of the pie 1041 | ; SweepAngle specifies the angle between the starting and ending points of the pie 1042 | ; 1043 | ; return status enumeration. 0 = success 1044 | ; 1045 | ; notes as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width 1046 | 1047 | Gdip_DrawPie(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle) 1048 | { 1049 | return DllCall("gdiplus\GdipDrawPie", "UPtr", pGraphics, "UPtr", pPen, "Float", x, "Float", y, "Float", w, "Float", h, "Float", StartAngle, "Float", SweepAngle) 1050 | } 1051 | 1052 | ;##################################################################################### 1053 | 1054 | ; Function Gdip_DrawLine 1055 | ; Description This function uses a pen to draw a line into the Graphics of a bitmap 1056 | ; 1057 | ; pGraphics Pointer to the Graphics of a bitmap 1058 | ; pPen Pointer to a pen 1059 | ; x1 x-coordinate of the start of the line 1060 | ; y1 y-coordinate of the start of the line 1061 | ; x2 x-coordinate of the end of the line 1062 | ; y2 y-coordinate of the end of the line 1063 | ; 1064 | ; return status enumeration. 0 = success 1065 | 1066 | Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2) 1067 | { 1068 | return DllCall("gdiplus\GdipDrawLine" 1069 | , "UPtr", pGraphics 1070 | , "UPtr", pPen 1071 | , "Float", x1 1072 | , "Float", y1 1073 | , "Float", x2 1074 | , "Float", y2) 1075 | } 1076 | 1077 | ;##################################################################################### 1078 | 1079 | ; Function Gdip_DrawLines 1080 | ; Description This function uses a pen to draw a series of joined lines into the Graphics of a bitmap 1081 | ; 1082 | ; pGraphics Pointer to the Graphics of a bitmap 1083 | ; pPen Pointer to a pen 1084 | ; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... 1085 | ; 1086 | ; return status enumeration. 0 = success 1087 | 1088 | Gdip_DrawLines(pGraphics, pPen, points) 1089 | { 1090 | points := StrSplit(points, "|") 1091 | pointF := Buffer(8*points.Length) 1092 | pointsLength := 0 1093 | for point in points { 1094 | coords := StrSplit(point, ",") 1095 | if (coords.Length != 2) { 1096 | if (coords.Length > 0) { 1097 | MsgBox("Skipping wrong points of length " coords.Length) 1098 | } 1099 | continue 1100 | } 1101 | NumPut("Float", coords[1], pointF, 8*(A_Index-1)) 1102 | NumPut("Float", coords[2], pointF, (8*(A_Index-1))+4) 1103 | pointsLength += 1 1104 | } 1105 | return DllCall("gdiplus\GdipDrawLines", "UPtr", pGraphics, "UPtr", pPen, "UPtr", pointF.Ptr, "Int", pointsLength) 1106 | } 1107 | 1108 | ;##################################################################################### 1109 | 1110 | ; Function Gdip_FillRectangle 1111 | ; Description This function uses a brush to fill a rectangle in the Graphics of a bitmap 1112 | ; 1113 | ; pGraphics Pointer to the Graphics of a bitmap 1114 | ; pBrush Pointer to a brush 1115 | ; x x-coordinate of the top left of the rectangle 1116 | ; y y-coordinate of the top left of the rectangle 1117 | ; w width of the rectanlge 1118 | ; h height of the rectangle 1119 | ; 1120 | ; return status enumeration. 0 = success 1121 | 1122 | Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h) 1123 | { 1124 | return DllCall("gdiplus\GdipFillRectangle" 1125 | , "UPtr", pGraphics 1126 | , "UPtr", pBrush 1127 | , "Float", x 1128 | , "Float", y 1129 | , "Float", w 1130 | , "Float", h) 1131 | } 1132 | 1133 | ;##################################################################################### 1134 | 1135 | ; Function Gdip_FillRoundedRectangle 1136 | ; Description This function uses a brush to fill a rounded rectangle in the Graphics of a bitmap 1137 | ; 1138 | ; pGraphics Pointer to the Graphics of a bitmap 1139 | ; pBrush Pointer to a brush 1140 | ; x x-coordinate of the top left of the rounded rectangle 1141 | ; y y-coordinate of the top left of the rounded rectangle 1142 | ; w width of the rectanlge 1143 | ; h height of the rectangle 1144 | ; r radius of the rounded corners 1145 | ; 1146 | ; return status enumeration. 0 = success 1147 | 1148 | Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r) 1149 | { 1150 | Region := Gdip_GetClipRegion(pGraphics) 1151 | Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4) 1152 | Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4) 1153 | Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4) 1154 | Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4) 1155 | _E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h) 1156 | Gdip_SetClipRegion(pGraphics, Region, 0) 1157 | Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4) 1158 | Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4) 1159 | Gdip_FillEllipse(pGraphics, pBrush, x, y, 2*r, 2*r) 1160 | Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r) 1161 | Gdip_FillEllipse(pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r) 1162 | Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r) 1163 | Gdip_SetClipRegion(pGraphics, Region, 0) 1164 | Gdip_DeleteRegion(Region) 1165 | return _E 1166 | } 1167 | 1168 | ;##################################################################################### 1169 | 1170 | ; Function Gdip_FillPolygon 1171 | ; Description This function uses a brush to fill a polygon in the Graphics of a bitmap 1172 | ; 1173 | ; pGraphics Pointer to the Graphics of a bitmap 1174 | ; pBrush Pointer to a brush 1175 | ; Points the coordinates of all the points passed as x1,y1|x2,y2|x3,y3..... 1176 | ; 1177 | ; return status enumeration. 0 = success 1178 | ; 1179 | ; notes Alternate will fill the polygon as a whole, wheras winding will fill each new "segment" 1180 | ; Alternate = 0 1181 | ; Winding = 1 1182 | 1183 | Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode:=0) 1184 | { 1185 | Points := StrSplit(Points, "|") 1186 | PointsLength := Points.Length 1187 | PointF := Buffer(8*PointsLength) 1188 | For eachPoint, Point in Points 1189 | { 1190 | Coord := StrSplit(Point, ",") 1191 | NumPut("Float", Coord[1], PointF, 8*(A_Index-1)) 1192 | NumPut("Float", Coord[2], PointF, (8*(A_Index-1))+4) 1193 | } 1194 | return DllCall("gdiplus\GdipFillPolygon", "UPtr", pGraphics, "UPtr", pBrush, "UPtr", PointF.Ptr, "Int", PointsLength, "Int", FillMode) 1195 | } 1196 | 1197 | ;##################################################################################### 1198 | 1199 | ; Function Gdip_FillPie 1200 | ; Description This function uses a brush to fill a pie in the Graphics of a bitmap 1201 | ; 1202 | ; pGraphics Pointer to the Graphics of a bitmap 1203 | ; pBrush Pointer to a brush 1204 | ; x x-coordinate of the top left of the pie 1205 | ; y y-coordinate of the top left of the pie 1206 | ; w width of the pie 1207 | ; h height of the pie 1208 | ; StartAngle specifies the angle between the x-axis and the starting point of the pie 1209 | ; SweepAngle specifies the angle between the starting and ending points of the pie 1210 | ; 1211 | ; return status enumeration. 0 = success 1212 | 1213 | Gdip_FillPie(pGraphics, pBrush, x, y, w, h, StartAngle, SweepAngle) 1214 | { 1215 | return DllCall("gdiplus\GdipFillPie" 1216 | , "UPtr", pGraphics 1217 | , "UPtr", pBrush 1218 | , "Float", x 1219 | , "Float", y 1220 | , "Float", w 1221 | , "Float", h 1222 | , "Float", StartAngle 1223 | , "Float", SweepAngle) 1224 | } 1225 | 1226 | ;##################################################################################### 1227 | 1228 | ; Function Gdip_FillEllipse 1229 | ; Description This function uses a brush to fill an ellipse in the Graphics of a bitmap 1230 | ; 1231 | ; pGraphics Pointer to the Graphics of a bitmap 1232 | ; pBrush Pointer to a brush 1233 | ; x x-coordinate of the top left of the ellipse 1234 | ; y y-coordinate of the top left of the ellipse 1235 | ; w width of the ellipse 1236 | ; h height of the ellipse 1237 | ; 1238 | ; return status enumeration. 0 = success 1239 | 1240 | Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h) 1241 | { 1242 | return DllCall("gdiplus\GdipFillEllipse", "UPtr", pGraphics, "UPtr", pBrush, "Float", x, "Float", y, "Float", w, "Float", h) 1243 | } 1244 | 1245 | ;##################################################################################### 1246 | 1247 | ; Function Gdip_FillRegion 1248 | ; Description This function uses a brush to fill a region in the Graphics of a bitmap 1249 | ; 1250 | ; pGraphics Pointer to the Graphics of a bitmap 1251 | ; pBrush Pointer to a brush 1252 | ; Region Pointer to a Region 1253 | ; 1254 | ; return status enumeration. 0 = success 1255 | ; 1256 | ; notes You can create a region Gdip_CreateRegion() and then add to this 1257 | 1258 | Gdip_FillRegion(pGraphics, pBrush, Region) 1259 | { 1260 | return DllCall("gdiplus\GdipFillRegion", "UPtr", pGraphics, "UPtr", pBrush, "UPtr", Region) 1261 | } 1262 | 1263 | ;##################################################################################### 1264 | 1265 | ; Function Gdip_FillPath 1266 | ; Description This function uses a brush to fill a path in the Graphics of a bitmap 1267 | ; 1268 | ; pGraphics Pointer to the Graphics of a bitmap 1269 | ; pBrush Pointer to a brush 1270 | ; Region Pointer to a Path 1271 | ; 1272 | ; return status enumeration. 0 = success 1273 | 1274 | Gdip_FillPath(pGraphics, pBrush, pPath) 1275 | { 1276 | return DllCall("gdiplus\GdipFillPath", "UPtr", pGraphics, "UPtr", pBrush, "UPtr", pPath) 1277 | } 1278 | 1279 | ;##################################################################################### 1280 | 1281 | ; Function Gdip_DrawImagePointsRect 1282 | ; Description This function draws a bitmap into the Graphics of another bitmap and skews it 1283 | ; 1284 | ; pGraphics Pointer to the Graphics of a bitmap 1285 | ; pBitmap Pointer to a bitmap to be drawn 1286 | ; Points Points passed as x1,y1|x2,y2|x3,y3 (3 points: top left, top right, bottom left) describing the drawing of the bitmap 1287 | ; sx x-coordinate of source upper-left corner 1288 | ; sy y-coordinate of source upper-left corner 1289 | ; sw width of source rectangle 1290 | ; sh height of source rectangle 1291 | ; Matrix a matrix used to alter image attributes when drawing 1292 | ; 1293 | ; return status enumeration. 0 = success 1294 | ; 1295 | ; notes if sx,sy,sw,sh are missed then the entire source bitmap will be used 1296 | ; Matrix can be omitted to just draw with no alteration to ARGB 1297 | ; Matrix may be passed as a digit from 0 - 1 to change just transparency 1298 | ; Matrix can be passed as a matrix with any delimiter 1299 | 1300 | Gdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx:="", sy:="", sw:="", sh:="", Matrix:=1) 1301 | { 1302 | Points := StrSplit(Points, "|") 1303 | PointsLength := Points.Length 1304 | PointF := Buffer(8*PointsLength) 1305 | For eachPoint, Point in Points 1306 | { 1307 | Coord := StrSplit(Point, ",") 1308 | NumPut("Float", Coord[1], PointF, 8*(A_Index-1)) 1309 | NumPut("Float", Coord[2], PointF, (8*(A_Index-1))+4) 1310 | } 1311 | 1312 | if !IsNumber(Matrix) 1313 | ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix) 1314 | else if (Matrix != 1) 1315 | 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") 1316 | else 1317 | ImageAttr := 0 1318 | 1319 | if (sx = "" && sy = "" && sw = "" && sh = "") 1320 | { 1321 | sx := 0, sy := 0 1322 | sw := Gdip_GetImageWidth(pBitmap) 1323 | sh := Gdip_GetImageHeight(pBitmap) 1324 | } 1325 | 1326 | _E := DllCall("gdiplus\GdipDrawImagePointsRect" 1327 | , "UPtr", pGraphics 1328 | , "UPtr", pBitmap 1329 | , "UPtr", PointF.Ptr 1330 | , "Int", PointsLength 1331 | , "Float", sx 1332 | , "Float", sy 1333 | , "Float", sw 1334 | , "Float", sh 1335 | , "Int", 2 1336 | , "UPtr", ImageAttr 1337 | , "UPtr", 0 1338 | , "UPtr", 0) 1339 | if ImageAttr 1340 | Gdip_DisposeImageAttributes(ImageAttr) 1341 | return _E 1342 | } 1343 | 1344 | ;##################################################################################### 1345 | 1346 | ; Function Gdip_DrawImage 1347 | ; Description This function draws a bitmap into the Graphics of another bitmap 1348 | ; 1349 | ; pGraphics Pointer to the Graphics of a bitmap 1350 | ; pBitmap Pointer to a bitmap to be drawn 1351 | ; dx x-coord of destination upper-left corner 1352 | ; dy y-coord of destination upper-left corner 1353 | ; dw width of destination image 1354 | ; dh height of destination image 1355 | ; sx x-coordinate of source upper-left corner 1356 | ; sy y-coordinate of source upper-left corner 1357 | ; sw width of source image 1358 | ; sh height of source image 1359 | ; Matrix a matrix used to alter image attributes when drawing 1360 | ; 1361 | ; return status enumeration. 0 = success 1362 | ; 1363 | ; notes if sx,sy,sw,sh are missed then the entire source bitmap will be used 1364 | ; Gdip_DrawImage performs faster 1365 | ; Matrix can be omitted to just draw with no alteration to ARGB 1366 | ; Matrix may be passed as a digit from 0 - 1 to change just transparency 1367 | ; Matrix can be passed as a matrix with any delimiter. For example: 1368 | ; MatrixBright= 1369 | ; ( 1370 | ; 1.5 |0 |0 |0 |0 1371 | ; 0 |1.5 |0 |0 |0 1372 | ; 0 |0 |1.5 |0 |0 1373 | ; 0 |0 |0 |1 |0 1374 | ; 0.05 |0.05 |0.05 |0 |1 1375 | ; ) 1376 | ; 1377 | ; notes MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1 1378 | ; MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1 1379 | ; MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|1|1|1|0|1 1380 | 1381 | Gdip_DrawImage(pGraphics, pBitmap, dx:="", dy:="", dw:="", dh:="", sx:="", sy:="", sw:="", sh:="", Matrix:=1) 1382 | { 1383 | if !IsNumber(Matrix) 1384 | ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix) 1385 | else if (Matrix != 1) 1386 | 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") 1387 | else 1388 | ImageAttr := 0 1389 | 1390 | if (sx = "" && sy = "" && sw = "" && sh = "") 1391 | { 1392 | if (dx = "" && dy = "" && dw = "" && dh = "") 1393 | { 1394 | sx := dx := 0, sy := dy := 0 1395 | sw := dw := Gdip_GetImageWidth(pBitmap) 1396 | sh := dh := Gdip_GetImageHeight(pBitmap) 1397 | } 1398 | else 1399 | { 1400 | sx := sy := 0 1401 | sw := Gdip_GetImageWidth(pBitmap) 1402 | sh := Gdip_GetImageHeight(pBitmap) 1403 | } 1404 | } 1405 | 1406 | _E := DllCall("gdiplus\GdipDrawImageRectRect" 1407 | , "UPtr", pGraphics 1408 | , "UPtr", pBitmap 1409 | , "Float", dx 1410 | , "Float", dy 1411 | , "Float", dw 1412 | , "Float", dh 1413 | , "Float", sx 1414 | , "Float", sy 1415 | , "Float", sw 1416 | , "Float", sh 1417 | , "Int", 2 1418 | , "UPtr", ImageAttr 1419 | , "UPtr", 0 1420 | , "UPtr", 0) 1421 | if ImageAttr 1422 | Gdip_DisposeImageAttributes(ImageAttr) 1423 | return _E 1424 | } 1425 | 1426 | ;##################################################################################### 1427 | 1428 | ; Function Gdip_SetImageAttributesColorMatrix 1429 | ; Description This function creates an image matrix ready for drawing 1430 | ; 1431 | ; Matrix a matrix used to alter image attributes when drawing 1432 | ; passed with any delimeter 1433 | ; 1434 | ; return returns an image matrix on sucess or 0 if it fails 1435 | ; 1436 | ; notes MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1 1437 | ; MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1 1438 | ; MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|1|1|1|0|1 1439 | 1440 | Gdip_SetImageAttributesColorMatrix(Matrix) 1441 | { 1442 | ColourMatrix := Buffer(100, 0) 1443 | Matrix := RegExReplace(RegExReplace(Matrix, "^[^\d-\.]+([\d\.])", "$1", , 1), "[^\d-\.]+", "|") 1444 | Matrix := StrSplit(Matrix, "|") 1445 | 1446 | loop 25 { 1447 | M := (Matrix[A_Index] != "") ? Matrix[A_Index] : Mod(A_Index-1, 6) ? 0 : 1 1448 | NumPut("Float", M, ColourMatrix, (A_Index-1)*4) 1449 | } 1450 | 1451 | DllCall("gdiplus\GdipCreateImageAttributes", "UPtr*", &ImageAttr:=0) 1452 | DllCall("gdiplus\GdipSetImageAttributesColorMatrix", "UPtr", ImageAttr, "Int", 1, "Int", 1, "UPtr", ColourMatrix.Ptr, "UPtr", 0, "Int", 0) 1453 | 1454 | return ImageAttr 1455 | } 1456 | 1457 | ;##################################################################################### 1458 | 1459 | ; Function Gdip_GraphicsFromImage 1460 | ; Description This function gets the graphics for a bitmap used for drawing functions 1461 | ; 1462 | ; pBitmap Pointer to a bitmap to get the pointer to its graphics 1463 | ; 1464 | ; return returns a pointer to the graphics of a bitmap 1465 | ; 1466 | ; notes a bitmap can be drawn into the graphics of another bitmap 1467 | 1468 | Gdip_GraphicsFromImage(pBitmap) 1469 | { 1470 | DllCall("gdiplus\GdipGetImageGraphicsContext", "UPtr", pBitmap, "UPtr*", &pGraphics:=0) 1471 | return pGraphics 1472 | } 1473 | 1474 | ;##################################################################################### 1475 | 1476 | ; Function Gdip_GraphicsFromHDC 1477 | ; Description This function gets the graphics from the handle to a device context 1478 | ; 1479 | ; hdc This is the handle to the device context 1480 | ; 1481 | ; return returns a pointer to the graphics of a bitmap 1482 | ; 1483 | ; notes You can draw a bitmap into the graphics of another bitmap 1484 | 1485 | Gdip_GraphicsFromHDC(hdc) 1486 | { 1487 | DllCall("gdiplus\GdipCreateFromHDC", "UPtr", hdc, "UPtr*", &pGraphics:=0) 1488 | return pGraphics 1489 | } 1490 | 1491 | ;##################################################################################### 1492 | 1493 | ; Function Gdip_GetDC 1494 | ; Description This function gets the device context of the passed Graphics 1495 | ; 1496 | ; hdc This is the handle to the device context 1497 | ; 1498 | ; return returns the device context for the graphics of a bitmap 1499 | 1500 | Gdip_GetDC(pGraphics) 1501 | { 1502 | DllCall("gdiplus\GdipGetDC", "UPtr", pGraphics, "UPtr*", &hdc:=0) 1503 | return hdc 1504 | } 1505 | 1506 | ;##################################################################################### 1507 | 1508 | ; Function Gdip_ReleaseDC 1509 | ; Description This function releases a device context from use for further use 1510 | ; 1511 | ; pGraphics Pointer to the graphics of a bitmap 1512 | ; hdc This is the handle to the device context 1513 | ; 1514 | ; return status enumeration. 0 = success 1515 | 1516 | Gdip_ReleaseDC(pGraphics, hdc) 1517 | { 1518 | return DllCall("gdiplus\GdipReleaseDC", "UPtr", pGraphics, "UPtr", hdc) 1519 | } 1520 | 1521 | ;##################################################################################### 1522 | 1523 | ; Function Gdip_GraphicsClear 1524 | ; Description Clears the graphics of a bitmap ready for further drawing 1525 | ; 1526 | ; pGraphics Pointer to the graphics of a bitmap 1527 | ; ARGB The colour to clear the graphics to 1528 | ; 1529 | ; return status enumeration. 0 = success 1530 | ; 1531 | ; notes By default this will make the background invisible 1532 | ; Using clipping regions you can clear a particular area on the graphics rather than clearing the entire graphics 1533 | 1534 | Gdip_GraphicsClear(pGraphics, ARGB:=0x00ffffff) 1535 | { 1536 | return DllCall("gdiplus\GdipGraphicsClear", "UPtr", pGraphics, "Int", ARGB) 1537 | } 1538 | 1539 | ;##################################################################################### 1540 | 1541 | ; Function Gdip_BlurBitmap 1542 | ; Description Gives a pointer to a blurred bitmap from a pointer to a bitmap 1543 | ; 1544 | ; pBitmap Pointer to a bitmap to be blurred 1545 | ; Blur The Amount to blur a bitmap by from 1 (least blur) to 100 (most blur) 1546 | ; 1547 | ; return if the function succeeds, the return value is a pointer to the new blurred bitmap 1548 | ; -1 = The blur parameter is outside the range 1-100 1549 | ; 1550 | ; notes This function will not dispose of the original bitmap 1551 | 1552 | Gdip_BlurBitmap(pBitmap, Blur) 1553 | { 1554 | if (Blur > 100 || Blur < 1) { 1555 | return -1 1556 | } 1557 | 1558 | sWidth := Gdip_GetImageWidth(pBitmap), sHeight := Gdip_GetImageHeight(pBitmap) 1559 | dWidth := sWidth//Blur, dHeight := sHeight//Blur 1560 | 1561 | pBitmap1 := Gdip_CreateBitmap(dWidth, dHeight) 1562 | G1 := Gdip_GraphicsFromImage(pBitmap1) 1563 | Gdip_SetInterpolationMode(G1, 7) 1564 | Gdip_DrawImage(G1, pBitmap, 0, 0, dWidth, dHeight, 0, 0, sWidth, sHeight) 1565 | 1566 | Gdip_DeleteGraphics(G1) 1567 | 1568 | pBitmap2 := Gdip_CreateBitmap(sWidth, sHeight) 1569 | G2 := Gdip_GraphicsFromImage(pBitmap2) 1570 | Gdip_SetInterpolationMode(G2, 7) 1571 | Gdip_DrawImage(G2, pBitmap1, 0, 0, sWidth, sHeight, 0, 0, dWidth, dHeight) 1572 | 1573 | Gdip_DeleteGraphics(G2) 1574 | Gdip_DisposeImage(pBitmap1) 1575 | 1576 | return pBitmap2 1577 | } 1578 | 1579 | ;##################################################################################### 1580 | 1581 | ; Function: Gdip_SaveBitmapToFile 1582 | ; Description: Saves a bitmap to a file in any supported format onto disk 1583 | ; 1584 | ; pBitmap Pointer to a bitmap 1585 | ; sOutput The name of the file that the bitmap will be saved to. Supported extensions are: .BMP,.DIB,.RLE,.JPG,.JPEG,.JPE,.JFIF,.GIF,.TIF,.TIFF,.PNG 1586 | ; Quality if saving as jpg (.JPG,.JPEG,.JPE,.JFIF) then quality can be 1-100 with default at maximum quality 1587 | ; 1588 | ; return if the function succeeds, the return value is zero, otherwise: 1589 | ; -1 = Extension supplied is not a supported file format 1590 | ; -2 = Could not get a list of encoders on system 1591 | ; -3 = Could not find matching encoder for specified file format 1592 | ; -4 = Could not get WideChar name of output file 1593 | ; -5 = Could not save file to disk 1594 | ; 1595 | ; notes This function will use the extension supplied from the sOutput parameter to determine the output format 1596 | 1597 | Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality:=75) 1598 | { 1599 | _p := 0 1600 | 1601 | SplitPath sOutput,,, &extension:="" 1602 | if (!RegExMatch(extension, "^(?i:BMP|DIB|RLE|JPG|JPEG|JPE|JFIF|GIF|TIF|TIFF|PNG)$")) { 1603 | return -1 1604 | } 1605 | extension := "." extension 1606 | 1607 | DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", &nCount:=0, "uint*", &nSize:=0) 1608 | ci := Buffer(nSize) 1609 | DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "UPtr", ci.Ptr) 1610 | if !(nCount && nSize) { 1611 | return -2 1612 | } 1613 | 1614 | loop nCount { 1615 | address := NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize, "UPtr") 1616 | sString := StrGet(address, "UTF-16") 1617 | if !InStr(sString, "*" extension) 1618 | continue 1619 | 1620 | pCodec := ci.Ptr+idx 1621 | break 1622 | } 1623 | 1624 | if !pCodec { 1625 | return -3 1626 | } 1627 | 1628 | if (Quality != 75) { 1629 | Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality 1630 | 1631 | if RegExMatch(extension, "^\.(?i:JPG|JPEG|JPE|JFIF)$") { 1632 | DllCall("gdiplus\GdipGetEncoderParameterListSize", "UPtr", pBitmap, "UPtr", pCodec, "uint*", &nSize) 1633 | EncoderParameters := Buffer(nSize, 0) 1634 | DllCall("gdiplus\GdipGetEncoderParameterList", "UPtr", pBitmap, "UPtr", pCodec, "UInt", nSize, "UPtr", EncoderParameters.Ptr) 1635 | nCount := NumGet(EncoderParameters, "UInt") 1636 | loop nCount 1637 | { 1638 | elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0) 1639 | if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6) 1640 | { 1641 | _p := elem + EncoderParameters.Ptr - pad - 4 1642 | NumPut("UInt", Quality, NumGet(NumPut("UInt", 4, NumPut("UInt", 1, _p+0)+20), "UInt")) 1643 | break 1644 | } 1645 | } 1646 | } 1647 | } 1648 | 1649 | _E := DllCall("gdiplus\GdipSaveImageToFile", "UPtr", pBitmap, "UPtr", StrPtr(sOutput), "UPtr", pCodec, "UInt", _p ? _p : 0) 1650 | 1651 | return _E ? -5 : 0 1652 | } 1653 | 1654 | ;##################################################################################### 1655 | 1656 | ; Function Gdip_GetPixel 1657 | ; Description Gets the ARGB of a pixel in a bitmap 1658 | ; 1659 | ; pBitmap Pointer to a bitmap 1660 | ; x x-coordinate of the pixel 1661 | ; y y-coordinate of the pixel 1662 | ; 1663 | ; return Returns the ARGB value of the pixel 1664 | 1665 | Gdip_GetPixel(pBitmap, x, y) 1666 | { 1667 | DllCall("gdiplus\GdipBitmapGetPixel", "UPtr", pBitmap, "Int", x, "Int", y, "uint*", &ARGB:=0) 1668 | return ARGB 1669 | } 1670 | 1671 | ;##################################################################################### 1672 | 1673 | ; Function Gdip_SetPixel 1674 | ; Description Sets the ARGB of a pixel in a bitmap 1675 | ; 1676 | ; pBitmap Pointer to a bitmap 1677 | ; x x-coordinate of the pixel 1678 | ; y y-coordinate of the pixel 1679 | ; 1680 | ; return status enumeration. 0 = success 1681 | 1682 | Gdip_SetPixel(pBitmap, x, y, ARGB) 1683 | { 1684 | return DllCall("gdiplus\GdipBitmapSetPixel", "UPtr", pBitmap, "Int", x, "Int", y, "Int", ARGB) 1685 | } 1686 | 1687 | ;##################################################################################### 1688 | 1689 | ; Function Gdip_GetImageWidth 1690 | ; Description Gives the width of a bitmap 1691 | ; 1692 | ; pBitmap Pointer to a bitmap 1693 | ; 1694 | ; return Returns the width in pixels of the supplied bitmap 1695 | 1696 | Gdip_GetImageWidth(pBitmap) 1697 | { 1698 | DllCall("gdiplus\GdipGetImageWidth", "UPtr", pBitmap, "uint*", &Width:=0) 1699 | return Width 1700 | } 1701 | 1702 | ;##################################################################################### 1703 | 1704 | ; Function Gdip_GetImageHeight 1705 | ; Description Gives the height of a bitmap 1706 | ; 1707 | ; pBitmap Pointer to a bitmap 1708 | ; 1709 | ; return Returns the height in pixels of the supplied bitmap 1710 | 1711 | Gdip_GetImageHeight(pBitmap) 1712 | { 1713 | DllCall("gdiplus\GdipGetImageHeight", "UPtr", pBitmap, "uint*", &Height:=0) 1714 | return Height 1715 | } 1716 | 1717 | ;##################################################################################### 1718 | 1719 | ; Function Gdip_GetDimensions 1720 | ; Description Gives the width and height of a bitmap 1721 | ; 1722 | ; pBitmap Pointer to a bitmap 1723 | ; Width ByRef variable. This variable will be set to the width of the bitmap 1724 | ; Height ByRef variable. This variable will be set to the height of the bitmap 1725 | ; 1726 | ; return No return value 1727 | ; Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the height 1728 | 1729 | Gdip_GetImageDimensions(pBitmap, &Width, &Height) 1730 | { 1731 | DllCall("gdiplus\GdipGetImageWidth", "UPtr", pBitmap, "uint*", &Width:=0) 1732 | DllCall("gdiplus\GdipGetImageHeight", "UPtr", pBitmap, "uint*", &Height:=0) 1733 | } 1734 | 1735 | ;##################################################################################### 1736 | 1737 | Gdip_GetDimensions(pBitmap, &Width, &Height) 1738 | { 1739 | Gdip_GetImageDimensions(pBitmap, &Width, &Height) 1740 | } 1741 | 1742 | ;##################################################################################### 1743 | 1744 | Gdip_GetImagePixelFormat(pBitmap) 1745 | { 1746 | DllCall("gdiplus\GdipGetImagePixelFormat", "UPtr", pBitmap, "UPtr*", &_Format:=0) 1747 | return _Format 1748 | } 1749 | 1750 | ;##################################################################################### 1751 | 1752 | ; Function Gdip_GetDpiX 1753 | ; Description Gives the horizontal dots per inch of the graphics of a bitmap 1754 | ; 1755 | ; pBitmap Pointer to a bitmap 1756 | ; Width ByRef variable. This variable will be set to the width of the bitmap 1757 | ; Height ByRef variable. This variable will be set to the height of the bitmap 1758 | ; 1759 | ; return No return value 1760 | ; Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the height 1761 | 1762 | Gdip_GetDpiX(pGraphics) 1763 | { 1764 | DllCall("gdiplus\GdipGetDpiX", "UPtr", pGraphics, "float*", &dpix:=0) 1765 | return Round(dpix) 1766 | } 1767 | 1768 | ;##################################################################################### 1769 | 1770 | Gdip_GetDpiY(pGraphics) 1771 | { 1772 | DllCall("gdiplus\GdipGetDpiY", "UPtr", pGraphics, "float*", &dpiy:=0) 1773 | return Round(dpiy) 1774 | } 1775 | 1776 | ;##################################################################################### 1777 | 1778 | Gdip_GetImageHorizontalResolution(pBitmap) 1779 | { 1780 | DllCall("gdiplus\GdipGetImageHorizontalResolution", "UPtr", pBitmap, "float*", &dpix:=0) 1781 | return Round(dpix) 1782 | } 1783 | 1784 | ;##################################################################################### 1785 | 1786 | Gdip_GetImageVerticalResolution(pBitmap) 1787 | { 1788 | DllCall("gdiplus\GdipGetImageVerticalResolution", "UPtr", pBitmap, "float*", &dpiy:=0) 1789 | return Round(dpiy) 1790 | } 1791 | 1792 | ;##################################################################################### 1793 | 1794 | Gdip_BitmapSetResolution(pBitmap, dpix, dpiy) 1795 | { 1796 | return DllCall("gdiplus\GdipBitmapSetResolution", "UPtr", pBitmap, "Float", dpix, "Float", dpiy) 1797 | } 1798 | 1799 | ;##################################################################################### 1800 | 1801 | Gdip_CreateBitmapFromFile(sFile, IconNumber:=1, IconSize:="") 1802 | { 1803 | SplitPath sFile,,, &extension:="" 1804 | if RegExMatch(extension, "^(?i:exe|dll)$") { 1805 | Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16 1806 | BufSize := 16 + (2*(A_PtrSize ? A_PtrSize : 4)) 1807 | 1808 | buf := Buffer(BufSize, 0) 1809 | hIcon := 0 1810 | 1811 | for eachSize, Size in StrSplit( Sizes, "|" ) { 1812 | DllCall("PrivateExtractIcons", "str", sFile, "Int", IconNumber-1, "Int", Size, "Int", Size, "UPtr*", &hIcon, "UPtr*", 0, "UInt", 1, "UInt", 0) 1813 | 1814 | if (!hIcon) { 1815 | continue 1816 | } 1817 | 1818 | if !DllCall("GetIconInfo", "UPtr", hIcon, "UPtr", buf.Ptr) { 1819 | DestroyIcon(hIcon) 1820 | continue 1821 | } 1822 | 1823 | hbmMask := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4)) 1824 | hbmColor := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4) + (A_PtrSize ? A_PtrSize : 4)) 1825 | if !(hbmColor && DllCall("GetObject", "UPtr", hbmColor, "Int", BufSize, "UPtr", buf.Ptr)) 1826 | { 1827 | DestroyIcon(hIcon) 1828 | continue 1829 | } 1830 | break 1831 | } 1832 | 1833 | if (!hIcon) { 1834 | return -1 1835 | } 1836 | 1837 | Width := NumGet(buf, 4, "Int"), Height := NumGet(buf, 8, "Int") 1838 | hbm := CreateDIBSection(Width, -Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm) 1839 | if !DllCall("DrawIconEx", "UPtr", hdc, "Int", 0, "Int", 0, "UPtr", hIcon, "UInt", Width, "UInt", Height, "UInt", 0, "UPtr", 0, "UInt", 3) { 1840 | DestroyIcon(hIcon) 1841 | return -2 1842 | } 1843 | 1844 | dib := Buffer(104) 1845 | DllCall("GetObject", "UPtr", hbm, "Int", A_PtrSize = 8 ? 104 : 84, "UPtr", dib.Ptr) ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize 1846 | Stride := NumGet(dib, 12, "Int"), Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0)) ; padding 1847 | DllCall("gdiplus\GdipCreateBitmapFromScan0", "Int", Width, "Int", Height, "Int", Stride, "Int", 0x26200A, "UPtr", Bits, "UPtr*", &pBitmapOld:=0) 1848 | pBitmap := Gdip_CreateBitmap(Width, Height) 1849 | _G := Gdip_GraphicsFromImage(pBitmap) 1850 | , Gdip_DrawImage(_G, pBitmapOld, 0, 0, Width, Height, 0, 0, Width, Height) 1851 | SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc) 1852 | Gdip_DeleteGraphics(_G), Gdip_DisposeImage(pBitmapOld) 1853 | DestroyIcon(hIcon) 1854 | 1855 | } else { 1856 | DllCall("gdiplus\GdipCreateBitmapFromFile", "UPtr", StrPtr(sFile), "UPtr*", &pBitmap:=0) 1857 | } 1858 | 1859 | return pBitmap 1860 | } 1861 | 1862 | ;##################################################################################### 1863 | 1864 | Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette:=0) 1865 | { 1866 | DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "UPtr", hBitmap, "UPtr", Palette, "UPtr*", &pBitmap:=0) 1867 | return pBitmap 1868 | } 1869 | 1870 | ;##################################################################################### 1871 | 1872 | Gdip_CreateHBITMAPFromBitmap(pBitmap, Background:=0xffffffff) 1873 | { 1874 | DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "UPtr", pBitmap, "UPtr*", &hbm:=0, "Int", Background) 1875 | return hbm 1876 | } 1877 | 1878 | ;##################################################################################### 1879 | 1880 | Gdip_CreateARGBBitmapFromHBITMAP(&hBitmap) { 1881 | ; struct BITMAP - https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmap 1882 | dib := Buffer(76+2*(A_PtrSize=8?4:0)+2*A_PtrSize) 1883 | DllCall("GetObject" 1884 | , "ptr", hBitmap 1885 | , "Int", dib.Size 1886 | , "ptr", dib.Ptr) ; sizeof(DIBSECTION) = 84, 104 1887 | , width := NumGet(dib, 4, "UInt") 1888 | , height := NumGet(dib, 8, "UInt") 1889 | , bpp := NumGet(dib, 18, "ushort") 1890 | 1891 | ; Fallback to built-in method if pixels are not 32-bit ARGB. 1892 | if (bpp != 32) { ; This built-in version is 120% faster but ignores transparency. 1893 | DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "ptr", hBitmap, "ptr", 0, "ptr*", &pBitmap:=0) 1894 | return pBitmap 1895 | } 1896 | 1897 | ; Create a handle to a device context and associate the image. 1898 | hdc := DllCall("CreateCompatibleDC", "ptr", 0, "ptr") ; Creates a memory DC compatible with the current screen. 1899 | obm := DllCall("SelectObject", "ptr", hdc, "ptr", hBitmap, "ptr") ; Put the (hBitmap) image onto the device context. 1900 | 1901 | ; Create a device independent bitmap with negative height. All DIBs use the screen pixel format (pARGB). 1902 | ; Use hbm to buffer the image such that top-down and bottom-up images are mapped to this top-down buffer. 1903 | cdc := DllCall("CreateCompatibleDC", "ptr", hdc, "ptr") 1904 | bi := Buffer(40, 0) ; sizeof(bi) = 40 1905 | NumPut( 1906 | "UInt", 40, ; Size 1907 | "UInt", width, ; Width 1908 | "Int", height, ; Height - Negative so (0, 0) is top-left. 1909 | "ushort", 1, ; Planes 1910 | "ushort", 32, ; BitCount / BitsPerPixel 1911 | bi) 1912 | hbm := DllCall("CreateDIBSection", "ptr", cdc, "ptr", bi.Ptr, "UInt", 0 1913 | , "ptr*", &pBits:=0 ; pBits is the pointer to (top-down) pixel values. 1914 | , "ptr", 0, "UInt", 0, "ptr") 1915 | ob2 := DllCall("SelectObject", "ptr", cdc, "ptr", hbm, "ptr") 1916 | 1917 | ; This is the 32-bit ARGB pBitmap (different from an hBitmap) that will receive the final converted pixels. 1918 | DllCall("gdiplus\GdipCreateBitmapFromScan0" 1919 | , "Int", width, "Int", height, "Int", 0, "Int", 0x26200A, "ptr", 0, "ptr*", &pBitmap:=0) 1920 | 1921 | ; Create a Scan0 buffer pointing to pBits. The buffer has pixel format pARGB. 1922 | Rect := Buffer(16, 0) ; sizeof(Rect) = 16 1923 | NumPut( 1924 | "UInt", width, ; Width 1925 | "UInt", height, ; Height 1926 | Rect, 8) 1927 | 1928 | BitmapData := Buffer(16+2*A_PtrSize, 0) ; sizeof(BitmapData) = 24, 32 1929 | NumPut( 1930 | "UInt", width, ; Width 1931 | "UInt", height, ; Height 1932 | "Int", 4 * width, ; Stride 1933 | "Int", 0xE200B, ; PixelFormat 1934 | "ptr", pBits, ; Scan0 1935 | BitmapData) 1936 | 1937 | ; Use LockBits to create a writable buffer that converts pARGB to ARGB. 1938 | DllCall("gdiplus\GdipBitmapLockBits" 1939 | , "ptr", pBitmap 1940 | , "ptr", Rect.Ptr 1941 | , "UInt", 6 ; ImageLockMode.UserInputBuffer | ImageLockMode.WriteOnly 1942 | , "Int", 0xE200B ; Format32bppPArgb 1943 | , "ptr", BitmapData.Ptr) ; Contains the pointer (pBits) to the hbm. 1944 | 1945 | ; Copies the image (hBitmap) to a top-down bitmap. Removes bottom-up-ness if present. 1946 | DllCall("gdi32\BitBlt" 1947 | , "ptr", cdc, "Int", 0, "Int", 0, "Int", width, "Int", height 1948 | , "ptr", hdc, "Int", 0, "Int", 0, "UInt", 0x00CC0020) ; SRCCOPY 1949 | 1950 | ; Convert the pARGB pixels copied into the device independent bitmap (hbm) to ARGB. 1951 | DllCall("gdiplus\GdipBitmapUnlockBits", "ptr", pBitmap, "ptr", BitmapData.Ptr) 1952 | 1953 | ; Cleanup the buffer and device contexts. 1954 | DllCall("SelectObject", "ptr", cdc, "ptr", ob2) 1955 | DllCall("DeleteObject", "ptr", hbm) 1956 | DllCall("DeleteDC", "ptr", cdc) 1957 | DllCall("SelectObject", "ptr", hdc, "ptr", obm) 1958 | DllCall("DeleteDC", "ptr", hdc) 1959 | 1960 | return pBitmap 1961 | } 1962 | 1963 | ;##################################################################################### 1964 | 1965 | Gdip_CreateARGBHBITMAPFromBitmap(&pBitmap) { 1966 | ; This version is about 25% faster than Gdip_CreateHBITMAPFromBitmap(). 1967 | ; Get Bitmap width and height. 1968 | DllCall("gdiplus\GdipGetImageWidth", "ptr", pBitmap, "uint*", &width:=0) 1969 | DllCall("gdiplus\GdipGetImageHeight", "ptr", pBitmap, "uint*", &height:=0) 1970 | 1971 | ; Convert the source pBitmap into a hBitmap manually. 1972 | ; struct BITMAPINFOHEADER - https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader 1973 | hdc := DllCall("CreateCompatibleDC", "ptr", 0, "ptr") 1974 | bi := Buffer(40, 0) ; sizeof(bi) = 40 1975 | NumPut( 1976 | "UInt", 40, ; Size 1977 | "UInt", width, ; Width 1978 | "Int", -height, ; Height - Negative so (0, 0) is top-left. 1979 | "ushort", 1, ; Planes 1980 | "ushort", 32, ; BitCount / BitsPerPixel 1981 | bi) 1982 | hbm := DllCall("CreateDIBSection", "ptr", hdc, "ptr", bi.Ptr, "UInt", 0, "ptr*", &pBits:=0, "ptr", 0, "UInt", 0, "ptr") 1983 | obm := DllCall("SelectObject", "ptr", hdc, "ptr", hbm, "ptr") 1984 | 1985 | ; Transfer data from source pBitmap to an hBitmap manually. 1986 | Rect := Buffer(16, 0) ; sizeof(Rect) = 16 1987 | NumPut( 1988 | "UInt", width, ; Width 1989 | "UInt", height, ; Height 1990 | Rect, 8) 1991 | BitmapData := Buffer(16+2*A_PtrSize, 0) ; sizeof(BitmapData) = 24, 32 1992 | NumPut( 1993 | "UInt", width, ; Width 1994 | "UInt", height, ; Height 1995 | "Int", 4 * width, ; Stride 1996 | "Int", 0xE200B, ; PixelFormat 1997 | "ptr", pBits, ; Scan0 1998 | BitmapData) 1999 | DllCall("gdiplus\GdipBitmapLockBits" 2000 | , "ptr", pBitmap 2001 | , "ptr", Rect.Ptr 2002 | , "UInt", 5 ; ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly 2003 | , "Int", 0xE200B ; Format32bppPArgb 2004 | , "ptr", BitmapData.Ptr) ; Contains the pointer (pBits) to the hbm. 2005 | DllCall("gdiplus\GdipBitmapUnlockBits", "ptr", pBitmap, "ptr", BitmapData.Ptr) 2006 | 2007 | ; Cleanup the hBitmap and device contexts. 2008 | DllCall("SelectObject", "ptr", hdc, "ptr", obm) 2009 | DllCall("DeleteDC", "ptr", hdc) 2010 | 2011 | return hbm 2012 | } 2013 | 2014 | ;##################################################################################### 2015 | 2016 | Gdip_CreateBitmapFromHICON(hIcon) 2017 | { 2018 | DllCall("gdiplus\GdipCreateBitmapFromHICON", "UPtr", hIcon, "UPtr*", &pBitmap:=0) 2019 | return pBitmap 2020 | } 2021 | 2022 | ;##################################################################################### 2023 | 2024 | Gdip_CreateHICONFromBitmap(pBitmap) 2025 | { 2026 | DllCall("gdiplus\GdipCreateHICONFromBitmap", "UPtr", pBitmap, "UPtr*", &hIcon:=0) 2027 | return hIcon 2028 | } 2029 | 2030 | ;##################################################################################### 2031 | 2032 | Gdip_CreateBitmap(Width, Height, Format:=0x26200A) 2033 | { 2034 | DllCall("gdiplus\GdipCreateBitmapFromScan0", "Int", Width, "Int", Height, "Int", 0, "Int", Format, "UPtr", 0, "UPtr*", &pBitmap:=0) 2035 | return pBitmap 2036 | } 2037 | 2038 | ;##################################################################################### 2039 | 2040 | Gdip_CreateBitmapFromClipboard() 2041 | { 2042 | if !DllCall("IsClipboardFormatAvailable", "UInt", 8) { 2043 | return -2 2044 | } 2045 | 2046 | if !DllCall("OpenClipboard", "UPtr", 0) { 2047 | return -1 2048 | } 2049 | 2050 | hBitmap := DllCall("GetClipboardData", "UInt", 2, "UPtr") 2051 | 2052 | if !DllCall("CloseClipboard") { 2053 | return -5 2054 | } 2055 | 2056 | if !hBitmap { 2057 | return -3 2058 | } 2059 | 2060 | pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap) 2061 | if (!pBitmap) { 2062 | return -4 2063 | } 2064 | 2065 | DeleteObject(hBitmap) 2066 | 2067 | return pBitmap 2068 | } 2069 | 2070 | ;##################################################################################### 2071 | 2072 | Gdip_SetBitmapToClipboard(pBitmap) 2073 | { 2074 | off1 := A_PtrSize = 8 ? 52 : 44, off2 := A_PtrSize = 8 ? 32 : 24 2075 | hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap) 2076 | oi := Buffer(A_PtrSize = 8 ? 104 : 84, 0) 2077 | DllCall("GetObject", "UPtr", hBitmap, "Int", oi.Size, "UPtr", oi.Ptr) 2078 | hdib := DllCall("GlobalAlloc", "UInt", 2, "UPtr", 40+NumGet(oi, off1, "UInt"), "UPtr") 2079 | pdib := DllCall("GlobalLock", "UPtr", hdib, "UPtr") 2080 | DllCall("RtlMoveMemory", "UPtr", pdib, "UPtr", oi.Ptr+off2, "UPtr", 40) 2081 | DllCall("RtlMoveMemory", "UPtr", pdib+40, "UPtr", NumGet(oi, off2 - (A_PtrSize ? A_PtrSize : 4), "UPtr"), "UPtr", NumGet(oi, off1, "UInt")) 2082 | DllCall("GlobalUnlock", "UPtr", hdib) 2083 | DllCall("DeleteObject", "UPtr", hBitmap) 2084 | DllCall("OpenClipboard", "UPtr", 0) 2085 | DllCall("EmptyClipboard") 2086 | DllCall("SetClipboardData", "UInt", 8, "UPtr", hdib) 2087 | DllCall("CloseClipboard") 2088 | } 2089 | 2090 | ;##################################################################################### 2091 | 2092 | Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format:=0x26200A) 2093 | { 2094 | DllCall("gdiplus\GdipCloneBitmapArea" 2095 | , "Float", x 2096 | , "Float", y 2097 | , "Float", w 2098 | , "Float", h 2099 | , "Int", Format 2100 | , "UPtr", pBitmap 2101 | , "UPtr*", &pBitmapDest:=0) 2102 | return pBitmapDest 2103 | } 2104 | 2105 | ;##################################################################################### 2106 | ; Create resources 2107 | ;##################################################################################### 2108 | 2109 | Gdip_CreatePen(ARGB, w) 2110 | { 2111 | DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "Float", w, "Int", 2, "UPtr*", &pPen:=0) 2112 | return pPen 2113 | } 2114 | 2115 | ;##################################################################################### 2116 | 2117 | Gdip_CreatePenFromBrush(pBrush, w) 2118 | { 2119 | DllCall("gdiplus\GdipCreatePen2", "UPtr", pBrush, "Float", w, "Int", 2, "UPtr*", &pPen:=0) 2120 | return pPen 2121 | } 2122 | 2123 | ;##################################################################################### 2124 | 2125 | Gdip_BrushCreateSolid(ARGB:=0xff000000) 2126 | { 2127 | DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, "UPtr*", &pBrush:=0) 2128 | return pBrush 2129 | } 2130 | 2131 | ;##################################################################################### 2132 | 2133 | ; HatchStyleHorizontal = 0 2134 | ; HatchStyleVertical = 1 2135 | ; HatchStyleForwardDiagonal = 2 2136 | ; HatchStyleBackwardDiagonal = 3 2137 | ; HatchStyleCross = 4 2138 | ; HatchStyleDiagonalCross = 5 2139 | ; HatchStyle05Percent = 6 2140 | ; HatchStyle10Percent = 7 2141 | ; HatchStyle20Percent = 8 2142 | ; HatchStyle25Percent = 9 2143 | ; HatchStyle30Percent = 10 2144 | ; HatchStyle40Percent = 11 2145 | ; HatchStyle50Percent = 12 2146 | ; HatchStyle60Percent = 13 2147 | ; HatchStyle70Percent = 14 2148 | ; HatchStyle75Percent = 15 2149 | ; HatchStyle80Percent = 16 2150 | ; HatchStyle90Percent = 17 2151 | ; HatchStyleLightDownwardDiagonal = 18 2152 | ; HatchStyleLightUpwardDiagonal = 19 2153 | ; HatchStyleDarkDownwardDiagonal = 20 2154 | ; HatchStyleDarkUpwardDiagonal = 21 2155 | ; HatchStyleWideDownwardDiagonal = 22 2156 | ; HatchStyleWideUpwardDiagonal = 23 2157 | ; HatchStyleLightVertical = 24 2158 | ; HatchStyleLightHorizontal = 25 2159 | ; HatchStyleNarrowVertical = 26 2160 | ; HatchStyleNarrowHorizontal = 27 2161 | ; HatchStyleDarkVertical = 28 2162 | ; HatchStyleDarkHorizontal = 29 2163 | ; HatchStyleDashedDownwardDiagonal = 30 2164 | ; HatchStyleDashedUpwardDiagonal = 31 2165 | ; HatchStyleDashedHorizontal = 32 2166 | ; HatchStyleDashedVertical = 33 2167 | ; HatchStyleSmallConfetti = 34 2168 | ; HatchStyleLargeConfetti = 35 2169 | ; HatchStyleZigZag = 36 2170 | ; HatchStyleWave = 37 2171 | ; HatchStyleDiagonalBrick = 38 2172 | ; HatchStyleHorizontalBrick = 39 2173 | ; HatchStyleWeave = 40 2174 | ; HatchStylePlaid = 41 2175 | ; HatchStyleDivot = 42 2176 | ; HatchStyleDottedGrid = 43 2177 | ; HatchStyleDottedDiamond = 44 2178 | ; HatchStyleShingle = 45 2179 | ; HatchStyleTrellis = 46 2180 | ; HatchStyleSphere = 47 2181 | ; HatchStyleSmallGrid = 48 2182 | ; HatchStyleSmallCheckerBoard = 49 2183 | ; HatchStyleLargeCheckerBoard = 50 2184 | ; HatchStyleOutlinedDiamond = 51 2185 | ; HatchStyleSolidDiamond = 52 2186 | ; HatchStyleTotal = 53 2187 | Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle:=0) 2188 | { 2189 | DllCall("gdiplus\GdipCreateHatchBrush", "Int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, "UPtr*", &pBrush:=0) 2190 | return pBrush 2191 | } 2192 | 2193 | ;##################################################################################### 2194 | 2195 | Gdip_CreateTextureBrush(pBitmap, WrapMode:=1, x:=0, y:=0, w:="", h:="") 2196 | { 2197 | if !(w && h) { 2198 | DllCall("gdiplus\GdipCreateTexture", "UPtr", pBitmap, "Int", WrapMode, "UPtr*", &pBrush:=0) 2199 | } else { 2200 | DllCall("gdiplus\GdipCreateTexture2", "UPtr", pBitmap, "Int", WrapMode, "Float", x, "Float", y, "Float", w, "Float", h, "UPtr*", &pBrush:=0) 2201 | } 2202 | 2203 | return pBrush 2204 | } 2205 | 2206 | ;##################################################################################### 2207 | 2208 | ; WrapModeTile = 0 2209 | ; WrapModeTileFlipX = 1 2210 | ; WrapModeTileFlipY = 2 2211 | ; WrapModeTileFlipXY = 3 2212 | ; WrapModeClamp = 4 2213 | Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode:=1) 2214 | { 2215 | CreatePointF(&PointF1:="", x1, y1), CreatePointF(&PointF2:="", x2, y2) 2216 | DllCall("gdiplus\GdipCreateLineBrush", "UPtr", PointF1.Ptr, "UPtr", PointF2.Ptr, "UInt", ARGB1, "UInt", ARGB2, "Int", WrapMode, "UPtr*", &LGpBrush:=0) 2217 | return LGpBrush 2218 | } 2219 | 2220 | ;##################################################################################### 2221 | 2222 | ; LinearGradientModeHorizontal = 0 2223 | ; LinearGradientModeVertical = 1 2224 | ; LinearGradientModeForwardDiagonal = 2 2225 | ; LinearGradientModeBackwardDiagonal = 3 2226 | Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode:=1, WrapMode:=1) 2227 | { 2228 | CreateRectF(&RectF:="", x, y, w, h) 2229 | DllCall("gdiplus\GdipCreateLineBrushFromRect", "UPtr", RectF.Ptr, "Int", ARGB1, "Int", ARGB2, "Int", LinearGradientMode, "Int", WrapMode, "UPtr*", &LGpBrush:=0) 2230 | return LGpBrush 2231 | } 2232 | 2233 | ;##################################################################################### 2234 | 2235 | Gdip_CloneBrush(pBrush) 2236 | { 2237 | DllCall("gdiplus\GdipCloneBrush", "UPtr", pBrush, "UPtr*", &pBrushClone:=0) 2238 | return pBrushClone 2239 | } 2240 | 2241 | ;##################################################################################### 2242 | ; Delete resources 2243 | ;##################################################################################### 2244 | 2245 | Gdip_DeletePen(pPen) 2246 | { 2247 | return DllCall("gdiplus\GdipDeletePen", "UPtr", pPen) 2248 | } 2249 | 2250 | ;##################################################################################### 2251 | 2252 | Gdip_DeleteBrush(pBrush) 2253 | { 2254 | return DllCall("gdiplus\GdipDeleteBrush", "UPtr", pBrush) 2255 | } 2256 | 2257 | ;##################################################################################### 2258 | 2259 | Gdip_DisposeImage(pBitmap) 2260 | { 2261 | return DllCall("gdiplus\GdipDisposeImage", "UPtr", pBitmap) 2262 | } 2263 | 2264 | ;##################################################################################### 2265 | 2266 | Gdip_DeleteGraphics(pGraphics) 2267 | { 2268 | return DllCall("gdiplus\GdipDeleteGraphics", "UPtr", pGraphics) 2269 | } 2270 | 2271 | ;##################################################################################### 2272 | 2273 | Gdip_DisposeImageAttributes(ImageAttr) 2274 | { 2275 | return DllCall("gdiplus\GdipDisposeImageAttributes", "UPtr", ImageAttr) 2276 | } 2277 | 2278 | ;##################################################################################### 2279 | 2280 | Gdip_DeleteFont(hFont) 2281 | { 2282 | return DllCall("gdiplus\GdipDeleteFont", "UPtr", hFont) 2283 | } 2284 | 2285 | ;##################################################################################### 2286 | 2287 | Gdip_DeleteStringFormat(hFormat) 2288 | { 2289 | return DllCall("gdiplus\GdipDeleteStringFormat", "UPtr", hFormat) 2290 | } 2291 | 2292 | ;##################################################################################### 2293 | 2294 | Gdip_DeleteFontFamily(hFamily) 2295 | { 2296 | return DllCall("gdiplus\GdipDeleteFontFamily", "UPtr", hFamily) 2297 | } 2298 | 2299 | ;##################################################################################### 2300 | 2301 | Gdip_DeleteMatrix(Matrix) 2302 | { 2303 | return DllCall("gdiplus\GdipDeleteMatrix", "UPtr", Matrix) 2304 | } 2305 | 2306 | ;##################################################################################### 2307 | ; Text functions 2308 | ;##################################################################################### 2309 | 2310 | Gdip_TextToGraphics(pGraphics, Text, Options, Font:="Arial", Width:="", Height:="", Measure:=0) 2311 | { 2312 | IWidth := Width 2313 | IHeight := Height 2314 | PassBrush := 0 2315 | 2316 | 2317 | pattern_opts := "i)" 2318 | RegExMatch(Options, pattern_opts "X([\-\d\.]+)(p*)", &xpos:="") 2319 | RegExMatch(Options, pattern_opts "Y([\-\d\.]+)(p*)", &ypos:="") 2320 | RegExMatch(Options, pattern_opts "W([\-\d\.]+)(p*)", &Width:="") 2321 | RegExMatch(Options, pattern_opts "H([\-\d\.]+)(p*)", &Height:="") 2322 | RegExMatch(Options, pattern_opts "C(?!(entre|enter))([a-f\d]+)", &Colour:="") 2323 | RegExMatch(Options, pattern_opts "Top|Up|Bottom|Down|vCentre|vCenter", &vPos:="") 2324 | RegExMatch(Options, pattern_opts "NoWrap", &NoWrap:="") 2325 | RegExMatch(Options, pattern_opts "R(\d)", &Rendering:="") 2326 | RegExMatch(Options, pattern_opts "S(\d+)(p*)", &Size:="") 2327 | 2328 | if Colour && IsInteger(Colour[2]) && !Gdip_DeleteBrush(Gdip_CloneBrush(Colour[2])) { 2329 | PassBrush := 1, pBrush := Colour[2] 2330 | } 2331 | 2332 | if !(IWidth && IHeight) && ((xpos && xpos[2]) || (ypos && ypos[2]) || (Width && Width[2]) || (Height && Height[2]) || (Size && Size[2])) { 2333 | return -1 2334 | } 2335 | 2336 | Style := 0 2337 | Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout" 2338 | for eachStyle, valStyle in StrSplit( Styles, "|" ) { 2339 | if RegExMatch(Options, "\b" valStyle) 2340 | Style |= (valStyle != "StrikeOut") ? (A_Index-1) : 8 2341 | } 2342 | 2343 | Align := 0 2344 | Alignments := "Near|Left|Centre|Center|Far|Right" 2345 | for eachAlignment, valAlignment in StrSplit( Alignments, "|" ) { 2346 | if RegExMatch(Options, "\b" valAlignment) { 2347 | Align |= A_Index*10//21 ; 0|0|1|1|2|2 2348 | } 2349 | } 2350 | 2351 | xpos := (xpos && (xpos[1] != "")) ? xpos[2] ? IWidth*(xpos[1]/100) : xpos[1] : 0 2352 | ypos := (ypos && (ypos[1] != "")) ? ypos[2] ? IHeight*(ypos[1]/100) : ypos[1] : 0 2353 | Width := (Width && Width[1]) ? Width[2] ? IWidth*(Width[1]/100) : Width[1] : IWidth 2354 | Height := (Height && Height[1]) ? Height[2] ? IHeight*(Height[1]/100) : Height[1] : IHeight 2355 | 2356 | if !PassBrush { 2357 | Colour := "0x" (Colour && Colour[2] ? Colour[2] : "ff000000") 2358 | } 2359 | 2360 | Rendering := (Rendering && (Rendering[1] >= 0) && (Rendering[1] <= 5)) ? Rendering[1] : 4 2361 | Size := (Size && (Size[1] > 0)) ? Size[2] ? IHeight*(Size[1]/100) : Size[1] : 12 2362 | 2363 | hFamily := Gdip_FontFamilyCreate(Font) 2364 | hFont := Gdip_FontCreate(hFamily, Size, Style) 2365 | FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000 2366 | hFormat := Gdip_StringFormatCreate(FormatStyle) 2367 | pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour) 2368 | 2369 | if !(hFamily && hFont && hFormat && pBrush && pGraphics) { 2370 | return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0 2371 | } 2372 | 2373 | CreateRectF(&RC:="", xpos, ypos, Width, Height) 2374 | Gdip_SetStringFormatAlign(hFormat, Align) 2375 | Gdip_SetTextRenderingHint(pGraphics, Rendering) 2376 | ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, &RC) 2377 | 2378 | if vPos { 2379 | ReturnRC := StrSplit(ReturnRC, "|") 2380 | 2381 | if (vPos[0] = "vCentre") || (vPos[0] = "vCenter") 2382 | ypos += (Height-ReturnRC[4])//2 2383 | else if (vPos[0] = "Top") || (vPos[0] = "Up") 2384 | ypos := 0 2385 | else if (vPos[0] = "Bottom") || (vPos[0] = "Down") 2386 | ypos := Height-ReturnRC[4] 2387 | 2388 | CreateRectF(&RC, xpos, ypos, Width, ReturnRC[4]) 2389 | ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, &RC) 2390 | } 2391 | 2392 | if !Measure { 2393 | ReturnRC := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, &RC) 2394 | } 2395 | 2396 | if !PassBrush { 2397 | Gdip_DeleteBrush(pBrush) 2398 | } 2399 | 2400 | Gdip_DeleteStringFormat(hFormat) 2401 | Gdip_DeleteFont(hFont) 2402 | Gdip_DeleteFontFamily(hFamily) 2403 | 2404 | return ReturnRC 2405 | } 2406 | 2407 | ;##################################################################################### 2408 | 2409 | Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, &RectF) 2410 | { 2411 | return DllCall("gdiplus\GdipDrawString" 2412 | , "UPtr", pGraphics 2413 | , "UPtr", StrPtr(sString) 2414 | , "Int", -1 2415 | , "UPtr", hFont 2416 | , "UPtr", RectF.Ptr 2417 | , "UPtr", hFormat 2418 | , "UPtr", pBrush) 2419 | } 2420 | 2421 | ;##################################################################################### 2422 | 2423 | Gdip_MeasureString(pGraphics, sString, hFont, hFormat, &RectF) 2424 | { 2425 | RC := Buffer(16) 2426 | DllCall("gdiplus\GdipMeasureString" 2427 | , "UPtr", pGraphics 2428 | , "UPtr", StrPtr(sString) 2429 | , "Int", -1 2430 | , "UPtr", hFont 2431 | , "UPtr", RectF.Ptr 2432 | , "UPtr", hFormat 2433 | , "UPtr", RC.Ptr 2434 | , "uint*", &Chars:=0 2435 | , "uint*", &Lines:=0) 2436 | 2437 | return RC.Ptr ? NumGet(RC, 0, "Float") "|" NumGet(RC, 4, "Float") "|" NumGet(RC, 8, "Float") "|" NumGet(RC, 12, "Float") "|" Chars "|" Lines : 0 2438 | } 2439 | 2440 | ; Near = 0 2441 | ; Center = 1 2442 | ; Far = 2 2443 | Gdip_SetStringFormatAlign(hFormat, Align) 2444 | { 2445 | return DllCall("gdiplus\GdipSetStringFormatAlign", "UPtr", hFormat, "Int", Align) 2446 | } 2447 | 2448 | ; StringFormatFlagsDirectionRightToLeft = 0x00000001 2449 | ; StringFormatFlagsDirectionVertical = 0x00000002 2450 | ; StringFormatFlagsNoFitBlackBox = 0x00000004 2451 | ; StringFormatFlagsDisplayFormatControl = 0x00000020 2452 | ; StringFormatFlagsNoFontFallback = 0x00000400 2453 | ; StringFormatFlagsMeasureTrailingSpaces = 0x00000800 2454 | ; StringFormatFlagsNoWrap = 0x00001000 2455 | ; StringFormatFlagsLineLimit = 0x00002000 2456 | ; StringFormatFlagsNoClip = 0x00004000 2457 | Gdip_StringFormatCreate(Format:=0, Lang:=0) 2458 | { 2459 | DllCall("gdiplus\GdipCreateStringFormat", "Int", Format, "Int", Lang, "UPtr*", &hFormat:=0) 2460 | return hFormat 2461 | } 2462 | 2463 | ; Regular = 0 2464 | ; Bold = 1 2465 | ; Italic = 2 2466 | ; BoldItalic = 3 2467 | ; Underline = 4 2468 | ; Strikeout = 8 2469 | Gdip_FontCreate(hFamily, Size, Style:=0) 2470 | { 2471 | DllCall("gdiplus\GdipCreateFont", "UPtr", hFamily, "Float", Size, "Int", Style, "Int", 0, "UPtr*", &hFont:=0) 2472 | return hFont 2473 | } 2474 | 2475 | Gdip_FontFamilyCreate(Font) 2476 | { 2477 | DllCall("gdiplus\GdipCreateFontFamilyFromName" 2478 | , "UPtr", StrPtr(Font) 2479 | , "UInt", 0 2480 | , "UPtr*", &hFamily:=0) 2481 | 2482 | return hFamily 2483 | } 2484 | 2485 | ;##################################################################################### 2486 | ; Matrix functions 2487 | ;##################################################################################### 2488 | 2489 | Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y) 2490 | { 2491 | DllCall("gdiplus\GdipCreateMatrix2", "Float", m11, "Float", m12, "Float", m21, "Float", m22, "Float", x, "Float", y, "UPtr*", &Matrix:=0) 2492 | return Matrix 2493 | } 2494 | 2495 | Gdip_CreateMatrix() 2496 | { 2497 | DllCall("gdiplus\GdipCreateMatrix", "UPtr*", &Matrix:=0) 2498 | return Matrix 2499 | } 2500 | 2501 | ;##################################################################################### 2502 | ; GraphicsPath functions 2503 | ;##################################################################################### 2504 | 2505 | ; Alternate = 0 2506 | ; Winding = 1 2507 | Gdip_CreatePath(BrushMode:=0) 2508 | { 2509 | DllCall("gdiplus\GdipCreatePath", "Int", BrushMode, "UPtr*", &pPath:=0) 2510 | return pPath 2511 | } 2512 | 2513 | Gdip_AddPathEllipse(pPath, x, y, w, h) 2514 | { 2515 | return DllCall("gdiplus\GdipAddPathEllipse", "UPtr", pPath, "Float", x, "Float", y, "Float", w, "Float", h) 2516 | } 2517 | 2518 | Gdip_AddPathPolygon(pPath, Points) 2519 | { 2520 | Points := StrSplit(Points, "|") 2521 | PointsLength := Points.Length 2522 | PointF := Buffer(8*PointsLength) 2523 | for eachPoint, Point in Points 2524 | { 2525 | Coord := StrSplit(Point, ",") 2526 | NumPut("Float", Coord[1], PointF, 8*(A_Index-1)) 2527 | NumPut("Float", Coord[2], PointF, (8*(A_Index-1))+4) 2528 | } 2529 | 2530 | return DllCall("gdiplus\GdipAddPathPolygon", "UPtr", pPath, "UPtr", PointF.Ptr, "Int", PointsLength) 2531 | } 2532 | 2533 | Gdip_DeletePath(pPath) 2534 | { 2535 | return DllCall("gdiplus\GdipDeletePath", "UPtr", pPath) 2536 | } 2537 | 2538 | ;##################################################################################### 2539 | ; Quality functions 2540 | ;##################################################################################### 2541 | 2542 | ; SystemDefault = 0 2543 | ; SingleBitPerPixelGridFit = 1 2544 | ; SingleBitPerPixel = 2 2545 | ; AntiAliasGridFit = 3 2546 | ; AntiAlias = 4 2547 | Gdip_SetTextRenderingHint(pGraphics, RenderingHint) 2548 | { 2549 | return DllCall("gdiplus\GdipSetTextRenderingHint", "UPtr", pGraphics, "Int", RenderingHint) 2550 | } 2551 | 2552 | ; Default = 0 2553 | ; LowQuality = 1 2554 | ; HighQuality = 2 2555 | ; Bilinear = 3 2556 | ; Bicubic = 4 2557 | ; NearestNeighbor = 5 2558 | ; HighQualityBilinear = 6 2559 | ; HighQualityBicubic = 7 2560 | Gdip_SetInterpolationMode(pGraphics, InterpolationMode) 2561 | { 2562 | return DllCall("gdiplus\GdipSetInterpolationMode", "UPtr", pGraphics, "Int", InterpolationMode) 2563 | } 2564 | 2565 | ; Default = 0 2566 | ; HighSpeed = 1 2567 | ; HighQuality = 2 2568 | ; None = 3 2569 | ; AntiAlias = 4 2570 | Gdip_SetSmoothingMode(pGraphics, SmoothingMode) 2571 | { 2572 | return DllCall("gdiplus\GdipSetSmoothingMode", "UPtr", pGraphics, "Int", SmoothingMode) 2573 | } 2574 | 2575 | ; CompositingModeSourceOver = 0 (blended) 2576 | ; CompositingModeSourceCopy = 1 (overwrite) 2577 | Gdip_SetCompositingMode(pGraphics, CompositingMode:=0) 2578 | { 2579 | return DllCall("gdiplus\GdipSetCompositingMode", "UPtr", pGraphics, "Int", CompositingMode) 2580 | } 2581 | 2582 | ;##################################################################################### 2583 | ; Extra functions 2584 | ;##################################################################################### 2585 | 2586 | Gdip_Startup() 2587 | { 2588 | if (!DllCall("LoadLibrary", "str", "gdiplus", "UPtr")) { 2589 | throw Error("Could not load GDI+ library") 2590 | } 2591 | 2592 | si := Buffer(A_PtrSize = 4 ? 20:32, 0) ; sizeof(GdiplusStartupInputEx) = 20, 32 2593 | NumPut("uint", 0x2, si) 2594 | NumPut("uint", 0x4, si, A_PtrSize = 4 ? 16:24) 2595 | DllCall("gdiplus\GdiplusStartup", "UPtr*", &pToken:=0, "Ptr", si, "UPtr", 0) 2596 | if (!pToken) { 2597 | throw Error("Gdiplus failed to start. Please ensure you have gdiplus on your system") 2598 | } 2599 | 2600 | return pToken 2601 | } 2602 | 2603 | Gdip_Shutdown(pToken) 2604 | { 2605 | DllCall("gdiplus\GdiplusShutdown", "UPtr", pToken) 2606 | hModule := DllCall("GetModuleHandle", "str", "gdiplus", "UPtr") 2607 | if (!hModule) { 2608 | throw Error("GDI+ library was unloaded before shutdown") 2609 | } 2610 | if (!DllCall("FreeLibrary", "UPtr", hModule)) { 2611 | throw Error("Could not free GDI+ library") 2612 | } 2613 | 2614 | return 0 2615 | } 2616 | 2617 | ; Prepend = 0; The new operation is applied before the old operation. 2618 | ; Append = 1; The new operation is applied after the old operation. 2619 | Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder:=0) 2620 | { 2621 | return DllCall("gdiplus\GdipRotateWorldTransform", "UPtr", pGraphics, "Float", Angle, "Int", MatrixOrder) 2622 | } 2623 | 2624 | Gdip_ScaleWorldTransform(pGraphics, x, y, MatrixOrder:=0) 2625 | { 2626 | return DllCall("gdiplus\GdipScaleWorldTransform", "UPtr", pGraphics, "Float", x, "Float", y, "Int", MatrixOrder) 2627 | } 2628 | 2629 | Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder:=0) 2630 | { 2631 | return DllCall("gdiplus\GdipTranslateWorldTransform", "UPtr", pGraphics, "Float", x, "Float", y, "Int", MatrixOrder) 2632 | } 2633 | 2634 | Gdip_ResetWorldTransform(pGraphics) 2635 | { 2636 | return DllCall("gdiplus\GdipResetWorldTransform", "UPtr", pGraphics) 2637 | } 2638 | 2639 | Gdip_GetRotatedTranslation(Width, Height, Angle, &xTranslation, &yTranslation) 2640 | { 2641 | pi := 3.14159, TAngle := Angle*(pi/180) 2642 | 2643 | Bound := (Angle >= 0) ? Mod(Angle, 360) : 360-Mod(-Angle, -360) 2644 | if ((Bound >= 0) && (Bound <= 90)) { 2645 | xTranslation := Height*Sin(TAngle), yTranslation := 0 2646 | } else if ((Bound > 90) && (Bound <= 180)) { 2647 | xTranslation := (Height*Sin(TAngle))-(Width*Cos(TAngle)), yTranslation := -Height*Cos(TAngle) 2648 | } else if ((Bound > 180) && (Bound <= 270)) { 2649 | xTranslation := -(Width*Cos(TAngle)), yTranslation := -(Height*Cos(TAngle))-(Width*Sin(TAngle)) 2650 | } else if ((Bound > 270) && (Bound <= 360)) { 2651 | xTranslation := 0, yTranslation := -Width*Sin(TAngle) 2652 | } 2653 | } 2654 | 2655 | Gdip_GetRotatedDimensions(Width, Height, Angle, &RWidth, &RHeight) 2656 | { 2657 | pi := 3.14159, TAngle := Angle*(pi/180) 2658 | 2659 | if !(Width && Height) { 2660 | return -1 2661 | } 2662 | 2663 | RWidth := Ceil(Abs(Width*Cos(TAngle))+Abs(Height*Sin(TAngle))) 2664 | RHeight := Ceil(Abs(Width*Sin(TAngle))+Abs(Height*Cos(Tangle))) 2665 | } 2666 | 2667 | ; RotateNoneFlipNone = 0 2668 | ; Rotate90FlipNone = 1 2669 | ; Rotate180FlipNone = 2 2670 | ; Rotate270FlipNone = 3 2671 | ; RotateNoneFlipX = 4 2672 | ; Rotate90FlipX = 5 2673 | ; Rotate180FlipX = 6 2674 | ; Rotate270FlipX = 7 2675 | ; RotateNoneFlipY = Rotate180FlipX 2676 | ; Rotate90FlipY = Rotate270FlipX 2677 | ; Rotate180FlipY = RotateNoneFlipX 2678 | ; Rotate270FlipY = Rotate90FlipX 2679 | ; RotateNoneFlipXY = Rotate180FlipNone 2680 | ; Rotate90FlipXY = Rotate270FlipNone 2681 | ; Rotate180FlipXY = RotateNoneFlipNone 2682 | ; Rotate270FlipXY = Rotate90FlipNone 2683 | 2684 | Gdip_ImageRotateFlip(pBitmap, RotateFlipType:=1) 2685 | { 2686 | return DllCall("gdiplus\GdipImageRotateFlip", "UPtr", pBitmap, "Int", RotateFlipType) 2687 | } 2688 | 2689 | ; Replace = 0 2690 | ; Intersect = 1 2691 | ; Union = 2 2692 | ; Xor = 3 2693 | ; Exclude = 4 2694 | ; Complement = 5 2695 | Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode:=0) 2696 | { 2697 | return DllCall("gdiplus\GdipSetClipRect", "UPtr", pGraphics, "Float", x, "Float", y, "Float", w, "Float", h, "Int", CombineMode) 2698 | } 2699 | 2700 | Gdip_SetClipPath(pGraphics, pPath, CombineMode:=0) 2701 | { 2702 | return DllCall("gdiplus\GdipSetClipPath", "UPtr", pGraphics, "UPtr", pPath, "Int", CombineMode) 2703 | } 2704 | 2705 | Gdip_ResetClip(pGraphics) 2706 | { 2707 | return DllCall("gdiplus\GdipResetClip", "UPtr", pGraphics) 2708 | } 2709 | 2710 | Gdip_GetClipRegion(pGraphics) 2711 | { 2712 | Region := Gdip_CreateRegion() 2713 | DllCall("gdiplus\GdipGetClip", "UPtr", pGraphics, "UPtr", Region) 2714 | return Region 2715 | } 2716 | 2717 | Gdip_SetClipRegion(pGraphics, Region, CombineMode:=0) 2718 | { 2719 | return DllCall("gdiplus\GdipSetClipRegion", "UPtr", pGraphics, "UPtr", Region, "Int", CombineMode) 2720 | } 2721 | 2722 | Gdip_CreateRegion() 2723 | { 2724 | DllCall("gdiplus\GdipCreateRegion", "UPtr*", &Region:=0) 2725 | return Region 2726 | } 2727 | 2728 | Gdip_DeleteRegion(Region) 2729 | { 2730 | return DllCall("gdiplus\GdipDeleteRegion", "UPtr", Region) 2731 | } 2732 | 2733 | ;##################################################################################### 2734 | ; BitmapLockBits 2735 | ;##################################################################################### 2736 | 2737 | Gdip_LockBits(pBitmap, x, y, w, h, &Stride, &Scan0, &BitmapData, LockMode := 3, PixelFormat := 0x26200a) 2738 | { 2739 | CreateRect(&_Rect:="", x, y, w, h) 2740 | BitmapData := Buffer(16+2*(A_PtrSize ? A_PtrSize : 4), 0) 2741 | _E := DllCall("Gdiplus\GdipBitmapLockBits", "UPtr", pBitmap, "UPtr", _Rect.Ptr, "UInt", LockMode, "Int", PixelFormat, "UPtr", BitmapData.Ptr) 2742 | Stride := NumGet(BitmapData, 8, "Int") 2743 | Scan0 := NumGet(BitmapData, 16, "UPtr") 2744 | return _E 2745 | } 2746 | 2747 | ;##################################################################################### 2748 | 2749 | Gdip_UnlockBits(pBitmap, &BitmapData) 2750 | { 2751 | return DllCall("Gdiplus\GdipBitmapUnlockBits", "UPtr", pBitmap, "UPtr", BitmapData.Ptr) 2752 | } 2753 | 2754 | ;##################################################################################### 2755 | 2756 | Gdip_SetLockBitPixel(ARGB, Scan0, x, y, Stride) 2757 | { 2758 | Numput("UInt", ARGB, Scan0+0, (x*4)+(y*Stride)) 2759 | } 2760 | 2761 | ;##################################################################################### 2762 | 2763 | Gdip_GetLockBitPixel(Scan0, x, y, Stride) 2764 | { 2765 | return NumGet(Scan0+0, (x*4)+(y*Stride), "UInt") 2766 | } 2767 | 2768 | ;##################################################################################### 2769 | 2770 | Gdip_PixelateBitmap(pBitmap, &pBitmapOut, BlockSize) 2771 | { 2772 | static PixelateBitmap := "" 2773 | 2774 | if (!PixelateBitmap) 2775 | { 2776 | if A_PtrSize != 8 ; x86 machine code 2777 | MCode_PixelateBitmap := " 2778 | (LTrim Join 2779 | 558BEC83EC3C8B4514538B5D1C99F7FB56578BC88955EC894DD885C90F8E830200008B451099F7FB8365DC008365E000894DC88955F08945E833FF897DD4 2780 | 397DE80F8E160100008BCB0FAFCB894DCC33C08945F88945FC89451C8945143BD87E608B45088D50028BC82BCA8BF02BF2418945F48B45E02955F4894DC4 2781 | 8D0CB80FAFCB03CA895DD08BD1895DE40FB64416030145140FB60201451C8B45C40FB604100145FC8B45F40FB604020145F883C204FF4DE475D6034D18FF 2782 | 4DD075C98B4DCC8B451499F7F98945148B451C99F7F989451C8B45FC99F7F98945FC8B45F899F7F98945F885DB7E648B450C8D50028BC82BCA83C103894D 2783 | C48BC82BCA41894DF48B4DD48945E48B45E02955E48D0C880FAFCB03CA895DD08BD18BF38A45148B7DC48804178A451C8B7DF488028A45FC8804178A45F8 2784 | 8B7DE488043A83C2044E75DA034D18FF4DD075CE8B4DCC8B7DD447897DD43B7DE80F8CF2FEFFFF837DF0000F842C01000033C08945F88945FC89451C8945 2785 | 148945E43BD87E65837DF0007E578B4DDC034DE48B75E80FAF4D180FAFF38B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945CC0F 2786 | B6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604010145F883C104FF4DCC75D8FF45E4395DE47C9B8B4DF00FAFCB85C9740B8B451499F7 2787 | F9894514EB048365140033F63BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB 2788 | 038975F88975E43BDE7E5A837DF0007E4C8B4DDC034DE48B75E80FAF4D180FAFF38B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955CC8A55 2789 | 1488540E038A551C88118A55FC88540F018A55F888140183C104FF4DCC75DFFF45E4395DE47CA68B45180145E0015DDCFF4DC80F8594FDFFFF8B451099F7 2790 | FB8955F08945E885C00F8E450100008B45EC0FAFC38365DC008945D48B45E88945CC33C08945F88945FC89451C8945148945103945EC7E6085DB7E518B4D 2791 | D88B45080FAFCB034D108D50020FAF4D18034DDC8BF08BF88945F403CA2BF22BFA2955F4895DC80FB6440E030145140FB60101451C0FB6440F010145FC8B 2792 | 45F40FB604080145F883C104FF4DC875D8FF45108B45103B45EC7CA08B4DD485C9740B8B451499F7F9894514EB048365140033F63BCE740B8B451C99F7F9 2793 | 89451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975103975EC7E5585DB7E468B4DD88B450C 2794 | 0FAFCB034D108D50020FAF4D18034DDC8BF08BF803CA2BF22BFA2BC2895DC88A551488540E038A551C88118A55FC88540F018A55F888140183C104FF4DC8 2795 | 75DFFF45108B45103B45EC7CAB8BC3C1E0020145DCFF4DCC0F85CEFEFFFF8B4DEC33C08945F88945FC89451C8945148945103BC87E6C3945F07E5C8B4DD8 2796 | 8B75E80FAFCB034D100FAFF30FAF4D188B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945C80FB6440E030145140FB60101451C0F 2797 | B6440F010145FC8B45F40FB604010145F883C104FF4DC875D833C0FF45108B4DEC394D107C940FAF4DF03BC874068B451499F7F933F68945143BCE740B8B 2798 | 451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975083975EC7E63EB0233F639 2799 | 75F07E4F8B4DD88B75E80FAFCB034D080FAFF30FAF4D188B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955108A551488540E038A551C8811 2800 | 8A55FC88540F018A55F888140883C104FF4D1075DFFF45088B45083B45EC7C9F5F5E33C05BC9C21800 2801 | )" 2802 | else ; x64 machine code 2803 | MCode_PixelateBitmap := " 2804 | (LTrim Join 2805 | 4489442418488954241048894C24085355565741544155415641574883EC28418BC1448B8C24980000004C8BDA99488BD941F7F9448BD0448BFA8954240C 2806 | 448994248800000085C00F8E9D020000418BC04533E4458BF299448924244C8954241041F7F933C9898C24980000008BEA89542404448BE889442408EB05 2807 | 4C8B5C24784585ED0F8E1A010000458BF1418BFD48897C2418450FAFF14533D233F633ED4533E44533ED4585C97E5B4C63BC2490000000418D040A410FAF 2808 | C148984C8D441802498BD9498BD04D8BD90FB642010FB64AFF4403E80FB60203E90FB64AFE4883C2044403E003F149FFCB75DE4D03C748FFCB75D0488B7C 2809 | 24188B8C24980000004C8B5C2478418BC59941F7FE448BE8418BC49941F7FE448BE08BC59941F7FE8BE88BC69941F7FE8BF04585C97E4048639C24900000 2810 | 004103CA4D8BC1410FAFC94863C94A8D541902488BCA498BC144886901448821408869FF408871FE4883C10448FFC875E84803D349FFC875DA8B8C249800 2811 | 0000488B5C24704C8B5C24784183C20448FFCF48897C24180F850AFFFFFF8B6C2404448B2424448B6C24084C8B74241085ED0F840A01000033FF33DB4533 2812 | DB4533D24533C04585C97E53488B74247085ED7E42438D0C04418BC50FAF8C2490000000410FAFC18D04814863C8488D5431028BCD0FB642014403D00FB6 2813 | 024883C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC17CB28BCD410FAFC985C9740A418BC299F7F98BF0EB0233F685C9740B418BC3 2814 | 99F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585C97E4D4C8B74247885ED7E3841 2815 | 8D0C14418BC50FAF8C2490000000410FAFC18D04814863C84A8D4431028BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2413BD17CBD 2816 | 4C8B7424108B8C2498000000038C2490000000488B5C24704503E149FFCE44892424898C24980000004C897424100F859EFDFFFF448B7C240C448B842480 2817 | 000000418BC09941F7F98BE8448BEA89942498000000896C240C85C00F8E3B010000448BAC2488000000418BCF448BF5410FAFC9898C248000000033FF33 2818 | ED33F64533DB4533D24533C04585FF7E524585C97E40418BC5410FAFC14103C00FAF84249000000003C74898488D541802498BD90FB642014403D00FB602 2819 | 4883C2044403D80FB642FB03F00FB642FA03E848FFCB75DE488B5C247041FFC0453BC77CAE85C9740B418BC299F7F9448BE0EB034533E485C9740A418BC3 2820 | 99F7F98BD8EB0233DB85C9740A8BC699F7F9448BD8EB034533DB85C9740A8BC599F7F9448BD0EB034533D24533C04585FF7E4E488B4C24784585C97E3541 2821 | 8BC5410FAFC14103C00FAF84249000000003C74898488D540802498BC144886201881A44885AFF448852FE4883C20448FFC875E941FFC0453BC77CBE8B8C 2822 | 2480000000488B5C2470418BC1C1E00203F849FFCE0F85ECFEFFFF448BAC24980000008B6C240C448BA4248800000033FF33DB4533DB4533D24533C04585 2823 | FF7E5A488B7424704585ED7E48418BCC8BC5410FAFC94103C80FAF8C2490000000410FAFC18D04814863C8488D543102418BCD0FB642014403D00FB60248 2824 | 83C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC77CAB418BCF410FAFCD85C9740A418BC299F7F98BF0EB0233F685C9740B418BC399 2825 | F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585FF7E4E4585ED7E42418BCC8BC541 2826 | 0FAFC903CA0FAF8C2490000000410FAFC18D04814863C8488B442478488D440102418BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2 2827 | 413BD77CB233C04883C428415F415E415D415C5F5E5D5BC3 2828 | )" 2829 | 2830 | PixelateBitmap := Buffer(StrLen(MCode_PixelateBitmap)//2) 2831 | nCount := StrLen(MCode_PixelateBitmap)//2 2832 | loop nCount { 2833 | NumPut("UChar", "0x" SubStr(MCode_PixelateBitmap, (2*A_Index)-1, 2), PixelateBitmap, A_Index-1) 2834 | } 2835 | DllCall("VirtualProtect", "UPtr", PixelateBitmap.Ptr, "UPtr", PixelateBitmap.Size, "UInt", 0x40, "UPtr*", 0) 2836 | } 2837 | 2838 | Gdip_GetImageDimensions(pBitmap, &Width:="", &Height:="") 2839 | 2840 | if (Width != Gdip_GetImageWidth(pBitmapOut) || Height != Gdip_GetImageHeight(pBitmapOut)) 2841 | return -1 2842 | if (BlockSize > Width || BlockSize > Height) 2843 | return -2 2844 | 2845 | E1 := Gdip_LockBits(pBitmap, 0, 0, Width, Height, &Stride1:="", &Scan01:="", &BitmapData1:="") 2846 | E2 := Gdip_LockBits(pBitmapOut, 0, 0, Width, Height, &Stride2:="", &Scan02:="", &BitmapData2:="") 2847 | if (E1 || E2) 2848 | return -3 2849 | 2850 | ; E := - unused exit code 2851 | DllCall(PixelateBitmap.Ptr, "UPtr", Scan01, "UPtr", Scan02, "Int", Width, "Int", Height, "Int", Stride1, "Int", BlockSize) 2852 | 2853 | Gdip_UnlockBits(pBitmap, &BitmapData1), Gdip_UnlockBits(pBitmapOut, &BitmapData2) 2854 | 2855 | return 0 2856 | } 2857 | 2858 | ;##################################################################################### 2859 | 2860 | Gdip_ToARGB(A, R, G, B) 2861 | { 2862 | return (A << 24) | (R << 16) | (G << 8) | B 2863 | } 2864 | 2865 | ;##################################################################################### 2866 | 2867 | Gdip_FromARGB(ARGB, &A, &R, &G, &B) 2868 | { 2869 | A := (0xff000000 & ARGB) >> 24 2870 | R := (0x00ff0000 & ARGB) >> 16 2871 | G := (0x0000ff00 & ARGB) >> 8 2872 | B := 0x000000ff & ARGB 2873 | } 2874 | 2875 | ;##################################################################################### 2876 | 2877 | Gdip_AFromARGB(ARGB) 2878 | { 2879 | return (0xff000000 & ARGB) >> 24 2880 | } 2881 | 2882 | ;##################################################################################### 2883 | 2884 | Gdip_RFromARGB(ARGB) 2885 | { 2886 | return (0x00ff0000 & ARGB) >> 16 2887 | } 2888 | 2889 | ;##################################################################################### 2890 | 2891 | Gdip_GFromARGB(ARGB) 2892 | { 2893 | return (0x0000ff00 & ARGB) >> 8 2894 | } 2895 | 2896 | ;##################################################################################### 2897 | 2898 | Gdip_BFromARGB(ARGB) 2899 | { 2900 | return 0x000000ff & ARGB 2901 | } 2902 | 2903 | ;##################################################################################### 2904 | 2905 | StrGetB(Address, Length:=-1, Encoding:=0) 2906 | { 2907 | ; Flexible parameter handling: 2908 | if !IsInteger(Length) { 2909 | Encoding := Length, Length := -1 2910 | } 2911 | 2912 | ; Check for obvious errors. 2913 | if (Address+0 < 1024) { 2914 | return 2915 | } 2916 | 2917 | ; Ensure 'Encoding' contains a numeric identifier. 2918 | if (Encoding = "UTF-16") { 2919 | Encoding := 1200 2920 | } else if (Encoding = "UTF-8") { 2921 | Encoding := 65001 2922 | } else if SubStr(Encoding,1,2)="CP" { 2923 | Encoding := SubStr(Encoding,3) 2924 | } 2925 | 2926 | if !Encoding { ; "" or 0 2927 | ; No conversion necessary, but we might not want the whole string. 2928 | if (Length == -1) 2929 | Length := DllCall("lstrlen", "Ptr", Address) 2930 | VarSetStrCapacity(&myString, Length) 2931 | DllCall("lstrcpyn", "str", myString, "Ptr", Address, "Int", Length + 1) 2932 | 2933 | } else if (Encoding = 1200) { ; UTF-16 2934 | char_count := DllCall("WideCharToMultiByte", "UInt", 0, "UInt", 0x400, "Ptr", Address, "Int", Length, "UInt", 0, "UInt", 0, "UInt", 0, "UInt", 0) 2935 | VarSetStrCapacity(&myString, char_count) 2936 | DllCall("WideCharToMultiByte", "UInt", 0, "UInt", 0x400, "Ptr", Address, "Int", Length, "str", myString, "Int", char_count, "UInt", 0, "UInt", 0) 2937 | 2938 | } else if IsInteger(Encoding) { 2939 | ; Convert from target encoding to UTF-16 then to the active code page. 2940 | char_count := DllCall("MultiByteToWideChar", "UInt", Encoding, "UInt", 0, "Ptr", Address, "Int", Length, "Ptr", 0, "Int", 0) 2941 | VarSetStrCapacity(&myString, char_count * 2) 2942 | char_count := DllCall("MultiByteToWideChar", "UInt", Encoding, "UInt", 0, "Ptr", Address, "Int", Length, "Ptr", myString.Ptr, "Int", char_count * 2) 2943 | myString := StrGetB(myString.Ptr, char_count, 1200) 2944 | } 2945 | 2946 | return myString 2947 | } 2948 | 2949 | 2950 | ; ====================================================================================================================== 2951 | ; Multiple Display Monitors Functions -> msdn.microsoft.com/en-us/library/dd145072(v=vs.85).aspx 2952 | ; by 'just me' 2953 | ; https://autohotkey.com/boards/viewtopic.php?f=6&t=4606 2954 | ; ====================================================================================================================== 2955 | GetMonitorCount() 2956 | { 2957 | Monitors := MDMF_Enum() 2958 | for k,v in Monitors { 2959 | count := A_Index 2960 | } 2961 | return count 2962 | } 2963 | 2964 | GetMonitorInfo(MonitorNum) 2965 | { 2966 | Monitors := MDMF_Enum() 2967 | for k,v in Monitors { 2968 | if (v.Num = MonitorNum) { 2969 | return v 2970 | } 2971 | } 2972 | } 2973 | 2974 | GetPrimaryMonitor() 2975 | { 2976 | Monitors := MDMF_Enum() 2977 | for k,v in Monitors { 2978 | if (v.Primary) { 2979 | return v.Num 2980 | } 2981 | } 2982 | } 2983 | ; ---------------------------------------------------------------------------------------------------------------------- 2984 | ; Name ..........: MDMF - Multiple Display Monitor Functions 2985 | ; Description ...: Various functions for multiple display monitor environments 2986 | ; Tested with ...: AHK 1.1.32.00 (A32/U32/U64) and 2.0-a108-a2fa0498 (U32/U64) 2987 | ; Original Author: just me (https://www.autohotkey.com/boards/viewtopic.php?f=6&t=4606) 2988 | ; Mod Authors ...: iPhilip, guest3456 2989 | ; Changes .......: Modified to work with v2.0-a108 and changed 'Count' key to 'TotalCount' to avoid conflicts 2990 | ; ................ Modified MDMF_Enum() so that it works under both AHK v1 and v2. 2991 | ; ................ Modified MDMF_EnumProc() to provide Count and Primary keys to the Monitors array. 2992 | ; ................ Modified MDMF_FromHWND() to allow flag values that determine the function's return value if the 2993 | ; ................ window does not intersect any display monitor. 2994 | ; ................ Modified MDMF_FromPoint() to allow the cursor position to be returned ByRef if not specified and 2995 | ; ................ allow flag values that determine the function's return value if the point is not contained within 2996 | ; ................ any display monitor. 2997 | ; ................ Modified MDMF_FromRect() to allow flag values that determine the function's return value if the 2998 | ; ................ rectangle does not intersect any display monitor. 2999 | ;................. Modified MDMF_GetInfo() with minor changes. 3000 | ; ---------------------------------------------------------------------------------------------------------------------- 3001 | ; 3002 | ; ====================================================================================================================== 3003 | ; Multiple Display Monitors Functions -> msdn.microsoft.com/en-us/library/dd145072(v=vs.85).aspx ======================= 3004 | ; ====================================================================================================================== 3005 | ; Enumerates display monitors and returns an object containing the properties of all monitors or the specified monitor. 3006 | ; ====================================================================================================================== 3007 | MDMF_Enum(HMON := "") { 3008 | static EnumProc := CallbackCreate(MDMF_EnumProc) 3009 | static Monitors := Map() 3010 | 3011 | if (HMON = "") { ; new enumeration 3012 | Monitors := Map("TotalCount", 0) 3013 | if !DllCall("User32.dll\EnumDisplayMonitors", "Ptr", 0, "Ptr", 0, "Ptr", EnumProc, "Ptr", ObjPtr(Monitors), "Int") 3014 | return False 3015 | } 3016 | 3017 | return (HMON = "") ? Monitors : Monitors.HasKey(HMON) ? Monitors[HMON] : False 3018 | } 3019 | ; ====================================================================================================================== 3020 | ; Callback function that is called by the MDMF_Enum function. 3021 | ; ====================================================================================================================== 3022 | MDMF_EnumProc(HMON, HDC, PRECT, ObjectAddr) { 3023 | Monitors := ObjFromPtrAddRef(ObjectAddr) 3024 | 3025 | Monitors[HMON] := MDMF_GetInfo(HMON) 3026 | Monitors["TotalCount"]++ 3027 | if (Monitors[HMON].Primary) { 3028 | Monitors["Primary"] := HMON 3029 | } 3030 | 3031 | return true 3032 | } 3033 | ; ====================================================================================================================== 3034 | ; Retrieves the display monitor that has the largest area of intersection with a specified window. 3035 | ; The following flag values determine the function's return value if the window does not intersect any display monitor: 3036 | ; MONITOR_DEFAULTTONULL = 0 - Returns NULL. 3037 | ; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor. 3038 | ; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the window. 3039 | ; ====================================================================================================================== 3040 | MDMF_FromHWND(HWND, Flag := 0) { 3041 | return DllCall("User32.dll\MonitorFromWindow", "Ptr", HWND, "UInt", Flag, "Ptr") 3042 | } 3043 | ; ====================================================================================================================== 3044 | ; Retrieves the display monitor that contains a specified point. 3045 | ; If either X or Y is empty, the function will use the current cursor position for this value and return it ByRef. 3046 | ; The following flag values determine the function's return value if the point is not contained within any 3047 | ; display monitor: 3048 | ; MONITOR_DEFAULTTONULL = 0 - Returns NULL. 3049 | ; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor. 3050 | ; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the point. 3051 | ; ====================================================================================================================== 3052 | MDMF_FromPoint(&X:="", &Y:="", Flag:=0) { 3053 | if (X = "") || (Y = "") { 3054 | PT := Buffer(8, 0) 3055 | DllCall("User32.dll\GetCursorPos", "Ptr", PT.Ptr, "Int") 3056 | 3057 | if (X = "") { 3058 | X := NumGet(PT, 0, "Int") 3059 | } 3060 | 3061 | if (Y = "") { 3062 | Y := NumGet(PT, 4, "Int") 3063 | } 3064 | } 3065 | return DllCall("User32.dll\MonitorFromPoint", "Int64", (X & 0xFFFFFFFF) | (Y << 32), "UInt", Flag, "Ptr") 3066 | } 3067 | ; ====================================================================================================================== 3068 | ; Retrieves the display monitor that has the largest area of intersection with a specified rectangle. 3069 | ; Parameters are consistent with the common AHK definition of a rectangle, which is X, Y, W, H instead of 3070 | ; Left, Top, Right, Bottom. 3071 | ; The following flag values determine the function's return value if the rectangle does not intersect any 3072 | ; display monitor: 3073 | ; MONITOR_DEFAULTTONULL = 0 - Returns NULL. 3074 | ; MONITOR_DEFAULTTOPRIMARY = 1 - Returns a handle to the primary display monitor. 3075 | ; MONITOR_DEFAULTTONEAREST = 2 - Returns a handle to the display monitor that is nearest to the rectangle. 3076 | ; ====================================================================================================================== 3077 | MDMF_FromRect(X, Y, W, H, Flag := 0) { 3078 | RC := Buffer(16, 0) 3079 | NumPut("Int", X, "Int", Y, "Int", X + W, "Int", Y + H, RC) 3080 | return DllCall("User32.dll\MonitorFromRect", "Ptr", RC.Ptr, "UInt", Flag, "Ptr") 3081 | } 3082 | ; ====================================================================================================================== 3083 | ; Retrieves information about a display monitor. 3084 | ; ====================================================================================================================== 3085 | MDMF_GetInfo(HMON) { 3086 | MIEX := Buffer(40 + (32 << !!1)) 3087 | NumPut("UInt", MIEX.Size, MIEX) 3088 | if DllCall("User32.dll\GetMonitorInfo", "Ptr", HMON, "Ptr", MIEX.Ptr, "Int") { 3089 | return {Name: (Name := StrGet(MIEX.Ptr + 40, 32)) ; CCHDEVICENAME = 32 3090 | , Num: RegExReplace(Name, ".*(\d+)$", "$1") 3091 | , Left: NumGet(MIEX, 4, "Int") ; display rectangle 3092 | , Top: NumGet(MIEX, 8, "Int") ; " 3093 | , Right: NumGet(MIEX, 12, "Int") ; " 3094 | , Bottom: NumGet(MIEX, 16, "Int") ; " 3095 | , WALeft: NumGet(MIEX, 20, "Int") ; work area 3096 | , WATop: NumGet(MIEX, 24, "Int") ; " 3097 | , WARight: NumGet(MIEX, 28, "Int") ; " 3098 | , WABottom: NumGet(MIEX, 32, "Int") ; " 3099 | , Primary: NumGet(MIEX, 36, "UInt")} ; contains a non-zero value for the primary monitor. 3100 | } 3101 | return False 3102 | } 3103 | 3104 | 3105 | ; Based on WinGetClientPos by dd900 and Frosti - https://www.autohotkey.com/boards/viewtopic.php?t=484 3106 | WinGetRect( hwnd, &x:="", &y:="", &w:="", &h:="" ) { 3107 | Ptr := A_PtrSize ? "UPtr" : "UInt" 3108 | CreateRect(&winRect, 0, 0, 0, 0) ;is 16 on both 32 and 64 3109 | ;VarSetCapacity( winRect, 16, 0 ) ; Alternative of above two lines 3110 | DllCall( "GetWindowRect", "Ptr", hwnd, "Ptr", winRect ) 3111 | x := NumGet(winRect, 0, "UInt") 3112 | y := NumGet(winRect, 4, "UInt") 3113 | w := NumGet(winRect, 8, "UInt") - x 3114 | h := NumGet(winRect, 12, "UInt") - y 3115 | } 3116 | --------------------------------------------------------------------------------