Что нового

Добавить кнопку в TitleBar

w3d

Новичок
Сообщения
84
Репутация
3
Можно ли добавить собственную кнопку к кнопкам "Минимизировать", "Свернуть", "Закрыть"?
Ну и соответственно повесить на нажатие ее какую-либо процедуру?
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
Мне удалось найти пример для Delphi, но адаптировать под AutoIt не хватает опыта...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
snoitaleR сказал(а):
Мне удалось найти пример для Delphi, но адаптировать под AutoIt не хватает опыта...

Это не будет работать со стилями Windows. Точнее будет, но выглядеть будет как при Windows Classic.

:(
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
Yashied
Я понял - искусственная кнопка...
Надо искать более низкоуровневые методы...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
Самый простой способ - сделать свой скин и наставить туда сколько угодно кнопок. :smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
622
Yashied сказал(а):
Самый простой способ - сделать свой скин и наставить туда сколько угодно кнопок. :smile:
а не подскажешь, как это сделать? создать окно в стиле POPUP? и начать оформлять?
просто мне тоже нативный вид Windows-окон не очень по душе
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
Вот пример (не мой).

Так же можно использовать GUICtrlSetOnHover библиотеку от CreatoR'а. :smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
622
да. именно так я и думал. окно без рамки с возможность сдвига по контролам :smile:
спасибо за пример, очень содежательный
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,665
Репутация
2,463
Yashied [?]
И ещё один, использующий слежение за кнопкой :smile:

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

$hGUI = GUICreate("                             Custom Caption button", 350, 200)

$hButton_GUI = GUICreate("", 65, 18, -1, -1, $WS_POPUP, -1, $hGUI)
$nMyButton = GUICtrlCreateButton("Minimize v2", 0, 0, 65, 18)

GUIRegisterMsg($WM_MOVE, "WM_MOVE")

_GUIButtonSetPos_Proc()

GUISetState(@SW_SHOW, $hButton_GUI)
GUISetState(@SW_SHOW, $hGUI)

While 1
	$nMsg = GUIGetMsg()
	
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nMyButton
			WinSetState($hGUI, "", @SW_MINIMIZE)
	EndSwitch
WEnd

Func WM_MOVE($hWndGUI, $iMsg, $wParam, $lParam)
	;Local $iX = BitAND($lParam, 0xFFF)
	;Local $iY = BitShift($lParam, 16)
	
	_GUIButtonSetPos_Proc()
EndFunc

Func _GUIButtonSetPos_Proc()
	Local $aGUIPos = WinGetPos($hGUI)
	Local $aGUIClientSize = WinGetClientSize($hGUI)
	
	Local $iX = $aGUIPos[0]
	Local $iY = $aGUIPos[1]
	
	Local $iBorder_Size = ($aGUIPos[2] - $aGUIClientSize[0]) / 2
	
	WinMove($hButton_GUI, "", $iX+25, $iY+$iBorder_Size)
EndFunc
 
Автор
W

w3d

Новичок
Сообщения
84
Репутация
3
Вообще, я имел в виду положить кнопку на совершенно постороннее окно, не AutoIT-овское.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
622
w3d сказал(а):
Вообще, я имел в виду положить кнопку на совершенно постороннее окно, не AutoIT-овское.
прости, просто мой хрустальный шар подвел меня. не сразу понял что окно не AutoIt- овское :laugh:
 
Автор
W

w3d

Новичок
Сообщения
84
Репутация
3
Перефразирую вопрос.
У меня есть $hWnd окна (не AutoIT-овского).
Можно ли в титлебаре нарисовать кнопку и привязать к ней какое-нить действие?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
622
грубо говоря, можно. но через известное место :shifty:
и то набор функций будет небогатым.
сворачивание, разворачивание окна, закрытие, заполнение полей, вычисление к.л. атрибутов, и пр.
принцип примерно таков, создаешь маленькое гуи с кнопкой, ставишь ее в уровень заголовке в нужном месте, привязываешь к ней функцию и пишешь еще одну ф-ю которая будет сохранять положение этого гуи относительно нужного тебе окна - чтобы всегда оставалась в заголовке по мере движения окна. вобщем, это того не стоит.
ну может и другие способы есть ;)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,665
Репутация
2,463
Kaster [?]
принцип примерно таков
Я этот принцип показал на примере выше, но со своим окном.

Вот пример для чужого окна:

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

Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)
Opt("WinWaitDelay", 0)

Run(@WindowsDir & "\Notepad.exe")
WinWait("[CLASS:Notepad]")

