Seite 1 von 1

EditorGadget - Cursorproblem

Verfasst: 04.11.2007 14:54
von RSBasic
Hallo,
ich habe zurzeit ein Problem mit dem EditorGadget.
Beim Schreiben fiel mir auf, dass beim EditorGadget, den ich in PB erstellt habe, einen Unterschied zu den anderen Editoren hat.
Zum Beispiel: PB Editor, Windows Editor (Notepad) etc.
Wenn man einen langen Text geschrieben hat und der Cursor befindet sich am Ende des Textes, aber wenn man mit der Rücktaste den Text nach und nach wieder löscht, dann stellt man fest, dass der Cursor und der Text selber nach oben springt.
Bei den anderen „normalen“ Editoren, ist der Fall nicht.
Der Cursor bleibt weiterhin beim Drücken der Rücktaste unten (Ende der Zeile des EditorGadgets).
Das einigste worauf man achten muss, ist die Cursorposition.
Hier ein Screenshot, ein Ablauf des Problems.
Jetzt können alle User das Problem verstehen (hoffentlich nicht ;-) )

Screenshot:
Bild

Alte Source-Beispiele:
Shardik hat geschrieben:Dieses Code-Beispiel klemmt die Rück-/Backspace-Taste im Editor-Gadget mit Hilfe eines Callback komplett ab:

Code: Alles auswählen

Procedure EditorCallback(WindowHandle.L, Msg.L, wParam.L, lParam.L)
  Shared PreviousCallback.L

  If Msg = #WM_KEYDOWN
    If wParam = #VK_BACK
      ProcedureReturn 0
    EndIf
  EndIf

  ProcedureReturn CallWindowProc_(PreviousCallback, WindowHandle, Msg, wParam, lParam)
EndProcedure

