Что нового

GUIFloatPanel - Создание плавающей панели над элементами GUI

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
Версия AutoIt
3.3.14.5
Версия
0.2
Библиотека GUIFloatPanel позволяет создавать плавающие панели над указанными элементами GUI.

Зарождение идеи для библиотеки тут.

Отличающиеся возможности:
* Может работать с внешними элементами и окнами (т.е можно назначать на элементы созданные с помощью _GUICtrl*_Create, и даже создавать панель на сторонних окнах).
* Построение меню для кнопки панели из указанной строки (см. описание к функции _GUICtrlFloatPanel_AddButton).
* Появление панели при наведении над указанными элементами.
* Появление панели при навигации с помощью TAB (не совместимо с флагом $FLOATPANEL_POPUPONHOVER).

Пример:
Код:
#include <GUIFloatPanel.au3>
#include <GUIEdit.au3>

$hGUI = GUICreate('GUIFloatPanel Example', 300, 200)

$iInput1 = GUICtrlCreateInput('', 20, 20, 200, 20)
$iInput2 = GUICtrlCreateInput('', 20, 50, 200, 20)
$hEdit = _GUICtrlEdit_Create($hGUI, 'Handle control', 20, 80, 200, 40)
$iLabel = GUICtrlCreateLabel('Label', 80, 140, 80, 20)

Dim $aInputs[2] = [$iInput1, $iInput2]
$hFloatPanel = _GUICtrlFloatPanel_Create($hGUI, $aInputs, 0xEBE8AB, 'Header', BitOR($FLOATPANEL_HEADER, $FLOATPANEL_POSTOPLEFT))
_GUICtrlFloatPanel_AddButton($hFloatPanel, 'shell32.dll', -29, _CustomMenu_Proc, 'Custom menu', True)
_GUICtrlFloatPanel_AddButton($hFloatPanel, 'shell32.dll', -40, _Menu_Proc, 'Menu from string', False, 'Func: _FncMsg;Calc: 1+9;Exec: cmd.exe;[MENU:Menu]{Menu Item1|[MENU:SubMenu]{SubMenu Item1|SubMenu Item2}}')
_GUICtrlFloatPanel_AddButton($hFloatPanel, '') ;Separator
_GUICtrlFloatPanel_AddButton($hFloatPanel, 'shell32.dll', -44, '', 'Dummy')

$hFloatPanel2 = _GUICtrlFloatPanel_Create($hGUI, $hEdit, -1, '', BitOR($FLOATPANEL_POSBOTTOMLEFT, $FLOATPANEL_POPUPONHOVER))
_GUICtrlFloatPanel_AssignCtrls($hFloatPanel2, $iLabel)
_GUICtrlFloatPanel_AddButton($hFloatPanel2, 'shell32.dll', -233, _OpenMyComp_Proc, 'My Computer')
_GUICtrlFloatPanel_AddButton($hFloatPanel2, '') ;Separator
_GUICtrlFloatPanel_AddButton($hFloatPanel2, 'shell32.dll', -5, _SelFolder_Proc, 'Select Folder')

GUISetState(@SW_SHOW, $hGUI)

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

Func _CustomMenu_Proc($hFloatPanel, $iBttnID, $iCtrlID)
    Local $iContextMenu = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
    Local $iCalc_MItem = GUICtrlCreateMenuItem('Calc', $iContextMenu)
    Local $iMsg_MItem = GUICtrlCreateMenuItem('Message', $iContextMenu)
    
    Local $hParent = _GUICtrlFloatPanel_GetParent($hFloatPanel)
    Local $iItem = _GUICtrlFloatPanel_ShowMenu($hFloatPanel, $iContextMenu, $iBttnID, True)
    
    Switch $iItem
        Case $iCalc_MItem
            Local $sInput = InputBox('Input', 'Calc:', '5 + 5', '', -1, -1, Default, Default, 0, $hParent)
            
            If @error Then
                Return $FLOATPANEL_RETNOHIDE
            EndIf
            
            ControlSetText($hParent, '', $iCtrlID, '=' & Execute($sInput))
        Case $iMsg_MItem
            MsgBox(64, @ScriptName, 'Ok', 0, $hParent)
        Case Else
            Return $FLOATPANEL_RETNOHIDE
    EndSwitch
    
    Return $FLOATPANEL_RETHIDE
