Что нового

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

w3d

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

snoitaleR

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

Yashied

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

:(
 

snoitaleR

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

Yashied

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

kaster

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

Yashied

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

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

kaster

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 165
Репутация
2 329
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 165
Репутация
2 329
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 165
Репутация
2 329
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 165
Репутация
2 329
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:
 
Верх