Jump to content

GDI+ SetClip


weaponx
 Share

Recommended Posts

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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
Link to comment
Share on other sites

  • 4 weeks later...

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • 1 month later...

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!

Link to comment
Share on other sites

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
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...