 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Guest
|
Posted: Tue Jul 15, 2008 8:18 pm Post subject: |
|
|
Thank you !
Please may I enquire, what is big difference between GDI & GDI+? I am guessing hBitmap and pBitmap are nearly same data bandwidth size... but one is higher quality? I don't understand.
but Thank you, it worked! |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1344
|
Posted: Thu Jul 17, 2008 4:46 pm Post subject: |
|
|
Due to an interesting request by infogulch:
Get avg color of portion of the screen
A small gui will appear in the centre of the screen. You can then drag a selection of the screen using ctrl and lbutton. it will then update the gui with the average of the colours almost instantly. Obviously not all of the code below is needed, but i just wanted to make it look nice and easy to use
Ensure you have version 1.17 from the 1st post
| Code: | #SingleInstance, Force
#NoEnv
DetectHiddenWindows, On
CoordMode, Mouse, Screen
SetBatchLines, -1
SetWinDelay, 0
SetWorkingDir %A_ScriptDir%
OnExit, Exit
; Uncomment if Gdip.ahk is not in your standard library
;#Include, Gdip.ahk
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
pBrush := Gdip_BrushCreateSolid(0x3300ff00), pPen := Gdip_CreatePen(0xbbff2233, 1)
Gui, 1: +AlwaysOnTop -Caption +ToolWindow +Border
Gui, 1: Margin, 0, 0
Gui, 1: Add, Picture, x0 y0 w50 h50 0xE hwndPic
Gui, 1: Show, AutoSize
Hotkey, ^LButton, Drag, On
Return
;########################################################################################
Drag:
Gui, 1: Submit, NoHide
MouseGetPos, x1, y1
Gui, 2: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
hwnd2 := WinExist()
Gui, 2: Show, NA
Loop
{
Sleep, 50
If !GetKeyState("LButton", "P")
Break
MouseGetPos, x2, y2
If (x2 = Oldx2) && (y2 = Oldy2)
Continue
If (x2 >= x1) && (y2 <= y1)
x := x1, y := y2, w := x2-x1, h := y1-y2
Else If (x2 >= x1) && (y2 >= y1)
x := x1, y := y1, w := x2-x1, h := y2-y1
Else If (x2 <= x1) && (y2 >= y1)
x := x2, y := y1, w := x1-x2, h := y2-y1
Else If (x2 <= x1) && (y2 <= y1)
x := x2, y := y2, w := x1-x2, h := y1-y2
Oldx2 := x2, Oldy2 := y2
hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm), G := Gdip_GraphicsFromHDC(hdc)
Gdip_FillRectangle(G, pBrush, 0, 0, w, h)
Gdip_DrawRectangle(G, pPen, 0, 0, w-1, h-1)
UpdateLayeredWindow(hwnd2, hdc, x, y, w, h)
Gdip_DeleteGraphics(G), SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
}
Gui, 2: Destroy
pBitmap1 := Gdip_BitmapFromScreen(x "|" y "|" w "|" h)
pBitmap2 := Gdip_CreateBitmap(1, 1), G2 := Gdip_GraphicsFromImage(pBitmap2)
pBitmap3 := Gdip_CreateBitmap(50, 50), G3 := Gdip_GraphicsFromImage(pBitmap3)
Gdip_DrawImage(G2, pBitmap1, 0, 0, 1, 1, 0, 0, 50, 50)
Gdip_FillRectangle(G3, pBrush2 := Gdip_BrushCreateSolid(Gdip_GetPixel(pBitmap2, 0, 0)), 0, 0, 50, 50)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap3)
SetImage(Pic, hBitmap)
Gdip_DeleteBrush(pBrush2)
Gdip_DisposeImage(pBitmap1), Gdip_DisposeImage(pBitmap2), Gdip_DisposeImage(pBitmap3)
Gdip_DeleteGraphics(G2), Gdip_DeleteGraphics(G3)
DeleteObject(hBitmap)
Return
;########################################################################################
Exit:
Gdip_DeleteBrush(pBrush), Gdip_DeletePen(pPen)
Gdip_Shutdown(pToken)
ExitApp
Return |
|
|
| Back to top |
|
 |
