Jump to content
Sign in to follow this  
weaponx

GDI+ SetClip

Recommended Posts

weaponx

This will clip a GDI graphics object to a given rectangle, effectively masking anything outside the rectangle. Also included is an inverse clip that will mask everything within the given rectangle. Very very useful!

Some info was taken from here:

http://msdn.microsoft.com/en-us/library/ms534038(VS.85).aspx

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>

Global Const $GUI_Width = 400, $GUI_Height = 300

; Create GUI
$hGUI = GUICreate("GDI+", $GUI_Width, $GUI_Height)
$hWnd = WinGetHandle("GDI+")
GUISetState()

_GDIPlus_Startup ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hWnd)

_AntiAlias($hGraphic)

_SetClip($hGraphic, 50, 50, 300, 200)

_GDIPlus_GraphicsDrawLine($hGraphic, 0,0,$GUI_Width, $GUI_Height)
_GDIPlus_GraphicsDrawLine($hGraphic, 0,$GUI_Height,$GUI_Width,0)

; Loop until user exits
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

; Clean up resources
_GDIPlus_GraphicsDispose ($hGraphic)
_GDIPlus_Shutdown ()

;---------------------------
; FUNCTIONS
;---------------------------
Func _SetClip($hGraphics, $x, $y, $width, $height)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetClipRectI", "hwnd", $hGraphics, "int", $x, "int", $y, "int", $width, "int", $height, "int",0)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc

Func _SetInverseClip($hGraphics, $x, $y, $width, $height)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetClipRectI", "hwnd", $hGraphics, "int", $x, "int", $y, "int", $width, "int", $height, "int",3)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc

Func _AntiAlias($hGraphics)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetSmoothingMode", "hwnd", $hGraphics, "int", 2)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc

Share this post


Link to post
Share on other sites
Malkey

Agreed, can be very useful.

_AntiAlias() gives good line definition.

Nice work.

Edited by Malkey

Share this post


Link to post
Share on other sites
monoceres

Yay weaponx you found it :P

Good job.


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites
weaponx

Yay weaponx you found it :P

Good job.

You will like this one. This will mask an elliptical region.

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>

Global Const $GUI_Width = 400, $GUI_Height = 400

; Create GUI
$hGUI = GUICreate("GDI+", $GUI_Width, $GUI_Height)
$hWnd = WinGetHandle("GDI+")
GUISetState()

_GDIPlus_Startup ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hWnd)

_AntiAlias($hGraphic)

_SetClipCircle($hGraphic, 50, 50, 300, 300)

;Draw diagonal lines across entire gui
For $X = 0 to $GUI_Width Step 4
    _GDIPlus_GraphicsDrawLine($hGraphic, $X,0,$GUI_Width, $GUI_Height-$X)
Next

For $X = $GUI_Width to 4 Step -4
    _GDIPlus_GraphicsDrawLine($hGraphic, 0,$X,$GUI_Width-$X, $GUI_Height)
Next

; Loop until user exits
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

; Clean up resources
_GDIPlus_GraphicsDispose ($hGraphic)
_GDIPlus_Shutdown ()

;---------------------------
; FUNCTIONS
;---------------------------
Func _SetClipCircle($hGraphics, $x, $y, $width, $height)
   
    ;Create struct to hold pointer to Path object
    $Path = DllStructCreate("dword")
   
    ;Create Path object, store pointer to it
    DllCall($ghGDIPDll, "none", "GdipCreatePath", "int", 0, "int", DllStructGetPtr($Path))
   
    ;Retrieve pointer from struct
    $pointer = DllStructGetData($Path,1)
   
    DllCall($ghGDIPDll, "none", "GdipAddPathEllipseI","int", $pointer,"int",$x,"int",$y,"int",$width,"int",$height)
   
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetClipPath", "hwnd", $hGraphics, "ptr", $pointer,"int",0)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc

Func _AntiAlias($hGraphics)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetSmoothingMode", "hwnd", $hGraphics, "int", 2)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc
Edited by weaponx

