Mouse scroll through directory tabs (aka Firefox-feature)

Here you can propose new features, make suggestions etc.

Moderators: white, Hacker, petermad, Stefan2

TStaedtler
Junior Member
Junior Member
Posts: 3
Joined: 2014-10-20, 12:47 UTC

Mouse scroll through directory tabs (aka Firefox-feature)

Post by *TStaedtler »

Hello,
Most of the time, I have multiple (>6) tabs open in order to switch fast between directories. At one moment, the names are too long, so the outermost tabs will disappear from sight (which, I know, might be remediated by changing the tabs font style or simply clicking in the arrow buttons).
Now, Firefox got this handy "mouse scroll through the tabs" feature which really changed things. Maybe a suggestion for 8.5X to integrate this functionality?

Thanks.
Thomas
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48083
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Interesting, I have never seen this function in Firefox! I will check it.
Author of Total Commander
https://www.ghisler.com
TStaedtler
Junior Member
Junior Member
Posts: 3
Joined: 2014-10-20, 12:47 UTC

Post by *TStaedtler »

There is a visual description of this feature on this site.
Last edited by TStaedtler on 2014-10-22, 03:43 UTC, edited 1 time in total.
TC 8.51 64bit Win 8.1
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

There's also various scripts on the forums that implement Right-Click + Scroll to cycle through tabs, from 2009 to 2012. As well as DragLock. I likely have scripts kicking around on my old desktop that enabled
Right-Click Scroll tabs, retains right-click select/desect and context menu. It would likely function in TCx64 as at least the FilePanels retained their ClassNames.

Most all other scripts for TC broke with TCx64 as Lazarus gives every single 'control' the same name, and we never got a standard way to query control names to enable scripts to function seamlessly between TC 32bit and 64bit. Thus scripts for x64 are nearly pointless as they require so much error-handling that it's hardly even worth it.

Here's one that requires the mouse to hover over the Tabs to scroll, though likely wont work with TCx64 as I noted above.
*BLINK* TC9 Added WM_COPYDATA and WM_USER queries for scripting.
TStaedtler
Junior Member
Junior Member
Posts: 3
Joined: 2014-10-20, 12:47 UTC

Post by *TStaedtler »

Thus scripts for x64 are nearly pointless as they require so much error-handling that it's hardly even worth it.
…which is my case. Thanks, Balderstorm for pointing at the topic "Tab wheel scroll functionality" back from 2009.

In the meantime, I use "Show tabs in multiple lines" which is a visually unsatisfying solution for the scroll-over function already suggested.
TC 8.51 64bit Win 8.1
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

Yeah scripting pretty much died when x64 was released. Most threads about AHK/PowerPro are 2+ years old or more.

We did get a slightly improved WM_COPYDATA - 3 years ago
Changelog wrote:
  • 25.11.11 Added: Send WM_COPYDATA with dwData='G'+256*'W': Same as with 'G'+256*'A', but data is returned as UTF-16 Unicode. dwData of return is 'R'+256*'W' (32/64)
  • 25.11.11 Added: Send WM_COPYDATA with dwData='G'+256*'A' and lpData pointing to command to get back WM_COPYDATA with various info. Supported commands A: Active side (returns L or R), or two byte command: first byte: L=left, R=right, S=source, T=target. Second byte: P=current path, C=list count, I=caret index, N=name of file under caret. dwData of return is 'R'+256*'A' (32/64)
  • 09.12.07 Added: Unicode support in WM_COPYDATA: prepend UTF8 byte order marker before each path containing Unicode characters (pure ANSI paths are passed as ANSI) -> /O switch now supports Unicode too
But its usefulness is limited, and it was never improved so we could query control names.

As you can see in these threads: All requests for better external scripting is either ignored, or denied.

And as I noted in the previous post, x64 TC completely broke AHK interaction with Total Commander as we cannot identify control names any longer.
Thread: TC 8 x64, Scripting Problems (Element Class Names) wrote:

Code: Select all

                     Window ClassNames
                  In TC 7.x       TC 8 x64
ButtonBar     ->  TButtonBar      Window
DrivePanel    ->  TDrivePanel     Window
DriveComboBox ->  TMyComboBox     LCLComboBox
DriveSizeInfo ->  TMyPanel        Window
Tab Control   ->  TMyTabControl   Window
Tabs          ->  TMyPanel        Window
AddressBar    ->  TPathPanel      Window
TabStops      ->  THeaderClick    Window
FilePanels    ->  TMyListBox      LCLListBox
StatusBar     ->  TMyPanel        Window
PathField     ->  TMyPanel        Window
CommandLine   ->  Edit            Edit
FunctionBar   ->  TMyPanel        Window
Those of us like NSP, Myself, and others rarely bother posting workarounds and scripts any longer. At least 90%+ of my thousands of lines of AHK scripts no longer function with TC x64.