$hParent = WinGetHandle("[CLASS:Notepad]")

$hButton_GUI = GUICreate("", 65, 18, -1, -1, $WS_POPUP, -1, $hParent)
$nMyButton = GUICtrlCreateButton("Button", 0, 0, 65, 18)
GUICtrlSetOnEvent(-1, "_Button_Event")

GUISetState(@SW_SHOW, $hButton_GUI)

$aOld_ParentPos = -1

While 1
	$aParentPos = WinGetPos($hParent)
	$aParentClientSize = WinGetClientSize($hParent)
	
	If Not IsArray($aParentPos) Then Exit
	
	If $aOld_ParentPos = -1 Or $aOld_ParentPos[0] <> $aParentPos[0] Or $aOld_ParentPos[1] <> $aParentPos[1] Then
		$aOld_ParentPos = $aParentPos
		
		$iX = $aParentPos[0]
		$iY = $aParentPos[1]
		
		$iBorder_Size = ($aParentPos[2] - $aParentClientSize[0]) / 2
		WinMove($hButton_GUI, "", ($iX + $aParentPos[2]) - 170, $iY + $iBorder_Size)
	Else
		Sleep(1)
	EndIf
WEnd

Func _Button_Event()
	ConsoleWrite("Button clicked" & @CRLF)
	Exit
EndFunc
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
622
CreatoR сказал(а):
Я этот принцип показал на примере выше, но со своим окном.
Pardon moi, Monsieur. Ни коим образом не посягал на ваш копирайт :beer:
 
Автор
W

w3d

Новичок
Сообщения
84
Репутация
3
CreatoR сказал(а):
Kaster [?]
принцип примерно таков
Я этот принцип показал на примере выше, но со своим окном.

Вот пример для чужого окна:

Великолепно!
А как можно определить высоту заголовка окна и какие стандартные кнопки на нем есть, чтобы разместить свою кнопку (например, размером 18х18) вплотную к ним?

И чтобы при нажатии на кнопку вываливалось меню из пары-тройки пунктов... :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,665
Репутация
2,463
w3d [?]
как можно определить высоту заголовка окна
Я это определяю в примере, используется общая высота окна минус высота его клиентской части.

какие стандартные кнопки на нем есть, чтобы разместить свою кнопку (например, размером 18х18) вплотную к ним?
Вот это уже посложнее, я сам пока над колдую.


тобы при нажатии на кнопку вываливалось меню из пары-тройки пунктов
Это проще:

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

Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)
Opt("WinWaitDelay", 0)

Run(@WindowsDir & "\Notepad.exe")
WinWait("[CLASS:Notepad]")

$hParent = WinGetHandle("[CLASS:Notepad]")

$hButton_GUI = GUICreate("", 65, 18, -1, -1, $WS_POPUP, -1, $hParent)
$nButton = GUICtrlCreateButton("Button", 0, 0, 65, 18)
GUICtrlSetOnEvent(-1, "_Button_Event")

$DummyMenu = GUICtrlCreateDummy()
$ContextMenu = GUICtrlCreateContextMenu($DummyMenu)
$MenuItem1 = GUICtrlCreateMenuItem("Some Item1", $ContextMenu)
$MenuItem2 = GUICtrlCreateMenuItem("Some Item2", $ContextMenu)
$MenuItem3 = GUICtrlCreateMenuItem("Some Item3", $ContextMenu)
GUICtrlCreateMenuItem("", $ContextMenu)
$Exit_Item = GUICtrlCreateMenuItem("Exit", $ContextMenu)
GUICtrlSetOnEvent(-1, "_Exit")

GUISetState(@SW_SHOW, $hButton_GUI)

$aOld_ParentPos = -1

While 1
    $aParentPos = WinGetPos($hParent)
    $aParentClientSize = WinGetClientSize($hParent)
    
    If Not IsArray($aParentPos) Then Exit
    
    If $aOld_ParentPos = -1 Or $aOld_ParentPos[0] <> $aParentPos[0] Or $aOld_ParentPos[1] <> $aParentPos[1] Or _
		$aOld_ParentPos[2] <> $aParentPos[2] Or $aOld_ParentPos[3] <> $aParentPos[3] Then
        
		$aOld_ParentPos = $aParentPos
		
        $iBorder_Size = ($aParentPos[2] - $aParentClientSize[0]) / 2
		
        $iX = ($aParentPos[0] + $aParentPos[2]) - 170
        $iY = $aParentPos[1] + $iBorder_Size
        
		If $aParentPos[2] < 170 Then $iX = $aParentPos[0] + $iBorder_Size
		
		WinMove($hButton_GUI, "", $iX, $iY)
    Else
        Sleep(1)
    EndIf
