Что нового

Прозрачный градиент поверх GUI

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Нужно создать две прозрачные полосы с градиентом, чтобы одна была сверху, а другая с низу.
И главное чтобы они были поверх главного окна.

Т.е чтобы я мог создать в главном окне Label, и он как бы затухал под этими градиенто-прозрачными (не знаю как это ещё назвать) полосами :stars:.

Кто что может предложить?
Думаю тут нужно копать в сторону GDI+, но вот как именно?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Я ничего не понял. Можешь от руки нарисовать и выложить скриншот?
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
Можешь от руки нарисовать и выложить скриншот?
Могу и не от руки, я до сих пор примерно вот так делал:

Код:
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

$hGUI = GUICreate("Test Script", 300, 200)
GUICtrlCreateLabel('Top Data' & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & 'Middle data' & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & 'Bottom Data', 20, 15, 260, 200, $SS_CENTER)

$aParentPos = WinGetPos($hGUI)
Dim $ahCover_GUI[21][2]

For $i = 0 To 20
	;Top Cover
	$ahCover_GUI[$i][0] = GUICreate("", $aParentPos[2] - 6, 4, $aParentPos[0] + 3, $aParentPos[1] + 25 + ($i * 2), $WS_POPUP, -1, $hGUI)
	GUISetBkColor(0xFFFFFF, $ahCover_GUI[$i][0])
	WinSetTrans($ahCover_GUI[$i][0], "", (255 / 20) * (-1 * ($i - 20)))
	
	;Bottom cover
	$ahCover_GUI[$i][1] = GUICreate("", $aParentPos[2] - 6, 4, $aParentPos[0] + 3, $aParentPos[1] + ($aParentPos[3] - 8) - ($i * 2), $WS_POPUP, -1, $hGUI)
	GUISetBkColor(0xFFFFFF, $ahCover_GUI[$i][1])
	WinSetTrans($ahCover_GUI[$i][1], "", (255 / 20) * (-1 * ($i - 20)))
Next

For $i = 0 To 20
	GUISetState(@SW_SHOW, $ahCover_GUI[$i][0])
	GUISetState(@SW_SHOW, $ahCover_GUI[$i][1])
Next

GUISetState(@SW_SHOW, $hGUI)
GUIRegisterMsg($WM_MOVE, "WM_MOVE")

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func WM_MOVE($hWndGUI, $MsgID, $WParam, $LParam)
	If $hWndGUI = $hGUI Then
		$aParentPos = WinGetPos($hGUI)
		
		For $i = 0 To 20
			WinMove($ahCover_GUI[$i][0], "", $aParentPos[0]+3, $aParentPos[1] + 25 + ($i * 2))
			WinMove($ahCover_GUI[$i][1], "", $aParentPos[0]+3, $aParentPos[1] + ($aParentPos[3] - 8) - ($i * 2))
		Next
	EndIf
EndFunc
 

Yashied

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


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

Вот здесь я рисовал тень с помощью GDI+. Посмотри, смысл тот же.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
Можно конечно нарисовать градиент как PNG, но без дополнительного окна вряд ли
Да, я пришёл к тому же выводу.

Сделал так:

Код:
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>

$hMain_GUI = GUICreate('Gradient Cover GUI (using GDI+)', 300, 200)
GUICtrlCreateLabel('Top Data' & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & 'Middle data' & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & 'Bottom Data', 20, 15, 260, 200, $SS_CENTER)
GUISetState(@SW_SHOW, $hMain_GUI)

$hCover_GUI = GUICreate('', 300, 200, -1, -1, $WS_POPUP, $WS_EX_LAYERED, $hMain_GUI)

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile(_GetGradientPNG())
_WinAPI_SetBitMap($hCover_GUI, $hImage, 255)

WM_MOVE($hMain_GUI, 0, 0, 0)
GUIRegisterMsg($WM_MOVE, 'WM_MOVE')
GUIRegisterMsg($WM_ACTIVATE, 'WM_ACTIVATE')
GUISetState(@SW_SHOWNOACTIVATE, $hCover_GUI)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			_GDIPlus_ImageDispose($hImage)
			_GDIPlus_Shutdown()
			Exit
	EndSwitch
WEnd

