ScrollArea - Can it be butchered?

Windows specific forum
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

ScrollArea - Can it be butchered?

Post 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?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: ScrollArea - Can it be butchered?

Post 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

User avatar
spikey
Enthusiast
Enthusiast
Posts: 769
Joined: Wed Sep 22, 2010 1:17 pm
Location: United Kingdom

Re: ScrollArea - Can it be butchered?

Post 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
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: ScrollArea - Can it be butchered?

Post 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
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ScrollArea - Can it be butchered?

Post 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)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: ScrollArea - Can it be butchered?

Post 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
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ScrollArea - Can it be butchered?

Post by IdeasVacuum »

Hi Rashad

Less code is nice to see..... but your first example using a call back gives a much smoother scroll.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ScrollArea - Can it be butchered?

Post 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.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: ScrollArea - Can it be butchered?

Post 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
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ScrollArea - Can it be butchered?

Post 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
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ScrollArea - Can it be butchered?

Post 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.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ScrollArea - Can it be butchered?

Post by IdeasVacuum »

Well, works OK with an Image Gadget but I'm trying to use an OpenGL Gadget - fails miserably :mrgreen:
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: ScrollArea - Can it be butchered?

Post 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
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ScrollArea - Can it be butchered?

Post by IdeasVacuum »

Ahhhh! I spend half a day convincing myself that scrollbars are alright - and then you throw temptation in my path again :mrgreen:
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ScrollArea - Can it be butchered?

Post 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.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Post Reply