WEnd

Func _Button_Event()
	ConsoleWrite("Button clicked" & @CRLF)
	
	_GUICtrlMenu_Show($hButton_GUI, $ContextMenu, $nButton)
EndFunc

Func _GUICtrlMenu_Show($hWnd, $nContextID, $nContextControlID, $iMouse=0)
	Local $hMenu = GUICtrlGetHandle($nContextID)
    Local $iCtrlPos = ControlGetPos($hWnd, "", $nContextControlID)
	
	Local $iX = $iCtrlPos[0]
	Local $iY = $iCtrlPos[1] + $iCtrlPos[3]
	
	; Convert the client (GUI) coordinates to screen (desktop) coordinates
	;ClientToScreen
	Local $stPoint = DllStructCreate("int;int")
    
    DllStructSetData($stPoint, 1, $iX)
    DllStructSetData($stPoint, 2, $iY)

    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
    
    $iX = DllStructGetData($stPoint, 1)
    $iY = DllStructGetData($stPoint, 2)
	;ClientToScreen
	
	If $iMouse Then
		$iX = MouseGetPos(0)
		$iY = MouseGetPos(1)
	EndIf
	
	DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $iX, "int", $iY, "hwnd", $hWnd, "ptr", 0)
EndFunc

Func _Exit()
	Exit
EndFunc


Также в этом примере поправил проблему с не перемещением кнопки при изменений размера окна.