skrommel
Joined: 30 Jul 2004 Posts: 175
|
Posted: Fri Jul 18, 2008 1:41 am Post subject: Transparency |
|
|
@tic: | Quote: | | but with 3 extra lines (one of them used to dispose of the pBitmap created), allowing us to save a gdi bitmap to disk |
Why can't I use your code to save a transparent PNG?
I have no problem saving a transparent PNG when it's created using pBitmap:=Gdip_CreateBitmap(width,height)
Skrommel _________________ www.1HourSoftware.com |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1344
|
Posted: Fri Jul 18, 2008 12:38 pm Post subject: |
|
|
I would suggest that if you are wanting to work with a gdi+ bitmap the entire time, and want to use it to update a gui and save it to disk, then follow this method:
| Code: | #SingleInstance, Force
#NoEnv
DetectHiddenWindows, On
CoordMode, Mouse, Screen
SetBatchLines, -1
SetWinDelay, 0
SetWorkingDir %A_ScriptDir%
; Uncomment if Gdip.ahk is not in your standard library
;#Include, Gdip.ahk
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
Width := 200, Height := 200
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA
hwnd1 := WinExist()
pBitmap := Gdip_CreateBitmap(Width, Height), Gp := Gdip_GraphicsFromImage(pBitmap)
pBrush := Gdip_BrushCreateSolid(0x77ff0000)
Gdip_FillRectangle(Gp, pBrush, Width//4, Height//4, Width//2, Height//2)
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm), Gh := Gdip_GraphicsFromHDC(hdc)
Gdip_DrawImage(Gh, pBitmap, 0, 0, Width, Height)
UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height)
Gdip_SaveBitmapToFile(pBitmap, "file.png")
Gdip_DeleteBrush(pBrush)
Gdip_DisposeImage(pBitmap)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(Gp), Gdip_DeleteGraphics(Gh)
Gdip_Shutdown(pToken)
Return
|
So work with a gdi+ bitmap (pBitmap) the entire time, and then whenever you want to update your gui with whatever you've been doing then just create a gdi bitmap:
| Code: | | hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm), Gh := Gdip_GraphicsFromHDC(hdc) |
and then draw your gdi+ bitmap into the gdi bitmap:
| Code: | | Gdip_DrawImage(Gh, pBitmap, 0, 0, Width, Height) |
You will then obviously have to dispose of all the extra stuff you created.
But the above example shows how we can use a bitmap with a transparent background and use it to update a gui and save it to disk
Hope that helps |
|
| Back to top |
|
 |
skrommel
Joined: 30 Jul 2004 Posts: 175
|
Posted: Sat Jul 19, 2008 7:02 pm Post subject: Slow |
|
|
I've tried similar code, but the problem is speed. It copies and redraws the entire screen instead of just the few changed pixels, so in a drawing app you'll end up with "square" circles and slow response.
I've found no way of just copying and updating the changed area, so my final solution was painting everything twice, once on the screen and once on the bitmap.
Is there no way to convert a DC bitmap into a transparent one, or loading a transparent bitmap into a DC?
Skrommel _________________ www.1HourSoftware.com |
|
| Back to top |
|
 |
