Jump to content

Highlighting the active tab item in SciTE


BugFix
 Share

Recommended Posts

I have already posted the script in the German forum, but I would like to make it available here as well.

  • Highlighting the active tab item in SciTE
  • Individual:
    • Frame color
    • Text color
    • Background color
    • Text color if not saved
    • Marker "Inactive item unsaved"
    • Marker position "Inactive item unsaved" optionally 'top' / 'bottom' / 'none'
  • Active item marking can be deactivated (if only unsaved marking is desired). The active item then receives the same marking as the inactive item when "unsaved".
  • Colors can be loaded as a scheme via INI
  • The compiled script can be ended with CMDLine parameter "/Exit".

Since Windows 10, the windows have a very "flat" look. One of the consequences of this is that it is not immediately apparent which item is active in a Tab-Ctrl.
When programming in SciTE, I usually have many tabs open at the same time. To make the active tab more visible, I draw it with a colored frame. In addition, unsaved tabs are marked separately with coloring of the top or bottom edge. The colors used for this can be stored individually as a scheme in an INI file.

Spoiler

; If INI is not available, default colors are loaded.
; INI-Name = Name_of_the_Exe.ini

[appearance]
; rect_highlight=true/false  "false" does NOT highlight the active item, default: "true".
rect_highlight=true
; idlepos=top/bottom/none    "none" does NOT mark unsaved inactive files, default: "top".
idlepos=top


[scheme]
; Specify which of the defined schemes should be active.
current=default


; One section for each scheme.
; scheme name
[default]
; the color of the rectangle of the active element
rect=0xCC483F
; the color of the text of the active element
text=0x800020
; the color of the background of the active element
bg=0xFFFFFF
; the color of the text of the active element if it is to be saved and is not saved
unsaved=0x3030FF
; the color of the top/bottom edge of an inactive element if it is to be saved and is not currently saved
idle=0x3030FF

Some schemes are predefined at the beginning of the script. Just try out what you like best.
I start the script via the autostart folder when Windows starts.

Here are a few pictures:

Active Tab tabitem_colored_0.png.dc386adea46252eb27ab1698ec4d650e.png   Active Tab, unsavedtabitem_colored_unsaved.png.8900235c0d6ac2515d4f3a9042463ce8.png

Active Tab, BG: blue / Text: white  tabitem_colored_2.png.fe6078f8b21d45940f9fe4457f08a1e5.png   ... BG: green / Text: white  tabitem_colored_3.png.64a07e3f29cb75727913b4b33b427bd4.png

Active Tab, left & right idle unsaved Tabstabitem_unsaved_idle_1.png.52df05ce8ba0e77fbc7344fc8a033b76.png

Active Tab unsaved too  tabitem_unsaved_idle_2.png.a46c0c5e0aa1b82686c75944aa51e0ed.png

;-- TIME_STAMP   2023-03-23 10:16:34   v 0.5

#cs
    v 0.5   [fixed] Flickering, a variable assignment was incorrect
            [fixed] Marking has failed by using keys ("F6", "Shift+F6") to change the buffer selection
    v 0.4   [added] Exit via CMDLine with parameter "/Exit"
            [added] Optionally adjustable via INI [appearance]:
                    - Mark active item: rect_highlight=true/false
                    - Position of the marker for "Inactive item unsaved": idlepos=top/bottom/none
    v 0.3   [added] Separate marker (colored line top) for "Inactive item unsaved".
    v 0.2   [added] Separate marking (text color) for unsaved files.
            [added] Loading of colors from an INI (color schemes) possible
#ce


#include <FontConstants.au3>
#include <GuiTab.au3>
#include <Misc.au3>
#include <WinAPIGdi.au3>
#include <WinAPISys.au3>
#include <WinAPIMisc.au3>
#include <WindowsConstants.au3>

Opt('TrayIconHide', 1)

If $CMDLINE[0] And $CMDLINE[1] = '/Exit' Then   ; CMD-Line: "@ScriptName.exe /Exit"
    Local $aProcessList = ProcessList(@ScriptName)
    For $i = 1 To $aProcessList[0][0] Step 1
        If $aProcessList[$i][1] <> @AutoItPID Then ProcessClose($aProcessList[$i][1])
    Next
EndIf

_Singleton(@ScriptName)


;~ HotKeySet("!{F8}", _End)            ; <Alt><F8> Beenden
OnAutoItExitRegister(_End)

Global $sINI = StringFormat("%s\%s.ini", @ScriptDir, StringTrimRight(@ScriptName, 4))
Global $gm_SciTE[]
$gm_SciTE.ExistsLast = 0
$gm_SciTE.ExistsCurr = 0

#cs
The colors can be defined in an INI file in the script folder.
If INI is not available, default colors are loaded.
INI-Name = Name_of_the_Exe.ini

