Jump to content

Recommended Posts

Posted (edited)

 SciTE_OverlayTab

Highlighting the active & unsaved tab item in SciTE

Inspired from  211131-highlighting-the-active-tab-item-in-scite/    (Thanks to BugFix 🏆

While the original was excellent, I found that I needed  to change some things.
Since I made these adjustments, I decided to share the revised code.

What's New

Spoiler

Version: 0.7

  • Feature: New "Significant" Tab Marking:

    • Introduced a new visual layer to mark important tabs.

    • Significant tabs are now highlighted with a 3px Purple top bar for quick identification.

    • Added Ctrl+Shift+6 shortcut to instantly toggle the "Significant" status on the currently focused tab.

Version: 0.8

  • Performance: I added an extra layer to the site's activity control to reduce processor activity.

Version: 0.9

  • Fix: Resolved x64 memory alignment issues in TCITEM structure (manual 4-byte padding).

  • Performance: Added State Signature Check (Checksum) to prevent redundant UI updates.

  • Performance: Implemented Static Variable caching for process handles and memory allocation.

  • Feature: Smart Garbage Collection for the Significant Tabs Map.

Version: 0.10

  • Feature: DPI Awareness:  added DPI Awareness to ensure overlays align correctly.

  • Bugfix: I made LastState Global, so I can update it externally as well.

Version: 0.11

  • Feature: Dynamic DPI Awareness alignment based on scite Awareness

Version: 0.12

  • Feature: Architecture Selector: Runs on x86 or x64 depending on SciTE.

  • Feature: State Management: Two colors  (Purple, Ctrl+Shift+6 | Green, Ctrl+Shift+7)  with smart toggle/switch.

  • Feature: Proportional UI: The "Significant" line breathes with the Tab, change from 3 pixels to 0.15 ratio

Version: 1.0

  • Performance:  Change the approach, that reads the tabs from the Buffers menu now and not from the tabs, so to have the full path

  • Feature: control to enable/disable HotKeys when scite is enabled/disabled

  • Feature: Feature: added Ctrl+E HotKey in scite to open file location in Explorer
    (to overcome the problem that if a script is running, scite's OpenFileLocation option is disabled)

 

 

SciTE_OverlayTab.au3

; https://www.autoitscript.com/forum/topic/213330-scite_overlaytab/
;--------------------------------------------------------------------------------------------------------------------------------
; Title...........: SciTE_OverlayTab.au3
; Description.....: Highlighting the active & unsaved tab item in SciTE
; AutoIt Version..: 3.3.18.0   Author: ioa747           Script Version: 1.0
; Note............: Testet in Windows 11 Pro 24H2       Date:27/03/2026
;                   New Layer added (Significant 1)  toggled with Ctrl+Shift+6
;                   New Layer added (Significant 2)  toggled with Ctrl+Shift+7
;--------------------------------------------------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
;~ #AutoIt3Wrapper_UseX64=y

#include <GuiTab.au3>
#include <Misc.au3>
#include <WinAPISysWin.au3>
#include <WindowsStylesConstants.au3>
#include <WinAPIProc.au3>
#include <WinAPIMem.au3>
#include <WinAPIGdiDC.au3>
#include <GuiMenu.au3>

Opt('TrayIconHide', 1)

_Singleton(@ScriptName)

Global $g_SciTE_Handle = _SciTE_ArchSlector()

Global Const $g_hActiveColor = 0x0026FF  ; Blue for active
Global Const $g_hUnSavedColor = 0xFF6A00 ; Orange for not stored
Global Const $g_hSign1Color = 0x800080   ; Purple for Significant 1
Global Const $g_hSign2Color = 0x007F0E   ; Green for Significant 2
Global Const $g_iOpacity = 50            ; Background transparency
Global Const $g_fTopBarRatio = 0.15      ; Significant line thickness

Global $g_aOverlayHwnd[0]
Global $g_aSigOverlayHwnd[0]
Global $g_mSignificant[]
Global $g_mSignColor[]
Global $g_sLastState = ""
Global $g_iActive
Global $g_aItems

; === HotKeySet -> _EnableHotKey(True/False) ===
; Ctrl+Shift+6  toggled Significant groub1
; Ctrl+Shift+7  toggled Significant groub2
; Ctrl+E        Open File Location in Explorer

OnAutoItExitRegister(_Exit)

_EnableHighDPI(_GetProcessDPIAwarenessLevel($g_SciTE_Handle))

While WinExists($g_SciTE_Handle)
    ; Update only if SciTE is visible/active
    _SciTEState()
    Sleep(100)
WEnd
;---------------------------------------------------------------------------------------
Func _SciTEState()
    ; Retrieve the state of the SciTEWindow.
    Local $iState = WinGetState($g_SciTE_Handle)
    Switch $iState
        Case 15, 47 ; exists+visible+enabled+active +maximized
            _EnableHotKey(True)
            _UpdateTabOverlays()
        Case Else
            _EnableHotKey(False)
            Sleep(500)
    EndSwitch
EndFunc   ;==>_SciTEState
;---------------------------------------------------------------------------------------
Func _UpdateTabOverlays()
    Local $hTab = ControlGetHandle($g_SciTE_Handle, "", "SciTeTabCtrl1")
    If @error Then Return

    Local $aPos = WinGetPos($g_SciTE_Handle)
    Local $iCount = _GUICtrlTab_GetItemCount($hTab)
    $g_iActive = _GUICtrlTab_GetCurFocus($hTab)

    $g_aItems = _GetSciTE_Buffers() ; get Items from Buffers menu

    ; State Signature: 'C:\Path\To\File.au3|1|8|3|100|100|800|600'
    ; [Path | Dirty | TabCount | ActiveIdx | X | Y | W | H]
    Local $sCurrentState = $g_aItems[$g_iActive][0] & "|" & $g_aItems[$g_iActive][1]
    $sCurrentState &= "|" & $iCount & "|" & $g_iActive
    $sCurrentState &= "|" & $aPos[0] & "|" & $aPos[1] & "|" & $aPos[2] & "|" & $aPos[3]

    If $sCurrentState = $g_sLastState Then Return

    $g_sLastState = $sCurrentState
    ; ConsoleWrite("$sCurrentState=" & $sCurrentState & @CRLF)

    ; Synchronize tables if the number of Tabs changes
    If $iCount <> UBound($g_aOverlayHwnd) Then
        _CleanupOverlays()
        ReDim $g_aOverlayHwnd[$iCount]
        ReDim $g_aSigOverlayHwnd[$iCount]
    EndIf

    For $i = 0 To $iCount - 1
        Local $tRect = _GUICtrlTab_GetItemRectEx($hTab, $i)

        ; Active/Unsaved Overlay
        Local $iBgColor = 0
        If $i = $g_iActive Then
            $iBgColor = $g_hActiveColor
        ElseIf $g_aItems[$i][1] Then
            $iBgColor = $g_hUnSavedColor
        EndIf

        $g_aOverlayHwnd[$i] = _ManageOverlay($hTab, $tRect, $iBgColor, $g_aOverlayHwnd[$i], False)

        ; Significant Overlay
        If MapExists($g_mSignificant, $g_aItems[$i][0]) Then
            $g_aSigOverlayHwnd[$i] = _ManageOverlay($hTab, $tRect, $g_mSignColor[$g_aItems[$i][0] & "_Color"], $g_aSigOverlayHwnd[$i], True)
        Else
            If IsHWnd($g_aSigOverlayHwnd[$i]) Then GUIDelete($g_aSigOverlayHwnd[$i])
        EndIf
    Next
    _CleanSignificantMap()
EndFunc   ;==>_UpdateTabOverlays
;---------------------------------------------------------------------------------------
Func _CleanSignificantMap()
    If UBound($g_mSignificant) = 0 Then Return
    Local $aKeys = MapKeys($g_mSignificant)
    For $sKey In $aKeys
        Local $bFound = False
        For $i = 0 To UBound($g_aItems) - 1
            If $g_aItems[$i][0] == $sKey Then
                $bFound = True
                ExitLoop
            EndIf
        Next

        If Not $bFound Then
            MapRemove($g_mSignificant, $sKey)
            MapRemove($g_mSignColor, $sKey & "_Color")
        EndIf
    Next
EndFunc   ;==>_CleanSignificantMap
;---------------------------------------------------------------------------------------
Func _ManageOverlay($hTab, $tRect, $iColor, $hExisting, $bIsTopBar)
    If $iColor = 0 Then
        If IsHWnd($hExisting) Then GUIDelete($hExisting)
        Return 0
    EndIf

    ; Prepare point structure for coordinate conversion
    Local $tPoint = DllStructCreate("int X;int Y")
    DllStructSetData($tPoint, "X", $tRect.Left)
    DllStructSetData($tPoint, "Y", $tRect.Top)

    ; Convert Tab's client coordinates to absolute screen coordinates
    ; Since we are DPI Aware, this returns physical pixels
    _WinAPI_ClientToScreen($hTab, $tPoint)

    Local $iX = DllStructGetData($tPoint, "X")
    Local $iY = DllStructGetData($tPoint, "Y")

    ; Calculate width and height directly from the Rect structure
    Local $iW = $tRect.Right - $tRect.Left
    Local $iH = $tRect.Bottom - $tRect.Top

    If $bIsTopBar Then
        $iH = Int($iH * $g_fTopBarRatio)
        If $iH < 2 Then $iH = 2
    EndIf

    Local $hOverlay = $hExisting
    If Not IsHWnd($hOverlay) Then
        ; Create the overlay window
        $hOverlay = GUICreate("", $iW, $iH, $iX, $iY, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_NOACTIVATE, $WS_EX_TRANSPARENT), $hTab)
        GUISetBkColor($iColor)
        WinSetTrans($hOverlay, "", ($bIsTopBar ? 150 : $g_iOpacity))
        GUISetState(@SW_SHOWNOACTIVATE, $hOverlay)
    Else
        ; If it already exists, just move and resize
        WinMove($hOverlay, "", $iX, $iY, $iW, $iH)
        GUISetBkColor($iColor, $hOverlay)
    EndIf

    Return $hOverlay
EndFunc   ;==>_ManageOverlay
;---------------------------------------------------------------------------------------
Func _CleanupOverlays()
    For $i = 0 To UBound($g_aOverlayHwnd) - 1
        GUIDelete($g_aOverlayHwnd[$i])
        GUIDelete($g_aSigOverlayHwnd[$i])
    Next
EndFunc   ;==>_CleanupOverlays
;---------------------------------------------------------------------------------------
Func _Exit()
    _CleanupOverlays()
    Exit
EndFunc   ;==>_Exit
;---------------------------------------------------------------------------------------
Func _GetProcessDPIAwarenessLevel($hWnd)
    Local $iPID
    _WinAPI_GetWindowThreadProcessId($hWnd, $iPID)

    Local $hProcess = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", 0x0400, "bool", False, "dword", $iPID) ; PROCESS_QUERY_INFORMATION
    If @error Or Not $hProcess[0] Then Return SetError(@error, 1, -2)

    ; 0 = Unaware, 1 = System Aware, 2 = Per Monitor Aware
    Local $aRet = DllCall("Shcore.dll", "long", "GetProcessDpiAwareness", "ptr", $hProcess[0], "int*", 0)

    _WinAPI_CloseHandle($hProcess[0])

    If @error Then Return SetError(@error, 2, -2)

    Switch $aRet[2]
        Case 0 ; PROCESS_DPI_UNAWARE
            ; ConsoleWrite("PROCESS_DPI_UNAWARE -1" & @CRLF)
            Return -1
        Case 1 ; PROCESS_SYSTEM_DPI_AWARE
            ; ConsoleWrite("PROCESS_SYSTEM_DPI_AWARE -2" & @CRLF)
            Return -2
        Case 2 ; PROCESS_PER_MONITOR_DPI_AWARE
            ; ConsoleWrite("PROCESS_PER_MONITOR_DPI_AWARE -4" & @CRLF)
            Return -4
        Case Else
            ; ConsoleWrite("Else -> PROCESS_SYSTEM_DPI_AWARE -2" & @CRLF)
            Return -2
    EndSwitch
EndFunc   ;==>_GetProcessDPIAwarenessLevel
;---------------------------------------------------------------------------------------
Func _EnableHighDPI($Awareness = -2)
    Local $hUser32 = DllOpen("user32.dll")
    Local $aRet = DllCall($hUser32, "bool", "SetProcessDpiAwarenessContext", "int_ptr", $Awareness)

    ; Fallback to basic DPI Awareness
    If @error Or Not $aRet[0] Then
        DllCall($hUser32, "bool", "SetProcessDPIAware")
    EndIf

    DllClose($hUser32)
EndFunc   ;==>_EnableHighDPI
;---------------------------------------------------------------------------------------
Func _SciTE_ArchSlector()

    Local $hSciTE = WinGetHandle('[CLASS:SciTEWindow]')
    If Not $hSciTE Then Exit
    Local $iPID
    _WinAPI_GetWindowThreadProcessId($hSciTE, $iPID)

    ; 2. ARCHITECTURE CHECK: Is SciTE 64-bit?
    Local $bSciTEIs64 = False
    If @OSArch = "X64" Then
        If Not _WinAPI_IsWow64Process($iPID) Then $bSciTEIs64 = True
    EndIf

    ; If SciTE is 64-bit but the script runs as 32-bit (or vice versa), restart to the correct one!
    If ($bSciTEIs64 And Not @AutoItX64) Or (Not $bSciTEIs64 And @AutoItX64) Then
        Local $sAutoItExe = $bSciTEIs64 ? StringReplace(@AutoItExe, "AutoIt3.exe", "AutoIt3_x64.exe") : StringReplace(@AutoItExe, "_x64.exe", ".exe")
        ; ConsoleWrite("$sAutoItExe=" & $sAutoItExe & @CRLF)
        If FileExists($sAutoItExe) Then
            Exit ShellExecute($sAutoItExe, '"' & @ScriptFullPath & '"') * 0 + 1
        EndIf
    EndIf

    Return $hSciTE

EndFunc   ;==>_SciTE_ArchSlector
;---------------------------------------------------------------------------------------
Func _GetSciTE_Buffers()
    Local $iStart = 5, $iSubItem = 7
    Local $hMenu = _GUICtrlMenu_GetMenu($g_SciTE_Handle)
    Local $hSubMenu = _GUICtrlMenu_GetItemSubMenu($hMenu, $iSubItem)
    Local $sCount = _GUICtrlMenu_GetItemCount($hSubMenu)

    If $sCount <= $iStart Then
        Local $aEmpty[1][2] = [["", 0]]
        Return $aEmpty
    EndIf

    Local $aResult[$sCount - $iStart][2]
    Local $sName, $idx
    For $i = $iStart To $sCount - 1
        $idx = $i - $iStart
        $sName = _GUICtrlMenu_GetItemText($hSubMenu, $i)
        $aResult[$idx][1] = 0 ; not dirty
        If StringLeft($sName, 1) = "&" Then $sName = StringTrimLeft($sName, 3)
        If StringRight($sName, 1) = "*" Then
            $sName = StringTrimRight($sName, 2)
            $aResult[$idx][1] = 1 ; dirty
        EndIf
        $aResult[$idx][0] = $sName
    Next
    Return $aResult
EndFunc   ;==>_GetSciTE_Buffers
;---------------------------------------------------------------------------------------
Func _EnableHotKey($bEnable = True)
    Local Static $bHotKeyStatus

    If $bHotKeyStatus = $bEnable Then Return
    $bHotKeyStatus = $bEnable

    If $bEnable Then
        HotKeySet("^+6", "_ToggleSignificant") ; <<--( toggled Significant with Ctrl+Shift+6 )--<<
        HotKeySet("^+7", "_ToggleSignificant") ; <<--( toggled Significant with Ctrl+Shift+7 )--<<
        HotKeySet("^e", "_OpenFileLocation")   ; <<--( Open File Location in Explorer with Ctrl+E )--<<
    Else
        HotKeySet("^+6")
        HotKeySet("^+7")
        HotKeySet("^e")
    EndIf
EndFunc
;---------------------------------------------------------------------------------------
Func _ToggleSignificant()
    Local $iColor
    Switch @HotKeyPressed
        Case "^+6"
            $iColor = $g_hSign1Color
        Case "^+7"
            $iColor = $g_hSign2Color
    EndSwitch

    Local $sID = $g_aItems[$g_iActive][0]

    If MapExists($g_mSignificant, $sID) Then
        If $g_mSignColor[$sID & "_Color"] = $iColor Then
            MapRemove($g_mSignificant, $sID)
            MapRemove($g_mSignColor, $sID & "_Color")
        Else
            $g_mSignificant[$sID] = True
            $g_mSignColor[$sID & "_Color"] = $iColor
        EndIf
    Else
        $g_mSignificant[$sID] = True
        $g_mSignColor[$sID & "_Color"] = $iColor
    EndIf
    $g_sLastState = "update"
EndFunc   ;==>_ToggleSignificant
;---------------------------------------------------------------------------------------
Func _OpenFileLocation()
    If FileExists($g_aItems[$g_iActive][0]) Then
        Run('explorer.exe /select, "' & $g_aItems[$g_iActive][0] & '"')
    EndIf
EndFunc
;---------------------------------------------------------------------------------------

 

Please, every comment is appreciated!
leave your comments and experiences here!
Thank you very much  :)

 