P.S
Кстати можно своё меню внедрить во внешнее приложение. Upd: Хм, внедрить то можно, а вот поставить обработчик событии вставленных пунктов, задача не из простых, у меня не получилось :(
 
Автор
W

w3d

Новичок
Сообщения
84
Репутация
3
Пробую в основном цикле программы отловить появление окна, чтобы нарисовать на нем кнопку:

Код:
If WinActive("Form1") Then
		$hGUI_Map  = WinGetHandle("Form1")
		_CreateButton()
	EndIf

Func _CreateButton()

	Opt("GUIOnEventMode", 1)
	Opt("WinWaitDelay", 0)
	$hButton_GUI = GUICreate("", 65, 18, -1, -1, $WS_POPUP, -1, $hGUI_Map)
	$nButton = GUICtrlCreateButton("Button", 0, 0, 65, 18)
	GUICtrlSetOnEvent(-1, "_Button_Event")
	GUISetState(@SW_SHOW, $hButton_GUI)

	$aOld_ParentPos = -1

	$aParentPos = WinGetPos($hGUI_Map)
    $aParentClientSize = WinGetClientSize($hGUI_Map)

    If Not IsArray($aParentPos) Then Exit

    If $aOld_ParentPos = -1 Or $aOld_ParentPos[0] <> $aParentPos[0] Or $aOld_ParentPos[1] <> $aParentPos[1] Or _
        $aOld_ParentPos[2] <> $aParentPos[2] Or $aOld_ParentPos[3] <> $aParentPos[3] Then

        $aOld_ParentPos = $aParentPos

        $iBorder_Size = ($aParentPos[2] - $aParentClientSize[0]) / 2

        $iX = ($aParentPos[0] + $aParentPos[2]) - 170
        $iY = $aParentPos[1] + $iBorder_Size

        If $aParentPos[2] < 170 Then $iX = $aParentPos[0] + $iBorder_Size

        WinMove($hButton_GUI, "", $iX, $iY)
    Else
        Sleep(1)
    EndIf

EndFunc

Func _Button_Event()
    ConsoleWrite("Button clicked" & @CRLF)
    ;_GUICtrlMenu_Show($hButton_GUI, $ContextMenu, $nButton)
EndFunc


в результате, если таскаю появившееся окно по экрану - остаются нарисованные кнопки в разных местах :(
 

CreatoR

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

Код:
#include <WindowsConstants.au3>

Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)
Opt("WinWaitDelay", 0)

Global $hButton_GUI, $nButton, $ContextMenu
Global $MenuItem1, $MenuItem2, $MenuItem3, $Exit_MenuItem
Global $aOld_ParentPos = -1, $hParent, $hOld_Parent

Global $sMain_Title = "[CLASS:Notepad]"

Run(@WindowsDir & "\Notepad.exe")
WinWait($sMain_Title)
$hParent = WinGetHandle($sMain_Title)

_ExternalButtonCreate_Proc()
AdlibEnable("_ExternalButtonFollow_Proc", 1)

While 1
    Sleep(100)
WEnd

Func _ExternalButtonCreate_Proc()
	$hButton_GUI = GUICreate("", 65, 18, -1, -1, $WS_POPUP, $WS_EX_TOPMOST+$WS_EX_TOOLWINDOW)
	$nButton = GUICtrlCreateButton("Button", 0, 0, 65, 18)
	GUICtrlSetOnEvent(-1, "_Button_Event")
	
	Local $DummyMenu = GUICtrlCreateDummy()
	$ContextMenu = GUICtrlCreateContextMenu($DummyMenu)
	$MenuItem1 = GUICtrlCreateMenuItem("Some Item1", $ContextMenu)
	$MenuItem2 = GUICtrlCreateMenuItem("Some Item2", $ContextMenu)
	$MenuItem3 = GUICtrlCreateMenuItem("Some Item3", $ContextMenu)
	GUICtrlCreateMenuItem("", $ContextMenu)
	$Exit_MenuItem = GUICtrlCreateMenuItem("Exit", $ContextMenu)
	GUICtrlSetOnEvent(-1, "_Exit")
	
	GUISetState(@SW_SHOW, $hButton_GUI)
EndFunc

Func _ExternalButtonFollow_Proc()
	If $hParent <> -1 And Not WinExists($hParent) Then
		GUISetState(@SW_HIDE, $hButton_GUI)
		$hParent = -1
	ElseIf $hParent = -1 And WinExists($sMain_Title) Then
		GUISetState(@SW_SHOW, $hButton_GUI)
		$hParent = WinGetHandle($sMain_Title)
	ElseIf $hParent = -1 Then
		Return
	EndIf
	
	$aParentPos = WinGetPos($hParent)
    $aParentClientSize = WinGetClientSize($hParent)
	
	If Not IsArray($aParentPos) Then Return
	
	If Not WinActive($hParent) And Not WinActive($hButton_GUI) Then
		$aParentPos[0] = -3200
		$aParentPos[1] = -3200
	EndIf
	
    If $aOld_ParentPos = -1 Or $aOld_ParentPos[0] <> $aParentPos[0] Or $aOld_ParentPos[1] <> $aParentPos[1] Or _
		$aOld_ParentPos[2] <> $aParentPos[2] Then
        
		$aOld_ParentPos = $aParentPos
		
        $iBorder_Size = ($aParentPos[2] - $aParentClientSize[0]) / 2
		
        $iX = ($aParentPos[0] + $aParentPos[2]) - 170
        $iY = $aParentPos[1] + $iBorder_Size
        
		If $aParentPos[2] < 170 Then $iX = $aParentPos[0] + $iBorder_Size
		
		WinMove($hButton_GUI, "", $iX, $iY)
    EndIf
EndFunc

Func _Button_Event()
	ConsoleWrite("Button clicked" & @CRLF)
	
	_GUICtrlMenu_Show($hButton_GUI, $ContextMenu, $nButton)
EndFunc

Func _GUICtrlMenu_Show($hWnd, $nContextID, $nContextControlID, $iMouse=0)
	Local $hMenu = GUICtrlGetHandle($nContextID)
    Local $iCtrlPos = ControlGetPos($hWnd, "", $nContextControlID)
	
	Local $iX = $iCtrlPos[0]
	Local $iY = $iCtrlPos[1] + $iCtrlPos[3]
	
	; Convert the client (GUI) coordinates to screen (desktop) coordinates
	;ClientToScreen
	Local $stPoint = DllStructCreate("int;int")
    
    DllStructSetData($stPoint, 1, $iX)
    DllStructSetData($stPoint, 2, $iY)

    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
    
    $iX = DllStructGetData($stPoint, 1)
    $iY = DllStructGetData($stPoint, 2)
	;ClientToScreen
	
	If $iMouse Then
		$iX = MouseGetPos(0)
		$iY = MouseGetPos(1)
	EndIf
	
	DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $iX, "int", $iY, "hwnd", $hWnd, "ptr", 0)
EndFunc

Func _Exit()
	Exit
EndFunc
 
Автор
W

w3d

Новичок
Сообщения
84
Репутация
3
Ага, только тут
Код:
Func _ExternalButtonCreate_Proc()
   ....
    GUISetState(@SW_SHOW, $hButton_GUI)
EndFunc

Надо
Код:
GUISetState(@SW_HIDE, $hButton_GUI)

иначе созданная кнопка остается висеть посреди экрана в ожидании запуска программы куда ее надо поставить :smile:
 
Верх