Close Thumbnail when cursor leaves client or menu area

Get help with using AutoHotkey and its commands and hotkeys
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Close Thumbnail when cursor leaves client or menu area

13 May 2017, 08:26

Hi!

Im trying to obtain a menu handle from a specific window using its handle and all this from an another script. Seans script uses
The #32768 is the classname of the (standard) menu window, meaning that the menu itself should be created to obtain via this method the menu handle of the context menu (:when out of scope, the menu window is simply destroyed). So, not much sense to control the context menus this way, IMHO.
In other words I cant use that, cuz it would trigger for every menu.
The app with the menu should be closed when mouse no longer hovers over the app. Meaning as is now the app closes when the menu pops up, cuz the window handle and menu handle is not the same. I would like to find a way for the mouse hover handler to accept menu popup without closing the entire window. The pop-up and close down is controlled from a separate script. Cant use more Onmmessage handlers in the "separate" script (cuz im already suffering from issues (involving Critical) due to the complexity of everything).

Seans script:

Code: Select all

#SingleInstance, Force
SetBatchLInes, -1
;WinGet, DVBV_ID, ID, dvbviewer_thumb
;msgbox % DVBV_ID
;WinWait, ahk_id #DVBV_ID
WinWait, ahk_class #32768
;SendMessage, OutputVar, 0, 0		; MN_GETHMENU
SendMessage, 0x1E1, 0, 0		; MN_GETHMENU
hMenu := ErrorLevel
msgbox % hMenu
sContents := GetMenu(hMenu)
WinWaitClose

MsgBox, % sContents