Edited by ioa747
Version: 1.0

I know that I know nothing

Posted (edited)


What's New in Version 0.7

  • New "Significant" Tab Marking:

    • Introduced a new visual layer to mark important tabs.

    • Significant tabs are now highlighted with a 3px Purple top bar for quick identification.

    • Added Ctrl+Shift+6 shortcut to instantly toggle the "Significant" status on the currently focused tab.

 

Update to Version 0.8

I added an extra layer to the site's activity control to reduce processor activity.

Edited by ioa747

I know that I know nothing

Posted (edited)

I'm getting a crash 

AutoIt3 ended. rc:-1073740940

when starting it as x64 execution. x86 runs properly.

I must add a Sleep(10) to the _ManageOverlay() function. I don't know why but the Tab blue rectangle was topmost painted althouth SciTE was in the background.

Just wondering why SciTE doesn't have this feature already onboard...

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (edited)

I prefer to run it on x86, and I didn't encounter any problems.
But I also tried it on x64, without Sleep(10), and I didn't encounter any problems here either.
(not even with the blue rectangle)

Can I ask what version of AutoIt  and what version of SciTE you're running?

My combination
AutoIt Version..: 3.3.18.0
SciTE, 32-bit, Version 4.4.6, Mar 12 2022 10:14:43
Windows 11 Pro, Version    25H2

 

