masterlink950 Posted March 15, 2016 Share Posted March 15, 2016 Hello, First off, I want to say that I very much appreciate the hard work that people put in to replying on these forums and helping newbs. I've gotten 99% of my answers through google, forum searches, and documentation. Okay, so. I'm actually sure this has been asked before, but I wasn't able to find anything and I'm having some difficulty. I want to delete tabs in a control with a middle click (or specifically, detect when a tab has been middle-clicked). Initially I was going to try to use GUIGetCursorInfo along with checking for a middle-click, the problem is, when the cursor is over a tab, it simply returns the ID of the whole control (I'm using the native tab functionality). If I can avoid it, I REALLY don't want to manually check coordinates of tabs when the middle mouse is clicked, as tabs are going to be generated dynamically (anywhere from one to infinity tabs if the user lets things get out of hand), and the window I'm using will be resizable (thus having to run checks if a tab is out of view, etc), but I can if I have no other choice. So basically, Is there either 1: a simple native/UDF way to detect middle-click on tabs, 2: a way to get GUIGetCursorInfo give the control ID of the tab itself instead of the control, or 3: something I haven't thought of all together? Thanks in advance! Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 15, 2016 Share Posted March 15, 2016 Tab of what? Could you post the code you've tried? masterlink950 1 Link to comment Share on other sites More sharing options...
masterlink950 Posted March 15, 2016 Author Share Posted March 15, 2016 I'm looking at find the tab ID of an AutoIt GUI. Here is some code I threw together from other examples to show what I'm trying to do. (It crashes if you middle-click outside of the GUI window. I didn't want to spend anymore time on it). #include <GUIConstantsEx.au3> #include <Misc.au3> $hGUI = GUICreate("Window with Tabs", 500, 500) Global $controlID = 0 GUICtrlCreateLabel("ID of clicked control:", 200, 1) $controlID = GUICtrlCreateLabel("0", 300, 1, 50) $dll = DllOpen("user32.dll") HotKeySet("{ESC}", "GetPos") $hTab = GUICtrlCreateTab(10, 10, 480, 480) For $i = 0 To 2 GUICtrlCreateTabItem("Tab " & $i) GUICtrlCreateButton("Button " & $i, 20 + ($i * 100), 40 + ($i * 50), 80, 30) Next GUICtrlCreateTabItem("") GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch If _IsPressed("04", $dll) Then GetPos() WEnd DllClose($dll) Func GetPos() Local $a = GUIGetCursorInfo() GUICtrlSetData($controlID, $a[4]) EndFunc You will see that when you middle-click anywhere inside the GUI tab control, it gives you the ID of the entire control. I need to make it so if you click on the individual tabs at the top, it will display the ID of only that tab. Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 15, 2016 Share Posted March 15, 2016 Perfect! Posting code takes away a lot of the guessing game and I don't have to spend the time putting together the GUI myself Here's a way to use WM_NOTIFY to get the index of the tab. It appears that WM_MBUTTONDOWN (and UP) are not being received when on a tab so I used the _IsPressed. expandcollapse popup#include <GUIConstantsEx.au3> #include <Misc.au3> #include <WindowsConstants.au3> #include <GUITab.au3> Global $iTabIndex = -1 Global $hGUI = GUICreate("Window with Tabs", 500, 500) Global $lblId = GUICtrlCreateLabel("ID of clicked control:", 200, 1) Global $hTab = GUICtrlCreateTab(10, 10, 480, 480) For $i = 0 To 2 GUICtrlCreateTabItem("Tab " & $i) GUICtrlCreateButton("Button " & $i, 20 + ($i * 100), 40 + ($i * 50), 80, 30) Next GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch If (_IsPressed(4)) Then DeleteTabItem() WEnd Func DeleteTabItem() If ($iTabIndex > -1) Then _GUICtrlTab_DeleteItem(GUICtrlGetHandle($hTab), $iTabIndex) $iTabIndex = -1 EndIf EndFunc ;==>DeleteTabItem Func WM_NOTIFY($hWndFrom, $iMsg, $wParam, $lParam) #forceref $hWndFrom, $iMsg, $wParam, $lParam Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Local $iCode = DllStructGetData($tNMHDR, "Code") Local $iIdFrom = DllStructGetData($tNMHDR, "IDFrom") Switch ($hWndFrom) Case $hGUI Switch ($iCode) Case -530 $iTabIndex = $iIdFrom EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY I'll test a WNDPROC tomorrow, see if it captures the middle mouse click Also, the -530 is used to parse the application for the tooltip text to display. It's in the ToolTipConstants.au3 Global Const $TTN_GETDISPINFOW = $TTN_FIRST - 10 ; [Unicode] Sent to retrieve information needed to display a ToolTip We're not displaying a tooltip but it's a good enough value to use to determine that the tab is being highlighted. masterlink950 1 Link to comment Share on other sites More sharing options...
masterlink950 Posted March 15, 2016 Author Share Posted March 15, 2016 That works pretty well, actually. The only problem is there is a delay in trying to use the tooltip display number to determine the tab that is highlighted. It also "keeps" that tab ID if you move outside of the GUI without hovering over another control, and if you middle-cick, it deletes that tab. same goes for if you hover over one tab long enough, and don't sit over another tab long enough for the tooltip ID to display. Do you think there is any other way we can identify what tab is selected? I even tried playing with the example for "_GUICtrlTab_Create" to see if I could identify what tab is pressed, but that doesn't do it either. It still displays the same ID regardless of different tabs. At this rate, I'm almost curious if I could just create my own tab system using labels as buttons. Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 16, 2016 Share Posted March 16, 2016 (edited) Idk, I feel like you're making it harder than it needs to be. There's nothing wrong with checking mouse coords for something if it works! I was at work all day and came home to see a question that looked enticing I got carried away. Here's the solution to your dilemma. I even included all of the possible windows messages you can get from the Window procedure for our tab control (There are like 3 values that I got that I could not find in the WindowsConstants.au3 file, even did a global search in the #include folder and didn't find it) expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GUITab.au3> #include <WinApi.au3> #include <WinAPIGdi.au3> Global $hGUI = GUICreate("Window with Tabs", 500, 500) Global $lblId = GUICtrlCreateLabel("Hovering over tab index: N/A | N/A", 190, 4, 200, 20) GUICtrlSetFont(-1, 8, 400, "", "Segoe UI") Global $tabMainTab = GUICtrlCreateTab(10, 30, 480, 480) Global $hWndTab = GUICtrlGetHandle($tabMainTab) Global $hWndProc = DllCallbackRegister("NewWndProc", "ptr", "hwnd;uint;wparam;lparam") Global $pOldWndProc = _WinAPI_SetWindowLong($hWndTab, $GWL_WNDPROC, DllCallbackGetPtr($hWndProc)) Global $iTabItems = 13 For $i = 0 To $iTabItems GUICtrlCreateTabItem("Tab " & $i) GUICtrlCreateButton("Button " & $i, 20, 100, 80, 30) Next GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd Func NewWndProc($hWndFrom, $iMsg, $wParam, $lParam) #forceref $hWndFrom, $iMsg, $wParam, $lParam ; Struct that can be used to get information for SOME of the Windows Messages below ; Use caution, using the $iCode or $iIdFrom on the wrong windows message will break your code. ; It's best to initialize them INSIDE the Switch ($iMsg) below. ; Check the URL to see what values you can get from the $lParam and $wParam Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) ;Local $iCode = DLLStructGetData($tNMHDR, "Code") ;Local $iIdFrom = DLLStructGetData($tNMHDR, "IDFrom") ; Only valid on mouse functions Local $iMouseX = _WinAPI_LoWord($lParam) Local $iMouseY = _WinAPI_HiWord($lParam) Switch ($hWndFrom) Case $hWndTab Switch ($iMsg) Case $WM_LBUTTONDOWN ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645607(v=vs.85).aspx Case $WM_LBUTTONUP ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645608%28v=vs.85%29.aspx Case $WM_RBUTTONDOWN ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms646242(v=vs.85).aspx Case $WM_RBUTTONUP ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms646243%28v=vs.85%29.aspx Case $WM_MBUTTONDOWN ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645610(v=vs.85).aspx Case $WM_MBUTTONUP ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645611%28v=vs.85%29.aspx For $i = 0 To $iTabItems Local $aTabRect = _GUICtrlTab_GetItemRect($hWndTab, $i) If (Not @error) Then If (_WinAPI_PtInRectEx($iMouseX, $iMouseY, $aTabRect[0], $aTabRect[1], $aTabRect[2], $aTabRect[3])) Then ConsoleWrite("Deleting tab index: " & $i & " | Tab text: " & _GUICtrlTab_GetItemText($hWndTab, $i)) _GUICtrlTab_DeleteItem($hWndTab, $i) $iTabItems -= 1 ExitLoop EndIf EndIf Next Case $WM_MOUSEMOVE ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645616%28v=vs.85%29.aspx For $i = 0 To $iTabItems Local $aTabRect = _GUICtrlTab_GetItemRect($hWndTab, $i) If (Not @error) Then If (_WinAPI_PtInRectEx($iMouseX, $iMouseY, $aTabRect[0], $aTabRect[1], $aTabRect[2], $aTabRect[3])) Then ExitLoop EndIf Next GUICtrlSetData($lblId, "Hovering over tab index: " & $i & " | " & _GUICtrlTab_GetItemText($hWndTab, $i)) Case $WM_NCHITTEST ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645618%28v=vs.85%29.aspx Case $WM_SETCURSOR ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648382%28v=vs.85%29.aspx Case $WM_PAINT ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd145213(v=vs.85).aspx Case $WM_MOUSELEAVE ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645615%28v=vs.85%29.aspx GUICtrlSetData($lblId, "Hovering over tab index: N/A | N/A") Case $WM_MOUSEACTIVATE ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645612%28v=vs.85%29.aspx Case $WM_NOTIFY ; https://msdn.microsoft.com/en-us/library/windows/desktop/bb775583%28v=vs.85%29.aspx Case $WM_NOTIFYFORMAT ; https://msdn.microsoft.com/en-us/library/windows/desktop/bb775584(v=vs.85).aspx Case $WM_UPDATEUISTATE ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms646361%28v=vs.85%29.aspx Case $WM_GETDLGCODE ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms645425%28v=vs.85%29.aspx Case $WM_IME_SETCONTEXT ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd374142(v=vs.85).aspx Case $WM_SETFOCUS ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms646283(v=vs.85).aspx Case $WM_ERASEBKGND ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648055%28v=vs.85%29.aspx Case $WM_NCPAINT ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd145212%28v=vs.85%29.aspx Case 0x001308, 0x00130A, 0x002006, 0x00133E, 0x00130C, 0x000129, 0x000210 ; Unknown messages that are constantly sent to the tab control but could not identify in WindowsConstants.au3 Case 0x00133C ; Unknown message sent to the tab control when highlighting an item Case Else ConsoleWrite('[' & @HOUR & ":" & @MIN & ":" & @SEC & ":" & @MSEC & "] Unknown Message: 0x" & Hex($iMsg, 6) & @LF & "############################################" & @LF) EndSwitch EndSwitch Return _WinAPI_CallWindowProc($pOldWndProc, $hWndFrom, $iMsg, $wParam, $lParam) EndFunc ;==>NewWndProc Also, I didn't actually test it but I'm guessing _GUICtrlTab_GetItemRect is just the same as _WinApi_GetRect which will get the rect of a given handle. Can be used on buttons, edits, etc. And since tab items are really just buttons Edited March 16, 2016 by InunoTaishou Added more messages to switch masterlink950 1 Link to comment Share on other sites More sharing options...
masterlink950 Posted March 18, 2016 Author Share Posted March 18, 2016 Wow. That is incredibly helpful! A great reference too, I like it! I was actually working on a script that when the middle mouse button is pressed, it changes a variable and emulate a L-mouse click if its inside the window. Whenever a tab switched, and if that earlier var was changed to true, it would delete the tab and revert back to the previous tab. A bit hacky, but it probably would have worked. However, this is much better. Thanks a ton! Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 18, 2016 Share Posted March 18, 2016 Lmao, sounds like a work around I would have done if I hadn't known about window procedures. I hope you were at least using a mouse hook so the WM_MBUTTONDOWN was never sent to the GUI masterlink950 1 Link to comment Share on other sites More sharing options...
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