Share this post


Link to post
Share on other sites
monoceres

You will like this one. This will mask an elliptical region.

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>

Global Const $GUI_Width = 400, $GUI_Height = 400

; Create GUI
$hGUI = GUICreate("GDI+", $GUI_Width, $GUI_Height)
$hWnd = WinGetHandle("GDI+")
GUISetState()

_GDIPlus_Startup ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hWnd)

_AntiAlias($hGraphic)

_SetClipCircle($hGraphic, 50, 50, 300, 300)

;Draw diagonal lines across entire gui
For $X = 0 to $GUI_Width Step 4
    _GDIPlus_GraphicsDrawLine($hGraphic, $X,0,$GUI_Width, $GUI_Height-$X)
Next

For $X = $GUI_Width to 4 Step -4
    _GDIPlus_GraphicsDrawLine($hGraphic, 0,$X,$GUI_Width-$X, $GUI_Height)
Next

; Loop until user exits
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

; Clean up resources
_GDIPlus_GraphicsDispose ($hGraphic)
_GDIPlus_Shutdown ()

;---------------------------
; FUNCTIONS
;---------------------------
Func _SetClipCircle($hGraphics, $x, $y, $width, $height)
   
    ;Create struct to hold pointer to Path object
    $Path = DllStructCreate("dword")
   
    ;Create Path object, store pointer to it
    DllCall($ghGDIPDll, "none", "GdipCreatePath", "int", 0, "int", DllStructGetPtr($Path))
   
    ;Retrieve pointer from struct
    $pointer = DllStructGetData($Path,1)
   
    DllCall($ghGDIPDll, "none", "GdipAddPathEllipseI","int", $pointer,"int",$x,"int",$y,"int",$width,"int",$height)
   
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetClipPath", "hwnd", $hGraphics, "ptr", $pointer,"int",0)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc

Func _AntiAlias($hGraphics)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetSmoothingMode", "hwnd", $hGraphics, "int", 2)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc
Veeery good, now the radar script can have it's rounded sweep :P

You should really try to standardize these two so they can be included in the GDI+ UDF :P


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites
weaponx

This one will create a text mask.

Before:

Posted Image

After:

Posted Image

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>

Global Const $GUI_Width = 400, $GUI_Height = 400

; Create GUI
$hGUI = GUICreate("GDI+", $GUI_Width, $GUI_Height)
$hWnd = WinGetHandle("GDI+")
GUISetState()

_GDIPlus_Startup ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hWnd)

_AntiAlias($hGraphic)

;Mask everything outside text region
_SetClipText($hGraphic, "autoit", 0, 100, $GUI_Width, $GUI_Height, "Trebuchet MS", 125)

;Draw diagonal lines across entire gui
For $X = 0 to $GUI_Width Step 4
    _GDIPlus_GraphicsDrawLine($hGraphic, $X,0,$GUI_Width, $GUI_Height-$X)
Next

For $X = $GUI_Width to 4 Step -4
    _GDIPlus_GraphicsDrawLine($hGraphic, 0,$X,$GUI_Width-$X, $GUI_Height)
Next

; Loop until user exits
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

; Clean up resources
_GDIPlus_GraphicsDispose ($hGraphic)
_GDIPlus_Shutdown ()

;---------------------------
; FUNCTIONS
;---------------------------