Edited by ioa747
add AutoIt too

I know that I know nothing

Posted

I'm using the x64 version of SciTE -> Version 5.5.8   Scintilla:5.5.8   Lexilla:5.4.6   Jan 12 2026 12:26:07

Autoit: 3.3.18.0

Win: 24H2

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted

I have the impression that this was fixed in Autoit version: 3.3.18.0

I also tried it on x64, and I didn't encounter any problems here either.

with 
AutoIt Version..: 3.3.18.0
SciTE, 64-bit, Version 5.5.8
Windows 11 Pro, Version    25H2

 

I know that I know nothing

Posted (edited)

Can somebody test if this works?

SciTeTabHook (I create two small DLLs (x86/x64) to hook SciTE which is apparently not possible using Autoit due to Memory Barrier / Local Address limits)

It should work with SciTE x86/x64. It is important to run AutoIt on the same architecture as SciTE!

Tray icon can be used to close Autoit script.

Thx.

@ioa747 sorry for hijacking your thread, but this fits in well here. :whistle:

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (edited)

@UEZ   Τhere is no problem,


and I am still looking for it
I think the problem is in the function __GUICtrl_TagOutProcess
which is called internally by _GUICtrlTab_GetItem
While the function correctly scales pointers to UINT64 for x64 targets, it completely ignores Structure Alignment/Padding requirements.

