Что нового

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

Rem

Новичок
Сообщения
9
Репутация
1
Добрый день!
Протестировал всю справку и форум, так и не удалось найти ответ.
В любой программе дочерние окна максимально зависимы от родительского: при развертывании или перемещении они не могут выйти за пределы рабочей области родительского окна. Подскажите, пожалуйста, возможно ли и как создать такое окно в AutoIT?
 

CreatoR

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

Код:
#include <GuiConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

$Gui = GUICreate("Move The parent - MDI Demo", 400, 300, -1, -1, $WS_OVERLAPPEDWINDOW)
$ChildGui = GUICreate("Child window", 200, 100, 5, 5, -1, $WS_EX_TOPMOST)

GUISetState(@SW_SHOW, $Gui)
DllCall("user32.dll", "int", "SetParent", "hwnd", $ChildGui, "hwnd", $Gui)
GUISetState(@SW_SHOW, $ChildGui)

While 1
	$Msg = GUIGetMsg(1)
	Select
		Case $Msg[1] = $Gui And $Msg[0] = -3
			Exit
	EndSelect
WEnd
 
Автор
R

Rem

Новичок
Сообщения
9
Репутация
1
[Окна, Диалоги] Re: Как создать дочернее окно, не способное выйти за рамки родительского окна?

Спасибо, и в догонку второй вопрос: как сделать так, чтобы это дочернее окно при развертывании внутри родительского окна полностью заполнило его рабочую область (стало без панели названия и кнопок)? А кнопка свертывания где-то появилась отдельно (ну чтобы можно было потом снова дочернее окно привести в первоначальное состояние).
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Никак, потому что GUI в AutoIt не поддерживает MDI окна. Если только самому что-то мудрить...
 
Автор
R

Rem

Новичок
Сообщения
9
Репутация
1
Yashied сказал(а):
Никак, потому что GUI в AutoIt не поддерживает MDI окна. Если только самому что-то мудрить...

Очень жаль, что AutoIT пока находится на таком уровне... Буду надеяться на лучшее...

Насчет мудрить самому: я еще пока дилетант в языке, но вот навскидку следующий костыль:
При развертывании дочернего окна:
а) переместить его на определенное расстояние по вертикали под рамку родительского (чтобы полосы с названием и кнопками не было видно)
б) увеличить размер доч. окна по вертикали ровно на столько, на сколько оно было перемещено
в) создать на панели родительского окна небольшую кнопочку сворачивания
г) при нажатии на неё дочернее окно сворачивается и принимает первоначальные установки

Такое возможно реализовать, и если да, то как?
 

CreatoR

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

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

$hMain_GUI = GUICreate("Move The parent - MDI Demo", 400, 300, -1, -1, $WS_OVERLAPPEDWINDOW)
$hChild_GUI = GUICreate("Child window", 200, 100, 5, 5, BitOr($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX), $WS_EX_TOPMOST)
$nRestore_Btn = GUICtrlCreateButton("", 180, 3, 18, 18)
GUICtrlSetFont($nRestore_Btn, 10)
GUICtrlSetState($nRestore_Btn, $GUI_HIDE)

GUISetState(@SW_SHOW, $hMain_GUI)
_WinAPI_SetParent($hChild_GUI, $hMain_GUI)
GUISetState(@SW_SHOW, $hChild_GUI)

While 1
    $aMsg = GUIGetMsg(1)
	
    Select
		Case $aMsg[0] = $GUI_EVENT_CLOSE
			Switch $aMsg[1]
				Case $hMain_GUI
					Exit
				Case $hChild_GUI
					GUIDelete($hChild_GUI)
			EndSwitch
		Case $aMsg[0] = $GUI_EVENT_MAXIMIZE
			GUISetStyle($WS_POPUPWINDOW, -1, $hChild_GUI)
			GUICtrlSetState($nRestore_Btn, $GUI_SHOW)
		Case $aMsg[0] = $nRestore_Btn
			GUISetState(@SW_RESTORE, $hChild_GUI)
			GUISetStyle(BitOr($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX), -1, $hChild_GUI)
			WinMove($hChild_GUI, "", 5, 5, 205, 120)
			GUICtrlSetState($nRestore_Btn, $GUI_HIDE)
    EndSelect
WEnd
 
Автор
R

Rem

Новичок
Сообщения
9
Репутация
1
[Окна, Диалоги] Re: Как создать дочернее окно, не способное выйти за рамки родительского окна?

