Что нового

[Элементы GUI] Дочернее окно поверх родительского окна с фоновой картинкой

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
Есть такой пример создания дочернего окна "внутри" родительского:

Код:
#include <WindowsConstants.au3>
#include <GUIConstants.au3>

$hGUI = GUICreate("Example", 600, 600, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU, $WS_SIZEBOX))

GUICtrlCreatePic(@ScriptDir & "\test.jpg", 0, 0, 600, 600) ; рисуем фоновый рисунок

GUISetState()
$h_cGUI = GUICreate("Child GUI", 500, 500, 50, 50, $WS_CHILD, BitOR($WS_EX_CLIENTEDGE, $WS_SIZEBOX), $hGUI)

GUISetState()


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


Однако, если установлено фоновое изображение на всю площадь родительского окна, дочернее окно не отображается.

Как можно сделать, чтобы дочернее окно было поверх этого изображения?

Пробовал через функции GDIPlus, там вроде можно сделать подобное, но при перемещении родительского окна фоновая картинка "стирается" :scratch:
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Код:
#include <GUIConstantsEx.au3>

Global $Button2 = -1

$Form1 = GUICreate("Form1", 600, 600)
GUICtrlCreatePic(@ScriptDir & '\test.jpg', 0, 0, 600, 600)
GUICtrlSetState(-1, $GUI_DISABLE)
$Button1 = GUICtrlCreateButton("Button1", 136, 112, 75, 25)
GUISetState()

$Child = _NewWindow($Form1)
GUISetState(@SW_SHOW, $Child)
If Not WinActive($Child) Then WinActivate($Child)

While 1
	$nMsg = GUIGetMsg(1)
	Switch $nMsg[0]
		Case $GUI_EVENT_CLOSE
			If $nMsg[1] = $Form1 Then Exit
			If $nMsg[1] = $Child Then GUISetState(@SW_HIDE, $Child)
		Case $Button1
			MsgBox(0, 'GUI1', 'Hello')
		Case $Button2
			MsgBox(0, 'GUI2', 'TEST')
	EndSwitch
WEnd

Func _NewWindow($Parent)
	Local $Form2
	$Form2 = GUICreate('Form2', 400, 300, -1, -1, -1, -1, $Parent)
	$Button2 = GUICtrlCreateButton('Hello', 30, 50, 100, 25)
	Return $Form2
EndFunc
 
Автор
W

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
Zaramot
Не совсем то - нужно, чтобы дочернее было зафиксировано внутри родительского.
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
WSWR
Какова цель встроенного окна? У меня пока не получилось, но был случай, когда я тоже делал встроенное окно и поняв что можно обойтись без него, так и сделал. Просто функция гененрирует нужные элементы в этой площадке потом удаляет и само наличие границ окна не придавало какого либо смысла.
 
Автор
W

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
AZJIO
Отображать специфическое содержимое.
Рабочий вариант с обычными элементами GUI не устраивает.

В принципе, самым простое решение - создание не 1, а 4 элементов Picture вокруг области встроенного дочернего окна, при этом каждый элемент будет отображать только часть исходной картинки-фона. Сейчас обдумываю, как с помощью GDIPlus разбить картинку на части с сохранением пропорций и т.д.

Ну, или просто откажусь от фоновой картинки :-X
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Немного коряво, зато работает :smile:
Код:
#include <WinAPIEx.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global $Img = @ScriptDir & '\test.jpg'

$Form1 = GUICreate("Mother Window", 800, 600)
;GUICtrlCreatePic('', 0, 0, 800, 600)
$Pic = GUICreate('', 800, 600, 0, 0, $WS_POPUP)
GUICtrlCreatePic($Img, 0, 0, 800, 600)
$Child1 = GUICreate("Child 1 Window", 500, 400, 250, 50, -1, $WS_EX_TOOLWINDOW)
$Child2 = GUICreate("Child 2 Window", 500, 400, 50, 150, -1, $WS_EX_TOOLWINDOW)
GUISetState(@SW_SHOW, $Form1)
GUISetState(@SW_SHOW, $Pic)
GUISetState(@SW_DISABLE, $Pic)
GUISetState(@SW_SHOW, $Child1)
GUISetState(@SW_SHOW, $Child2)