In x64 architecture, a 64-bit pointer must be aligned to an 8-byte boundary.

Current Logic: uint Mask (4); uint State (4); uint StateMask (4); ptr pszText (8) -> Puts pszText at Offset 12.

Windows x64 Requirement: Requires 4 bytes of padding after StateMask to align pszText at Offset 16.
(I think, it's at the limit of my knowledge)

and based on this logic I proceeded to an bypass of _GUICtrlTab_GetItem -> __GUICtrl_TagOutProcess
to see what happens

; https://www.autoitscript.com/forum/topic/213330-scite_overlaytab/
;--------------------------------------------------------------------------------------------------------------------------------
; Title...........: SciTE_OverlayTab.au3
; Description.....: Highlighting the active & unsaved tab item in SciTE
; AutoIt Version..: 3.3.18.0   Author: ioa747           Script Version: 0.10
; Note............: Testet in Windows 11 Pro 24H2       Date:22/03/2026
;                   New Layer added (Significant)  toggled with Ctrl+Shift+6
;--------------------------------------------------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
;~ #AutoIt3Wrapper_UseX64=y

#include <GuiTab.au3>
#include <Misc.au3>
#include <WinAPISysWin.au3>
#include <WindowsStylesConstants.au3>
#include <WinAPIProc.au3>
#include <WinAPIMem.au3>

Opt('TrayIconHide', 1)
_Singleton(@ScriptName)

DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext", "int_ptr", -2)

Global Const $g_hActiveColor = 0x0026FF      ; Blue for active
Global Const $g_hUnSavedColor = 0xFF6A00     ; Orange for not stored
Global Const $g_hSignificantColor = 0x800080 ; Purple for Significant
Global Const $g_iOpacity = 50                ; Background transparency
Global Const $g_iTopBarHeight = 3            ; Significant line thickness

Global $g_aOverlayHwnd[0]
Global $g_aItemsText[0]
Global $g_aSigOverlayHwnd[0]
Global $g_mSignificant[]
Global $g_SciTE_Handle = WinGetHandle('[CLASS:SciTEWindow]')
Global $g_sLastState = ""

If Not $g_SciTE_Handle Then Exit

HotKeySet("^+6", "_ToggleSignificant") ; <<--( toggled Significant with Ctrl+Shift+6 )--<<
OnAutoItExitRegister(_Exit)

While WinExists($g_SciTE_Handle)
    ; Update only if SciTE is visible/active
    _SciTEState()
    Sleep(100)
WEnd

;---------------------------------------------------------------------------------------
Func _SciTEState()
    ; Retrieve the state of the SciTEWindow.
    Local $iState = WinGetState($g_SciTE_Handle)
    Switch $iState
        Case 15, 47 ; exists+visible+enabled+active +maximized
            _UpdateTabOverlays()
        Case Else
            Sleep(1000)
    EndSwitch
EndFunc   ;==>_SciTEState
;---------------------------------------------------------------------------------------
Func _UpdateTabOverlays()
    Local $hTab = _GetHwnd_SciTeTabCtrl()
    If @error Then Return

    Local $iCount = _GUICtrlTab_GetItemCount($hTab)
    Local $iActive = _GUICtrlTab_GetCurFocus($hTab)
    Local $aPos = WinGetPos($g_SciTE_Handle)

    ; State Signature: '&6 SciTE_OverlayTab.au3|6|5|280|0|1647|1039'
    Local $sCurrentState = _SciTE_GetTabText($hTab, $iActive)
    $sCurrentState &= "|" & $iCount & "|" & $iActive
    $sCurrentState &= "|" & $aPos[0] & "|" & $aPos[1] & "|" & $aPos[2] & "|" & $aPos[3]

    If $sCurrentState = $g_sLastState Then Return

    $g_sLastState = $sCurrentState

    ; Synchronize tables if the number of Tabs changes
    If $iCount <> UBound($g_aOverlayHwnd) Then
        _CleanupOverlays()
        ReDim $g_aOverlayHwnd[$iCount]
        ReDim $g_aSigOverlayHwnd[$iCount]
        ReDim $g_aItemsText[$iCount]
    EndIf

    For $i = 0 To $iCount - 1
        Local $sRawText = _SciTE_GetTabText($hTab, $i)
        Local $sCleanID = _GetCleanTabID($sRawText)
        Local $tRect = _GUICtrlTab_GetItemRectEx($hTab, $i)
        $g_aItemsText[$i] = $sCleanID

        ; Active/Unsaved Overlay
        Local $iBgColor = 0
        If $i = $iActive Then
            $iBgColor = $g_hActiveColor
        ElseIf StringRight($sRawText, 1) = '*' Then
            $iBgColor = $g_hUnSavedColor
        EndIf

        $g_aOverlayHwnd[$i] = _ManageOverlay($hTab, $tRect, $iBgColor, $g_aOverlayHwnd[$i], False)

        ; Significant Overlay
        If MapExists($g_mSignificant, $sCleanID) Then
            $g_aSigOverlayHwnd[$i] = _ManageOverlay($hTab, $tRect, $g_hSignificantColor, $g_aSigOverlayHwnd[$i], True)
        Else
            If IsHWnd($g_aSigOverlayHwnd[$i]) Then _DeleteHandle($g_aSigOverlayHwnd[$i])
        EndIf
    Next
    _CleanSignificantMap()
EndFunc   ;==>_UpdateTabOverlays
;---------------------------------------------------------------------------------------
Func _GetCleanTabID($sText)
    If StringLeft($sText, 1) = "&" Then $sText = StringTrimLeft($sText, 3)
    If StringRight($sText, 1) = "*" Then $sText = StringTrimRight($sText, 2)
    Return $sText
EndFunc   ;==>_GetCleanTabID
;---------------------------------------------------------------------------------------
Func _CleanSignificantMap()
    If UBound($g_mSignificant) = 0 Then Return
    Local $aKeys = MapKeys($g_mSignificant)
    For $sKey In $aKeys
        Local $bFound = False
        For $i = 0 To UBound($g_aItemsText) - 1
            If $g_aItemsText[$i] == $sKey Then
                $bFound = True
                ExitLoop
            EndIf
        Next
        If Not $bFound Then MapRemove($g_mSignificant, $sKey)
    Next
EndFunc   ;==>_CleanSignificantMap
;---------------------------------------------------------------------------------------
Func _ToggleSignificant()
    Local $hTab = _GetHwnd_SciTeTabCtrl()
    If @error Then Return

    Local $sID = _GetCleanTabID(_SciTE_GetTabText($hTab, _GUICtrlTab_GetCurFocus($hTab)))

    If MapExists($g_mSignificant, $sID) Then
        MapRemove($g_mSignificant, $sID)
    Else
        $g_mSignificant[$sID] = True
    EndIf
    $g_sLastState = "?"
EndFunc   ;==>_ToggleSignificant
;---------------------------------------------------------------------------------------
Func _ManageOverlay($hTab, $tRect, $iColor, $hExisting, $bIsTopBar)
    If $iColor = 0 Then
        If IsHWnd($hExisting) Then _DeleteHandle($hExisting)
        Return 0
    EndIf

    Local $tPoint = DllStructCreate("int X;int Y")
    DllStructSetData($tPoint, "X", $tRect.Left)
    DllStructSetData($tPoint, "Y", $tRect.Top)
    _WinAPI_ClientToScreen($hTab, $tPoint)

    Local $iX = DllStructGetData($tPoint, "X")
    Local $iY = DllStructGetData($tPoint, "Y")
    Local $iW = $tRect.Right - $tRect.Left
    Local $iH = ($bIsTopBar ? $g_iTopBarHeight : ($tRect.Bottom - $tRect.Top))

    Local $hOverlay = $hExisting
    If Not IsHWnd($hOverlay) Then
        $hOverlay = GUICreate("", $iW, $iH, $iX, $iY, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_NOACTIVATE, $WS_EX_TRANSPARENT), $hTab)
        GUISetBkColor($iColor)
        WinSetTrans($hOverlay, "", ($bIsTopBar ? 150 : $g_iOpacity))
        GUISetState(@SW_SHOWNOACTIVATE, $hOverlay)
    Else
        WinMove($hOverlay, "", $iX, $iY, $iW, $iH)
        GUISetBkColor($iColor, $hOverlay)
    EndIf
    Return $hOverlay
