Что нового

Функция градиент

musicstashall

Знающий
Сообщения
322
Репутация
7
Народ, дайте способ рисовать градиенты, а то я отчаялся. Кроме WinAPI, там очень неудобно. Если мне нужно сделать переход между двумя цветами, черным и белым, например, то функция может нарисовать только под прямым углом, либо справа налево, либо сверху вниз. Если делать угол, то только в 45°, при этом необходимо задать третью точку перехода и присвоить ей какой-то цвет, а мне нужно только два цвета, черный и белый. Кроме GDIPlus, в нем рисунок стирается, когда окно уходит за границы экрана. В последнем всё хорошо, но косяк с рисунком не устраивает конечно. Если посмотреть любой пример GDIPlus из спраки, это можно увидеть. Плиз, дайте нормальную функцию. Вот, что я испробовал:
WinAPI:
Код:
_WinAPI_GradientFill

GDIPlus:
Код:
_GDIPlus_LineBrushCreateFromRectWithAngle
 
A

Alofa

Гость
Алгоритм работы графического интерфейса Windows основан на его обновлении. Т.е. для корректного отображения все окна должны постоянно при необходимости перерисовываться, а вот когда это нужно и кто за это отвечает - уже другой вопрос.
При использовании в скрипте _GDIPlus вся ответственность за перерисовку лежит на ваших плечах (почему-то справка об этом умалчивает).
Как все устроить? Я по крайней мере знаю 3 варианта:
- Вариант 1 (Перерисовка в цикле)
Вариант дан только для примера. В большинстве случаев так не стоит делать (смотри Ответ #3).
Код:
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $hGUI, $hGraphics, $hBrush, $tRectF
Local $iWidth = 400, $iHeight = 100
$hGUI = GUICreate('Кисть градиента с заданным углом (Вариант 1)', $iWidth, $iHeight)

GUIRegisterMsg($WM_MOVE, 'WM_MOVE') ; Для перерисовки окна во время перетаскивания
GUISetState()

_GDIPlus_Startup()
$tRectF = _GDIPlus_RectFCreate(0, 0, $iWidth, $iHeight)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBrush = _GDIPlus_LineBrushCreateFromRectWithAngle($tRectF, 0xFF000000, 0xFFFFFFFF, 45)

Do
	WM_MOVE()
Until GUIGetMsg() = $GUI_EVENT_CLOSE

; Очищает ресурсы
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()

; ================================================================
Func WM_MOVE()
	_GDIPlus_GraphicsFillRect($hGraphics, 0, 0, $iWidth, $iHeight, $hBrush)
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOVE

- Вариант 2 (Задействуем WM_PAINT)
Код:
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $hGUI, $hGraphics, $hBrush, $tRectF
Local $iWidth = 400, $iHeight = 100
$hGUI = GUICreate('Кисть градиента с заданным углом (Вариант 2)', $iWidth, $iHeight)

GUIRegisterMsg($WM_PAINT, 'WM_PAINT')
GUISetState()

_GDIPlus_Startup()
$tRectF = _GDIPlus_RectFCreate(0, 0, $iWidth, $iHeight)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBrush = _GDIPlus_LineBrushCreateFromRectWithAngle($tRectF, 0xFF000000, 0xFFFFFFFF, 45)
WM_PAINT()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

; Очищает ресурсы
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()

; ================================================================
Func WM_PAINT()
	_GDIPlus_GraphicsFillRect($hGraphics, 0, 0, $iWidth, $iHeight, $hBrush)
	Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_WM_PAINT

- Вариант 3 (пускай все делает Autoit) [Для статичных рисунков]
Код:
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local Const $STM_SETIMAGE = 0x0172
Local $hGUI, $iPic, $tRectF, $hBitmap, $hGraphics, $hBrush, $hGDIBmp
Local $iWidth = 400, $iHeight = 100

$hGUI = GUICreate('Кисть градиента с заданным углом (Вариант 3)', $iWidth, $iHeight)
$iPic = GUICtrlCreatePic('', 0, 0) ; Ширину и высоту можон не задавать
GUISetState()

_GDIPlus_Startup()
$tRectF = _GDIPlus_RectFCreate(0, 0, $iWidth, $iHeight)
$hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
$hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2)
$hBrush = _GDIPlus_LineBrushCreateFromRectWithAngle($tRectF, 0xFF000000, 0xFFFFFFFF, 45)
_GDIPlus_GraphicsFillRect($hGraphics, 0, 0, $iWidth, $iHeight, $hBrush)
$hGDIBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)

