Page 1 of 1

ScrollArea - Can it be butchered?

Posted: Thu Feb 20, 2020 12:35 pm
by IdeasVacuum
Windows only:

I would like to be able to scroll a ScrollArea Gadget by dragging the mouse on it's client area and not have scrollbars.

Any ideas?

Re: ScrollArea - Can it be butchered?

Posted: Thu Feb 20, 2020 1:33 pm
by firace
Something like this? (Still buggy though)

Code: Select all


OpenWindow(0, 0, 0, 405, 240, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
ScrollAreaGadget(0, 10, 10, 390,220, 575, 455, 30)
ButtonGadget  (1, 10, 10, 230, 30,"Button 1")
ButtonGadget  (2, 50, 250, 230, 30,"Button 2")
SetWindowLong_(GadgetID(0), #GWL_STYLE, GetWindowLong_(GadgetID(0), #GWL_STYLE)&~#WS_HSCROLL&~#WS_VSCROLL)
SetWindowPos_(GadgetID(0), 0,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE|#SWP_NOZORDER|#SWP_FRAMECHANGED)


Repeat
  e = WaitWindowEvent(50)
  
  select e  
      
    case 13116 : End 
    Case 513
      While WindowEvent() <> 514 
        
        SetGadgetAttribute(0, #PB_ScrollArea_X, WindowMouseX(0))
        SetGadgetAttribute(0, #PB_ScrollArea_Y, WindowMouseY(0))
      Wend  
      
  EndSelect 
ForEver


Re: ScrollArea - Can it be butchered?

Posted: Thu Feb 20, 2020 1:55 pm
by spikey
Spy++ tells me that the ScrollAreaGadget gets the usual selection of WM_ messages.

A search for 'subclass scrollarea' found (amongst others):-
viewtopic.php?f=13&t=42202
viewtopic.php?f=13&t=39845
viewtopic.php?f=7&t=30143

Re: ScrollArea - Can it be butchered?

Posted: Thu Feb 20, 2020 2:19 pm
by RASHAD
Hi IdeasVacuum
I did the next snippet long time back perhaps it could be of some use

Code: Select all

Global imgw,imgh,Down,oldx,oldy,m.TRACKMOUSEEVENT
m\cbSize = SizeOf(m)
m\dwFlags = #TME_LEAVE

Procedure IsMouseOver(hWnd) 
  GetWindowRect_(hWnd,mr.RECT)
  GetCursorPos_(mp.POINT) 
  Result = PtInRect_(mr,mp\y << 32 + mp\x) 
  ProcedureReturn Result 
EndProcedure

Procedure WndProc(hwnd, uMsg, wParam, lParam)
  result = #PB_ProcessPureBasicEvents 
  Select uMsg    
    Case #WM_MOUSEMOVE
      GetCursorPos_(p.POINT)      
      ScreenToClient_(WindowID(0),p)
      m\hwndTrack =WindowID(0)
      TrackMouseEvent_(@m)
      If IsGadget(1) And IsMouseOver(GadgetID(1)) And Down = 1
        SetCursor_(LoadCursor_(0, #IDC_SIZEALL))
        MoveWindow_(GadgetID(1),GadgetX(1)+p\x-oldx,GadgetY(1)+p\y-oldy,imgw,imgh,1)
        ;If (GadgetX(1)+GadgetWidth(1)) > (GadgetX(0)+GadgetWidth(0))
        ;  SetGadgetAttribute(0, #PB_ScrollArea_X,GadgetX(1)+p\x-oldx)
        ;EndIf
        If (GadgetX(1)+p\x-oldx+12) <= GadgetX(0)
          ;SetGadgetAttribute(0, #PB_ScrollArea_X,0)
          MoveWindow_(GadgetID(1),0,GadgetY(1)+p\y-oldy,imgw,imgh,1)
        ElseIf (GadgetY(1)+p\y-oldy+12) <= GadgetY(0)
          ;SetGadgetAttribute(0, #PB_ScrollArea_Y,0)
          MoveWindow_(GadgetID(1),GadgetX(1)+p\x-oldx,0,imgw,imgh,1)
        EndIf
      EndIf
      oldx = p\x
      oldy = p\y
      
    Case #WM_MOUSELEAVE
      Down = 0    
   
    Case #WM_MOUSEWHEEL
   
    Case #WM_MOVE
   
    Case #WM_MOVING
    
    Case #WM_SIZE
      MoveWindow_(GadgetID(10),10,10,WindowWidth(0)-20,WindowHeight(0)-20,1)
         
    Case #WM_LBUTTONUP
      Down = 0
           
   EndSelect
   
  ProcedureReturn result 
EndProcedure

LoadImage(0, #PB_Compiler_Home + "examples/sources/Data/Geebee2.bmp")
;ResizeImage(0, 500,500,#PB_Image_Smooth)
imgw = ImageWidth(0)
imgh = ImageHeight(0)

If OpenWindow(0, 0, 0, 800,600, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget| #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
  ContainerGadget(10,10,10,780,580,#PB_Container_Flat)
    ScrollAreaGadget(0, -2000, -2000, 4000,4000, 4000,4000,50)
      ShowScrollBar_(GadgetID(0), #SB_BOTH, #False)
      ImageGadget(1, 2000, 2000, imgw,imgh, ImageID(0))
    CloseGadgetList()
  CloseGadgetList()
  DisableGadget(10,1)
    
  SetWindowCallback(@WndProc())
  Repeat
    Select WaitWindowEvent()
      Case  #PB_Event_CloseWindow
        End 
        
      Case #WM_LBUTTONDOWN
        Down = 1
        If IsMouseOver(GadgetID(1))
          DisableGadget(10,1)
          GetCursorPos_(p.POINT)
          ScreenToClient_(WindowID(0),p)
          oldx = p\x
          oldy = p\y
        ElseIf IsMouseOver(GadgetID(0))
          DisableGadget(10,0)
          SetCursor_(LoadCursor_(0, #IDC_SIZEALL))
          SendMessage_(GadgetID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
        EndIf         
    EndSelect
  ForEver
EndIf

Re: ScrollArea - Can it be butchered?

Posted: Thu Feb 20, 2020 9:57 pm
by IdeasVacuum
Thanks Guys - all good stuff.

Rashad's method is absolutely beautiful! I'd like it to be an official, optional, setup for the gadget in PB 8)

Re: ScrollArea - Can it be butchered?

Posted: Fri Feb 21, 2020 1:54 pm
by RASHAD
Hi IdeasVacuum :)
Thanks for the nice compliment
Now for the recent time
Very simple and direct

Code: Select all

#SC_DragMove      = $F012

LoadImage(0, #PB_Compiler_Home + "examples/sources/Data/Geebee2.bmp")
imgw = ImageWidth(0)
imgh = ImageHeight(0)

If OpenWindow(0, 0, 0, 800,600, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget| #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
  ContainerGadget(10,10,10,780,480,#PB_Container_Flat)
    ScrollAreaGadget(0, -2000, -2000, 4000,4000, 4000,4000,50)
      ShowScrollBar_(GadgetID(0), #SB_BOTH, #False)
      ImageGadget(1, 2000, 2000, imgw,imgh, ImageID(0))
    CloseGadgetList()
  CloseGadgetList()
  DisableGadget(10,1)   

  Repeat
    Select WaitWindowEvent()
      Case  #PB_Event_CloseWindow
        Quit = 1
       
      Case #WM_LBUTTONDOWN
        GetCursorPos_(p.POINT)
        ScreenToClient_ (GadgetID(10), @p)
        If ChildWindowFromPoint_(GadgetID(10),p\y << 32 + p\x) = GadgetID(0)
          SetCursor_(LoadCursor_(0, #IDC_SIZEALL))
          SendMessage_(GadgetID(0), #WM_SYSCOMMAND , #SC_DragMove,0)
        EndIf
    EndSelect
  Until Quit = 1
EndIf

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 12:00 am
by IdeasVacuum
Hi Rashad

Less code is nice to see..... but your first example using a call back gives a much smoother scroll.

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 12:21 am
by IdeasVacuum
.... something I don't get: Why is the Scroll Area Gadget itself oversized and not just the Scroll Area inner client area, as it would be if scrollbars were used?

Edit: I see now, the whole Scroll Area Gadget is being moved, not the inner area. So it need not be a Scroll Area Gadget, it could perhaps be a plain old Container..... but my ideal world scenario is to scroll the inner area of a Scroll Gadget by dragging the mouse on it instead of using the scroll bars.

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 12:46 am
by RASHAD
Hi IV :P
I was thinking of using the ScrollArea with a huge MAP moving it in all directions and maybe zoom in or out after that

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 1:19 am
by IdeasVacuum
Geebee1000.jpg

Code: Select all

#SC_DragMove = $F012
UseJPEGImageDecoder()
LoadImage(0, "C:\MY_TEMP\Geebee1000.jpg")
imgw = ImageWidth(0)
imgh = ImageHeight(0)

If OpenWindow(0, 0, 0, 800,600, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

    ContainerGadget(10,0,0,800,600,#PB_Container_BorderLess)
    ContainerGadget(0, -1000, -1000, 4000,4000,#PB_Container_BorderLess)
        ImageGadget(1, 1000, 1000, imgw,imgh, ImageID(0))
    CloseGadgetList()
    CloseGadgetList()
      DisableGadget(10,1)
     SetWindowColor(0,RGB(0,0,200))
     SetGadgetColor(0,#PB_Gadget_BackColor,RGB(0,200,0))
     SetGadgetColor(10,#PB_Gadget_BackColor,RGB(0,200,0))   

  Repeat
    Select WaitWindowEvent()
      Case  #PB_Event_CloseWindow
        Quit = 1
       
      Case #WM_LBUTTONDOWN
        GetCursorPos_(p.POINT)
        ScreenToClient_ (GadgetID(10), @p)
        If ChildWindowFromPoint_(GadgetID(10),p\y << 32 + p\x) = GadgetID(0)
          SetCursor_(LoadCursor_(0, #IDC_SIZEALL))
          SendMessage_(GadgetID(0), #WM_SYSCOMMAND , #SC_DragMove,0)
        EndIf
    EndSelect
  Until Quit = 1
EndIf

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 11:30 am
by IdeasVacuum
Hi Rashad

That's essentially my use (but not a map), see my variation of your code. I have used a colour background on the containers so I could see what was happening. It works, but not so slick.

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 4:10 pm
by IdeasVacuum
Well, works OK with an Image Gadget but I'm trying to use an OpenGL Gadget - fails miserably :mrgreen:

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 7:31 pm
by RASHAD
Hi IV
With OpenGL gadget

Code: Select all

#SC_DragMove = $F012
;UseJPEGImageDecoder()
;LoadImage(0, "Geebee1000.jpg")
;imgw = ImageWidth(0)
;imgh = ImageHeight(0)

Global RollAxisX.f
Global RollAxisY.f
Global RollAxisZ.f

Global RotateSpeedX.f = 1.0
Global RotateSpeedY.f
Global RotateSpeedZ.f = 1.0

Global ZoomFactor.f = 1.0 ; Distance of the camera. Negative value = zoom back

Procedure DrawCube(Gadget)
  SetGadgetAttribute(Gadget, #PB_OpenGL_SetContext, #True)
  
  glPushMatrix_()                  ; Save the original Matrix coordinates
  glMatrixMode_(#GL_MODELVIEW)

  glTranslatef_(0, 0, ZoomFactor)  ;  move it forward a bit

  glRotatef_ (RollAxisX, 1.0, 0, 0) ; rotate around X axis
  glRotatef_ (RollAxisY, 0, 1.0, 0) ; rotate around Y axis
  glRotatef_ (RollAxisZ, 0, 0, 1.0) ; rotate around Z axis
 
  RollAxisX + RotateSpeedX 
  RollAxisY + RotateSpeedY 
  RollAxisZ + RotateSpeedZ 

  ; clear framebuffer And depth-buffer

  glClear_ (#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)

  ; draw the faces of a cube
  
  ; draw colored faces

  glDisable_(#GL_LIGHTING)
  glBegin_  (#GL_QUADS)
  
  ; Build a face, composed of 4 vertex ! 
  ; glBegin() specify how the vertexes are considered. Here a group of
  ; 4 vertexes (GL_QUADS) form a rectangular surface.

  ; Now, the color stuff: It's r,v,b but with float values which
  ; can go from 0.0 To 1.0 (0 is .. zero And 1.0 is full intensity) 
  
  glNormal3f_ (0,0,1.0)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (0.5,0.5,0.5)   
  glColor3f_  (0,1.0,1.0)         
  glVertex3f_ (-0.5,0.5,0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (-0.5,-0.5,0.5)
  glColor3f_  (0,0,0)
  glVertex3f_ (0.5,-0.5,0.5) 

  ; The other face is the same than the previous one 
  ; except the colour which is nice blue To white gradiant

  glNormal3f_ (0,0,-1.0)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glColor3f_  (0,0,1.0)
  glVertex3f_ (-0.5,0.5,-0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (0.5,0.5,-0.5)
  glColor3f_  (1.0,1.0,1.0)
  glVertex3f_ (0.5,-0.5,-0.5)
  
  glEnd_()
  
  ; draw shaded faces

  glEnable_(#GL_LIGHTING)
  glEnable_(#GL_LIGHT0)
  glBegin_ (#GL_QUADS)

  glNormal3f_ (   0, 1.0,   0)
  glVertex3f_ ( 0.5, 0.5, 0.5)
  glVertex3f_ ( 0.5, 0.5,-0.5)
  glVertex3f_ (-0.5, 0.5,-0.5)
  glVertex3f_ (-0.5, 0.5, 0.5)

  glNormal3f_ (0,-1.0,0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glVertex3f_ (0.5,-0.5,-0.5)
  glVertex3f_ (0.5,-0.5,0.5)
  glVertex3f_ (-0.5,-0.5,0.5)

  glNormal3f_ (1.0,0,0)
  glVertex3f_ (0.5,0.5,0.5)
  glVertex3f_ (0.5,-0.5,0.5)
  glVertex3f_ (0.5,-0.5,-0.5)
  glVertex3f_ (0.5,0.5,-0.5)

  glNormal3f_ (-1.0,   0,   0)
  glVertex3f_ (-0.5,-0.5,-0.5)
  glVertex3f_ (-0.5,-0.5, 0.5)
  glVertex3f_ (-0.5, 0.5, 0.5)
  glVertex3f_ (-0.5, 0.5,-0.5)

  glEnd_()

  glPopMatrix_()
  glFinish_()

  SetGadgetAttribute(Gadget, #PB_OpenGL_FlipBuffers, #True)
EndProcedure


Procedure SetupGL()
    
  glMatrixMode_(#GL_PROJECTION)
  gluPerspective_(30.0, 200/200, 1.0, 10.0) 
  
  ; position viewer
  glMatrixMode_(#GL_MODELVIEW)
  
  glTranslatef_(0, 0, -5.0)
  
  glEnable_(#GL_DEPTH_TEST)   ; Enabled, it slowdown a lot the rendering. It's to be sure than the
                              ; rendered objects are inside the z-buffer.
  
  glEnable_(#GL_CULL_FACE)    ; This will enhance the rendering speed as all the back face will be
                              ; ignored. This works only with CLOSED objects like a cube... Singles
                              ; planes surfaces will be visibles only on one side.
    
  glShadeModel_(#GL_SMOOTH)
EndProcedure


Procedure HandleError (Result, Text$)
  If Result = 0
    MessageRequester("Error", Text$, 0)
    End
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 800,600, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

    ContainerGadget(10,0,0,800,600,#PB_Container_BorderLess)
      ContainerGadget(20, -1000, -1000, 4000,4000,#PB_Container_BorderLess)
          OpenGLGadget(0, 1000, 1000, 200, 200)
          SetupGL()

          OpenGLGadget(1, 1500, 1000, 300, 300)
          SetupGL()
      CloseGadgetList()
    CloseGadgetList()
      DisableGadget(10,1)
     ;DisableGadget(20,1)
     ;SetWindowColor(0,RGB(0,0,200))
     ;SetGadgetColor(0,#PB_Gadget_BackColor,RGB(0,200,0))
     ;SetGadgetColor(10,#PB_Gadget_BackColor,RGB(0,200,0))   
  AddWindowTimer(0, 1, 16)
  Repeat
    Select WaitWindowEvent()
      Case  #PB_Event_CloseWindow
        Quit = 1
        
      Case #PB_Event_Timer
        If EventTimer() = 1
          DrawCube(0)
          DrawCube(1)
        EndIf
       
      Case #WM_LBUTTONDOWN
        GetCursorPos_(p.POINT)
        ScreenToClient_ (GadgetID(20), @p)
        If ChildWindowFromPoint_(GadgetID(20),p\y << 32 + p\x) = GadgetID(0)
          RemoveWindowTimer(0,1)
          SetCursor_(LoadCursor_(0, #IDC_SIZEALL))
          SendMessage_(GadgetID(0), #WM_SYSCOMMAND , #SC_DragMove,0)
          AddWindowTimer(0, 1, 16)
        ElseIf ChildWindowFromPoint_(GadgetID(20),p\y << 32 + p\x) = GadgetID(1)
          RemoveWindowTimer(0,1)
          SetCursor_(LoadCursor_(0, #IDC_SIZEALL))
          SendMessage_(GadgetID(1), #WM_SYSCOMMAND , #SC_DragMove,0)
          AddWindowTimer(0, 1, 16)
        EndIf
    EndSelect
  Until Quit = 1
EndIf

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 9:13 pm
by IdeasVacuum
Ahhhh! I spend half a day convincing myself that scrollbars are alright - and then you throw temptation in my path again :mrgreen:

Re: ScrollArea - Can it be butchered?

Posted: Sat Feb 22, 2020 11:17 pm
by IdeasVacuum
Your example works really well Rashad and I have made it maximum Window Size with an oversize OGL gadget, no problem.

Tried incorporating it into my project but currently it does not work, possibly because I'm using glOrtho_() to hold the proportional representation of the model, I'm not sure at the moment.

I'm going to set it aside for now as I have other issues to solve, but many many thanks for your help and I'm sure I will get my implementation right in the end.