Func _GetGradientPNG($sPNG_File = '')
	If $sPNG_File = '' Or Not FileExists($sPNG_File) Then
		$sPNG_File = @TempDir & '\Gradient.png'
	EndIf
	
	Local $hFile = FileOpen($sPNG_File, 16+2)
	
	FileWrite($hFile, '0x89504E470D0A1A0A0000000D494844520000012C000000C8080600000052DFDC55000003EF4944415478DAEDD6A16D16001485513A000BC0001D800118A003E0ABEB6BD1D85A6465655D1DAE0A5583C14082403469424853FAC39B80E76E6E72CE04577DB947877F5E001438122CA0C504EB393D02606382F5273D02606382F5941E01B031C17A4C8F00D89860FD4E8F00D89860FD4A8F00D898603DA447006C4CB0EED323003626583FD323003626583FD22300362658DFD223003626585FD323003626585FD2230036265877E911001B13ACCFE911001B13ACDBF408808D09D6A7F408808D09D64D7A04C0C604EB3A3D0260638275951E01B031C1BA4C8F00D898607D4C8F00D898605DA447006C4CB03EA447006C4CB0DEA747006C4CB0CED3230036265867E911001B13ACD3F408808D09D6BBF408808D09D6497A04C0C604EB6D7A04C0C604EB4D7A04C0C604EB383D02606382F52A3D0260E1FB04EB657A05C0C6517A00C096600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A08165043B0801A8205D4102CA086600135040BA82158400DC1026A1C1D0E87F406809509D6CBF408808D09D65CACD7E92100FF33C13A4E8F00D89860BD498F00D89860BD4D8F00D898609DA447006C4CB0DEA547006C4CB04ED3230036265867E911001B13ACF3F408808D09D6FBF408808D09D687F408808D09D6457A04C0C604EB637A04C0C604EB323D0260638275951E01B031C1BA4E8F00D89860DDA447006C4CB03EA547006C4CB06ED323003626589FD3230036265877E911001B13AC2FE911001B13ACAFE911001B13AC6FE911001B13AC1FE911001B13AC9FE911001B13ACFBF408808D09D6437A04C0C604EB577A04C0C604EB777A04C0C604EB313D02606382F5941E01B031C1FA931E01B031C17A4E8F00D898601DD2230036040BA8F117BB6D14DA7E8BBB9F0000000049454E44AE426082')
	
	FileClose($hFile)
	
	Return $sPNG_File
EndFunc

Func _WinAPI_SetBitmap($hGUI, $hImage, $iOpacity)
	Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend
	Local  Const $AC_SRC_ALPHA = 1
	
	$hScrDC = _WinAPI_GetDC(0)
	$hMemDC = _WinAPI_CreateCompatibleDC($hScrDC)
	$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
	$hOld = _WinAPI_SelectObject($hMemDC, $hBitmap)
	$tSize = DllStructCreate($tagSIZE)
	$pSize = DllStructGetPtr($tSize)
	DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage))
	DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage))
	$tSource = DllStructCreate($tagPOINT)
	$pSource = DllStructGetPtr($tSource)
	$tBlend = DllStructCreate($tagBLENDFUNCTION)
	$pBlend = DllStructGetPtr($tBlend)
	DllStructSetData($tBlend, "Alpha", $iOpacity)
	DllStructSetData($tBlend, "Format", $AC_SRC_ALPHA)
	_WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA)
	_WinAPI_ReleaseDC(0, $hScrDC)
	_WinAPI_SelectObject($hMemDC, $hOld)
	_WinAPI_DeleteObject($hBitmap)
	_WinAPI_DeleteDC($hMemDC)
EndFunc

Func WM_ACTIVATE($hWnd, $iMsg, $wParam, $lParam)
	If $hWnd = $hCover_GUI And BitAND($wParam, 0xFFFF) Then
		WinActivate($hMain_GUI)
	EndIf
EndFunc

Func WM_MOVE($hWnd, $iMsg, $wParam, $lParam)
	If $hWnd = $hMain_GUI Then
		Local $aPos = WinGetPos($hWnd)
		Local $aClientSize = WinGetClientSize($hWnd)
		Local $iBorder = ($aPos[2] - $aClientSize[0]) / 2
		Local $iCaption = $aPos[3] - $aClientSize[1] - $iBorder
		
		WinMove($hCover_GUI, '', $aPos[0] + 3, $aPos[1] + $iCaption)
	EndIf
EndFunc
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
Вот здесь я рисовал тень с помощью GDI+. Посмотри, смысл тот же.
Спасибо, но у меня наверное много времени уйдёт чтобы адаптировать под свою задачу, проще загружать из файла.
Хотя я был бы не против варианта с рисованием градиента прямо в скрипте :whistle:, да и возможностей думаю будет побольше (размер, цвет и т.д.).
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Остановился всё таки на варианте с файлом, но есть по этому поводу другая проблема.
Возможно ли теперь загруженное изображение с файла заполнить другим цветом? :scratch:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вот так лучше всего сделать (с краткими комментариями).

Код:
#Include <GDIP.au3>

; Инициализируем GDI+
_GDIPlus_Startup()

; Создаем пустой GDI+ битмап размером 300x200
$hBitmap = _GDIPlus_BitmapCreateFromScan0(300, 200)