[appearance]
; rect_highlight=true/false  "false" does NOT highlight the active item, default: "true".
rect_highlight=true

; idlepos=top/bottom/none    "none" does NOT mark unsaved inactive files, default: "top".
idlepos=top


[scheme]
; Specify which of the defined schemes should be active.
current=default

; One section for each scheme.
[default]
rect=0xCC483F
text=0x800020
bg=0xFFFFFF
unsaved=0x3030FF
idle=0x3030FF

[blue_invers]
rect=0xCC483F
text=0xFFF0F0
bg=0x800020
unsaved=0xA9A5F7
idle=0xA9A5F7

[green_invers]
rect=0x005F00
text=0xEDFFED
bg=0x409340
unsaved=0x1DE6B5
idle=0x1DE6B5

#ce

; appearance
$gm_SciTE.bHighlight       = (_IniOrDefault($sINI, 'rect_highlight', 'true', 'appearance') = 'true')
$gm_SciTE.IdlePos          = _IniOrDefault($sINI, 'idlepos', 'top', 'appearance')

; scheme: default (blue):
$gm_SciTE.RectColor        = _IniOrDefault($sINI, 'rect'   , 0xCC483F) ; BGR
$gm_SciTE.TextColor        = _IniOrDefault($sINI, 'text'   , 0x800020) ; BGR
$gm_SciTE.BGColor          = _IniOrDefault($sINI, 'bg'     , 0xFFFFFF) ; BGR
$gm_SciTE.TextColorUnsaved = _IniOrDefault($sINI, 'unsaved', 0x3030FF) ; BGR
$gm_SciTE.IdleUnsaved      = _IniOrDefault($sINI, 'idle'   , 0x3030FF) ; BGR

_CheckSciTE()   ; the effect takes place immediately
AdlibRegister(_CheckSciTE, 750)

While True
    Sleep(5000)
WEnd


Func _End()
    AdlibUnRegister(_CheckSciTE)
;~     MsgBox(0, 'SciTE TabItem', 'Beendet!')
    Exit
EndFunc


Func _CheckSciTE()
    If ProcessExists("SciTE.exe") Then
        $gm_SciTE.ExistsCurr = 1
        If $gm_SciTE.ExistsLast = 0 Then $gm_SciTE.ExistsLast = 1
        If $gm_SciTE.bHighlight Then
            _DrawTabItem()
            AdlibRegister(_MouseHoversTab, 150)
        EndIf
        _MarkUnsavedIdleTab()
    Else
        $gm_SciTE.ExistsCurr = 0
        If $gm_SciTE.ExistsLast = 1 Then
            $gm_SciTE.ExistsLast = 0
            If $gm_SciTE.bHighlight Then AdlibUnRegister(_MouseHoversTab)
        EndIf
    EndIf
EndFunc


Func _MouseHoversTab()
    Local Static $iHoverLast = 1    ; when starting the program, exit from the item must be simulated
    Local $mTab = _SciTE_GetActiveTabInfo()
    If @error Then Return
    Local $tPoint = _WinAPI_GetMousePos(True, $mTab.hTab)
    Local $tRect = $mTab.RectItem
    Local $isHover = _WinAPI_PtInRect($tRect, $tPoint)
    If $isHover = 1 And $iHoverLast = 0 Then
        $iHoverLast = 1
    ElseIf $isHover = 0 And $iHoverLast = 1 Then
        $iHoverLast = 0
        Return _DrawTabItem()
    EndIf
EndFunc


Func _MarkUnsavedIdleTab()
    If $gm_SciTE.IdlePos = 'none' Then Return
    Local $hTab = __GetHwnd_SciTeTabCtrl()
    If @error Then Return SetError(1)
    Local $iActive = _GUICtrlTab_GetCurFocus($hTab)
    For $i = 0 To _GUICtrlTab_GetItemCount($hTab) -1
        If $i = $iActive And $gm_SciTE.bHighlight Then ContinueLoop
        If StringRight(_GUICtrlTab_GetItemText($hTab, $i), 1) = '*' Then
            _DrawMarkerUnsaved($hTab, $i)
        EndIf
    Next
EndFunc


Func _DrawMarkerUnsaved($_hTab, $_iItem)
    Local $tRect = _GUICtrlTab_GetItemRectEx($_hTab, $_iItem)
    Local $tRectDraw = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct")
    If $gm_SciTE.IdlePos = 'top' Then
        $tRectDraw.Left   = $tRect.Left
        $tRectDraw.Top    = $tRect.Top -1
        $tRectDraw.Right  = $tRect.Right
        $tRectDraw.Bottom = $tRect.Top
    Else
        $tRectDraw.Left   = $tRect.Left
        $tRectDraw.Top    = $tRect.Bottom +2
        $tRectDraw.Right  = $tRect.Right
        $tRectDraw.Bottom = $tRect.Bottom +3
    EndIf
    Local $hDC = _WinAPI_GetDC($_hTab)
    Local $hPen = _WinAPI_CreatePen($PS_SOLID, 2, $gm_SciTE.IdleUnsaved)
    Local $hOldPen = _WinAPI_SelectObject($hDC, $hPen)
    _WinAPI_Rectangle($hDC, $tRectDraw)
    _WinAPI_SelectObject($hDC, $hOldPen)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_ReleaseDC(0, $hDC)
