seniors 发表于 2013-6-7 20:39:59

第十三讲 GDI+区域及剪切区域

一、GDI+区域
1、建立_GDIPlus_RegionCreate;创建空区域
_GDIPlus_RegionCreateFromHrgn;从GDI区域句柄建立GDI+区域
_GDIPlus_RegionCreateFromPath;从路径对象建立区域
_GDIPlus_RegionCreateFromRect;建立矩形区域
_GDIPlus_RegionCreateFromRgnData;从区域数据建立区域GDI+的路径和区域与GDI的路径和区域不同,GDI只能有一个路径和区域,而GDI+可以同时有多个路径和区域
2、区域混合_GDIPlus_RegionCombinePath;区域与路径混合
_GDIPlus_RegionCombineRect;区域与矩形混合
_GDIPlus_RegionCombineRegion;区域与区域混合;~ 区域的相交模式:
;~ 0 - 用新区域替换已存在的区域
;~ 1 - 用区域自身和新区域的相交部分替换已存在的区域
;~ 2 - 用区域自身和新区域的结合部分替换已存在的区域
;~ 3 - 对两个区域执行异或(XOR)操作的结果替换已存在的区域位于两区域的XOR部分的点表示它在其中一个但不同时在两个区域中
;~ 4 - 用区域自身和新区域外部替换已存在的区域
;~ 5 - 用在已存在区域的外部的新区域部分替换已存在的区域
3、区域的填充
区域没有描边,只有填充,填充函数在3.3.7.15中有误
改为如下吧
Func _GDIPlus__GraphicsFillRegion($hGraphics, $hRegion, $hBrush = 0)
        Local $iTmpErr, $iTmpExt, $aResult
        __GDIPlus_BrushDefCreate($hBrush)
        $aResult = DllCall($ghGDIPDll, "uint", "GdipFillRegion", "hwnd", $hGraphics, "hwnd", $hBrush, "hwnd", $hRegion)
        $iTmpErr = @error
        $iTmpExt = @extended
        __GDIPlus_BrushDefDispose()
        If $iTmpErr Then Return SetError($iTmpErr, $iTmpExt, False)
        $GDIP_STATUS = $aResult
        Return $aResult = 0
EndFunc   ;==>_GDIPlus__GraphicsFillRegion

二、剪切区域(画布的剪切区域)
剪切区域和区域是两回事,应该都叫区域我就放一起了
画布设置了剪切区域后,所有的绘制操作,只有在剪切区域时才能绘制
建立方法_GDIPlus_GraphicsSetClipHrgn
_GDIPlus_GraphicsSetClipPath
_GDIPlus_GraphicsSetClipRect
_GDIPlus_GraphicsSetClipRegion剪切区域的混合模式和区域的混合模式一样
剪切区域的释放
_GDIPlus_GraphicsResetClip($hGraphics)

例子中,右下二个就是剪切区域

#include <APIConstants.au3>
#include <WinAPIEx.au3>
#include <GDIPlus.au3>
#include <GDIPlusEx.au3>

GUICreate("第十三讲 GDI+区域", 500, 200)
$nCtrlId = GUICtrlCreatePic("", 0, 0, 500, 200)
$hPicWnd = GUICtrlGetHandle($nCtrlId)

GUISetState()
update()

While 1
        $Msg = GUIGetMsg()
        Switch $Msg
                Case -3
                        ExitLoop
        EndSwitch
WEnd
GUIDelete()
Exit

Func update()
        Local $HWND_CX = _WinAPI_GetWindowWidth($hPicWnd)
        Local $HWND_CY = _WinAPI_GetWindowHeight($hPicWnd)
        _GDIPlus_Startup()
        $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hPicWnd)
        _GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2)
        $hBitmap = _GDIPlus_BitmapCreateFromGraphics($HWND_CX, $HWND_CY, $hGraphics)
        $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
        _GDIPlus_GraphicsClear($hBackbuffer, 0xFFECE9D8)
        _GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, 2);光滑模式,2为8*8抗距齿
        CombinemodeComp($hBackbuffer)
        _GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, 0, 0, $HWND_CX, $HWND_CY)
        _GDIPlus_BitmapDispose($hBitmap)
        _GDIPlus_GraphicsDispose($hBackbuffer)
        _GDIPlus_GraphicsDispose($hGraphics)
        _GDIPlus_Shutdown()
EndFunc   ;==>update