EndFunc

Func _Menu_Proc($hFloatPanel, $iMenuItemID, $iCtrlID)
    Local $hParent = _GUICtrlFloatPanel_GetParent($hFloatPanel)
    Local $sItem = GUICtrlRead($iMenuItemID, 1)
    Local $sAction = StringRegExpReplace($sItem, '^(\w+):\h*.*', '\1')
    Local $sParam = StringRegExpReplace($sItem, '^\w+:\h*(.*)', '\1')
    
    Switch $sAction
        Case 'Func'
            $sItem = 'Return: ' & Call($sParam, $hParent)
        Case 'Calc'
            $sItem = '=' & Execute($sParam)
        Case 'Exec'
            $sItem = 'PID: ' & ShellExecute($sParam)
    EndSwitch
    
    ControlSetText($hParent, '', $iCtrlID, $sItem)
EndFunc

Func _FncMsg($hParent)
    Return Int(MsgBox(36, @ScriptName, 'Hello i am a message, ok?', 0, $hParent) = 6)
EndFunc

Func _OpenMyComp_Proc($hFloatPanel, $iBttnID, $iCtrlID)
    ShellExecute('::{20D04FE0-3AEA-1069-A2D8-08002B30309D}')
    Return $FLOATPANEL_RETHIDE
EndFunc

Func _SelFolder_Proc($hFloatPanel, $iBttnID, $iCtrlID)
    Local $hParent = _GUICtrlFloatPanel_GetParent($hFloatPanel)
    Local $sSel = FileSelectFolder('Select', '', 0, '', $hParent)
    
    If Not @error Then
        ControlSetText($hParent, '', $iCtrlID, $sSel)
        Return $FLOATPANEL_RETHIDE
    EndIf
    
    Return $FLOATPANEL_RETNOHIDE
EndFunc
 
Автор
G.Sandler
Источник
Ссылка на источник

Вложения

Последнее редактирование:

joiner

Модератор
Локальный модератор
Сообщения
3 254
Репутация
552
жаль, что на ранних версиях не работает.
использую версию 3.3.12.0
Ошибок не выдает, но панель пустая(смотри скрин)
Попутно использую бета версию, там все работает\
Кстати, при наведении на Edit и Label появляются две иконки, но кликнуть на них нельзя. К чему это сделано?
 

Вложения

Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
жаль, что на ранних версиях не работает.
Было бы жаль если бы не работала на поздних версиях )).

использую версию 3.3.12.0
А разрабатывалось под 3.3.14.5, пора обновляться :blum: .

при наведении на Edit и Label появляются две иконки, но кликнуть на них нельзя. К чему это сделано?
Кликнуть можно, нужно их успеть словить. Это из за флага $FLOATPANEL_TRANSPARENT или $FLOATPANEL_POPUPONHOVER, и об этом написано в описании к функции.
Возможно он лишний, позже посмотрю как можно оставлять панель "в действий" пока мышка находится в пределах панели (с учётом что она невидима).
 
Последнее редактирование:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
В 3.3.12.0 есть какая то проблема с WinMove:

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

$hParent = GUICreate('')
GUISetState()

$hGUI = GUICreate('Test Script', 1, 18, -1, -1, $WS_POPUP, $WS_EX_MDICHILD, $hParent)

$iButton1 = GUICtrlCreateIcon('shell32.dll', -5, 1, 1, 16, 16)
WinMove($hGUI, '', Default, Default, 16, 18)

