Seite 1 von 2

Scintilla scrollen

Verfasst: 19.02.2015 20:06
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)

Re: Scintilla scrollen

Verfasst: 19.02.2015 20:52
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.

Re: Scintilla scrollen

Verfasst: 19.02.2015 22:17
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 ???

Re: Scintilla scrollen

Verfasst: 20.02.2015 10:03
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

Re: Scintilla scrollen

Verfasst: 20.02.2015 12:03
von Nino
Und um hier keine wichtige Frage offen zu lassen ...
jear hat geschrieben:TxtLaenge = txtlaenge ???
Ja.

Re: Scintilla scrollen

Verfasst: 20.02.2015 12:32
von jear
Nino hat geschrieben:Und um hier keine wichtige Frage offen zu lassen ...
jear hat geschrieben:TxtLaenge = txtlaenge ???
Ja.
Nö, kann nicht sein.

Re: Scintilla scrollen

Verfasst: 20.02.2015 12:38
von Nino
jear hat geschrieben:Nö, kann nicht sein.
Nö? Wieso denn nicht?

Re: Scintilla scrollen

Verfasst: 20.02.2015 12:42
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

Re: Scintilla scrollen

Verfasst: 20.02.2015 13:22
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:

Re: Scintilla scrollen

Verfasst: 20.02.2015 13:35
von Danilo
Klingt komisch, ist aber so! :D