EndFunc   ;==>_ManageOverlay
;---------------------------------------------------------------------------------------
Func _DeleteHandle(ByRef $hWnd)
    GUIDelete($hWnd)
    $hWnd = 0
EndFunc   ;==>_DeleteHandle
;---------------------------------------------------------------------------------------
Func _CleanupOverlays()
    For $i = 0 To UBound($g_aOverlayHwnd) - 1
        _DeleteHandle($g_aOverlayHwnd[$i])
        _DeleteHandle($g_aSigOverlayHwnd[$i])
    Next
EndFunc   ;==>_CleanupOverlays
;---------------------------------------------------------------------------------------
Func _GetHwnd_SciTeTabCtrl()
    Local $hTabCtrl = ControlGetHandle($g_SciTE_Handle, "", "SciTeTabCtrl1")
    If @error Then Return SetError(1, 0, Null)
    Return $hTabCtrl
EndFunc   ;==>_GetHwnd_SciTeTabCtrl
;---------------------------------------------------------------------------------------
Func _Exit()
    _CleanupOverlays()
    Exit
EndFunc   ;==>_Exit
;---------------------------------------------------------------------------------------
Func _SciTE_GetTabText($hTab, $iIndex)
    ; Static variables - Allocated ONLY ONCE
    Local Static $hProcess = 0
    Local Static $bIsTarget64 = False
    Local Static $pRemoteText = 0
    Local Static $pRemoteItem = 0
    Local Static $sTag = ""
    Local Static $bInitialized = False
    Local Static $tLocalItem = 0
    Local Static $iMaxLen = 512

    ; === Initialization Block: Runs ONLY ONCE ===
    If Not $bInitialized Then
        Local $iPID
        _WinAPI_GetWindowThreadProcessId($hTab, $iPID)

        $hProcess = _WinAPI_OpenProcess(BitOR($PROCESS_VM_OPERATION, $PROCESS_VM_READ, $PROCESS_VM_WRITE, $PROCESS_QUERY_INFORMATION), False, $iPID)
        If Not $hProcess Then Return ""

        If @OSArch = "X64" Then
            If Not _WinAPI_IsWow64Process($iPID) Then $bIsTarget64 = True
        EndIf

        $pRemoteText = _MemVirtualAllocEx($hProcess, 0, $iMaxLen * 2, $MEM_COMMIT, $PAGE_READWRITE)

        ; Define proper struct with padding for x64 alignment
        $sTag = $bIsTarget64 ? _
                "struct;uint Mask;uint State;uint StateMask;uint Padding;ptr Text;int TextMax;int Image;int Padding2;int64 Param;endstruct" : _
                "struct;uint Mask;uint State;uint StateMask;uint TextPtr;int TextMax;int Image;uint Param;endstruct"

        $tLocalItem = DllStructCreate($sTag)
        $pRemoteItem = _MemVirtualAllocEx($hProcess, 0, DllStructGetSize($tLocalItem), $MEM_COMMIT, $PAGE_READWRITE)

        $bInitialized = True
    EndIf

    ; === Fast Execution Block: Minimal CPU cycles ===
    DllStructSetData($tLocalItem, "Mask", 1) ; $TCIF_TEXT
    If $bIsTarget64 Then
        DllStructSetData($tLocalItem, "Text", $pRemoteText)
    Else
        DllStructSetData($tLocalItem, "TextPtr", $pRemoteText)
    EndIf
    DllStructSetData($tLocalItem, "TextMax", $iMaxLen)

    ; Write the local struct to the pre-allocated remote memory
    _WinAPI_WriteProcessMemory($hProcess, $pRemoteItem, DllStructGetPtr($tLocalItem), DllStructGetSize($tLocalItem), 0)

    ; Request data from SciTE (0x133C = TCM_GETITEMW)
    Local $iRet = _SendMessage($hTab, 0x133C, $iIndex, $pRemoteItem)

    Local $sText = ""
    If $iRet Then
        Local $tResult = DllStructCreate("wchar[" & $iMaxLen & "]")
        _WinAPI_ReadProcessMemory($hProcess, $pRemoteText, DllStructGetPtr($tResult), $iMaxLen * 2, 0)
        $sText = DllStructGetData($tResult, 1)
    EndIf

    Return $sText