Sunrise Guest
|
Posted: Sun Jul 20, 2008 5:29 pm Post subject: |
|
|
Tic, I want to draw a complex Filled shape with several sides and straight angles. It has no curves. Could you pls start me on some path to understanding how best to draw something simple with multiple sides and angles? One or two demonstrations would be so excellent to get me on my Web feet, if possible
hey, I have really enjoyed working thru your tutorials to understand concepts, and use of the gdip commands This was something I couldn't quite ascertain how to do yet, but would like to  |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2526 Location: Australia, Qld
|
Posted: Mon Jul 21, 2008 9:17 am Post subject: Re: Slow |
|
|
| skrommel wrote: | I've found no way of just copying and updating the changed area, so my final solution was painting everything twice, once on the screen and once on the bitmap. | Have you tried painting everything onto the bitmap, then painting the bitmap onto the screen? As an added benefit, the image is presented to the screen in a single drawing operation. This usually eliminates any flicker that may be present.
If the screen is represented by a handle to a device context (hdc), you can use Gdip_GraphicsFromHDC to retrieve a GDI+ Graphics object. The Graphics object should be deleted with Gdip_DeleteGraphics before using any GDI functions with the original hdc.
There are also functions which tic has not yet wrapped:
| Code: | ; Get a device context from a Graphics object:
DllCall("gdiplus\GdipGetDC", "uint", pGraphics, "uint*", hdc)
; Release the device context before using the Graphics object again:
DllCall("gdiplus\GdipReleaseDC", "uint", pGraphics, "uint", hdc)
; Get a Graphics object from a window handle:
DllCall("gdiplus\GdipCreateFromHWND", hwnd, "uint*", pGraphics)
|
|
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1344
|
Posted: Mon Jul 21, 2008 12:38 pm Post subject: |
|
|
Skrommel:
I think you are going about it the wrong way. If you are wanting to make a drawing application then you would use a gdi bitmap to let the user draw onto, and update the window with this, and then when they go to save what they have drawn, simpley convert it to a gdi+ bitmap. I do not believe it is necessary to get the graphics of the window. When I get time I'll write a quick start to a drawing app that allows a couple of drawing functions and can have layers if you wish to demonstrate the way I would do it, but I'll have to see when I get some time.
Sunrise:
To fill polygons you would use Gdip_FillPolygon() and you pass the points on the polygon as "x1,y1|x2,y2|x3,y3......"
So a square would look like:
| Code: | | Gdip_FillPolygon(pGraphics, pBrush, "0,0|100,0|100,100|0,100|0,0") |
That last coordinate is optional to close the polygon. I will start on a helper function if you wish to allow quick and easy construction of uniform polygons.
Taking the 1st example I have added a simple function to construct these uniform polygons as demonstrated here:
| Code: | ; gdi+ ahk tutorial 1 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Tutorial to draw a single ellipse and rectangle to the screen
#SingleInstance, Force
#NoEnv
SetBatchLines, -1
; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip.ahk
; Start gdi+
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
OnExit, Exit
; Set the width and height we want as our drawing area, to draw everything in. This will be the dimensions of our bitmap
Width := 800, Height := 800
; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
; Show the window
Gui, 1: Show, NA
; Get a handle to this window we have created in order to update it later
hwnd1 := WinExist()
; 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
hbm := CreateDIBSection(Width, Height)
; Get a device context compatible with the screen
hdc := CreateCompatibleDC()
; Select the bitmap into the device context
obm := SelectObject(hdc, hbm)
; Get a pointer to the graphics of the bitmap, for use with drawing functions
G := Gdip_GraphicsFromHDC(hdc)
; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling)
Gdip_SetSmoothingMode(G, 4)
pBrush := Gdip_BrushCreateSolid(0x660000ff)
Gdip_FillUniformPolygon(G, pBrush, 9, 100, 100, 50)
Gdip_DeleteBrush(pBrush)
; 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
; So this will position our gui at (0,0) with the Width and Height specified earlier
UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height)
; Select the object back into the hdc
SelectObject(hdc, obm)
; Now the bitmap may be deleted
DeleteObject(hbm)
; Also the device context related to the bitmap may be deleted
DeleteDC(hdc)
; The graphics may now be deleted
Gdip_DeleteGraphics(G)
Return
;#######################################################################
Gdip_FillUniformPolygon(pGraphics, pBrush, Sides, x, y, Length, FillMode=0)
{
a := 0, Points := x "," y "|"
Loop, %Sides%
{
x += Length*Cos(a), y += Length*Sin(a)
Points .= x "," y "|"
a += ((4*ATan(1))/180)*(360/Sides)
}
StringTrimRight, Points, Points, 1
Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode)
}
;#######################################################################
Exit:
; gdi+ may now be shutdown on exiting the program
Gdip_Shutdown(pToken)
ExitApp
Return |
I have not added Gdip_FillUniformPolygon() to the library as I would prefer it to be in the form of:
| Code: | | Gdip_FillUniformPolygon(pGraphics, pBrush, Sides, x, y, w, h, FillMode=0) |
so rather than specifying the length of each side, you could specify the width and height of the entire polygon, but this will be a bit tricky, so will do it when I have more time. Try the above example and ask if you have any other problems |
|
| Back to top |
|
 |