; Получаем контекст битмапа
$hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap)

; Делаем битмап полностью прозрачным
_GDIPlus_GraphicsClear($hGraphic, 0)

; Создаем кисть размером 300x50 для рисования верхнего градиента от 100% белого (0xFFFFFFFF) до полностью прозрачного (0x00FFFFFF)
$tRect = DllStructCreate($tagGDIPRECTF)
DllStructSetData($tRect, 'X', 0)
DllStructSetData($tRect, 'Y', 0)
DllStructSetData($tRect, 'Width', 300)
DllStructSetData($tRect, 'Height', 50)
$hBrush = _GDIPlus_LineBrushCreateFromRect($tRect, 0xFFFFFFFF, 0x00FFFFFF, 1)

; Рисуем верхний градиент
_GDIPlus_GraphicsFillRect($hGraphic, 0, 0, 300, 50, $hBrush)

; Поворачиваем кисть на 180 градусов
_GDIPlus_LineBrushRotateTransform($hBrush, 180)

; Рисуем нижний градиент
_GDIPlus_GraphicsFillRect($hGraphic, 0, 150, 300, 50, $hBrush)

; Удаляем ненужные ресурсы
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_BrushDispose($hBrush)

; Сохраняем битмап в файл для проверки того, что получилось
_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & '\Test.png')

; Удаляем битмап
_GDIPlus_GraphicsDispose($hGraphic)

; Деинициализируем GDI+
_GDIPlus_Shutdown()



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

Естественно в файл сохранять не нужно, это только для проверки.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied,
Как всегда - супер!!! Огромное Вам спасибо! (Особенно за комментарии) :thanks:
 

Yashied

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

Вот так можно добиться этого эффекта без дополнительных окон.

Код:
#Include <APIConstants.au3>
#Include <GDIP.au3>
#Include <GUIConstantsEx.au3>
#Include <StaticConstants.au3>
#Include <WinAPIEx.au3>

OnAutoItExitRegister('OnAutoItExit')

_GDIPlus_Startup()

$tRect = DllStructCreate($tagGDIPRECTF)
DllStructSetData($tRect, 1, 0)
DllStructSetData($tRect, 2, 0)
DllStructSetData($tRect, 3, 300)
DllStructSetData($tRect, 4, 50)
$hBrush1 = _GDIPlus_LineBrushCreateFromRect($tRect, 0xFFFFFFFF, 0x00FFFFFF, 1)
$hBrush2 = _GDIPlus_LineBrushCreateFromRect($tRect, 0x00FFFFFF, 0xFFFFFFFF, 1)

$hForm = GUICreate('MyGUI', 300, 200)

GUICtrlCreateLabel('', 0, 0, 300, 200)
GUICtrlSetState(-1, $GUI_DISABLE)
$hLabel = GUICtrlGetHandle(-1)

GUICtrlCreateLabel('Top Data' & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & 'Middle data' & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & 'Bottom Data', 20, 15, 260, 200, $SS_CENTER)

$hDll = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam')
$pDll = DllCallbackGetPtr($hDll)
$hProc = _WinAPI_SetWindowLongEx($hLabel, $GWL_WNDPROC, $pDll)

GUISetState()

Do
Until GUIGetMsg() = -3

_GDIPlus_BrushDispose($hBrush1)
_GDIPlus_BrushDispose($hBrush2)
_GDIPlus_Shutdown()

Func _WinProc($hWnd, $iMsg, $wParam, $lParam)
	Switch $iMsg
		Case $WM_PAINT

			Local $tPAINT, $tRect, $hDC, $hGraphic

			$hDC = _WinAPI_BeginPaint($hWnd, $tPAINT)
			$hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)
			_GDIPlus_GraphicsFillRect($hGraphic, 0, 0, 300, 50, $hBrush1)
			_GDIPlus_GraphicsFillRect($hGraphic, 0, 150, 300, 50, $hBrush2)
			_GDIPlus_GraphicsDispose($hGraphic)
			_WinAPI_EndPaint($hWnd, $tPAINT)
			Return 0
	EndSwitch
	Return _WinAPI_CallWindowProc($hProc, $hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_WinProc

Func OnAutoItExit()
	_WinAPI_SetWindowLongEx($hLabel, $GWL_WNDPROC, $hProc)
	DllCallbackFree($hDll)
EndFunc   ;==>OnAutoItExit



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

Упростил код.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied
Спасибо!
Всё супер!
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Вот где я это использовал.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied
Есть проблема на XP.
Если использовать стиль $WS_EX_COMPOSITED, то заливки не видно, есть идеи как это поправить? :scratch:
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481

Yashied

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
И с этим проблема, при использовании $WS_EX_LAYERED, нельзя использовать $WS_CHILD, а мне это нужно...
 
Верх