EndFunc   ;==>_SciTE_GetTabText
;---------------------------------------------------------------------------------------

 

Edited by ioa747
Script Version: 0.10 - LastState as Global

I know that I know nothing

Posted

I tested version 0.11 (both compiled as 32 and 64 bit) on Windows 11 Home 25H2.
Everything works fine 👍


 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Posted
...
_Singleton(@ScriptName)
While Not WinExists(WinGetHandle('[CLASS:SciTEWindow]')) ; added this..
    Sleep(2000)
WEnd
...
While WinExists($g_SciTE_Handle)
    ; Update only if SciTE is visible/active
    _SciTEState()
    Sleep(100)
WEnd
ShellExecute(@AutoItExe, '"' & @ScriptFullPath & '"') ; ..because of the self restart  =)
...

That way it's always on.
Note: don't do what I do. Am dangerous ( because am lazy ) 😅

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)

oops. I think is all good 😅

Spoiler

..interesting:

Spoiler
...
;~ Opt('TrayIconHide', 1)
TraySetIcon(StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 0, -1) - 1) & "\SciTE\SciTE.exe", 0)
TraySetToolTip(@ScriptName & '  -  ' & (@AutoItX64 ? "x64" : "x86") & @LF & "SciTE not loaded" & @LF & " ")
_Singleton(@ScriptName)

