Scintilla scrollen

Anfängerfragen zum Programmieren mit PureBasic.
stevie1401
Beiträge: 700
Registriert: 19.10.2014 15:51
Kontaktdaten:

Scintilla scrollen

Beitrag von stevie1401 »

Ich versuche nach ganz unten zu scrollen mit folgendem Code:

Code: Alles auswählen

 
TxtLaenge = ScintillaSendMessage(2, #SCI_GETLENGTH , 0, 0)
ScintillaSendMessage(2, #SCI_GOTOPOS, txtlaenge)
Das funktioniert nur dann, wenn der Text innerhalb des Scintillagadgets nicht automatisch gebrochen wird.

Wenn der hinzugefügte Text gebrochen wird, also länger als das Scintillagadget breit ist, dann scrollt es nur bis zu vor oder vorvorletzten Zeile.
Hat jemand eine Idee, wie man das beheben kann?

(Purebasic 5.24)
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Scintilla scrollen

Beitrag von HeX0R »

stevie1401 hat geschrieben:Ich versuche nach ganz unten zu scrollen mit folgendem Code:

Code: Alles auswählen

 
TxtLaenge = ScintillaSendMessage(2, #SCI_GETLENGTH , 0, 0)
ScintillaSendMessage(2, #SCI_GOTOPOS, txtlaenge)
Hmm... bei mir passiert da gar nichts.
Benutzeravatar
jear
Beiträge: 288
Registriert: 17.10.2004 01:59
Wohnort: Ammerland

Re: Scintilla scrollen

Beitrag von jear »

HeX0R hat geschrieben:
stevie1401 hat geschrieben:Ich versuche nach ganz unten zu scrollen mit folgendem Code:

Code: Alles auswählen

 
TxtLaenge = ScintillaSendMessage(2, #SCI_GETLENGTH , 0, 0)
ScintillaSendMessage(2, #SCI_GOTOPOS, txtlaenge)
Hmm... bei mir passiert da gar nichts.
TxtLaenge = txtlaenge ???
Man ist nie zu alt zum lernen, auch wenn man dabei manchmal alt aussieht!
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Scintilla scrollen

Beitrag von Danilo »

Erstmal ein Code der das Problem zeigt:

Code: Alles auswählen

Procedure MakeScintillaText(text.s)
    Static sciText.s
    CompilerIf #PB_Compiler_Unicode
        sciText = Space(StringByteLength(text, #PB_UTF8))
        PokeS(@sciText, text, -1, #PB_UTF8)
    CompilerElse
        sciText = text
    CompilerEndIf
    ProcedureReturn @sciText
EndProcedure

If OpenWindow(0, 0, 0, 320, 390, "ScintillaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    
    If InitScintilla()
        ScintillaGadget(0, 10, 10, 300, 370, 0)
        SetActiveGadget(0)
        
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows
            If OSVersion() >= #PB_OS_Windows_Vista
                ScintillaSendMessage(0, #SCI_SETTECHNOLOGY, #SC_TECHNOLOGY_DIRECTWRITE)
            EndIf
        CompilerEndIf
        
        ScintillaSendMessage(0, #SCI_SETWRAPMODE,   #SC_WRAP_WORD)
        
        For i = 0 To 31
            Text$ + " line"
            append$ = "Line "+Str(i)+": "+Text$+Chr(10)
            ScintillaSendMessage(0, #SCI_APPENDTEXT, Len(append$), MakeScintillaText(append$))
        Next
        
        TxtLaenge = ScintillaSendMessage(0, #SCI_GETLENGTH , 0, 0)
        ScintillaSendMessage(0, #SCI_GOTOPOS, TxtLaenge)
        
        ScintillaSendMessage(0, #SCI_SCROLLTOEND)
        
    EndIf
    
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
stevie1401 hat geschrieben:Wenn der hinzugefügte Text gebrochen wird, also länger als das Scintillagadget breit ist, dann scrollt es nur bis zu vor oder vorvorletzten Zeile.
Hat jemand eine Idee, wie man das beheben kann?
Das ist leider etwas komplizierter, siehe Scintilla Documentation - Line Wrapping:
Wrapping is not performed immediately there is a change but is delayed until the display is redrawn. This delay improves performance by allowing a set of changes to be performed and then wrapped and displayed once. Because of this, some operations may not occur as expected. If a file is read and the scroll position moved to a particular line in the text, such as occurs when a container tries to restore a previous editing session, then the scroll position will have been determined before wrapping so an unexpected range of text will be displayed. To scroll to the position correctly, delay the scroll until the wrapping has been performed by waiting for an initial SCN_PAINTED notification.
Das scrollen musst Du also verzögern, bis das Gadget neu gezeichnet wurde. Erst beim zeichnen
werden die Positionen, die durch das Wordwrap anders sind, richtig berechnet.

Für die Umsetzung gibt es sicherlich verschiedene Ansätze. Ich würde sowas wie eine LinkedList machen,
der Du Befehle hinzufügst, die dann bei der Nachricht #SCN_PAINTED im Scintilla-Callback abgearbeitet werden.

Ein simples Beispiel dazu:

Code: Alles auswählen

Global NewList ScintillaPaintedCommands()

Enumeration ScintillaPaintedCommands
    #SCROLL_TO_END
    #SET_CURSOR_TO_END
EndEnumeration

Procedure MakeScintillaText(text.s)
    Static sciText.s
    CompilerIf #PB_Compiler_Unicode
        sciText = Space(StringByteLength(text, #PB_UTF8))
        PokeS(@sciText, text, -1, #PB_UTF8)
    CompilerElse
        sciText = text
    CompilerEndIf
    ProcedureReturn @sciText
EndProcedure

Procedure ScintillaCallBack(Gadget, *scinotify.SCNotification)
    If *scinotify\nmhdr\code = #SCN_PAINTED;#SCN_UPDATEUI
        ForEach ScintillaPaintedCommands()
            Select ScintillaPaintedCommands()
                Case #SCROLL_TO_END
                    ScintillaSendMessage(Gadget, #SCI_SCROLLTOEND)
                Case #SET_CURSOR_TO_END
                    ScintillaSendMessage(Gadget, #SCI_GOTOPOS,
                                         ScintillaSendMessage(Gadget, #SCI_GETLENGTH , 0, 0))
                    ;ScintillaSendMessage(Gadget, #SCI_SCROLLCARET)
            EndSelect
        Next
        ClearList( ScintillaPaintedCommands() )
    EndIf
EndProcedure


If OpenWindow(0, 0, 0, 320, 390, "ScintillaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    
    If InitScintilla()
        ScintillaGadget(0, 10, 10, 300, 370, @ScintillaCallBack())
        SetActiveGadget(0)
        
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows
            If OSVersion() >= #PB_OS_Windows_Vista
                ScintillaSendMessage(0, #SCI_SETTECHNOLOGY, #SC_TECHNOLOGY_DIRECTWRITE)
            EndIf
        CompilerEndIf
        
        ScintillaSendMessage(0, #SCI_SETWRAPMODE,   #SC_WRAP_WORD)

        For i = 0 To 31
            Text$ + " line"
            append$ = "Line "+Str(i)+": "+Text$+Chr(10)
            ScintillaSendMessage(0, #SCI_APPENDTEXT, Len(append$), MakeScintillaText(append$))
            
            If AddElement( ScintillaPaintedCommands() )
                ScintillaPaintedCommands() = #SET_CURSOR_TO_END
            EndIf
            ScintillaSendMessage(0, #SCI_SCROLLTOEND)
            
            ; Zeile zur Verzögerung, um es besser zu sehen
            ;While WindowEvent():Wend : Delay(400)
            
        Next
        
    EndIf
    
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Scintilla scrollen

Beitrag von Nino »

Und um hier keine wichtige Frage offen zu lassen ...
jear hat geschrieben:TxtLaenge = txtlaenge ???
Ja.
Benutzeravatar
jear
Beiträge: 288
Registriert: 17.10.2004 01:59
Wohnort: Ammerland

Re: Scintilla scrollen

Beitrag von jear »

Nino hat geschrieben:Und um hier keine wichtige Frage offen zu lassen ...
jear hat geschrieben:TxtLaenge = txtlaenge ???
Ja.
Nö, kann nicht sein.
Man ist nie zu alt zum lernen, auch wenn man dabei manchmal alt aussieht!
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Scintilla scrollen

Beitrag von Nino »

jear hat geschrieben:Nö, kann nicht sein.
Nö? Wieso denn nicht?
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Scintilla scrollen

Beitrag von Danilo »

PB (und die meisten BASIC im Allgemeinen) unterscheidet nicht zwischen Groß- und Kleinschreibung (im Gegensatz zu Sprachen der C-Familie, z.B.: C, C++, C#, Java, ...).

Code: Alles auswählen

a = 12
deBUg A
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Scintilla scrollen

Beitrag von Nino »

Danilo hat geschrieben:PB (und die meisten BASIC im Allgemeinen) unterscheidet nicht zwischen Groß- und Kleinschreibung
Nö Danilo, das
kann nicht sein
:lol:
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Scintilla scrollen

Beitrag von Danilo »

Klingt komisch, ist aber so! :D
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Antworten