$iButton2 = GUICtrlCreateIcon('shell32.dll', -6, 17, 1, 16, 16)
WinMove($hGUI, '', Default, Default, 38, 18)

GUISetState(@SW_SHOW, $hGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
Нашёл какой то странный баг-прикол...
Если запускать пример из SciTE, то всё ок, а если из проводника то в некоторых случаях не видно элементов у панели которая показывается при наведении.
 

liond66

Новичок
Сообщения
94
Репутация
1
Мне кажется неудобной логика использования (или я чего то не понимаю).
Скажем я планирую 2 вида меню. Создаю их заранее 1 раз.
Далее у меня в ходе разработки программы появляются 50-100 элементов ввода.
Я предполагаю после создания каждого (отдельного) элемента привязывать к нему меню.
Здесь же строится меню и подставляется имя поля ввода.
Значит мне придётся создавать меню и кнопки 50-100 раз?
Наверно можно при создании меню дать пустышку (dummy) как элемент, а потом через AssignCtrls привязывать к настоящим элементам?
Я бы хотел создание меню функцией, отдельной от создания GUI с элементами.
 
Последнее редактирование:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
Логика простая.
1. Создаётся панель которой назначаются элементы
2. Создаётся кнопка с вызовом функции.
3. Задаются отдельно элементы определённым панелям.

Я предполагаю после создания каждого (отдельного) элемента привязывать к нему меню.
А при чём тут меню, речь шла о всплывающей панели с кнопками, и меню уже для них.

Здесь же строится меню и подставляется имя поля ввода.
Где здесь?
Это пример, можно что угодно сделать.

мне придётся создавать меню и кнопки 50-100 раз?
Меню можно один раз создать:

Код:
#include <GUIFloatPanel.au3>

Global $iContextMenu, $iMItem1, $iMItem2

$hGUI = GUICreate('GUIFloatPanel Example', 300, 200)

_CreateMenu()
$iInput1 = GUICtrlCreateInput('', 20, 20, 200, 20)

$hFloatPanel = _GUICtrlFloatPanel_Create($hGUI, $iInput1)
_GUICtrlFloatPanel_AddButton($hFloatPanel, 'shell32.dll', -29, _Proc, 'Menu', True)

GUISetState(@SW_SHOW, $hGUI)

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

Func _Proc($hFloatPanel, $iBttnID, $iCtrlID)
    Local $iItem = _GUICtrlFloatPanel_ShowMenu($hFloatPanel, $iContextMenu, $iBttnID, True)
    
    Switch $iItem
        Case $iMItem1, $iMItem2
            GUICtrlSetData($iCtrlID, Execute(GUICtrlRead($iItem, 1)))
    EndSwitch
    
    Return $FLOATPANEL_RETHIDE
EndFunc

Func _CreateMenu()
    $iContextMenu = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
    $iMItem1 = GUICtrlCreateMenuItem('2+3', $iContextMenu)
    $iMItem2 = GUICtrlCreateMenuItem('4+6', $iContextMenu)
EndFunc
 

liond66

Новичок
Сообщения
94
Репутация
1
А при чём тут меню, речь шла о всплывающей панели с кнопками, и меню уже для них.
Ну это я и имел ввиду: панель+кнопки+меню.

1. Создаётся панель которой назначаются элементы
По моему получилось как раз наоборот: сначала элемент, а затем панель.
Этот порядок, по моей логике, и является проблемой.
Пока нет поля ввода, я не могу создать панель и создать кнопки.
Представьте программу у которой 50 дочерних окон с несколькими полями (число разное).
Значит нужно несколько сот раз (на каждое поле) создавать панель и кнопки.
Избыточность кода. Я надеюсь, что можно по другому.
Нужно придумать как, по аналогии с последним примером (функция _CreateMenu), создать панель со всеми кнопками и меню через функцию, а присвоение одной строкой добавлять после создания поля.
Или даже вызывать функцию создания панели со списком полей, если конечно можно использовать непостоянное число аргументов (для разного количества полей).[/QUOTE][/QUOTE]
 
Последнее редактирование модератором:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
Пока нет поля ввода, я не могу создать панель и создать кнопки.
Что мешает?
Я понимаю что у библиотеки нет справки, но создавалась она на коленке, и я предполагал что тот кому она нужна, как минимум залезет в её описание внутри (у каждой используемой функции).

Код:
#include <GUIFloatPanel.au3>
#include <GUIEdit.au3>

$hGUI = GUICreate('GUIFloatPanel Example', 300, 200)

;Создание панели
$hFloatPanel = _GUICtrlFloatPanel_Create($hGUI, 0, 0xEBE8AB, 'Header', BitOR($FLOATPANEL_HEADER, $FLOATPANEL_POSTOPLEFT))
_GUICtrlFloatPanel_AddButton($hFloatPanel, 'shell32.dll', -29, _CustomMenu_Proc, 'Custom menu', True)
_GUICtrlFloatPanel_AddButton($hFloatPanel, 'shell32.dll', -40, _Menu_Proc, 'Menu from string', False, 'Func: _FncMsg;Calc: 1+9;Exec: cmd.exe;[MENU:Menu]{Menu Item1|[MENU:SubMenu]{SubMenu Item1|SubMenu Item2}}')
_GUICtrlFloatPanel_AddButton($hFloatPanel, '') ;Separator
_GUICtrlFloatPanel_AddButton($hFloatPanel, 'shell32.dll', -44, '', 'Dummy')

$iInput1 = GUICtrlCreateInput('', 20, 20, 200, 20)
$iInput2 = GUICtrlCreateInput('', 20, 50, 200, 20)

;Присвоение элементов к панели
Dim $aInputs[2] = [$iInput1, $iInput2]
_GUICtrlFloatPanel_AssignCtrls($hFloatPanel, $aInputs)

GUISetState(@SW_SHOW, $hGUI)

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


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

нужно несколько сот раз (на каждое поле) создавать панель и кнопки
Не нужно.
Вникни пожалуйста в суть работы библиотеки (каждой публичной функции), она сделана по аналогий с другими библиотеками такого характера.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
Если речь про то чтобы отвязать панель от GUI, то не думаю что это хорошая идея, все элементы так или иначе привязываются к определённому окну, и ничего страшного нет в том, чтобы у каждого окна была своя панель или набор панелей.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
Обновление:

v0.2
* Теперь функция _GUICtrlFloatPanel_AddButton при удачном выполнении возвращает ID добавленной кнопки.
+ Добавлена функция _GUICtrlFloatPanel_DeleteButton.
+ Добавлена функция_GUICtrlFloatPanel_UnAssignCtrls.
* Функция _GUICtrlFloatPanel_AddButton теперь также принимает в качестве параметра $hFunc название функции в виде строки.
* Исправлена проблема с отображением кнопок на панели.
* Улучшено позицианирование кнопок на панели.
* Уточнения в документации к функциям.
* Пример изменён.
 

liond66

Новичок
Сообщения
94
Репутация
1
Спасибо за пример, всё стало понятнее.
Я за то, чтобы отвязать панель от GUI на этапе создания.
Я создаю панель, создав функцию, с именем GUI в качестве аргумента.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
Я за то, чтобы отвязать панель от GUI на этапе создания.
Я посмотрю что можно сделать, для этого нужно изменить алгоритм обработки.
Я создаю панель, создав функцию, с именем GUI в качестве аргумента.
В функцию передаётся параметр $hFloatPanel, и с помощью _GUICtrlFloatPanel_GetParent можно получить дескриптор GUI.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 444
Репутация
2 393
В общем я пришёл к выводу что нет необходимости отвязывать панель от родительского GUI (да и слишком сложный обработчик получается), всё решается и так.
 

liond66

Новичок
Сообщения
94
Репутация
1
Да, всё и так нормально работает. Спасибо за Ваш проект.
 
Верх