Что нового

[Элементы GUI] Динамическое изменение размеров GUICtrl (растягивание мышей)

Pelerin

Осваивающий
Сообщения
81
Репутация
23
Поможите пожалуйста!
Хочу сделать окно на подобие explorer.exe, чтобы слева был TreView, а справа например Edit, и чтобы можно было менять размер TreeView и при этом Edit растягивался на оставшуюся область окна.

Подскажите в какую сторону копать и по какому принципу оно должно работать. Думаю это должны быть два фрейма со свойством $WS_SIZEBOX. Но как их создать?

Чтобы было понятно что требуется, вот накидал на HIASM простенькое окно. Благо там все просто делается...

Заранее спасибо.
 

VladUs

Скриптер
Сообщения
621
Репутация
181
Так вроде для этих же целей есть функция GUICtrlSetResizing ()
 
Автор
Pelerin

Pelerin

Осваивающий
Сообщения
81
Репутация
23
VladUs
Не знаю как объяснить...)
Надо чтобы можно было грызуном навести на границу между TreeView и Edit и растянуть TreeView до нужных размеров. При этом размер и положение основного окна не меняется, как например в Total-е можно менять размер файловых панелей. Если можно это сделать с помощью GUICtrlSetResizing (), то как?
 

CreatoR

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

Пример:
Код:
#include <GUIConstantsEx.au3>
#include <GUICtrl_SetResizing.au3>

$hGUI = GUICreate("_GUICtrl_SetOnResize - Example", 700, 480)

$Edit = GUICtrlCreateEdit("", 40, 40, 280, 200)
_GUICtrl_SetOnResize($hGUI, $Edit, 10, $iDefCtrlMinSize, $i_RESIZE_LEFT_EDGE) ;Resize only Left edge (-1 resize all)

$ListView = GUICtrlCreateListView("Column", 340, 40, 300, 200)
GUICtrlCreateListViewItem("Item", $ListView)
_GUICtrl_SetOnResize($hGUI, $ListView, 10, $iDefCtrlMinSize, BitOR($i_RESIZE_TOP_EDGE, $i_RESIZE_BOTTOM_EDGE)) ;Resize Top + Bottom

$Checkbox = GUICtrlCreateCheckbox("Some Checkbox", 40, 270)
GUICtrlSetBkColor(-1, 0xFFFFFF)
_GUICtrl_SetOnResize($hGUI, $Checkbox, 10, $iDefCtrlMinSize, BitOR($i_RESIZE_LEFT_EDGE, $i_RESIZE_RIGHT_EDGE)) ;Resize Left + Right

$Label = GUICtrlCreateLabel("Some Label", 40, 320, -1, 15)
GUICtrlSetBkColor(-1, 0x0000FF)
GUICtrlSetColor(-1, 0xFFFFFF)
_GUICtrl_SetOnResize($hGUI, $Label, 10, 15, BitOR($i_RESIZE_TOP_EDGE, $i_RESIZE_RIGHT_EDGE)) ;Resize Top + Right

$Button = GUICtrlCreateButton("Some Button", 40, 370, 100, 40)
_GUICtrl_SetOnResize($hGUI, $Button, 10, $iDefCtrlMinSize, BitOR($i_RESIZE_BOTTOM_EDGE, $i_RESIZE_LEFT_EDGE)) ;Resize Bottom + Left

GUISetState(@SW_SHOW, $hGUI)

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


Сама UDF во вложений.
 
Автор
Pelerin

Pelerin