;混合模式对比
Func CombinemodeComp($hGraphics)
        Local $hPen = _GDIPlus_PenCreate(0xFFFF0000, 1)
        Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)
        ;从矩形区域建立区域
        Local $tRectF = _GDIPlus_RectFCreate(10, 20, 80, 30)
        Local $hRgn1 = _GDIPlus_RegionCreateFromRect($tRectF)
        ;从路径建立区域
        Local $hPath = _GDIPlus_PathCreate()
        _GDIPlus_PathAddEllipse($hPath, 25, 10, 50, 50)
        Local $hRgn2 = _GDIPlus_RegionCreateFromPath($hPath)
       
;~ 区域的相交模式:
;~ 0 - 用新区域替换已存在的区域
;~ 1 - 用区域自身和新区域的相交部分替换已存在的区域
;~ 2 - 用区域自身和新区域的结合部分替换已存在的区域
;~ 3 - 对两个区域执行异或(XOR)操作的结果替换已存在的区域位于两区域的XOR部分的点表示它在其中一个但不同时在两个区域中
;~ 4 - 用区域自身和新区域外部替换已存在的区域
;~ 5 - 用在已存在区域的外部的新区域部分替换已存在的区域
        Local $hRgn
        For $i = 1 To 5
                ;复制区域1
                $hRgn = _GDIPlus_RegionClone($hRgn1)
                ;把区域2通过模式$i混合到$hRgn
                _GDIPlus_RegionCombineRegion($hRgn, $hRgn2, $i)
                ;填充$hRgn
                _GraphicsFillRegion($hGraphics, $hRgn, $hBrush)
                ;释放$hRgn
                _GDIPlus_RegionDispose($hRgn)
               
                _GDIPlus_GraphicsDrawRect($hGraphics, 5, 5, 90, 60)
                _GraphicsDrawString($hGraphics, "混合模式" & $i, 10, 70)
                _GDIPlus_GraphicsTranslateTransform($hGraphics, 100, 0)
        Next
       
        _GDIPlus_GraphicsResetTransform($hGraphics)
        _GDIPlus_GraphicsTranslateTransform($hGraphics, 0, 90)
        ;绘制$hRgn1和$hRgn2的原始外形,由于区域没有绘制外形的函数,所以直接绘制了原始圆形路径和原始矩形
        _GraphicsDrawPath($hGraphics, $hPath, $hPen);原始圆形路径
        _GDIPlus_PenSetColor($hPen, 0xFF00FF00)
        _GDIPlus_GraphicsDrawRect($hGraphics, 10, 20, 80, 30, $hPen);原始矩形
        _GraphicsDrawString($hGraphics, "原区域形状", 10, 70)
        ;释放
        _GDIPlus_PathDispose($hPath)
        _GDIPlus_RegionDispose($hRgn1)
        _GDIPlus_RegionDispose($hRgn2)
       
;==============================下面是画布剪切区域的设置======================

        Local $hFamily = _GDIPlus_FontFamilyCreate("Arial")
        Local $tLayout = _GDIPlus_RectFCreate(0, 0)
        $hPath = _GDIPlus_PathCreate()
        _GDIPlus_PathAddString($hPath, "Au3", $tLayout, $hFamily, 1, 100)
        _GDIPlus_GraphicsTranslateTransform($hGraphics, 100, 0)
        _GraphicsDrawPath($hGraphics, $hPath, $hPen)
        _GDIPlus_PenSetColor($hPen, 0xFFFF0000)
        ;从路径获取画布的剪切区域============
        _GDIPlus_GraphicsSetClipPath($hGraphics, $hPath)
        ;以下同心圆超出剪切区域的不会绘制出来
        For $i = 0 To 30
                _GDIPlus_GraphicsDrawEllipse($hGraphics, 125 - $i * 5, 60 - $i * 5, $i * 10, $i * 10, $hPen)
        Next
        ;使剪切区域无限大,相当于不设置剪切区域
        _GDIPlus_GraphicsResetClip($hGraphics)
        _GDIPlus_PathDispose($hPath)
        ;以下设置从区域设置剪切区域================
        _GDIPlus_GraphicsTranslateTransform($hGraphics, 250, 0)
        $hPath = _GDIPlus_PathCreate(1)
        _GDIPlus_PathAddEllipse($hPath, 5, 5, 100, 100)
        _GDIPlus_PathAddEllipse($hPath, 80, 5, 30, 30)
        _GDIPlus_BrushSetSolidColor($hBrush, 0x33003399)
        _GraphicsFillPath($hGraphics, $hPath, $hBrush)
        ;从路径设置区域
        $hRgn = _GDIPlus_RegionCreateFromPath($hPath)
        _GDIPlus_PathDispose($hPath)
        ;从区域设置画布的剪切区域
        _GDIPlus_GraphicsSetClipRegion($hGraphics, $hRgn)
        _GDIPlus_BrushSetSolidColor($hBrush, 0xFFFF0000)
        For $i = 0 To 10
                _GraphicsDrawString($hGraphics, "我爱Autoit,I love au3", 0, $i * 14, $hBrush)
        Next
        _GDIPlus_RegionDispose($hRgn)
        _GDIPlus_BrushDispose($hBrush)
        _GDIPlus_PenDispose($hPen)