EndFunc


Func _DrawTabItem()
    Local $mTab = _SciTE_GetActiveTabInfo()
    If @error Then Return
    Local $hDC = _WinAPI_GetDC($mTab.hTab)
    Local $hFont = _WinAPI_CreateFont(14.5, 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _
        $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Lucida Sans Unicode Standard')
    Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont)
    Local $tRect = $mTab.RectItem       ; extract to variable - otherwise no ByRef access possible
    Local $dY = (@OSVersion = "Win_7" ? 2 : 1)
    _WinAPI_InflateRect($tRect, 2, $dY) ; enlarge rectangle
    _WinAPI_OffsetRect($tRect, 0, 1)    ; move rectangle down by 1px

    ; draw and fill rect
    Local $hPen = _WinAPI_CreatePen($PS_SOLID, 2, $gm_SciTE.RectColor)
    Local $hBrush = _WinAPI_CreateSolidBrush($gm_SciTE.BGColor)
    Local $hOldPen = _WinAPI_SelectObject($hDC, $hPen)
    Local $hOldBrush = _WinAPI_SelectObject($hDC, $hBrush)
    _WinAPI_Rectangle($hDC, $tRECT)

    ; draw text
    If StringRight($mTab.Item, 1) = '*' Then
        _WinAPI_SetTextColor($hDC, $gm_SciTE.TextColorUnsaved)
    Else
        _WinAPI_SetTextColor($hDC, $gm_SciTE.TextColor)
    EndIf
    _WinAPI_SetBkColor($hDC, $gm_SciTE.BGColor)
    ; move the text down a bit more
    _WinAPI_OffsetRect($tRect, 0, 3)
    _WinAPI_DrawText($hDC, $mTab.Item, $tRect, BitOR($DT_BOTTOM,$DT_CENTER))

    ; clear ressources
    _WinAPI_SelectObject($hDC, $hOldFont)
    _WinAPI_DeleteObject($hFont)
    _WinAPI_SelectObject($hDC, $hOldPen)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_SelectObject($hDC, $hOldBrush)
    _WinAPI_DeleteObject($hBrush)
    _WinAPI_ReleaseDC(0, $hDC)
EndFunc


Func _SciTE_GetActiveTabInfo()
    Local $mResult[], $hTab = __GetHwnd_SciTeTabCtrl()
    If @error Then Return SetError(1)
    $mResult.hTab     = $hTab
    $mResult.Index    = _GUICtrlTab_GetCurFocus($hTab)
    $mResult.Item     = _GUICtrlTab_GetItemText($hTab, $mResult.Index)
    $mResult.RectItem = _GUICtrlTab_GetItemRectEx($hTab, $mResult.Index)
    Return $mResult
EndFunc


Func __GetHwnd_SciTE()
    Local $hScite = WinGetHandle('[ACTIVE]')
    If _WinAPI_GetClassName($hScite) = 'SciTEWindow' Then
        Return $hScite
    Else
        Return SetError(1, 0, Null)
    EndIf
EndFunc


Func __GetHwnd_SciTeTabCtrl()
    Local $hScite = __GetHwnd_SciTE()
    If @error Then Return SetError(1, 0, Null)
    Local $aChild, $hWndTab = Null
    $aChild = _WinAPI_EnumChildWindows($hScite) ; only visible
    If Not @error Then
        For $i = 1 To $aChild[0][0]
            If $aChild[$i][1] = "SciTeTabCtrl" Then
                $hWndTab = $aChild[$i][0]
                ExitLoop
            EndIf
        Next
    EndIf
    Return SetError(($hWndTab = Null ? 1 : 0), 0, $hWndTab)
EndFunc


; read from INI if exists
Func _IniOrDefault($_sINI, $_sKey, $_sDefault, $_sec=Null)
    Local $sVal = $_sDefault, $sSec = $_sec = Null ? 'scheme' : $_sec
    If FileExists($_sINI) Then
        If $sSec = 'scheme' Then $sSec = IniRead($_sINI, 'scheme', 'current', 'default')
        $sVal = IniRead($_sINI, $sSec, $_sKey, $_sDefault)
    EndIf
    Return $sVal
EndFunc

 

SciTE_DrawTabItem.au3

Best Regards BugFix  

Link to comment
Share on other sites

  • Moderators

bugfix,

Very nice - thanks for posting.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...