Almost all other File Managers are either script-friendly, or have included a scripting language or BOTH. Whereas Total Commander is actively hostile to scripting due to the differences between 32bit/64bit and the inability to query for control class names.

I didn't think I would live to see the day that Microsoft's File Explorer became more friendly to scripting/automation than Total Commander... yet there it is.

Ghisler F***ing paid Plugin writers to release an x64 version. And he actively screwed everyone else that used TC with external scripting languages.

Sorry if I sound bitter.
*BLINK* TC9 Added WM_COPYDATA and WM_USER queries for scripting.
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48083
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Sorry, I really cannot do anything about the horrible control naming in Lazarus. I tried modifying the class library at the time I ported TC to 64-bit, but it caused many problems which I couldn't handle.
Author of Total Commander
https://www.ghisler.com
User avatar
nsp
Power Member
Power Member
Posts: 1805
Joined: 2005-12-04, 08:39 UTC
Location: Lyon (FRANCE)
Contact:

Post by *nsp »

ghisler(Author) wrote:Sorry, I really cannot do anything about the horrible control naming in Lazarus. I tried modifying the class library at the time I ported TC to 64-bit, but it caused many problems which I couldn't handle.
For sure you cannot do anything about the lazarus namming but you can at least think about extending the message handling or even embed a kind of API ...

I did not push anyone to switch to 64bit because automation is in many case lost and i need 32bit plugin. You also refused to incorporate a 32/64bit proxy mechanism.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

And as I noted in this thread (also linked above). WM_COPYDATA could be enhanced to allow querying control ID's.

Either:
1) Send "controls" message to TC; TC replies with a list of all controls by english-recognizablename + its ID (e.g. TabBar:0x1275de,ButtonBar:0x55e29a, etc
2) Send a named-control message to TC; TC replies with that control's ID.

1 - Easier to implement, slightly more work for the scripting engine to handle - but not much, just parse the list to find what you need.
2 - More work to implement, cleaner scipts, don't need to parse the list.

The initial improvement to WM_COPYDATA gave me hope, wow look TC will be able to basically do, Question/Answer ... but beyond that initial addition to WM_COPYDATA 3 years ago, its been completely ignored.
*BLINK* TC9 Added WM_COPYDATA and WM_USER queries for scripting.
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48083
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

WM_COPYDATA does not allow to return data other than a simple integer value. If you want to return data, you have to send back another WM_COPYDATA message, or save the data to a file. Both are not really good solutions. I also thought about some kind of OLE automation, but it is very complex, and objects are sometimes not deleted, or deleted too much, resulting in frequent crashes. I really don't know how I could implement a better automation interface. :(
Author of Total Commander
https://www.ghisler.com
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

The ID of controls is an integer value.

And thats not even true. We can already query paths and file names.
TC Changelog wrote:25.11.11 Added:
Send WM_COPYDATA with dwData='G'+256*'A' and lpData pointing to command to get back WM_COPYDATA with various info. Supported commands A: Active side (returns L or R), or two byte command: first byte: L=left, R=right, S=source, T=target. Second byte: P=current path, C=list count, I=caret index, N=name of file under caret. dwData of return is 'R'+256*'A' (32/64)
*BLINK* TC9 Added WM_COPYDATA and WM_USER queries for scripting.
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48083
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Yes, it's as I described:
If you want to return data, you have to send back another WM_COPYDATA message
This is just not ideal. Maybe I could use a pipe? I'm using this with great success to communicate with tcmadmin.exe and tcmdx64.exe to send/receive data very quickly. But I don't know how well it works to use pipes with tools like AutoHotkey: It seems to work only via DllCall:
http://www.autohotkey.com/board/topic/103403-ipc-using-named-pipes/
Author of Total Commander
https://www.ghisler.com
User avatar
Hacker
Moderator
Moderator
Posts: 13065
Joined: 2003-02-06, 14:56 UTC
Location: Bratislava, Slovakia

Post by *Hacker »

Christian,
I don't know how well it works to use pipes with tools like AutoHotkey: It seems to work only via DllCall
Well, I think we'd figure it out somehow. :)
For what it's worth, we could also use UDP.
http://www.autohotkey.com/board/topic/94376-socket-class-%C3%BCberarbeitet/ (German)

Roman
Mal angenommen, du drückst Strg+F, wählst die FTP-Verbindung (mit gespeichertem Passwort), klickst aber nicht auf Verbinden, sondern fällst tot um.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

