Что нового

_WinAPI_RadialGradientFill() - Создание радиальных градиентов

Статус
Закрыто для дальнейших ответов.

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
AutoIt: 3.4.0.0
Версия: Prerelease

Категория: WinAPI

Описание: Я искал в MSDN кикие-либо функции для создания радиальных градиентов... и ничего не нашел. Пришлось самому написать. Что из этого получилось, можно увидеть ниже. Эта функция будет включена в библиотеку WinAPIEx.au3 при следующем обновлении (версия 2.3).

Код: Пример + Функция
Код:
#Include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global Const $STM_SETIMAGE = 0x0172
Global Const $STM_GETIMAGE = 0x0173

Global $hForm, $Msg, $Pic, $hPic, $hObj, $hBitmap, $hDC, $hDestDC, $hDestSv

; Create GUI
$hForm = GUICreate('MyGUI', 400, 400)
$Pic = GUICtrlCreatePic('', 0, 0, 400, 400)
$hPic = GUICtrlGetHandle($Pic)

; Create gradient
$hDC = _WinAPI_GetDC($hPic)
$hDestDC = _WinAPI_CreateCompatibleDC($hDC)
$hBitmap = _WinAPI_CreateCompatibleBitmapEx($hDC, 400, 400, 0xFFFFFF)
$hDestSv = _WinAPI_SelectObject($hDestDC, $hBitmap)
For $i = 0 To 315 Step 45
	_WinAPI_RadialGradientFill($hDestDC, 200, 200, 180, Random(0, 0xFFFFFF, 1), 0xFFFFFF, $i, $i + 45)
Next
_WinAPI_ReleaseDC($hPic, $hDC)
_WinAPI_SelectObject($hDestDC, $hDestSv)
_WinAPI_DeleteDC($hDestDC)

; Set gradient to control
_SendMessage($hPic, $STM_SETIMAGE, 0, $hBitmap)
$hObj = _SendMessage($hPic, $STM_GETIMAGE)
If $hObj <> $hBitmap Then
	_WinAPI_FreeObject($hBitmap)
EndIf

GUISetState()

While 1
	$Msg = GUIGetMsg()
	Switch $Msg
		Case $GUI_EVENT_CLOSE
			ExitLoop
		Case $GUI_EVENT_PRIMARYDOWN

	EndSwitch
WEnd

; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_RadialGradientFill
; Description....: Fills radial gradient.
; Syntax.........: _WinAPI_RadialGradientFill($hDC, $iX, $iY, $iRadius, $iRGB1, $iRGB2 [, $iAngleStart [, $iAngleEnd [, $iStep]]] )
; Parameters.....: $hDC         - Handle to the destination device context.
;                  $iX          - The x-coordinate of the central point, in logical units.
;                  $iY          - The y-coordinate of the central point, in logical units.
;                  $iRadius     - The circle radius to filling the gradient.
;                  $iRGB1       - The color information at the central point.
;                  $iRGB2       - The color information at the edges of circle.
;                  $iAngleStart - The angle to start filling at, in degree.
;                  $iAngleEnd   - The angle to end filling at, in degree.
;                  $iStep       - The gradient filling step in degree. The larger value of this parameter, the gradient will be
;                                 better, but it's require more time, and vice versa.
; Return values..: Success  - 1.
;                  Failure  - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: This function does not fills gradient with transparency, and does not use antialiasing.
; Related........:
; Link...........: None
; Example........: Yes
; ===============================================================================================================================

Func _WinAPI_RadialGradientFill($hDC, $iX, $iY, $iRadius, $iRGB1, $iRGB2, $iAngleStart = 0, $iAngleEnd = 360, $iStep = 5)

	Local $Val

	If Abs($iAngleStart) > 360 Then
		$iAngleStart = Mod($iAngleStart, 360)
	EndIf
	If Abs($iAngleEnd) > 360 Then
		$iAngleEnd = Mod($iAngleEnd, 360)
	EndIf
	If ($iAngleStart < 0) Or ($iAngleEnd < 0) Then
		$iAngleStart += 360
		$iAngleEnd += 360
	EndIf
	If $iAngleStart > $iAngleEnd Then
		$Val = $iAngleStart
		$iAngleStart = $iAngleEnd
		$iAngleEnd = $Val
	EndIf

	Local $K = 4 * ATan(1) / 180
	Local $Xp = Round($iX + $iRadius * Cos($K * $iAngleStart))
	Local $Yp = Round($iY - $iRadius * Sin($K * $iAngleStart))
	Local $Xn, $Yn, $An = $iAngleStart
	Local $Vertex[3][3]

	While $An < $iAngleEnd
		$An += $iStep
		If $An > $iAngleEnd Then
			$An = $iAngleEnd
		EndIf
		$Xn = Round($iX + $iRadius * Cos($K * $An))
		$Yn = Round($iY - $iRadius * Sin($K * $An))
		$Vertex[0][0] = $iX
		$Vertex[0][1] = $iY
		$Vertex[0][2] = $iRGB1
		$Vertex[1][0] = $Xp
		$Vertex[1][1] = $Yp
		$Vertex[1][2] = $iRGB2
		$Vertex[2][0] = $Xn
		$Vertex[2][1] = $Yn
		$Vertex[2][2] = $iRGB2
		If Not _WinAPI_GradientFill($hDC, $Vertex, 0, 2) Then
			Return SetError(1, 0, 0)
		EndIf
		$Xp = $Xn
		$Yp = $Yn
	WEnd
	Return 1