While Not WinExists(WinGetHandle('[CLASS:SciTEWindow]'))
    Sleep(2000)
WEnd
...
_EnableHighDPI(_GetProcessDPIAwarenessLevel($g_SciTE_Handle))

TraySetToolTip(@ScriptName & '  -  ' & (@AutoItX64 ? "x64" : "x86") & @LF & "DPI_AWARE: " & _GetProcessDPIAwarenessLevel($g_SciTE_Handle) & @LF & " ")


While WinExists($g_SciTE_Handle)
    ; Update only if SciTE is visible/active
    _SciTEState()
    Sleep(100)
WEnd
ShellExecute(@AutoItExe, '"' & @ScriptFullPath & '"')
...

 

I did more to my edit than what I showed. I first tested on a remote desktop via RDP. And the prior versions didn't show the DPI mishap and toying with the tray icon I saw that on my hardware PC it shows DPI awareness -4 and that makes sense but the RDP one shows -1 🤔
Don't know how the OS does anything but ... this is something that had no clue would be like that.

It all works great in v0.11. But I wanted to share this because I just did not know: Why did v0.7 worked on the RDP session and not on the local one, and now I know :)
Note: limited testing on a single monitor RDP. Would have to dig deeper on "Use all my monitors for the remote session" but am not that curious.

Edit1: Did not try on the same version of SciTE 😕

Edit2:
image.thumb.png.d4c4dd6b3d2038315945dd067974596a.png

...on RDP Ctrl+Shift+6 does the above on "Version 5.5.6   Scintilla:5.5.6   Lexilla:5.4.4 Jun  5 2025 10:01:05 "

 

Edited by argumentum
oops

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...