And AHK has the ability to directly call/use DLLCALL. As well as attach to stdinput/error/stdoutput of a console window for monitoring cmdline tools.

Really there's almost nothing that can't be done. It's just not always obvious how, and one might need to request assistance from some of the
AHK Masters @ ahkscript.org

Code: Select all

 #  USER 	POSTS
 1  joedf    2488 
 2  lexikos  1154  (Primary Developer of AHK v1.1|v2.0)
 3  tank     1107
 4  just me  1029
 5  nnnik     941
... of course SKAN, HotKeyIt, finics and others (they just haven't posted as much on ahkscript.org
Interesting things by JoeDF: on Github.
*BLINK* TC9 Added WM_COPYDATA and WM_USER queries for scripting.
User avatar
LonerD
Senior Member
Senior Member
Posts: 381
Joined: 2010-06-19, 20:18 UTC
Location: Makeyevka, Russia
Contact:

Post by *LonerD »

2TStaedtler
If it still actually - this is my script.

Code: Select all

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Script: Tabs scrolling with mouse
; Script version: 1.72 (2015.04.19)
; Script author: LonerD
; Some code: Balderstrom, YMP etc
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Considers following nuances:
; - work with active TC window x32/x64;
; - work with multiple running copies;
; - work with opened/closed FTP-connection;
; - work with opened trees in file panels;
; - wheel rotation under the file panels.
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~
#NoEnv
#NoTrayIcon
#KeyHistory, 0
#InstallMouseHook
#SingleInstance, force
SetBatchLInes, -1
SendMode Input
 
#IfWinActive, ahk_class TTOTAL_CMD
{
  WheelDown::
  WheelUp::
  {
    WinGet, TCHWND, ID, A
    ControlGetFocus, aControl, % "ahk_id " TCHWND
    MouseGetPos,,,, mControl
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    SeparateTree := 0
    Loop, 3
    {
      ControlGetText, TMyText%A_Index%, TMyListBox%A_Index%, % "ahk_id " TCHWND
      ControlGetText, LCLText%A_Index%, LCLListBox%A_Index%, % "ahk_id " TCHWND
      if ( TMyText%A_Index% = "W_TreeList2" || LCLText%A_Index% = "W_TreeList2" )
      {
        SeparateTree := 2
        break
      }
      else if ( TMyText%A_Index% = "W_TreeList1" || LCLText%A_Index% = "W_TreeList1" )
        SeparateTree := 1
    }
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    WinGet, TCPID, PID, A
    if ( A_Is64bitOS = 0 )
      TCArch := 32
    else
      TCArch := GetBitness(TCPID)

    ; Розбираємося с такою фігнею як зміщення дисків залежно від наявних елементів інтерфейсу
    EnvGet, commander_path, commander_path
    EnvGet, commander_ini, commander_ini
    IniRead, RedirectLayout, % commander_ini, Layout, RedirectSection, 0
    Transform, LayoutINI, Deref, % (RedirectLayout ? RedirectLayout : commander_ini)
    LayoutINI := ExpandEnvVars (LayoutINI)
    IniRead, DriveCombo, % LayoutINI, Layout, DriveCombo, 1

    TMyTabControl1 := TCArch=32 ? "TMyTabControl1":"SysTabControl321" ; файлова панель з вкладками зліва
    TMyTabControl2 := TCArch=32 ? "TMyTabControl2":"SysTabControl322" ; файлова панель з вкладками справа
    if ( DriveCombo = 0 )
    {
      TDrivePanel2 := TCArch=32 ? "TDrivePanel2":"Window5" ; панель з дисками зліва
      TMyPanel2 := TCArch=32 ? "TMyPanel2":"Window6" ; панель з дисками зліва (розміри)
      TDrivePanel1 := TCArch=32 ? "TDrivePanel1":"Window3" ; панель з дисками справа
      TMyPanel1 := TCArch=32 ? "TMyPanel1":"Window4" ; панель з дисками справа (розміри)
      TMyPanel6 := TCArch=32 ? "TMyPanel6":"Window10" ; файлова панель з вкладками зліва
      TMyPanel7 := TCArch=32 ? "TMyPanel7":"Window11" ; панель статусу зліва
      TMyPanel9 := TCArch=32 ? "TMyPanel9":"Window15" ; файлова панель з вкладками справа
      TMyPanel10 := TCArch=32 ? "TMyPanel10":"Window16" ; панель статусу справа
    }
    else
    {
      TDrivePanel2 := TCArch=32 ? "TDrivePanel2":"Window4" ; панель з дисками зліва
      TMyPanel6 := TCArch=32 ? "TMyPanel6":"Window12" ; панель з дисками зліва
      TDrivePanel1 := TCArch=32 ? "TDrivePanel1":"Window3" ; панель з дисками справа
      TMyPanel9 := TCArch=32 ? "TMyPanel9":"Window17" ; панель з дисками справа
      TMyPanel4 := TCArch=32 ? "TMyPanel4":"Window8" ; файлова панель з вкладками і віконцем диску зліва
      TMyPanel5 := TCArch=32 ? "TMyPanel5":"Window9" ; панель статусу зліва
      TMyPanel7 := TCArch=32 ? "TMyPanel7":"Window13" ; файлова панель з вкладками і віконцем диску справа
      TMyPanel8 := TCArch=32 ? "TMyPanel8":"Window14" ; панель статусу справа
    }
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Loop, 3
      TMyListBox%A_Index% := TCArch=32 ? "TMyListBox" . (SeparateTree + A_Index):"LCLListBox" . (SeparateTree + A_Index)

    WinGet, TCControls, ControlList, % "ahk_id " TCHWND
    TCFTPMode := 0
    Loop, Parse, TCControls, `n, `r
    {
      if ( A_LoopField = TMyListBox3 )
      {
        TCFTPMode := 1
        break
      }
    }

    TMyListBoxL := TCArch=32 ? "TMyListBox" . (2 + SeparateTree + TCFTPMode):"LCLListBox" . (2 + SeparateTree + TCFTPMode)
    TMyListBoxR := TCArch=32 ? "TMyListBox" . (1 + SeparateTree + TCFTPMode):"LCLListBox" . (1 + SeparateTree + TCFTPMode)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if( mControl = TDrivePanel2 || mControl = TMyPanel2 || mControl = TMyPanel6 || mControl = TMyPanel4 || mControl = TMyPanel5 ) ; || mControl = TMyTabControl1 )
    {
      DllCall("LockWindowUpdate", "uint", TCHWND)
      TCTabScroll( A_ThisHotkey, (aControl != TMyListBoxL), 4001, 4002 )
      DllCall("LockWindowUpdate", "uint", 0)
    }
    else if( mControl = TDrivePanel1 || mControl = TMyPanel1 || mControl = TMyPanel9 || mControl = TMyPanel10 || mControl = TMyPanel8 ) ; || mControl = TMyTabControl2 )
    {
      DllCall("LockWindowUpdate", "uint", TCHWND)
      TCTabScroll( A_ThisHotkey, (aControl != TMyListBoxR), 4002, 4001 )
      DllCall("LockWindowUpdate", "uint", 0)
    }
    else if( mControl = TMyPanel7 )
    {
      DllCall("LockWindowUpdate", "uint", TCHWND)
      if ( DriveCombo = 0 )
        TCTabScroll( A_ThisHotkey, (aControl != TMyListBoxL), 4001, 4002 )
      else
        TCTabScroll( A_ThisHotkey, (aControl != TMyListBoxR), 4002, 4001 )
      DllCall("LockWindowUpdate", "uint", 0)
    }
    else
      Send, {%A_ThisHotkey%}
    Return
  }