Единственная проблема: когда открыто дочернее окно, свернуть, закрыть родительское - невозможно.

Может быть проблема закралась где-то здесь:
DllCall("user32.dll", "int", "SetParent", "hwnd", $hChild_GUI, "hwnd", $hMain_GUI)

Вобщем, что делать???
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
Если только самому что-то мудрить
Типа такого:

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

Opt("GUIEventOptions", 1)

$hMain_GUI = GUICreate("Move The parent - MDI Demo", 400, 300, -1, -1, $WS_OVERLAPPEDWINDOW)
$hChild_GUI = GUICreate("Child window", 200, 100, 5, 5, BitOr($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX), BitOR($WS_EX_TOPMOST, $WS_EX_MDICHILD), $hMain_GUI)

$nRestore_Btn = GUICtrlCreateButton("", 180, 3, 18, 18)
GUICtrlSetFont($nRestore_Btn, 10)
GUICtrlSetState($nRestore_Btn, $GUI_HIDE)

GUISetState(@SW_SHOW, $hMain_GUI)
GUISetState(@SW_SHOW, $hChild_GUI)

$aParent_Pos = WinGetPos($hMain_GUI)
$aLast_Child_Pos = WinGetPos($hChild_GUI)

GUIRegisterMsg($WM_SIZE, "WM_SIZE")

While 1
    $aMsg = GUIGetMsg(1)
	
    Select
		Case $aMsg[0] = $GUI_EVENT_CLOSE
			Switch $aMsg[1]
				Case $hMain_GUI
					Exit
				Case $hChild_GUI
					GUIDelete($hChild_GUI)
			EndSwitch
		Case $aMsg[0] = $GUI_EVENT_MINIMIZE
			$aLast_Child_Pos = WinGetPos($hChild_GUI)
			
			Switch $aMsg[1]
				Case $hMain_GUI
					GUISetState(@SW_MINIMIZE, $hMain_GUI)
				Case $hChild_GUI
					GUISetState(@SW_MINIMIZE, $hChild_GUI)
					WinMove($hChild_GUI, "", $aParent_Pos[0]+3, $aParent_Pos[1]+$aParent_Pos[3]-35, $aParent_Pos[2]-6, $aParent_Pos[3]-33)
			EndSwitch
		Case $aMsg[0] = $GUI_EVENT_RESTORE
			Switch $aMsg[1]
				Case $hMain_GUI
					GUISetState(@SW_RESTORE, $hMain_GUI)
				Case $hChild_GUI
					GUISetState(@SW_RESTORE, $hChild_GUI)
					WinMove($hChild_GUI, "", $aLast_Child_Pos[0], $aLast_Child_Pos[1], $aLast_Child_Pos[2], $aLast_Child_Pos[3])
			EndSwitch
		Case $aMsg[0] = $GUI_EVENT_MAXIMIZE
			$aLast_Child_Pos = WinGetPos($hChild_GUI)
			WinMove($hChild_GUI, "", $aParent_Pos[0]+3, $aParent_Pos[1]+30, $aParent_Pos[2]-6, $aParent_Pos[3]-33)
			GUISetStyle($WS_POPUP, -1, $hChild_GUI)
			GUICtrlSetState($nRestore_Btn, $GUI_SHOW)
		Case $aMsg[0] = $nRestore_Btn
			GUISetState(@SW_RESTORE, $hChild_GUI)
			GUISetStyle(BitOr($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX), -1, $hChild_GUI)
			WinMove($hChild_GUI, "", $aLast_Child_Pos[0], $aLast_Child_Pos[1], $aLast_Child_Pos[2], $aLast_Child_Pos[3])
			GUICtrlSetState($nRestore_Btn, $GUI_HIDE)
    EndSelect
WEnd

Func WM_SIZE()
	$aParent_Pos = WinGetPos($hMain_GUI)
EndFunc


Конечно тут ещё многое нужно учесть, например вынос дочернего окна за рамки родительского.
 

CreatoR

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

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

Opt("GUIEventOptions", 1)

Global $aLast_Child_Pos

$hMain_GUI = GUICreate("Move The parent - MDI Demo", 400, 300, -1, -1, BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPCHILDREN))
$nDummy = GUICtrlCreateLabel("", -100, -100)
GUICtrlSetState($nDummy, $GUI_HIDE)
GUISetState(@SW_SHOW, $hMain_GUI)

