Page 1 of 3

How Syncronize scroll in two gadgets?

Posted: Tue Aug 08, 2006 10:29 pm
by chen
Hi,

Is there a way to syncronize vertical scrolling in two gadgets?

Im trying to manage 2 editorGadgets, one of them contains data and
the other one row numbers... thats the idea.

The editorGadgets showing the number has a hidden vertical scroll bar,
I get this placing this gadget in a ContainerGadget.

The second Editor contains the data and its vertical scroll bar is visible..
I want using this bar to syncronize the up-down movement using only
this scroll bar....

Code: Select all

If OpenWindow(0, 0, 0, 322, 150, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
     
    ContainerGadget(2,5,5,50,133)
      EditorGadget(0, 5, 5, 65, 133)
    CloseGadgetList()
    EditorGadget(1, 60, 10, 250, 133)
    For a = 0 To 20 
      AddGadgetItem(0, a, Str(a)) 
      AddGadgetItem(1, a, "Line "+Str(a))
    Next 
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 
  EndIf 
Help required... thanks

Posted: Tue Aug 08, 2006 10:46 pm
by Xombie
You mean like ...

Code: Select all

EnableExplicit
;
Define.l HoldEvent, a, HoldLine, CurrentLine, lResult
;
Define.b DoQuit
;
If OpenWindow(0, 0, 0, 322, 150, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
   ContainerGadget(2,5,5,50,133) 
      EditorGadget(0, 5, 5, 65, 133) 
   CloseGadgetList() 
   EditorGadget(1, 60, 10, 250, 133) 
   For a = 0 To 20 
      AddGadgetItem(0, a, Str(a)) 
      AddGadgetItem(1, a, "Line "+Str(a)) 
   Next
   ;
   Repeat
      ;
      HoldEvent = WaitWindowEvent()
      ;
      If HoldEvent = #PB_Event_CloseWindow
         ; Close the program.
         DoQuit = #True
         ;
      ElseIf HoldEvent = #PB_Event_Gadget
         ;
         If EventGadget() = 1
            ;
            If EventType() = 1024
               ;
               HoldLine = SendMessage_(GadgetID(1), #EM_GETFIRSTVISIBLELINE, 0, 0)
               ;
               CurrentLine = SendMessage_(GadgetID(0), #EM_GETFIRSTVISIBLELINE, 0, 0)
               ; 
               lResult = SendMessage_(GadgetID(0), #EM_LINESCROLL, 0, HoldLine - CurrentLine)
               ;
            EndIf
            ;
         EndIf
         ;
      EndIf
      ;
   Until DoQuit
   ;
EndIf
;-
End
;-
... that?

EDIT: Incidentally, you can use...

Code: Select all

ShowScrollbar_(GadgetID(1), #SB_BOTH, #False)
... to turn off a control's scrollbar rather than using the container.

Posted: Tue Aug 08, 2006 10:53 pm
by chen
Yes, Like that...

One question?... Is there a way to do it without API or is the only way?

Thanks Xombie

Posted: Tue Aug 08, 2006 10:59 pm
by Xombie
Hmmm... not that I see. Maybe Fred could add it to the SetGadgetAttribute() and add something like a "#PB_Editor_LineNumber" constant?

Posted: Tue Aug 08, 2006 11:14 pm
by chen
Ok...
Im testing your code and I see this:

If you scroll down line by line the line number are sincronized with the data
But?
If you advance by page there are no one-one relation.... for example

65 point to line 66

Code: Select all

EnableExplicit
;
Define.l HoldEvent, a, HoldLine, CurrentLine, lResult
;
Define.b DoQuit
;
If OpenWindow(0, 0, 0, 322, 150, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
  ContainerGadget(2,5,5,50,138)
    EditorGadget(0, 5, 5, 65, 140)
  CloseGadgetList()
  EditorGadget(1, 60, 10, 250, 133)
  For a = 0 To 1000
    AddGadgetItem(0, a, Str(a))
    AddGadgetItem(1, a, "Line "+Str(a))
  Next
  ;
  Repeat
    ;
    HoldEvent = WaitWindowEvent()
    ;
    If HoldEvent = #PB_Event_CloseWindow
      ; Close the program.
      DoQuit = #True
      ;
    ElseIf HoldEvent = #PB_Event_Gadget
      ;
      If EventGadget() = 1
        ;
        If EventType() = 1024
          ;
          HoldLine = SendMessage_(GadgetID(1), #EM_GETFIRSTVISIBLELINE, 0, 0)
          ;
          CurrentLine = SendMessage_(GadgetID(0), #EM_GETFIRSTVISIBLELINE, 0, 0)
          ;
          lResult = SendMessage_(GadgetID(0), #EM_LINESCROLL, 0, HoldLine - CurrentLine)
          ;
        EndIf
        ;
      EndIf
      ;
    EndIf
    ;
  Until DoQuit
  ;
EndIf
;-
End
;-
DO I need to consider something else...?

Anyway Im going to try by myself.... thanks indeed...

Posted: Tue Aug 08, 2006 11:21 pm
by srod
Here's another way which synchronises even when dragging the thumb:

Code: Select all

Global oldproc

Procedure WindowCallback(hWnd, uMsg, wParam, lParam)
  Protected topitem, currentitem
    Result = CallWindowProc_(oldproc, hWnd, uMsg, wParam, lParam)
    Select uMsg
      Case #WM_VSCROLL
        SendMessage_(GadgetID(0), #WM_VSCROLL, wParam, lParam)
      Case #WM_KEYUP, #WM_KEYDOWN
        topitem = SendMessage_(GadgetID(1),#EM_GETFIRSTVISIBLELINE,0,0)
        currentitem = SendMessage_(GadgetID(0),#EM_GETFIRSTVISIBLELINE,0,0)
        If topitem-currentitem
          SendMessage_(GadgetID(1),#EM_LINESCROLL,0,0) ;Just for alignment!
          SendMessage_(GadgetID(0),#EM_LINESCROLL,0,topitem-currentitem)
        EndIf
    EndSelect
  ProcedureReturn Result
EndProcedure


If OpenWindow(0, 0, 0, 322, 150, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
    ContainerGadget(2,5,5,50,133) 
      EditorGadget(0, 5, 5, 65, 133) 
    CloseGadgetList() 
    EditorGadget(1, 60, 10, 250, 133) 
    For a = 0 To 200 
      AddGadgetItem(0, a, Str(a)) 
      AddGadgetItem(1, a, "Line "+Str(a)) 
    Next 
    oldproc=SetWindowLong_(GadgetID(1), #GWL_WNDPROC, @WindowCallback())
    Repeat
    ev=WaitWindowEvent()
    Until ev = #PB_Event_CloseWindow 
EndIf 
Incidentally, Sparkie posted some code which automatically placed line numbers in an editor gadget. That is, you do not need a second editor gadget etc.

Posted: Tue Aug 08, 2006 11:28 pm
by netmaestro
Dammit Srod!! where you buying your holster oil? [edit] Ha - tweaked my code to be 4 lines shorter than yours! :twisted:

Code: Select all

Procedure Callback(hwnd, msg, wparam, lparam) 
  result = #PB_ProcessPureBasicEvents 
  If msg=#WM_COMMAND 
    If IsGadget(1) 
      If lparam = GadgetID(1) 
        If wparam >> 16 = 1024 ; EN_UPDATE 
          SendMessage_(GadgetID(1), #EM_GETSCROLLPOS, 0, @pt.point) 
          SendMessage_(GadgetID(0), #EM_SETSCROLLPOS, 0, @pt) 
        EndIf 
      EndIf 
    EndIf 
    result = 0 
  EndIf 
  ProcedureReturn result 
EndProcedure 

If OpenWindow(0, 0, 0, 322, 150, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  SetWindowCallback(@Callback()) 
   ContainerGadget(2,5,5,50,133) 
      EditorGadget(0, 5, 5, 65, 133) 
   CloseGadgetList() 
   EditorGadget(1, 60, 10, 250, 133) 
   For a = 0 To 20 
      AddGadgetItem(0, a, Str(a)) 
      AddGadgetItem(1, a, "Line "+Str(a)) 
   Next 
   Repeat : Until WaitWindowEvent()=#WM_CLOSE 
EndIf 
End

Posted: Tue Aug 08, 2006 11:33 pm
by Xombie
chen wrote:Ok...
Im testing your code and I see this:

If you scroll down line by line the line number are sincronized with the data
But?
If you advance by page there are no one-one relation.... for example

65 point to line 66

Code: Select all

< snip snip >
DO I need to consider something else...?

Anyway Im going to try by myself.... thanks indeed...
It's checking the first visible line item and including anything that's even partially visible. Using a callback and checking for the scroll message rather than watching the line number of the edit control is much better - a la srod's code. That way they match exactly and you aren't constrained by PB's limitation of not providing events while moving the little scrollbar itself.

Posted: Tue Aug 08, 2006 11:37 pm
by srod
I like your code netmaestro. Pretty slick! :)

Which notification message corresponds to 1024?

Posted: Tue Aug 08, 2006 11:37 pm
by netmaestro
Gotcha srod - my code works with the mousewheel and yours doesnt :D :D :D

Posted: Tue Aug 08, 2006 11:40 pm
by srod
Pah, who needs a mousewheel? :lol:

Posted: Tue Aug 08, 2006 11:51 pm
by netmaestro
1024 is #EN_UPDATE:
MSDN wrote:The EN_UPDATE notification message is sent when an edit control is about to redraw itself.
Sorry, I really should have used the constant instead of the value, it would've been easier to read. I'm bad for that. :oops:

Posted: Tue Aug 08, 2006 11:58 pm
by srod
Yep, your's is definitely the best way. Very nice.

Posted: Wed Aug 09, 2006 12:57 am
by chen
Battle at the top :wink:

Help a lot thanks.....

Posted: Fri Oct 20, 2006 3:09 pm
by RegisLG
In my program i have the EnableExplicit activated.
I wanted to use netmastro's code, but i need to know the variable declation i must write in the procedure.

Can someone help me please ?