Осваивающий
Сообщения
81
Репутация
23
CreatoR
Чего-то оно ругается:
Код:
C:\Program Files\AutoIt3\Include\GUICtrl_SetResizing.au3(3,48) : ERROR: AdlibEnable(): undefined function.
AdlibEnable ("_GUICtrl_SetResizing_Handler", 50)
:( Может версия Autoit не та? У меня v3.3.6.1
 
Автор
Pelerin

Pelerin

Осваивающий
Сообщения
81
Репутация
23
Ок! все работает. Сейчас буду изучать UDF. Спасибо за помощь
 
Автор
Pelerin

Pelerin

Осваивающий
Сообщения
81
Репутация
23
CreatoR,
спасибо, но мне немного не хватило функционала. см http://autoit-script.ru/index.php?topic=4825.msg35045#msg35045

Но я зато понял принцип её работы. Буду писать код заточенный под конкретную задачу, уже есть идеи.
 
Автор
Pelerin

Pelerin

Осваивающий
Сообщения
81
Репутация
23
Нашел решение своей задачи. Что примечательно без дополнительных UDF, только родные функции AutoIt.
Вот решил поделиться решением, вдруг кому-то еще пригодится...
Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>

$leftctrl_width = 100
$rightctrl_width = 285
$splitter_x = 105

$win = GUICreate (@ScriptName, 400, 400, -1 , -1, $GUI_SS_DEFAULT_GUI, $WS_EX_COMPOSITED)
$leftctrl = GUICtrlCreateTreeView (5, 5, $leftctrl_width, 390, '', $WS_EX_CLIENTEDGE)
$splitter = GUICtrlCreateLabel ('', $splitter_x, 5, 5, 390)
GUICtrlSetCursor($splitter, 13)
GUICtrlSetState ($splitter, $Gui_ontop)
$rightctrl = GUICtrlCreateEdit("edit", 110, 5, $rightctrl_width, 390)

GUISetState (@SW_SHOW)
Do
	$msg = GUIGetMsg()
	If $msg = $splitter Then
		$Win_client_size=WinGetClientSize($win)
		$Cursor_info=GUIGetCursorInfo()
		If $Cursor_info[2]=1 Then
			$last_x = $Cursor_info[0]
			Do
				$Cursor_info=GUIGetCursorInfo()
				Select
					Case $last_x < $Cursor_info[0]; Move to right
						If  $rightctrl_width <= 10 Then
							$leftctrl_width = $Win_client_size[0]-25
							$rightctrl_width = 10
							$splitter_x = $Win_client_size[0]-20
						Else
							$delta = $Cursor_info[0]-$last_x
							$leftctrl_width += $delta
							$rightctrl_width -= $delta
							$splitter_x += $delta
						EndIf
					Case $last_x > $Cursor_info[0]; Move to left
						if $leftctrl_width <= 10 then
							$leftctrl_width = 10
							$rightctrl_width = $Win_client_size[0] - 25
							$splitter_x = 15
						Else
							$delta = $last_x-$Cursor_info[0]
							$leftctrl_width -= $delta
							$rightctrl_width += $delta
							$splitter_x -= $delta
						EndIf
					Case Else
						ContinueLoop
				EndSelect
				GUICtrlSetPos($Splitter, $splitter_x, '')
				GUICtrlSetPos ($leftctrl, 5, 5, $leftctrl_width)
				GUICtrlSetPos ($rightctrl , $splitter_x+5, 5, $rightctrl_width)
				$last_x = $Cursor_info[0]
			Until $Cursor_info[2]=0
		EndIf
	EndIf
Until $msg = $GUI_EVENT_CLOSE
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Pelerin [?]
Нашел решение своей задачи
Мда.... нет слов.

А нельзя было просто написать, что нужен разделитель между элементами?

без дополнительных UDF, только родные функции AutoIt
Вообще то UDF обычно строятся с родных функций AutoIt ;)

Вот более корректный пример разделителя:

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

Opt('GUIOnEventMode', 1)

#Region - Variable setup
Global $iSizerHeight = 5
Global $iSizerTopLimit = 40
Global $iSizerBottomLimit = 35 + 20

;~ NOT Constants - These need to be changeable
Global $IGNORE_WM_MOVE = False
Global $IGNORE_WM_PAINT = False
#EndRegion - Variable setup

#Region - GUI construction
$gui_Main = GUICreate('Seperator Drag Control', 400, 300, -1, -1, $WS_OVERLAPPEDWINDOW, BitOR($WS_EX_ACCEPTFILES, $WS_EX_COMPOSITED))
GUISetOnEvent($GUI_EVENT_CLOSE, '_Generic')

$lb_ContentFrame = GUICtrlCreateLabel('ContentFrame', 0, 0, 400, 180, $SS_SUNKEN)
GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)
GUICtrlSetState(-1, $GUI_HIDE)

$lb_SizerFrame = GUICtrlCreateLabel('SizerFrame', 0, 180, 400, $iSizerHeight, $SS_SUNKEN)
GUICtrlSetResizing(-1, $GUI_DOCKSTATEBAR + $GUI_DOCKRIGHT + $GUI_DOCKLEFT)
GUICtrlSetState(-1, $GUI_HIDE)

$lb_ConsoleFrame = GUICtrlCreateLabel('ConsoleFrame', 0, 185, 400, 95, $SS_SUNKEN)
GUICtrlSetResizing(-1, $GUI_DOCKSTATEBAR + $GUI_DOCKRIGHT + $GUI_DOCKLEFT)
GUICtrlSetState(-1, $GUI_HIDE)

$lb_Status = GUICtrlCreateLabel('', 0, 280, 400, 20, BitOR($SS_CENTERIMAGE, $SS_SUNKEN))
GUICtrlSetResizing(-1, $GUI_DOCKSTATEBAR + $GUI_DOCKRIGHT + $GUI_DOCKLEFT)
#EndRegion - GUI construction

#Region - Sub Frames
$gui_Content = GUICreate('ContentFrameWin', 1, 1, 0, 0, $WS_CHILD, Default, $gui_Main)
GUISetOnEvent($GUI_EVENT_CLOSE, '_Generic')
GUISetOnEvent($GUI_EVENT_DROPPED, '_Generic')
$ed_Content = GUICtrlCreateEdit('', 0, 0, 1, 1)
GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)
GUISetState()