skrommel
Joined: 30 Jul 2004 Posts: 175
|
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2526 Location: Australia, Qld
|
Posted: Wed Jul 23, 2008 7:38 am Post subject: |
|
|
| scrommel wrote: | | @ Lexicos: I can't get Gdip_GraphicsFromHDC to create a transparent bitmap. | Of course: Gdip_GraphicsFromHDC has nothing to do with creating a bitmap. If you had already created a GDI+ bitmap and wanted to draw it onto the screen, you could use Gdip_GraphicsFromHDC to create a Graphics object to wrap the screen hdc. Whether or not the bitmap is transparent is irrelevant. If you create a 32-bit ARGB GDI+ bitmap, it should be transparent by default. It only becomes opaque when you draw an opaque image onto it or fill it with an opaque colour. For instance, in your script posted at donationcoder.com:
| Code: | hBrush:= Gdip_BrushCreateSolid("0xFF" background) ; <- This is an opaque/solid brush.
Gdip_FillRectangle(pGraphic3, hBrush, 0, 0, width3, height3)
Gdip_DeleteBrush(hBrush) |
|
|
| Back to top |
|
 |
skrommel
Joined: 30 Jul 2004 Posts: 175
|
Posted: Thu Jul 24, 2008 1:04 am Post subject: |
|
|
Lexikos wrote:
| Quote: | | Gdip_GraphicsFromHDC has nothing to do with creating a bitmap |
Sorry, I ment Gdip_GraphicsFromHDC can't be used as a basis for saving a transparent png file, it gets a black backround.
Skrommel _________________ www.1HourSoftware.com |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2526 Location: Australia, Qld
|
Posted: Thu Jul 24, 2008 8:29 am Post subject: |
|
|
Gdip_GraphicsFromHDC is used to get a GDI+ Graphics object for drawing onto a GDI device context. It does not modify the underlying object of the device context (which may or may not be a bitmap), so it will only "get a black background" if the underlying bitmap already had a black background.
I suggest there is some other issue. |
|
| Back to top |
|
 |
thirtydot
Joined: 24 Jul 2008 Posts: 3
|
Posted: Thu Jul 24, 2008 11:11 am Post subject: |
|
|
When saving a .jpg using Gdip_SaveBitmapToFile, is it possible to change the output quality? (0-100 in photoshop, for example)
edit:
I found out it's possible.
From Gdip.ahk
| Code: | | E := DllCall("gdiplus\GdipSaveImageToFile", "UInt", pBitmap, "UInt", &wOutput, "UInt", pCodec, "UInt", 0) |
There's an additional argument that this can be called with, which can set the jpg quality, however I'm unsure how to build the "tParams" argument.
http://bb4w.wikispaces.com/Saving+a+JPEG+image
Last edited by thirtydot on Thu Jul 24, 2008 11:31 am; edited 1 time in total |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1344
|
Posted: Thu Jul 24, 2008 11:29 am Post subject: |
|
|
Skrommel:
I think you are going about the problem in slightly the wrong way, and don't think those functions you are adding are necessary. At the weekend I'll write a quick app to show how I think it should be done
thirtydot:
I have not added that yet, but I'll make a modification to that function and release an update to Gdip in the next couple of days |
|
| Back to top |
|
 |
thirtydot
Joined: 24 Jul 2008 Posts: 3
|
Posted: Thu Jul 24, 2008 11:32 am Post subject: |
|
|
Oh, thanks  |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|