GUICtrlSendMsg($iPic, $STM_SETIMAGE, 0, $hGDIBmp)

; Очищает ресурсы
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_DeleteObject($hGDIBmp)
_GDIPlus_Shutdown()
$tRectF = 0

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Супер! спасибо огромное. :IL_AutoIt_1:

Еще пара вопросов. Вот, я создал рисунок из четырех квадратов послойно, и мне нужно этому объекту присвоить идентификатор... как это сделать?? И другой вопрос: как вырезать внутри квадрата прозрачную полость, чтобы через нее были видны нижние слои рисунка?
 

Prog

Продвинутый
Сообщения
537
Репутация
65
Alofa [?]
для корректного отображения все окна должны постоянно перерисовываться
И получим полную загрузку процессора (как минимум одного из его ядер).
Окна не должны постоянно перерисовываться, а только в случае если в этом есть необходимость. Но даже в таком случае окно обычно перерисовывается не полностью, а лишь частично.
 
A

Alofa

Гость
OffTopic:
Prog сказал(а):
... Окна не должны постоянно перерисовываться, а только в случае если в этом есть необходимость.
Изменил пост.

Prog сказал(а):
... перерисовывается не полностью, а лишь частично.
Не знал, что окно может перерисовываться частично, я думал это делается поэлементно. Сообщение WM_PAINT
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Заметил, WM_PAINT перерисовывает только по мере необходимости. Вполне приемлемо. Делаю следующим образом, сталкиваюсь с задачей — как передать свои параметры в функцию WM_PAINT:
Код:
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $hGUI, $hGraphics, $hBrush, $tRectF
Local $x, $y, $w, $h, $Color1, $Color2

$hGUI = GUICreate('Кисть градиента с заданным углом (Вариант 3)', 300, 150)
GUIRegisterMsg($WM_PAINT, 'WM_PAINT')
GUISetState()
ButtomActive(21, 4)

Func ButtomActive($x, $y)
	_GDIPlus_Startup()
	Graphic($x, $y , 72, 72, 0xFFE5F3FF, 0xFFE5F3FF)
EndFunc

Func Graphic($x, $y, $w, $h, $Color1, $Color2)
	$tRectF = _GDIPlus_RectFCreate($x, $y, $w, $h)
	$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
	$hBrush = _GDIPlus_LineBrushCreateFromRectWithAngle($tRectF, $Color1, $Color2, 45)
	WM_PAINT($x, $y, $w, $h)
    ConsoleWrite('Отправляем: ' & $x & ', ' & $y & ', ' & $w & ', ' & $h & @cr)
	; Очищает ресурсы
	_GDIPlus_BrushDispose($hBrush)
	_GDIPlus_GraphicsDispose($hGraphics)
	_GDIPlus_Shutdown()
EndFunc
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
; ================================================================
Func WM_PAINT($x, $y, $w, $h)
    _GDIPlus_GraphicsFillRect($hGraphics, $x, $y, $w, $h, $hBrush)
    ConsoleWrite('Получаем: ' & $x & ', ' & $y & ', ' & $w & ', ' & $h & @cr)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_WM_PAINT
 
A

Alofa

Гость
musicstashall сказал(а):
...как передать свои параметры в функцию WM_PAINT
Не надо туда ничего передавать. Вы неправильно понимаете ее предназначение.
Почитайте:
- функция GUIRegisterMsg()
- Сообщения Windows и их источники


Добавлено:
Сообщение автоматически объединено:

musicstashall сказал(а):
... Еще пара вопросов...
Каждый вопрос в своей теме.
 

Prog

Продвинутый
Сообщения
537
Репутация
65
OffTopic:
Alofa [?]
Не знал, что окно может перерисовываться частично, я думал это делается поэлементно. Сообщение WM_PAINT
Может. При получении сообщения WM_PAINT можно определить размер области требующей перерисовки с помощью функции GetUpdateRect или BeginPaint.
Сообщение WM_PAINT отправляется не только окну но и контролам (дочерним окнам), т. е. при перерисовке, сообщение WM_PAINT может быть отправлено не всем контролам, если требуется перерисовать часть окна.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
musicstashall [?]
Еще пара вопросов. Вот, я создал рисунок из четырех квадратов послойно, и мне нужно этому объекту присвоить идентификатор... как это сделать??

Предупреждение За нарушение общих правил (пункт В.4):
Не лепите несколько вопросов разной тематики в один пост. По типу "Ребят, а ещё такой вопрос...". Каждый вопрос в свою тему.


С уважением, ваш Глобальный модератор.
 
Верх