Jump to content

Best way to make a scrolling log w/o flicker? (w/removing old lines)


Go to solution Solved by Melba23,

Recommended Posts

Posted

I want to have a scrolling log that my script will periodically append lines to. I have done this with a GUI with an edit control but the problem is that an edit control has a limited amount of text that it can hold so I want to keep removing the oldest lines from the edit control when that limit is reached before I add a new line. I have gotten this to work except that it flickers pretty badly and is also slow.

Here is my code:

#include <GuiEdit.au3>
#include <WindowsConstants.au3>
#include <date.au3>
#include <array.au3>
#include <GuiListBox.au3>

Opt("GUIOnEventMode", 1)
Opt("GUIResizeMode", $GUI_DOCKAUTO)

$gui_width=1085
$gui_height=483
$Form1 = GUICreate("TEST", $gui_width, $gui_height, -1, -1, BitOR($GUI_SS_DEFAULT_GUI,$WS_MAXIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_TABSTOP))
$aiwe = GUICtrlCreateEdit("", 0, 0, $gui_width, $gui_height, BitOR($GUI_SS_DEFAULT_EDIT,$ES_READONLY))
_GUICtrlEdit_SetLimitText($aiwe,15000)
GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKBOTTOM)
GUISetState(@SW_SHOW)

GUISetOnEvent($GUI_EVENT_CLOSE, "closebuttonfunc")
func closebuttonfunc()
    Exit
EndFunc

While 1
    sleep(100)
    logout('TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE ')
WEnd

func logout($msg)
    $systime=_Date_Time_GetSystemTime()
    $systime=_Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($systime))
    $darray=_Date_Time_SystemTimeToArray($systime)
    $datetime=StringFormat("%04d/%02d/%02d %02d:%02d:%02d.%03d", $darray[2], $darray[0], $darray[1], $darray[3], $darray[4], $darray[5], $darray[6])

    ;below is for limiting the output lines
    local $logcharlimit=_GUICtrlEdit_GetLimitText($aiwe)
    local $lines=StringSplit(_GUICtrlEdit_GetText($aiwe),@CRLF,3)
    local $msgtoadd=$datetime&' '&$msg&@CRLF
    While StringLen(_ArrayToString($lines,@CRLF)&$msgtoadd)>=$logcharlimit      ;if adding the new $msg would put us over the char limit then delete the oldest (top) line
        _ArrayDelete($lines,0)
    WEnd

    _GUICtrlEdit_BeginUpdate($aiwe)
    _GUICtrlEdit_SetText($aiwe,_ArrayToString($lines,@CRLF))
    _GUICtrlEdit_AppendText($aiwe, $msgtoadd)
    _GUICtrlEdit_EndUpdate($aiwe)
    _GUICtrlEdit_Scroll($aiwe, 4)
EndFunc

I understand that the reason for the slowness and flickering is that I am rewriting all the lines into the edit box every time but I couldn't figure out a better way to delete only the top line.

Is there a better way?

I have tried using a list box control and just removing the top line when the limit of items is reached but that also flickers pretty badly...

I was curious of what other apps that have a scrolling log/buffer are using in their GUI's. I used the autoit window info tool on mIRC to see what it was using because it displays text really fast without any flickering and it says it is a class: "static". Not sure what that means...

  • Moderators
  • Solution
Posted

garbb,

This code still flickers a bit, but a lot less than your original on my machine. I have also changed the code to limit the text rewriting as much as possible: :)

#include <GUIConstantsEx.au3>
#include <GuiEdit.au3>
#include <WindowsConstants.au3>
#include <date.au3>
#include <array.au3>
#include <GuiListBox.au3>
#include <ScrollBarsConstants.au3>


Opt("GUIOnEventMode", 1)
Opt("GUIResizeMode", $GUI_DOCKAUTO)

$gui_width = 1085
$gui_height = 483
$logcharlimit = 15000 ; Max size of edit
$logcharbuffer = 500  ; Buffer to hold 2 x longest expected line

$Form1 = GUICreate("TEST", $gui_width, $gui_height, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP))
$aiwe = GUICtrlCreateEdit("", 0, 0, $gui_width, $gui_height, BitOR($GUI_SS_DEFAULT_EDIT, $ES_READONLY))
_GUICtrlEdit_SetLimitText($aiwe, $logcharlimit)
GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKBOTTOM)
GUISetState(@SW_SHOW)

GUISetOnEvent($GUI_EVENT_CLOSE, "closebuttonfunc")
Func closebuttonfunc()
    Exit
EndFunc   ;==>closebuttonfunc

While 1
    Sleep(100)
    logout('TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE TEST OF A LONG LINE ')
WEnd

Func logout($msg)
    $systime = _Date_Time_GetSystemTime()
    $systime = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($systime))
    $darray = _Date_Time_SystemTimeToArray($systime)
    $datetime = StringFormat("%04d/%02d/%02d %02d:%02d:%02d.%03d", $darray[2], $darray[0], $darray[1], $darray[3], $darray[4], $darray[5], $darray[6])

    _GUICtrlEdit_BeginUpdate($aiwe)
    ; Get line count
    $iLines_Count = _GUICtrlEdit_GetLineCount($aiwe)
    ; Check position of first char of last line is not inside buffer
    If _GUICtrlEdit_LineIndex($aiwe, $iLines_Count - 1) > $logcharlimit - $logcharbuffer Then
        ; Move down lines until we get to a value greater then the buffer
        For $i = 1 To $iLines_Count - 1
            $iCurrLine_Index = _GUICtrlEdit_LineIndex($aiwe, $i)
            If $iCurrLine_Index > $logcharbuffer Then
                ; Select and delete lines to that point
                _GUICtrlEdit_SetSel($aiwe, 0, $iCurrLine_Index - 1)
                _GUICtrlEdit_ReplaceSel($aiwe, "", False)
                ; No point in looking further
                ExitLoop
            EndIf
        Next
    EndIf
    ; Text is now smaller by at least twice the buffer size so add new text
    _GUICtrlEdit_AppendText($aiwe, $datetime & " " & $msg & @CRLF)
    _GUICtrlEdit_EndUpdate($aiwe)
    ; Select the last character and scroll it into view
    _GUICtrlEdit_SetSel($aiwe, -1, -1)
    _GUICtrlEdit_Scroll($aiwe, $SB_SCROLLCARET)
EndFunc   ;==>logout
As all code instructions need to be interpreted, updating every 100 ms without any flickering is asking a lot of any AutoIt GUI - especially when the majority of the GUI is text that needs to be redrawn! ;)

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

 

Posted

Wow. Yeah there still is some flickering but your code is significantly better and faster. I guess its because of only deleting the top of the log and good usage of beginupdate and endupdate?

Thanks!

  • Moderators
Posted

garbb,

Glad I could help. :)

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

 

Posted

If I add extended style $WS_EX_COMPOSITED to gui (double buffering?) then all flicker is gone for me.

$Form1 = GUICreate("TEST", $gui_width, $gui_height, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP), $WS_EX_COMPOSITED)

Well that is if the mouse cursor is hovering on it, and I've no Idea why that would occur, seems quite odd.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

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
  • Recently Browsing   0 members

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