Func _SetClipText($hGraphics, $sText, $x, $y, $width, $height, $sFont = "Arial", $iSize = 12)
   
    ;Create Path object, store pointer to it
    $Path = DllCall($ghGDIPDll, "none", "GdipCreatePath", "int", 0, "int*", 0)
   
    ;Retrieve pointer from struct
    $pPath = $Path[2]

    $hFamily = _GDIPlus_FontFamilyCreate($sFont)
    
    ;Rect (Int)
    $Rect = DllStructCreate("int Left;int Top;int Right;int Bottom")
    DllStructSetData($Rect,"Left", $x)
    DllStructSetData($Rect,"Right", $width)
    DllStructSetData($Rect,"Top", $y)
    DllStructSetData($Rect,"Bottom", $height)
    $pRect = DllStructGetPtr($Rect)
    
    ;Use generic string formatting
    $hFormat = _GDIPlus_StringFormatCreate()    
   
    ;GpStatus WINGDIPAPI GdipAddPathStringI(GpPath *path, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFontFamily *family, INT style, REAL emSize, GDIPCONST Rect *layoutRect, GDIPCONST GpStringFormat *format)
    $rs = DllCall($ghGDIPDll, "int", "GdipAddPathStringI","int",$pPath, "wstr",$sText, "int",-1, "hwnd",$hFamily, "long",0, "float",$iSize, "int",$pRect, "long", $hFormat)
    If @ERROR Then ConsoleWrite("@ERROR: " & @ERROR & " @EXTENDED: " & @EXTENDED & @CRLF)
    If $rs[0] = 2 Then ConsoleWrite("Status: One of the arguments passed to the method was not valid." & @CRLF)    
        
    _GDIPlus_StringFormatDispose ($hFormat)    
    _GDIPlus_FontFamilyDispose($hFamily)
    
    ;Trace path with pen
    $hPen = _GDIPlus_PenCreate ()
    DllCall($ghGDIPDll, "none", "GdipDrawPath", "hwnd", $hGraphics,"int", $hPen, "int", $pPath)
    _GDIPlus_PenDispose ($hPen)
   
    ;Apply mask
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetClipPath", "hwnd", $hGraphics, "ptr", $pPath,"int",0)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc

Func _AntiAlias($hGraphics)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetSmoothingMode", "hwnd", $hGraphics, "int", 2)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc
Edited by weaponx

Share this post


Link to post
Share on other sites
fisofo

This one will create a text mask.

Man, I know this is a month old, but just wanted to say thanks! Just what I was looking for ;) This GDI stuff is awesome.

Btw, just a quick side question, is the $hWnd really necessary? I noticed this in the GDI examples in the helpfile too... isn't $hGUI already a window handle?

Share this post


Link to post
Share on other sites
weaponx

Btw, just a quick side question, is the $hWnd really necessary? I noticed this in the GDI examples in the helpfile too... isn't $hGUI already a window handle?

You are correct. I'm not sure why they do that in the examples.

Share this post


Link to post
Share on other sites
monoceres

I needed a function that clips a rounded rectangle, here's the function:

Func _SetRoundedRectClip($g,$x,$y,$w,$h,$r)
   $Path = DllStructCreate("dword")
   DllCall($ghGDIPDll, "none", "GdipCreatePath", "int", 0, "int", DllStructGetPtr($Path))
   $pointer = DllStructGetData($Path,1)
   DllCall($ghGDIPDll, "none", "GdipAddPathArc","int", $pointer,"float",$x,"float",$y,"float",$r,"float",$r,"float",180,"float",90)
   DllCall($ghGDIPDll, "none", "GdipAddPathArc","int", $pointer,"float",$x+($w - $r - 1),"float",$y,"float",$r,"float",$r,"float",270,"float",90)
   DllCall($ghGDIPDll, "none", "GdipAddPathArc","int", $pointer,"float",$x+($w - $r - 1),"float",$y+($h - $r - 1),"float",$r,"float",$r,"float",0,"float",90)
   DllCall($ghGDIPDll, "none", "GdipAddPathArc","int", $pointer,"float",$x,"float",$y+($h - $r - 1),"float",$r,"float",$r,"float",90,"float",90)
   $aResult = DllCall($ghGDIPDll, "int", "GdipSetClipPath", "hwnd", $g, "ptr", $pointer,"int",0)
EndFunc

:P


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites
Zedna

Nice weaponx! Thanks

It would be good if you can make it as standard UDFs with simple examples inside GDIPlus include:

_SetClipRect
_SetClipRoundRect
_SetClipRectInverse
_SetClipCircle
_SetClipEllipse
_SetClipText
_SetClipAntiAlias

You have got some stars from me :-)

Edited by Zedna

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×