_WinAPI_SetParent($Pic, $Form1)
_WinAPI_SetParent($Child1, $Form1)
_WinAPI_SetParent($Child2, $Form1)

While 1
	$nMsg = GUIGetMsg(1)
	Switch $nMsg[0]
		Case $GUI_EVENT_CLOSE
			If $nMsg[1] = $Form1 Then Exit
			If $nMsg[1] = $Child1 Then GUISetState(@SW_HIDE, $Child1)
			If $nMsg[1] = $Child2 Then GUISetState(@SW_HIDE, $Child2)
	EndSwitch
WEnd
 
Автор
W

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
Zaramot
Спасибо, тоже интересный вариант.

Сделал вот так с пропорциональным уменьшением картинки(предполагается, что картинка большого разрешения, много больше разрешения GUI, а дочернее окно - одно):
Код:
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <GDIPlus.au3>

Global $iWidth = 1300
Global $iHeight = 900

Global $h_cGUI_Width = 400
Global $h_cGUI_Height = 500

Global $h_cGUI_x = 400
Global $h_cGUI_y = 200

Global $image = _PathSplitByRegExp(@ScriptDir & '\test.bmp')


$hGUI = GUICreate('Example', $iWidth, $iHeight, 0, 0, BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU))

_Pic(0)
_Pic(1)
_Pic(2)
_Pic(3)
_Pic(4)

GUISetState()