$aChild_GUI = _MDI_GUICreate("Child window", 200, 100, 5, 5, BitOr($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX), $WS_EX_TOPMOST, $hMain_GUI)

While 1
    $aMsg = GUIGetMsg(1)
    
    Select
        Case $aMsg[0] = $GUI_EVENT_CLOSE
            Switch $aMsg[1]
                Case $hMain_GUI
                    Exit
                Case Else
                    GUIDelete($aMsg[1])
			EndSwitch
		Case $aMsg[0] = $GUI_EVENT_MINIMIZE
			If $aMsg[1] = $hMain_GUI Then
				GUISetState(@SW_MINIMIZE, $aMsg[1])
				ContinueLoop
			EndIf
			
			$aLast_Child_Pos = WinGetPos($aMsg[1])
            GUISetState(@SW_MINIMIZE, $aMsg[1])
		Case $aMsg[0] = $GUI_EVENT_RESTORE
			GUISetState(@SW_RESTORE, $aMsg[1])
        Case $aMsg[0] = $GUI_EVENT_MAXIMIZE
			If $aMsg[1] = $hMain_GUI Then
				GUISetState(@SW_MAXIMIZE, $aMsg[1])
				ContinueLoop
			EndIf
			
			$aLast_Child_Pos = WinGetPos($aMsg[1])
			GUISetState(@SW_MAXIMIZE, $aMsg[1])
            GUISetStyle($WS_POPUPWINDOW, -1, $aMsg[1])
			GUICtrlSetState($aChild_GUI[1], $GUI_SHOW)
        Case $aMsg[0] = $aChild_GUI[1]
			If $aMsg[1] = $hMain_GUI Then
				ContinueLoop
			EndIf
			
			Local $tPoint = DllStructCreate("int X;int Y")
			DllStructSetData($tPoint, "X", $aLast_Child_Pos[0])
			DllStructSetData($tPoint, "Y", $aLast_Child_Pos[1])

			_WinAPI_ScreenToClient($hMain_GUI, $tPoint)
			
			$aLast_Child_Pos[0] = DllStructGetData($tPoint, "X")
			$aLast_Child_Pos[1] = DllStructGetData($tPoint, "Y")
			
            GUISetState(@SW_RESTORE, $aMsg[1])
            GUISetStyle(BitOr($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX), -1,$aMsg[1] )
            WinMove($aMsg[1], "", $aLast_Child_Pos[0], $aLast_Child_Pos[1], $aLast_Child_Pos[2], $aLast_Child_Pos[3])
			
			GUICtrlSetState($aChild_GUI[1], $GUI_HIDE)
    EndSelect
WEnd

Func _MDI_GUICreate($sTitle, $iWidth, $iHeight, $iLeft, $iTop, $nStyle, $nExStyle, $hWnd)
	Local $hChild_GUI = GUICreate($sTitle, $iWidth, $iHeight, $iLeft, $iTop, $nStyle, $nExStyle, $hWnd)
	Local $nRestore_Btn = GUICtrlCreateButton("p", $iWidth - 20, 3, 18, 18)
	GUICtrlSetFont($nRestore_Btn, 10, 400, 0, "Wingdings")
	GUICtrlSetState($nRestore_Btn, $GUI_HIDE)
	
	_WinAPI_SetParent($hChild_GUI, $hWnd)
	GUISetState(@SW_SHOW, $hChild_GUI)
	
	Local $aRet[2] = [$hChild_GUI, $nRestore_Btn]
	Return $aRet
EndFunc


Нужно было просто создать любой элемент в родительском GUI.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Правильней было бы создать MDI с помощью API, но геморно это...
 
Автор
R

Rem

Новичок
Сообщения
9
Репутация
1
Нашёл как обойти это:

Отличное решение!
Однако появилась новая проблема - скорее из-за _WinAPI_SetParent($hChild_GUI, $hWnd) в Func _MDI_GUICreate; созданные через GraphGDIPlus.au3 графики перестали выводиться в это дочернее окно (цифровые значения выводятся, а окно диаграммы и самого графика нет).

Тема получилось связанной с другой темой: http://autoit-script.ru/index.php/topic,3435.msg24576/topicseen.html#new

Со всех сторон засада :scratch:

Вобщем либо строить график через структуру и Bitmap и возможно эта проблема изчезнет, либо в этой теме придумывать, что делать с выводом графика через GraphGDIPlus.au3.
 
Верх