EndFunc   ;==>_WinAPI_RadialGradientFill

Скриншот:

post_img_011.png
post_img_012.png

Источник: Yashied
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Yashied
Супер! :thumbs_up:
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Спасибо.
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вот тоже самое, но с использованием GDI+. Здесь градиент уже может быть полупрозрачным. Красота!

Код:
#Include <GDIP.au3>
#Include <WinAPI.au3>


_GDIPlus_Startup()

GUICreate('MyGUI', 800, 600)
$Pic = GUICtrlCreatePic('', 0, 0, 800, 600)
$hPic = GUICtrlGetHandle(-1)

$hBitmap = _WinAPI_CreateBitmap(800, 600, 1, 32)
$hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
_WinAPI_DeleteObject($hBitmap)
$hGraphics = _GDIPlus_ImageGetGraphicsContext($hImage)
$hBitmap = _GDIPlus_ImageLoadFromFile(@WindowsDir & '\Web\Wallpaper\Ascent.jpg')
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, 0, 0, 800, 600)
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_GraphicsDrawRadialGradient($hGraphics, 800, 0, 600, 0xFFFF0000, 0, 45, 180)
_GDIPlus_GraphicsDrawRadialGradient($hGraphics, 310, 130, 100, 0xFF00FFFF, 0)
_GDIPlus_GraphicsDrawRadialGradient($hGraphics, 414, 314, 100, 0xFFFFFF00, 0)
_GDIPlus_GraphicsDrawRadialGradient($hGraphics, 550, 470, 100, 0xFF00FF00, 0)
$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageDispose($hImage)

$hObj = _SendMessage($hPic, 0x0172, 0, $hBitmap)
If $hObj Then
	_WinAPI_DeleteObject($hObj)
EndIf

GUISetState()

Do
Until GUIGetMsg() = -3

_GDIPlus_Shutdown()

Func _GDIPlus_GraphicsDrawRadialGradient($hGraphics, $iX, $iY, $iRadius, $iARGB1, $iARGB2, $iStartAngle = 0, $iEndAngle = 360, $iStep = 5)

	If $iStep < 1 Then
		$iStep = 1
	EndIf

	Local $Xi = $iX - $iRadius, $Yi = $iY - $iRadius, $Di = 2 * $iRadius
	Local $hBrush, $hMatrix, $Smooth = _GDIPlus_GraphicsGetSmoothingMode($hGraphics)
	Local $Start = True

	_GDIPlus_GraphicsSetSmoothingMode($hGraphics, 0)
	$hBrush = _GDIPlus_LineBrushCreate(0, 0, $iRadius, 0, $iARGB1, $iARGB2, 3)
	$hMatrix = _GDIPlus_MatrixCreate()
	_GDIPlus_MatrixTranslate($hMatrix, $iX, $iY)
	While $iStartAngle < $iEndAngle
		If $iStartAngle + $iStep > $iEndAngle Then
			$iStep = $iEndAngle - $iStartAngle
		EndIf
		If $Start Then
			_GDIPlus_MatrixRotate($hMatrix, $iStartAngle + $iStep / 2)
			$Start = False
		Else
			_GDIPlus_MatrixRotate($hMatrix, $iStep)
		EndIf
		_GDIPlus_LineBrushSetTransform($hBrush, $hMatrix)
		_GDIPlus_GraphicsFillPie($hGraphics, $Xi, $Yi, $Di, $Di, $iStartAngle, $iStep, $hBrush)
		$iStartAngle += $iStep
	WEnd
	_GDIPlus_GraphicsSetSmoothingMode($hGraphics, $Smooth)
	_GDIPlus_MatrixDispose($hMatrix)
	_GDIPlus_BrushDispose($hBrush)
	Return 1
EndFunc   ;==>_GDIPlus_GraphicsDrawRadialGradient


GDIP.au3
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Тема закрыта, поскольку данная функция присутствует в библиотеке WinAPIEx.au3 v2.3 и дальнейшее обсуждение здесь является бессмысленным.
 
Статус
Закрыто для дальнейших ответов.
Верх