$gui_Sizer = GUICreate('SizerFrameWin', 400, $iSizerHeight, 0, 180, $WS_CHILD, Default, $gui_Main)
GUISetCursor(11, 1)
GUICtrlCreateLabel('', -5, 0, 410, $iSizerHeight, Default, $GUI_WS_EX_PARENTDRAG)
GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)
GUISetState()

$gui_Console = GUICreate('ConsoleFrameWin', 400, 90, 0, 190, $WS_CHILD, Default, $gui_Main)
GUISetOnEvent($GUI_EVENT_CLOSE, '_Generic')
$ed_Console = GUICtrlCreateEdit('', 0, 0, 400, 90)
GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)
GUISetState()
#EndRegion - Sub Frames

GUIRegisterMsg($WM_SIZE, 'WM_SIZE')
GUIRegisterMsg($WM_MOVE, 'WM_MOVE')
GUIRegisterMsg($WM_PAINT, 'WM_PAINT')

GUISetState(@SW_SHOW, $gui_Main)

While 1
	Sleep(100)
WEnd

;~ GUI Functions -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=>

Func _Generic()
	Switch @GUI_CtrlId
		Case $GUI_EVENT_CLOSE
			Exit 2
	EndSwitch
EndFunc

;~ Functions -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=>

Func _WinPosFromControl($hCtrlWnd, $iCtrl, $hMoveWnd)
	Local $aControl = ControlGetPos($hCtrlWnd, '', $iCtrl)
	WinMove($hMoveWnd, '', $aControl[0], $aControl[1], $aControl[2], $aControl[3])
EndFunc

;~ Window Message Functions -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=> -=>

Func WM_SIZE($hWnd, $iMsg, $iWParam, $iLParam)
	If $hWnd = $gui_Main Then
		If Not BitAND(WinGetState($gui_Main), 16 + 32) Then
			$aSaveWinPos = WinGetPos($gui_Main)
		EndIf
	EndIf
	
	Return $GUI_RUNDEFMSG
EndFunc

Func WM_MOVE($hWnd, $iMsg, $iWParam, $iLParam)
	If $IGNORE_WM_MOVE Then Return $GUI_RUNDEFMSG
	
	If $hWnd = $gui_Main Then
		If Not BitAND(WinGetState($gui_Main), 16 + 32) Then
			$aSaveWinPos = WinGetPos($gui_Main)
		EndIf
	ElseIf $hWnd = $gui_Sizer Then
		$aClient = WinGetClientSize($gui_Main)
		$iYPos = BitShift($iLParam, 16)
		$iTopEdge = $iSizerTopLimit
		$iBottomEdge = $aClient[1] - $iSizerBottomLimit - 10 ; -10 to account for the height of the sizebar
		If $iYPos <= $iTopEdge Then $iYPos = $iTopEdge
		If $iYPos >= $iBottomEdge Then $iYPos = $iBottomEdge
		
		WinMove($gui_Sizer, '', 0, $iYPos, $aClient[0], $iSizerHeight)
		GUICtrlSetPos($lb_SizerFrame, 0, $iYPos, $aClient[0], $iSizerHeight)
		GUICtrlSetPos($lb_ContentFrame, 0, 0, $aClient[0], $iYPos)
		GUICtrlSetPos($lb_ConsoleFrame, 0, $iYPos + $iSizerHeight, $aClient[0], $aClient[1] - 20 - $iSizerHeight - $iYPos)
	EndIf
EndFunc

Func WM_PAINT($hWnd = 0, $iMsg = 0)
	If $IGNORE_WM_PAINT Then Return $GUI_RUNDEFMSG
	
	If $hWnd = $gui_Main Then
		_WinPosFromControl($gui_Main, $lb_ContentFrame, $gui_Content)
		_WinPosFromControl($gui_Main, $lb_SizerFrame, $gui_Sizer)
		_WinPosFromControl($gui_Main, $lb_ConsoleFrame, $gui_Console)
	EndIf
EndFunc
 
Автор
Pelerin

Pelerin

Осваивающий
Сообщения
81
Репутация
23
CreatoR
Вот более корректный пример разделителя:
Да интересно... Я так и думал что надо использовать фреймы, но мне казалось где-то есть для этого специальная функция... А вот GUICreate() внутри GUICreate()... теперь буду знать.

Вообще то UDF обычно строятся с родных функций AutoIt
А я и не против ;) Просто зачем нужна UDF если есть родная функция?

А нельзя было просто написать, что нужен разделитель между элементами?
Наверно можно было, но я не знал как :smile: Кстати тему которую далAZJIO я тоже видел, но не понял о чем там речь идет :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Pelerin [?]
Просто зачем нужна UDF если есть родная функция?
Где есть родная функция? там целый огород у тебя в примере, а это было бы проще если была бы UDF (которя кстати есть где то на офф. форуме).
 
Верх