Func _Pic($n)
	_GDIPlus_Startup()
	
	$hSource = _GDIPlus_ImageLoadFromFile($image[0])
	$Size = _GDIPlus_GetImageDimension($hSource)
	Switch $n
		Case 0
			$hDestination = _GDIPlus_CreateBitmapFromScan0($iWidth, $iHeight, 0, _GDIPlus_GetImagePixelFormat($hSource))
			$hGraphics = _GDIPlus_ImageGetGraphicsContext($hDestination)
			_GDIPlus_GraphicsDrawImageRect($hGraphics, $hSource, 0, 0, $iWidth, $iHeight)
			_GDIPlus_ImageSaveToFile($hDestination, @ScriptDir & '\' & 'test' & $n & '.' & $image[4])
		Case 1
			$hDestination = _GDIPlus_CreateBitmapFromScan0($iWidth, $h_cGUI_y, 0, _GDIPlus_GetImagePixelFormat($hSource))
			$hGraphics = _GDIPlus_ImageGetGraphicsContext($hDestination)
			_GDIPlus_GraphicsDrawImageRect($hGraphics, $hSource, 0, 0, $Size[0], $Size[1])
			_GDIPlus_ImageSaveToFile($hDestination, @ScriptDir & '\' & 'test' & $n & '.' & $image[4])
			GUICtrlCreatePic(@ScriptDir & '\' & 'test' & $n & '.' & $image[4], 0, 0, $iWidth, $h_cGUI_y)
		Case 2
			$hDestination = _GDIPlus_CreateBitmapFromScan0($iWidth, $iHeight - ($h_cGUI_Height + $h_cGUI_y), 0, _GDIPlus_GetImagePixelFormat($hSource))
			$hGraphics = _GDIPlus_ImageGetGraphicsContext($hDestination)
			_GDIPlus_GraphicsDrawImageRect($hGraphics, $hSource, 0, -($h_cGUI_Height + $h_cGUI_y), $Size[0], $Size[1])
			_GDIPlus_ImageSaveToFile($hDestination, @ScriptDir & '\' & 'test' & $n & '.' & $image[4])
			GUICtrlCreatePic(@ScriptDir & '\' & 'test' & $n & '.' & $image[4], 0, $h_cGUI_Height + $h_cGUI_y, $iWidth, $iHeight - ($h_cGUI_Height + $h_cGUI_y))
		Case 3
			$hDestination = _GDIPlus_CreateBitmapFromScan0($h_cGUI_x, $iHeight, 0, _GDIPlus_GetImagePixelFormat($hSource))
			$hGraphics = _GDIPlus_ImageGetGraphicsContext($hDestination)
			_GDIPlus_GraphicsDrawImageRect($hGraphics, $hSource, 0, 0, $Size[0], $Size[1])
			_GDIPlus_ImageSaveToFile($hDestination, @ScriptDir & '\' & 'test' & $n & '.' & $image[4])
			GUICtrlCreatePic(@ScriptDir & '\' & 'test' & $n & '.' & $image[4], 0, 0, $h_cGUI_x, $iHeight)
		Case 4
			$hDestination = _GDIPlus_CreateBitmapFromScan0(($iWidth - ($h_cGUI_x + $h_cGUI_Width)), $iHeight, 0, _GDIPlus_GetImagePixelFormat($hSource))
			$hGraphics = _GDIPlus_ImageGetGraphicsContext($hDestination)
			_GDIPlus_GraphicsDrawImageRect($hGraphics, $hSource, -($h_cGUI_x + $h_cGUI_Width), 0, $Size[0], $Size[1])
			_GDIPlus_ImageSaveToFile($hDestination, @ScriptDir & '\' & 'test' & $n & '.' & $image[4])
			GUICtrlCreatePic(@ScriptDir & '\' & 'test' & $n & '.' & $image[4], ($h_cGUI_x + $h_cGUI_Width), 0, ($iWidth - ($h_cGUI_x + $h_cGUI_Width)), $iHeight)
	EndSwitch
	_GDIPlus_GraphicsDispose($hGraphics)
	_GDIPlus_ImageDispose($hDestination)
	_GDIPlus_ImageDispose($hSource)
	_GDIPlus_Shutdown()
	GuiCtrlSetState(-1, $GUI_DISABLE)
	If $n = 0 Then $image[0] = @ScriptDir & '\test0.' & $image[4]
EndFunc   ;==>_Pic


$h_cGUI = GUICreate('Child GUI', $h_cGUI_Width, $h_cGUI_Height, $h_cGUI_x, $h_cGUI_y, $WS_CHILD, BitOR($WS_EX_CLIENTEDGE, $WS_SIZEBOX), $hGUI)

GUISetState()

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd
Func _GDIPlus_CreateBitmapFromScan0($iWidth, $iHeight, $iStride = 0, $iPixelFormat = 0x0026200A, $pScan0 = 0)
	Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromScan0', 'int', $iWidth, 'int', $iHeight, 'int', $iStride, 'int', $iPixelFormat, 'ptr', $pScan0, 'ptr*', 0)
	If(@error) Or($Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	Return $Ret[6]
EndFunc   ;==>_GDIPlus_CreateBitmapFromScan0

Func _GDIPlus_GetImageDimension($hImage)
	Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hImage, 'float*', 0, 'float*', 0)
	If(@error) Or($Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	Local $Result[2]
	$Result[0] = $Ret[2]
	$Result[1] = $Ret[3]
	Return $Result
EndFunc   ;==>_GDIPlus_GetImageDimension

Func _GDIPlus_GetImagePixelFormat($hImage)
	Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImagePixelFormat', 'ptr', $hImage, 'uint*', 0)
	If(@error) Or($Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	Return $Ret[2]
EndFunc   ;==>_GDIPlus_GetImagePixelFormat

Func _PathSplitByRegExp($sPath)
	If StringStripWS($sPath, 8) = '' Then
		Return SetError(1, 0, 0)
	EndIf

	$sPath = StringReplace($sPath, '/', '\')

	Local $aRet = StringRegExp($sPath, '^(?i)([a-z]:|\\\\(?:\?\\)?[a-z0-9_.$]+\\[a-z0-9_.]+\$?)?(\\(?:[^\\/:*?"<>|\r\n]+\\)*)?([^\\/:*?"<>|\r\n.]*)\.?((?:[^.\\/:*?"<>|\r\n]+)?)$', 2)

	Switch @error
		Case 1
			Return SetError(2, 0, 0) ;Array is invalid. No matches.
		Case 2
			Return SetError(3, @extended, 0) ;Bad pattern, array is invalid. @Extended = offset of error in pattern.
	EndSwitch

	Return $aRet
EndFunc   ;==>_PathSplitByRegExp

Спасибо Yashied за пример обрезки изображения.
 
Верх