Что нового

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Версия 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
Источник
Ссылка на источник

Вложения

  • GUIFloatPanel_0.1b.zip
    6.8 КБ · Просмотры: 15
  • GUIFloatPanel_0.2.zip
    7.7 КБ · Просмотры: 31
Последнее редактирование:

joiner

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

Вложения

  • Безымянный.jpg
    Безымянный.jpg
    22.5 КБ · Просмотры: 25
Автор
CreatoR

CreatoR

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

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

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
В 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,671
Репутация
2,481
Нашёл какой то странный баг-прикол...
Если запускать пример из SciTE, то всё ок, а если из проводника то в некоторых случаях не видно элементов у панели которая показывается при наведении.
 

liond66

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Логика простая.
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

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

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

CreatoR

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

Код:
#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,671
Репутация
2,481
Если речь про то чтобы отвязать панель от GUI, то не думаю что это хорошая идея, все элементы так или иначе привязываются к определённому окну, и ничего страшного нет в том, чтобы у каждого окна была своя панель или набор панелей.
 
Автор
CreatoR

CreatoR

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

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

liond66

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

CreatoR

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

CreatoR

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

liond66

Новичок
Сообщения
117
Репутация
2
Да, всё и так нормально работает. Спасибо за Ваш проект.
Сообщение автоматически объединено:

Здравствуйте.
Начал реально применять эту библиотеку и столкнулся с проблемой:
если в программе используется GUIRegisterMsg($WM_COMMAND (с элементом ввода, не имеющим плавающей панели),
когда я открываю через панель окно, частенько происходит полное зависание графического интерфейса с выходом из программы без сообщения.
Для примера прилагаю изменённый файл примера.
Я изменил меню Calc на вызов окна. При его вызове хотябы раз из десяти происходит зависание, или чаще.
Как это можно исправить?
Спасибо.
Сообщение автоматически объединено:

ув.CreatoR
Не могли бы Вы, как автор библиотеки, посмотреть в чём конфликт, и по возможности исправить?
И несколько вопросов:
1. можно ли создать под-меню в первом варианте меню: _CustomMenu_Proc
2. можно ли передать дополнительный параметер в функцию _CustomMenu_Proc при вызове?
Она получает 3 параметра через DLL. Как добавить четвёртый? Иногда нужно передать переменную родительского окна для выполнемия minimize.
Спасибо.
Сообщение автоматически объединено:

К сожалению обнаружил новый конфликт с функцией GetRegion.
Функция не моя, готовая с интернета.
Запустив файл GetRegion.au3 - протягиваем мышкой и видим прямоугольную зону, и координаты начала и конца выделения.
Файл "Example and GetRegion.au3" содержит оригинальный пример + функцию GetRegion.
При запуске этого примера после выбора кнопки GetRegion прямоугольная зона не обозначается и координаты конца зоны совпадают с координатами начала зоны выделения.
Что делать?
Сообщение автоматически объединено:

 

Вложения

  • ExampleChanged.au3
    5.2 КБ · Просмотры: 1
  • Example and GetRegion.au3
    8.8 КБ · Просмотры: 1
  • GetRegion.au3
    5.3 КБ · Просмотры: 1
Последнее редактирование:
Верх