Siker Posted March 28, 2022 Posted March 28, 2022 I'm trying to auto-generate some system tray menu items based on the number of monitors a person has in their setup, but I'm having trouble. The way I have it set up, the auto-generated system tray items have to be in the same case in the switch statement. Inside that switch statement, I'm running a function that has an integer as the second variable that represents which monitor the function should use. As far as I can tell, I'd need to be able to let the program know which tray item got selected from inside the case, but after a couple hours searching and trying different things to do that I've come up short. Included is all parts of the script related to things you can do from the system tray in the current version of the script so that the code can be run as-is for testing. In short, it resizes and moves an open window with the exact name as is specified with the $sTargetWindowName variable so that the titlebar and borders are off-screen, so as to emulate "borderless windowed" functionality in applications without said functionality built in (e.g. certain games where losing focus on the window in fullscreen by interacting with other windows disconnects you from a server you're on). The toolbar menu and options in question simply let the user choose which monitor the "borderless-ized" window goes onto. expandcollapse popup#NoTrayIcon #include-Once #include <WinAPIGdi.au3>;for _GetMonitors() #include <WinAPISys.au3>;for _GetMonitors() #include <TrayConstants.au3>;for $TRAY_ICONSTATE_SHOW AutoItSetOption("TrayMenuMode", 3) AutoItSetOption("TrayAutoPause", 0) AutoItSetOption( "WinTitleMatchMode", 3) Global $aMonitors[1][5] $aMonitors[0][0] = 0 ;MAIN ;================================================================================================== Global $sTargetWindowName = "Example Window" _TrayMenu() ;================================================================================================== Func _TrayMenu() If $aMonitors[0][0] == 0 Then _GetMonitors() EndIf Local $idBorderlessize = TrayCreateMenu ("Borderless-ize") Local $BorderlessizeMonitor[$aMonitors[0][0]] For $i=0 to $aMonitors[0][0] - 1 Local $Msg = "Monitor " & $i + 1 $BorderlessizeMonitor[$i] = TrayCreateItem ($Msg, $idBorderlessize) Next TrayCreateItem("") Local $idPreferences = TrayCreateItem("Preferences") Local $idAbout = TrayCreateItem("About") TrayCreateItem ("") Local $idExit = TrayCreateItem ("Exit") TraySetState ($TRAY_ICONSTATE_SHOW) While 1 Switch TrayGetMsg() Case $BorderlessizeMonitor[0] To $BorderlessizeMonitor[$aMonitors[0][0] - 1] ;figure out how to get which menu item got pressed so it can be passed to the _Borderlessize function as the second parameter. _Borderlessize($sTargetWindowName, 1) Case $idPreferences ;will allow users to set preferences such as the default monitor, which windows they'd like to manipulate, etc. Case $idAbout ;will open a messagebox Case $idExit ExitLoop EndSwitch WEnd EndFunc;==> _TrayMenu ;Moves and resizes the specified window in a way that emulates windowed borderless on the specified monitor, hence "Borderless-ize" ;If no monitor is specified, monitor that window is on is used. Func _Borderlessize($sWindow = "", $Monitor = 0) If $aMonitors[0][0] == 0 Then _GetMonitors() EndIf Local $Msg = "" If @NumParams = 1 Then Local $iM = _WinOnMonitor($sWindow) If $iM = -1 Then $Msg &= $sWindow & " is not open." MsgBox(0, "", $Msg) Return ElseIf $iM = 0 Then $Msg &= $sWindow & " is not on any display monitors." & @CRLF & @CRLF $Msg &= "Please make sure the top left corner of the" & @CRLF & "window is visible and try again." MsgBox(0, "", $Msg) Return EndIf Else $iM = $Monitor EndIf Local $ixBorder = _WinAPI_GetSystemMetrics(32) Local $iyBorder = _WinAPI_GetSystemMetrics(33) Local $iMenu = _WinAPI_GetSystemMetrics(15) + 5 ;the +5 is for the 5 extra pixels of height unaccounted for by getting the titlebar height and border thickness. ;I wish I didn't have to hard-code this in, but that's not what I'm here for. I'll make a separate post for this. Local $iX = $aMonitors[$iM][1] - $ixBorder Local $iY = $aMonitors[$iM][2] - $iMenu - $iyBorder Local $iW = $aMonitors[$iM][3] + ($ixBorder * 2) Local $iH = $aMonitors[$iM][4]+ ($iyBorder*2) + $iMenu WinSetState($sWindow, "", @SW_RESTORE) WinMove($sWindow, "", $iX, $iY, $iW, $iH) EndFunc ;==> _Borderlessize ;Loads the $aMonitors array with information about the display monitors such as size and position. Func _GetMonitors() $aMonitors = _WinAPI_EnumDisplayMonitors() If IsArray($aMonitors) Then ReDim $aMonitors[$aMonitors[0][0] + 1][5] For $ix = 1 To $aMonitors[0][0] $aPos = _WinAPI_GetPosFromRect($aMonitors[$ix][1]) For $j = 0 To 3 $aMonitors[$ix][$j + 1] = $aPos[$j] Next Next EndIf EndFunc ;==> _GetMonitors This is my first time using the forums, so I'm not sure if I included too much of the code. If I did, my apologies.
ad777 Posted March 28, 2022 Posted March 28, 2022 (edited) @Siker _WinOnMonitor:Function is missing. Edited March 28, 2022 by ad777 none
Nine Posted March 28, 2022 Posted March 28, 2022 (edited) This should work for you : Local $iMsg While True $iMsg = TrayGetMsg() Switch $iMsg Case $BorderlessizeMonitor[0] To $BorderlessizeMonitor[$aMonitors[0][0] - 1] ;figure out how to get which menu item got pressed so it can be passed to the _Borderlessize function as the second parameter. _Borderlessize($sTargetWindowName, $iMsg - $BorderlessizeMonitor[0] + 1) ; ..... EndSwitch WEnd One other solution is to go onEventMode, then you can use @TRAY_ID to know which item was selected. Edited March 28, 2022 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
Siker Posted March 29, 2022 Author Posted March 29, 2022 19 hours ago, Nine said: One other solution is to go onEventMode, then you can use @TRAY_ID to know which item was selected. I had tried the first solution a couple times, it always went screwy. I assume it's because at any one moment in the loop, the program is *either* getting the tray message or running the switch, and because the tray message can include things like "moused over" or "double clicked", it was a roll of the dice as to whether the switch statement would actually be using the right tray message. Either way, it didn't work. The second solution was exactly what I was looking for, and I managed to get exactly what I wanted after a couple more hours of research, trial, and error. @Tray_ID doesn't return the text of the tray item like I had originally thought, but rather returns the controlID (which is a number created when the tray item is created), which caused some (literal) headaches. This meant I had to create an array that would store the controlID on creation, and the value that I wanted to pass to _Borderlessize based on which controlID was pressed (I called this array $aBorderlessizeIds). I also made each auto-generated tray item point to the same function when I used TrayItemSetOnEvent, which I called _TrayBorderlessize. Once we get to _TrayBorderlessize, it's just a matter of using _ArraySearch to figure out which row in the array has the same controlID as returned by @Tray_ID, and then using the ArraySearch value to grab the number I wanted from the $aBorderlessizeIds array. Here's the code, with everything not related to the autogeneration of menu items cut out: Global $aBorderlessizeIds[1][1] Func _TrayMenu() If $aMonitors[0][0] == 0 Then _GetMonitors() EndIf Local $idBorderlessize = TrayCreateMenu ("Borderless-ize") Local $idBorderlessizeItem = 0 ReDim $aBorderlessizeIds[$aMonitors[0][0]][2] Local $i = 0 For $i=0 to $aMonitors[0][0] - 1 Local $Msg = "Monitor " & $i + 1 $idBorderlessizeItem = TrayCreateItem ($Msg, $idBorderlessize) $aBorderlessizeIds[$i][0] = Int($idBorderlessizeItem) $aBorderlessizeIds[$i][1] = $i +1 TrayItemSetOnEvent(-1, "_TrayBorderlessize") EndFunc;==> _TrayMenu Func _TrayBorderlessize() Local $Index = Int(_ArraySearch($aBorderlessizeIds, @TRAY_ID, 0, 0, 0, 0, 1, 0)) _Borderlessize($sTargetWindowName, $aBorderlessizeIds[$Index][1]) EndFunc;==> _TrayBorderlessize
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now