OpenWindow(0,0,0,500,500,"Windows-Vorlage",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
EditorGadget(1,10,10,480,480,0)
PreviousCallback = SetWindowLong_(GadgetID(1), #GWL_WNDPROC, @EditorCallback())
SetActiveGadget(1)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Der Nachteil liegt darin, daß der eingegebene Text nicht mehr mit der Rück-Taste gelöscht werden kann. Dagegen funktioniert das Löschen von Zeichen mit der "Entf"-Taste (z.B. nach Änderung der Cursor-Position mit den Pfeiltasten) weiterhin problemlos. Soll die Zurück-Taste nur auf der ersten Zeichenposition einer Zeile abgeschaltet werden, müßte eine entsprechende Abfrage noch im Callback eingebaut werden.
Shardik hat geschrieben:Hier ist die Version, bei der die Rück-Taste nur für die erste Spalte abgeschaltet ist (wie die Ermittlung der Cursor-Position im EditorGadget funktioniert, hat netmaestro im englischen Forum bereits gezeigt: http://www.purebasic.fr/english/viewtop ... 50&start=3)

Code: Alles auswählen

Procedure EditorCallback(WindowHandle.L, Msg.L, wParam.L, lParam.L)
  Shared PreviousCallback.L

  Protected CharPosition.L
  Protected CurrentColumn.L
  Protected CurrentLine.L

  If Msg = #WM_KEYDOWN
    If wParam = #VK_BACK
      SendMessage_(GadgetID(1), #EM_GETSEL, @CharPosition, 0)
      CurrentLine = SendMessage_(GadgetID(1), #EM_LINEFROMCHAR, -1, 0)
      CurrentColumn = CharPosition - SendMessage_(GadgetID(1), #EM_LINEINDEX, -1, 0)

      If CurrentColumn = 0
        ProcedureReturn 0
      EndIf
    EndIf
  EndIf

  ProcedureReturn CallWindowProc_(PreviousCallback, WindowHandle, Msg, wParam, lParam)
EndProcedure

OpenWindow(0,0,0,500,500,"Windows-Vorlage",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
EditorGadget(1,10,10,480,480,0)
PreviousCallback = SetWindowLong_(GadgetID(1), #GWL_WNDPROC, @EditorCallback())
SetActiveGadget(1)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
#NULL hat geschrieben:

Code: Alles auswählen

OpenWindow(0,0,0,500,200,"Windows-Vorlage",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
  EditorGadget(1,10,10,480,180,0) :: SetActiveGadget(1)
Repeat
  event = WaitWindowEvent()
  SendMessage_(GadgetID(1), #EM_SCROLL, #SB_LINEDOWN, 0)
Until event = #PB_Event_CloseWindow
so geht schon das was du willst (der code ist in der form natürlich quark), aber du kriegst andere probleme, z.b. kann man mit dem cursor zu weit hoch laufen. vielleicht mußt du vorher die altuelle scrollweite checken, oder die cursor position.
kannst das ja auch mal in ein callback bauen und nur bei rücktaste ausführen. vielleicht eigntet sich auf eine andere konstante als #SB_LINEDOWN.
mußte mal hier gucken: http://msdn2.microsoft.com/en-us/library/bb775458.aspx ..bei > messages > EM_SCROLL oder WM_VSCROLL

<edit>

Code: Alles auswählen

SendMessage_(GadgetID(1), #WM_VSCROLL, #SB_ENDSCROLL, 0)
scheint ganz gut zu gehen.
Falko hat geschrieben:Naja, wer den Notepadeditor kennt, weiss, was gemeint ist :lol:
Anscheinend kann das EditorGadget() ohne API sowas nicht!!

Enter so lange drücken, bis der Cursor unten ist und sich der vertikale
Scrollbalken zeigt und verkleinert. Danach mal einfach die Backspacetaste
festhalten, sodaß der Cursor wieder bis zur ersten Zeile.
Dann mal die Augen aufmachen und sich wundern, warum das beim EditorGadget mit dem Cursor anders ist. :roll:

Mit dem Stringgadget wird der Notepad schon eher getroffen, ganz ohne API

Code: Alles auswählen

If OpenWindow(0,0,0,500,500,"Windows-Vorlage",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(0))
    StringGadget(1,10,10,480,480,"",#ES_MULTILINE| #ES_AUTOHSCROLL|#WS_VSCROLL )
  EndIf
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf 
[Edit] Zu langsam. Vorgänger hat es gut beschrieben. Nun macht mal
den Scrollbalken wieder weg :lol:
[/Edit]

Gruß Falko
Problembeschreibung in der dritten Person:
Shardik hat geschrieben:Hurra, ich habe es endlich kapiert... 8) :lol: :twisted:

Ich versuche einmal das Problem mit meinen Worten in Form einer Anleitung nachvollziehbar zu machen:

1.Schritt: RSBasics erstes Code-Beispiel aus dem ersten Beitrag kopieren, in die PureBASIC-IDE einfügen und starten
2.Schritt: Den Cursor mit Mausklick in Zeile 1 und Position 1 sichtbar machen
3.Schritt: Solange <Enter> drücken bis ein Scroll-Balken erscheint
4.Schritt: Dann noch dreimal zusätzlich <Enter> drücken
5.Schritt: Dann dreimal die Rück-Taste drücken

Ergebnis: Der Cursor wandert hoch, aber eigentlich sollte er ja am Ende des Gadgets stehenbleiben und nur der Scroll-Balken sollte sich verkürzen

6.Schritt: Noch einmal die Rück-Taste drücken und voilá: der Scrollbalken ist weg und der Cursor steht wieder am Ende des Editor-Gadgets :wink:

Jetzt muß nur noch jemand eine Lösung finden... :oops:
--------------------------------------------------
Thread bereinigt wegen unverständlicher Problembeschreibung
(RSBasic)

Verfasst: 06.11.2007 18:21
von #NULL

Code: Alles auswählen

Procedure EditorCallback(WindowHandle.L, Msg.L, wParam.L, lParam.L)
  Shared PreviousCallback.L

  If Msg = #WM_KEYDOWN
    If wParam = #VK_BACK
      Debug "here"
      SendMessage_(GadgetID(1), #WM_VSCROLL, #SB_PAGEDOWN, 0)
    EndIf
  EndIf

  ProcedureReturn CallWindowProc_(PreviousCallback, WindowHandle, Msg, wParam, lParam)
EndProcedure

OpenWindow(0,0,0,500,200,"Windows-Vorlage",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
EditorGadget(1,10,10,480,180,0)
PreviousCallback = SetWindowLong_(GadgetID(1), #GWL_WNDPROC, @EditorCallback())
SetActiveGadget(1)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Verfasst: 06.11.2007 19:37
von RSBasic
@#NULL
Ah sehr gut, danke :D
Ich dachte schon, es gibt doch keine Lösung mehr :mrgreen:

Aber ein kleines Problem habe ich noch.

Wenn man die Rücktaste drückt, dann kommt ja natürlich "Debug "here".
Das ist ja nicht das Problem, sondern...
Bild

Kannst du oder kann man das noch beheben?
Dann wärs perfekt :allright:
:)

PS: Thread wurde bereinigt und hoffe, es ist so ok.

Verfasst: 06.11.2007 20:50
von Falko
Das würde ich so machen:

Code: Alles auswählen

...
SendMessage_(GadgetID(1), #WM_VSCROLL, #SB_PAGEUP, 0)
...

Verfasst: 06.11.2007 20:58
von RSBasic
@Falko
Danke, das Problem siehe Screenshot wurde behoben :)

@Shardik & @#NULL & @Falko
Ich möchte mich nochmal bei euch bedanken.
Auch wenn ich mich am Anfang schlecht ausgedrückt habe, ihr wart ne große Hilfe :allright:
Danke :)