Tricky (and bugie?) method:
#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