Return
}
#IfWinActive
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TCTabScroll( key, panelCheck, pane1, pane2 )
{
  cmd := (key == "WheelUp" ? 3006 : 3005)
  if( panelCheck )
  {
    PostMessage, 0x433, pane1
    Sleep, 50
    PostMessage, 0x433, cmd
    PostMessage, 0x433, pane2
  }
  else
    PostMessage, 0x433, cmd
  Sleep, 100
  Return
}
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GetBitness(Process) {
  Process, Exist, %Process%
  If !(PID := ErrorLevel)
    return 0
  hProcess := DllCall("OpenProcess", "uint", 0x400
                                   , "uint", 0, "uint", PID, "ptr")
  If (hProcess = 0)
    return 0
  res := DllCall("IsWow64Process", "ptr", hProcess, "int *", Wow64Process)
  If (res = 0)
    return 0
  DllCall("CloseHandle", "ptr", hProcess)
  return Wow64Process? 32:64
}
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ExpandEnvVars(ppath)
{
  VarSetCapacity(Dest, 2000)
  DllCall("ExpandEnvironmentStrings", Str, ppath, Str, Dest, Int, 1998)
  Return, Dest
}
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"I used to feel guilty in Cambridge that I spent all day playing games, while I was supposed to be doing mathematics. Then, when I discovered surreal numbers, I realized that playing games IS math." John Horton Conway
Post Reply