GetMenu(hMenu)
{
	Loop, % DllCall("GetMenuItemCount", "Uint", hMenu)
	{
		idx := A_Index - 1
		idn := DllCall("GetMenuItemID", "Uint", hMenu, "int", idx)
		nSize++ := DllCall("GetMenuString", "Uint", hMenu, "int", idx, "Uint", 0, "int", 0, "Uint", 0x400)
		VarSetCapacity(sString, nSize)
		DllCall("GetMenuString", "Uint", hMenu, "int", idx, "str", sString, "int", nSize, "Uint", 0x400)	;MF_BYPOSITION
		If !sString
		   sString := "---------------------------------------"
		sContents .= idx . " : " . idn . A_Tab . A_Tab . sString . "`n"
		If (idn = -1) && (hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", idx))
		   sContents .= GetMenu(hSubMenu)
	}
	Return	sContents
}
The small handler from the "separate" script:

Code: Select all

Hover_delay := 50 ; hover delay, from when the mouse stops moving
CoordMode, Mouse, Screen
SetTimer, Hovercheck, 10
Hovercheck:
MouseGetPos, x, y
if (x != lastx or y != lasty) {
 SetTimer, Hovering, -50   ;%Hover_delay%
 lastx := x
 lasty := y
}
Return
;--------------------------------------------------------------------------
Hovering:
MouseGetPos,,, Win

;If (Win != WinActive("dvbviewer_thumb"))
Tooltip % "Window= " Win "`n" WinExist("dvbviewer_thumb")
If (Win != WinExist("dvbviewer_thumb"))
  ;WinClose, dvbviewer_thumb
;SetTimer, Hovercheck, Off
;SetTimer, Hovering, Off   ;%Hover_delay%
Return
Last edited by zcooler on 28 May 2017, 13:04, edited 2 times in total.
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Obtain menu handle from its window handle

15 May 2017, 15:01

Ok, I did integrated the gui into the separate script and can now get the Menu handle and coordinates, but the popup GUI still closes when opening the menu and move cursor upon it. Hmm...this is humongously tricky :( I can retrieve handle, xpos, ypos for the menu, but how would one conditioning it?
Closedown should be done:
1. If cursor leaves main window popup (no menu shown) (working)
2. If menu pops up over main window popup avoid closedown as long as menu exists. Cursor should be abled to hover freely over main window popup and menu area without closedown (the menu can be quite big and have coordinates way bigger than the main window popup. (Not working)
3. It gets even trickier...the menu has tooltips which also may trigger a closedown, but dont hope so. (disabled them for now)

Updated handler:

Code: Select all

HovercheckDVBVThumb:
MouseGetPos, Dx, Dy
if (Dx != lastDx or Dy != lastDy) {
 SetTimer, HoveringDVBVThumb, -100  ; hover delay 50, from when the mouse stops moving
 lastDx := Dx
 lastDy := Dy
}
Return
; ----------------------------------------------------------------------------------------------------------------------
HoveringDVBVThumb:
MouseGetPos,,, WinDVBV

   VarSetCapacity(PT, 8, 0)
   DllCall("User32.dll\GetCursorPos", "Ptr", &PT)
   DllCall("User32.dll\ScreenToClient", "Ptr", HMENU, "Ptr", &PT)
   MX := NumGet(PT, 0, "Int")
   MY := NumGet(PT, 4, "Int")
   ;msgbox % "X= " MX "`nY= " MY
Tooltip % "Window= " WinDVBV "`n" WinExist("dvbviewer_thumb") "`n" HMENU "`nMX= " MX "`nMY= " MY "`nlastDx= " lastDx "`nlastDy= " lastDy
If ((WinDVBV != WinExist("dvbviewer_thumb")) And (MX != lastDx or MY != lastDy)) {
   SetTimer, HovercheckDVBVThumb, Off
   OnMessage(0x020A, "")
   SetTimer, MouseOverDVBViewerIMG, 100
   GoSub, DVBVThumb_Destroy
}
Return
; ----------------------------------------------------------------------------------------------------------------------
DVBVThumb_Destroy:
;WinClose, dvbviewer_thumb
Thumbnail_Destroy(hThumb1) 
Gui, DVBV: Destroy 
DVBVThumb_Shown := False
Return
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Mouse hover over window with menu

16 May 2017, 06:18

Made a script which is testable. Apparently Im not smart enough to figure this one out, have been spending days on it now without any big success, so please please can someone show me how it is supposed to be done.

Hover mouse over ok button launches the main popup. When mouse cursor leaves main popup coordinates it should and does close.
The tricky part begins when main popup has a menu (or toggle from windowed to fullscreen mode which is not implemented in this sample but involves main popup changes size and coordinates), cuz when rightclick to bring up the context menu and hover mouse over menu, main popup closes, which Im trying to avoid. How to get the hover handler to accept popups of the popup without closing the main popup? Hmm...sorry for my english, noobness in the area and general lack of ingenuity...hopefully it is understandable where Im going with this...

Code: Select all

Gui, Add, Text,, First name:
Gui, Add, Text,, Last name:
Gui, Add, Edit, vFirstName ym  ; The ym option starts a new column of controls.
Gui, Add, Edit, vLastName
Gui, Add, Button, default +hwndDVBVPIC, OK  ; The label ButtonOK (if it exists) will be run when the button is pressed.
Gui, Show,, Simple Input Example
SetTimer, MouseOverDVBViewerIMG, 100
return

MouseOverDVBViewerIMG:
Gui, Submit, NoHide
MouseGetPos,,,,HWND, 2
If (HWND = DVBVPIC) {
 ;for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process  where name = 'dvbviewer.exe' ")
  ; process, exist, % process.ProcessId
   ;If (ErrorLevel) {
     If (DVBVThumb_Shown)
         GoSub, DVBVThumb_Destroy
     SetTimer, DVBVThumb_Show, -1
	 SetTimer, MouseOverDVBViewerIMG, Off
	 Return
   ;}
   /*
   Else {       ; DVBViewer is not started we end up here
     AddTooltip(DVBVPIC , " " DVBViewer_Tooltip " ") 
	 SetTimer, MouseOverDVBViewerIMG, Off
	 Sleep, 8000
	 SetTimer, MouseOverDVBViewerIMG, 100
	 Return
   }
   */
}
Return

; ----------------------------------------------------------------------------------------------------------------------
DVBVThumb_Show(file:=0) {
  Global IDT_HTHUMB, HMENU, CHSwitchCom
 ;Gui, DVBV: Color, 000000
  Gui, DVBV: +LastFound +hwndhDestination1
  Gui, DVBV: +ToolWindow -AlwaysOnTop +E0x00040000 ;-Caption ;Forces a top-level window onto the taskbar when the window is visible. ; +E0x08000000 ; A top-level window created with this style does not become the foreground window when the user clicks it.   
  Gui, DVBV: Add, Text, x0 y0 w376 h251 gMouseClicks +hwndHTHUMB, TTTTTTTTTTTTTTTTTTTTT				; text with glabel
  FavArray := ["Channel1", "Channel2", "Channel3", "Channel4", "Channel5", "Channel6", "Channel7", "Channel8", "Channel9", "Channel10"
  , "Channel11", "Channel12", "Channel13", "Channel14", "Channel15", "Channel16", "Channel17", "Channel18", "Channel19", "Channel20"]
  Menu, DVBVContextMenu, Add
  Menu, DVBVContextMenu, DeleteAll
  For index, channel in FavArray {
	Menu, DVBVContextMenu, Add, %channel%, MenuHandler, +Radio
    Menu, DVBVContextMenu, ToggleCheck, %channel%
  } 
  HMENU := MenuGetHandle("DVBVContextMenu") + 0
  Gui, DVBV: Show, x550 y455 w376 h251, dvbviewer_thumb
  ;--------------------------
  DVBVThumb_Shown := True
  CoordMode, Mouse, Screen
  SetTimer, HovercheckDVBVThumb, 10
  Return
  ; ----------------------------------------------------------------------------------------------------------------------
  MouseClicks:
  If (A_Gui = "DVBV") && (A_GuiEvent = "DoubleClick") { ; Gui Double Left click
    ;ToolTip, % "you Left DOUBLE Clicked me", 300, 300
    WinActivate, ahk_class TfrmMain
    ;WinShow,  ahk_class TfrmMain
  }
  return
  ;--------------------------------------------------------------------------
  DVBVGuiContextMenu:
  ShowMenu(HMENU)
  return
  ;--------------------------------------------------------------------------
  MenuHandler:
  ;Menu_CheckRadioGroup(HMENU, A_ThisMenuItemPos, 1)
  return
}
;----------------------------------------------------------------------------------------------------------------------
HovercheckDVBVThumb:
MouseGetPos, Dx, Dy
if (Dx != lastDx or Dy != lastDy) {
 SetTimer, HoveringDVBVThumb, -100  ; hover delay 50, from when the mouse stops moving
 lastDx := Dx
 lastDy := Dy
}
Return
; ----------------------------------------------------------------------------------------------------------------------
HoveringDVBVThumb:
MouseGetPos, m_x, m_y, m_hw_target
   VarSetCapacity(PT, 8, 0)
   DllCall("User32.dll\GetCursorPos", "Ptr", &PT)
   DllCall("User32.dll\ScreenToClient", "Ptr", HMENU, "Ptr", &PT)
   MX := NumGet(PT, 0, "Int")
   MY := NumGet(PT, 4, "Int")
   ;msgbox % "X= " MX "`nY= " MY
;Tooltip % "Window= " m_hw_target "`n" WinExist("dvbviewer_thumb") "`n" HMENU "`nMX= " MX "`nMY= " MY "`nlastDx= " m_x "`nlastDy= " m_y
   SendMessage, 0x84,, ( m_y << 16 )|m_x,, ahk_id %m_hw_target%
   ;WinGet, OutputVar, ID, HMENU
   ;tooltip % m_hw_target "`n" OutputVar 
   ;rcmenu := false

  If (m_hw_target = WinExist("ahk_id " m_hw_target)) And (m_hw_target != WinActive("dvbviewer_thumb")) { ; Hover over context menu
	;If (m_hw_target = WinExist("dvbviewer_thumb"))
	 ;rcmenu := true
	 Tooltip, hover over contextmenu=`n ahk_id %m_hw_target%`nrcmenu= %rcmenu%
	 ;Tooltip, hover over contextmenu 
	  
	 ;SetTimer, HovercheckDVBVThumb, Off
     ;OnMessage(0x020A, "")
     ;SetTimer, MouseOverDVBViewerIMG, 100
     ;GoSub, DVBVThumb_Destroy
   }
   If (m_hw_target != WinActive("dvbviewer_thumb")) { ; Hover over dvbviewer_thumb
	 ;Tooltip, hover over dvbviewer_thumb=`n ahk_id %m_hw_target%`nrcmenu= %rcmenu%
	 ;If (rcmenu) { 
	  SetTimer, HovercheckDVBVThumb, Off
      OnMessage(0x020A, "")
      SetTimer, MouseOverDVBViewerIMG, 100
      GoSub, DVBVThumb_Destroy
    ;}
    ;Else
        ;Return
   }
Return
; ----------------------------------------------------------------------------------------------------------------------
DVBVThumb_Destroy:
;WinClose, dvbviewer_thumb
Gui, DVBV: Destroy 
DVBVThumb_Shown := False
Return
; ==================================================================================================================================
; Shows a user-defined menu without blocking the script.
; Parameters:
;     HMENU          -  name or handle of a user-defined menu. This menu must not be the 'Tray' menu.
;     X              -  x-position of the upper-left corner of the menu in screen coordinates.
;                       Default: -1 - current cursor position.
;     Y              -  y-position of the upper-left corner of the menu in screen coordinates.
;                       Default: -1 - current cursor position.
; Return value:
;     True if the menu could be shown, otherwise False.
; Remarks:
;     Parts of code adapted from script_menu.cpp -> UserMenu::Display
;     Because the function prevents the default AHK handling of menues there might be unwanted side-effects.
; ==================================================================================================================================
ShowMenu(HMENU, X := -1, Y := -1) {
   If !DllCall("IsMenu", "Ptr", HMENU) && !(HMENU := MenuGetHandle(HMENU))
      Return False
   If (MenuGetName(HMENU) = "Tray")
      Return False
   ; Determine the display position
   If (X = -1) || (Y = -1) {
      VarSetCapacity(PT, 8, 0)
      DllCall("GetCursorPos", "Ptr", &PT)
      If (X = -1)
         X := NumGet(PT, 0, "Int")
      If (Y = -1)
         Y := NumGet(PT, 4, "Int")
	;msgbox % "X= " X "`nY= " Y	 
   }
   ; Set the AHK main window as the foreground window, if needed
   ThisTID := DllCall("GetCurrentThreadId", "UInt")
   ForeWin := DllCall("GetForegroundWindow", "UPtr")
   If (ChangeFore := !(ForeWin) || (DllCall("GetWindowThreadProcessId", "Ptr", ForeWin, "Ptr", 0, "UInt") <> ThisTID))
      While !DllCall("SetForegroundWindow", "Ptr", A_ScriptHwnd, "UInt")
         DllCall("Sleep", "UInt", 10)
   ; Activate the message handler
   MsgFunc := Func("ShowMenuEnterMenuLoop")
   OnMessage(0x0211, MsgFunc, -1) ; WM_ENTERMENULOOP
   ; Activate the timer
   TimerFunc := Func("ShowMenuCheckCursorPosition").Bind(HMENU)
   SetTimer, %TimerFunc%, 10
   Result := DllCall("TrackPopupMenuEx", "Ptr", HMENU, "UInt", 0, "Int", X, "Int", Y, "Ptr", A_ScriptHwnd, "Ptr", 0, "UInt")
   ; Remove the ToolTip, if any
   ;;;;;;;;;;;;ToolTipEx("") ;ToolTip
   ; Deactivate the message handler
   OnMessage(0x0211, MsgFunc, 0) ; WM_ENTERMENULOOP
   ; Deactivate the timer
   SetTimer, %TimerFunc%, Delete
   ; Reset the timer's static variables
   ShowMenuCheckCursorPosition(0)
   ; Restore the foreground window, if needed
   If (ChangeFore) && (ForeWin) && (DllCall("GetForegroundWindow", "UPtr") = A_ScriptHwnd)
      DllCall("SetForegroundWindow", "Ptr", ForeWin, "UInt")
   Return Result
}
; ==================================================================================================================================
ShowMenuEnterMenuLoop() {
   Return 0 ; prevents AHK menu processing
}
; ==================================================================================================================================
ShowMenuCheckCursorPosition(HMENU) {
   Static ThisMenu := 0, ThisItem := 0
   If (HMENU <> ThisMenu) {
      ThisMenu := HMENU
      ThisItem := 0
   }
   If (HMENU = 0)
      Return
   DllCall("GetCursorPos", "Int64P", PT)
   If (Item := DllCall("MenuItemFromPoint", "Ptr", 0, "Ptr", HMENU, "Int64", PT, "Int") + 1) {
      If (Item <> ThisItem) {
         st := SystemTime.Now()
         DllCall("oleaut32\SystemTimeToVariantTime", "Ptr", st.p, "Double*", oleSt)
         ;iDVBViewer := ComObjActive("DVBViewerServer.DVBViewer")
         ;ChannelNR := iDVBViewer.channelmanager(channelnumber).GetbyChannelname
         ;channelnumber := 0 ; number of your wanted channel
         epgcid := iDVBViewer.channelmanager(Item -1).EPGChannelID
         SuD := iDVBViewer.channelmanager.GetByEPGChannelID(epgcid).tuner.SID
         TuD := iDVBViewer.channelmanager.GetByEPGChannelID(epgcid).tuner.TransportStreamID
         epgnow := iDVBViewer.epgmanager.Get(SuD,TuD,oleSt,oleSt).item(0).Title
         epgnext := iDVBViewer.epgmanager.Get(SuD,TuD,oleSt,0).item(1).Title
         starttime := iDVBViewer.epgmanager.Get(SuD,TuD,oleSt,oleSt).item(0).Time
         endtime := iDVBViewer.epgmanager.Get(SuD,TuD,oleSt,0).item(0).Endtime
         ;duration := iDVBViewer.epgmanager.Get(SuD,TuD,oleSt,oleSt).item(0).Duration
         ;showinfo := iDVBViewer.epgmanager.Get(SuD,TuD,oleSt,oleSt).item(0).Description
         ;msgbox % starttime . "  " . epgnow . "`n" . endtime "  " epgnext " "
         ;msgbox % duration "`n" showinfo
         EPGNow_Time := SubStr(starttime, InStr(starttime, " ") + 1, InStr(starttime, ":") - InStr(starttime, " ") + 2)
         EPGNext_Time := SubStr(endtime, InStr(endtime, " ") + 1, InStr(endtime, ":") - InStr(endtime, " ") + 2)
		 ;---ERROR handling for shows starting at midnight when 00:00:00 time is missing------
		 If ((EPGNow_Time = 20) && (epgnow <> ""))
		   EPGNow_Time := "00:00"
		 Else If ((EPGNext_Time = 20) && (epgnext <> ""))
		   EPGNext_Time := "00:00"
		 ;---------------------------------------------------------------------------------
		 ;---ERROR handling for when no broadcasts are aired (often at nights) = time and title is missing------
		 If ((EPGNow_Time <> "") && (epgnow <> "")) {
		 ;------------------------------------------------------------------------------------------------------
		 NowAndNext := EPGNow_Time . "  " . epgnow . " `n " . EPGNext_Time "  " epgnext " "	  
		 Sleep, 200 ; Delay tooltip pop-up 200 milliseconds
		 ;;;;;;;;ToolTipEx(" " NowAndNext " ", , , , , "Black", "White") ;ToolTip, The mouse cursor is on item %Item%
		 }
		 ;;;Else
		   ;;;;;;;ToolTipEx("") ;ToolTip
     }
   }
   ;;;;;Else
      ;;;;;;;;;ToolTipEx("") ;ToolTip
   ThisItem := Item
}
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Close Thumbnail when cursor leaves client or menu area

28 May 2017, 13:12

Bump
Hmm...where are all the skillful guys that usually solve these tricky GUI issues in a heartbeat? Masterful folks like just me is not interested anymore...sad days for me and for the AHK forum in general :(

Return to “Ask For Help”

Who is online

Users browsing this forum: Google [Bot], mikeyww, songdg and 61 guests