EndFunc   ;==>CombinemodeComp

;_GDIPlus_GraphicsDrawString这个函数,我认为他没有设置$hBrush,所以我改成这样就可以用不同的画刷了
Func _GraphicsDrawString($hGraphics, $sString, $nX, $nY, $hBrush = 0, $sFont = "Arial", $nSize = 10, $iFormat = 0)
        Local $hFormat = _GDIPlus_StringFormatCreate($iFormat)
        Local $hFamily = _GDIPlus_FontFamilyCreate($sFont)
        Local $hFont = _GDIPlus_FontCreate($hFamily, $nSize)
        Local $tLayout = _GDIPlus_RectFCreate($nX, $nY, 0, 0)
        Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphics, $sString, $hFont, $tLayout, $hFormat)
        __GDIPlus_BrushDefCreate($hBrush)
        Local $aResult = _GDIPlus_GraphicsDrawStringEx($hGraphics, $sString, $hFont, $aInfo, $hFormat, $hBrush)
        Local $iError = @error
        __GDIPlus_BrushDefDispose()
        _GDIPlus_FontDispose($hFont)
        _GDIPlus_FontFamilyDispose($hFamily)
        _GDIPlus_StringFormatDispose($hFormat)
        Return SetError($iError, 0, $aResult)
EndFunc   ;==>_GraphicsDrawString

;下面这两个描路径和填充路径,在3.3.9.5中已经更正了,我用的是3.3.7.15画笔和画刷设置不对,可以改成这样的就行了
Func _GraphicsDrawPath($hGraphics, $hPath, $hPen = 0)
        Local $iTmpErr, $iTmpExt, $aResult
        __GDIPlus_PenDefCreate($hPen)
        $aResult = DllCall($ghGDIPDll, "uint", "GdipDrawPath", "hwnd", $hGraphics, "hwnd", $hPen, "hwnd", $hPath)
        $iTmpErr = @error
        $iTmpExt = @extended
        __GDIPlus_PenDefDispose()
        If $iTmpErr Then Return SetError($iTmpErr, $iTmpExt, False)
        $GDIP_STATUS = $aResult
        Return $aResult = 0
EndFunc   ;==>_GraphicsDrawPath

Func _GraphicsFillPath($hGraphics, $hPath, $hBrush = 0)
        Local $iTmpErr, $iTmpExt, $aResult
        __GDIPlus_BrushDefCreate($hBrush)
        $aResult = DllCall($ghGDIPDll, "uint", "GdipFillPath", "hwnd", $hGraphics, "hwnd", $hBrush, "hwnd", $hPath)
        $iTmpErr = @error
        $iTmpExt = @extended
        __GDIPlus_BrushDefDispose()
        If $iTmpErr Then Return SetError($iTmpErr, $iTmpExt, False)
        $GDIP_STATUS = $aResult
        Return $aResult = 0
EndFunc   ;==>_GraphicsFillPath

Func _GraphicsFillRegion($hGraphics, $hRegion, $hBrush = 0)
        Local $iTmpErr, $iTmpExt, $aResult
        __GDIPlus_BrushDefCreate($hBrush)
        $aResult = DllCall($ghGDIPDll, "uint", "GdipFillRegion", "hwnd", $hGraphics, "hwnd", $hBrush, "hwnd", $hRegion)
        $iTmpErr = @error
        $iTmpExt = @extended
        __GDIPlus_BrushDefDispose()
        If $iTmpErr Then Return SetError($iTmpErr, $iTmpExt, False)
        $GDIP_STATUS = $aResult
        Return $aResult = 0
EndFunc   ;==>_GraphicsFillRegion

lpxx 发表于 2013-6-7 21:00:06

感谢分享,学习了

lpxx 发表于 2013-6-7 23:36:55

不知道啥时才能到达你这个高度。

xms77 发表于 2013-6-8 09:27:55

学习了,感谢分享!

zmdzhxj 发表于 2019-8-17 12:38:10

反复看了几遍帖子,厉害啊

qxguoxing 发表于 2019-10-12 15:19:59

来学习学习!

xtgem 发表于 2022-10-18 21:41:55

高 !实在是高!
页: [1]
查看完整版本: 第十三讲 GDI+区域及剪切区域