
So I agree that narrowing is necessary.
- Narrowing to the Scrollbar Gadget is of course mandatory.

- Narrowing to #WM_HSCROLL and #WM_VSCROLL is clever.

- Alas, narrowing to ScrollCode is nonsense.

However, we still need ScrollCode!


Yes, if you examine the code, you will see that I embedded #WM_HSCROLL with the ScrollCode to get a halt in the events if the GetGadgetState() has changed compared with the kept state in the last WindowCallback! (=variables Hstate/Vstate)
It is rather complex, but it is the compromise between speed and having the image completely and nicely at the left or right side (or completely at the top/bottom).
There is no flickering nor erratic movements with large images.
I would like to thank you for your cooperation involving this problem, Shardik.


If you use the free software Paint.NET, you can compare the image scrolling there: open a large jpg file, do a "Save As" in jpg format, give a new name, and then you will get a window to adjust the jpeg quality, together with a scrollable image. PureBasic can do that now too!

Note: please adjust the LoadImage() to open a large image.
Code: Select all
;(c) Shardik 2011-05-25
;(c) Charvista 2011-12-28
EnableExplicit
Enumeration
#Image ; loaded image
#ImageBis ; duplicate image
#Gadget ; image gadget
#Window ; window
#ScbGadH ; scrollbar gadget horizontal
#ScbGadV ; scrollbar gadget vertical
EndEnumeration
Define.i WinWidth,WinHeight,HMarge,VMarge,GWidth,GHeight,ScrollCode
Procedure WindowCallback(WindowHandle.i,Msg.i,wParam.i,lParam.i)
Static.i MsgCount1,MsgCount2,MsgCount3,Hstate,Vstate
Shared GWidth,GHeight,ScrollCode
If lParam=GadgetID(#ScbGadH) Or lParam=GadgetID(#ScbGadV)
MsgCount1+1
ScrollCode.i=WParam & $FFFF
If (Msg=#WM_HSCROLL And ScrollCode<>#SB_THUMBPOSITION And ScrollCode<>#SB_ENDSCROLL) Or GetGadgetState(#ScbGadH)<>Hstate Or (Msg=#WM_VSCROLL And ScrollCode<>#SB_THUMBPOSITION And ScrollCode<>#SB_ENDSCROLL) Or GetGadgetState(#ScbGadV)<>Vstate
; with #WM_HSCROLL/#WM_VSCROLL, it will only update if the cursor is ON the scrollbar
; if used here and scrollbar is moved to start or end too quickly, will show some "latency" when the mouse button is released
MsgCount2+1
;ScrollCode.i=WParam & $FFFF
;If ScrollCode<>#SB_THUMBPOSITION And ScrollCode<>#SB_ENDSCROLL
;MsgCount3+1
Hstate=GetGadgetState(#ScbGadH)
Vstate=GetGadgetState(#ScbGadV)
GrabImage(#Image,#ImageBis,Hstate,Vstate,GWidth,GHeight)
SetGadgetState(#Gadget,ImageID(#ImageBis))
Debug "Redraws for messages generated by ScrollBarGadget: " + Str(MsgCount1)
Debug "Redraws with filtering of #WM_HSCROLL: " + Str(MsgCount2)
Debug "Redraws with filtering of #WM_HSCROLL and ScrollCode: " + Str(MsgCount3)
;EndIf
EndIf
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
UsePNGImageDecoder()
UseJPEGImageDecoder()
LoadImage(#Image,"c:/users/myname/pictures/aVeryLargeImage.png") ;#PB_Compiler_Home+"/examples/3D/Data/Water/Foam.png")
WinWidth=390;200
WinHeight=320;200
OpenWindow(#Window,0,0,WinWidth,WinHeight,"Image scrolling",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)
HMarge=5
VMarge=5
GWidth=WinWidth-(2*HMarge)-20; marge left & right
GHeight=WinHeight-(2*VMarge)-20; marge top & bottom
ImageGadget(#Gadget,HMarge,VMarge,GWidth,GHeight,0,#PB_Image_Border)
; never use ImageWidth() as width for ImageGadget() because this will automatically replace the width of the ImageGadget() with the width of the image!
; so if you want a fixed ImageGadget width, use a fixed value => here GWidth used.
; same rule applies for ImageHeight().
ScrollBarGadget(#ScbGadH,HMarge,WindowHeight(#Window)-20,GWidth,15,0,ImageWidth(#Image),GWidth)
ScrollBarGadget(#ScbGadV,WindowWidth(#Window)-20,VMarge,15,GHeight,0,ImageHeight(#Image),GHeight,#PB_ScrollBar_Vertical)
GrabImage(#Image,#ImageBis,0,0,GWidth,GHeight)
SetGadgetState(#Gadget,ImageID(#ImageBis))
SetWindowCallback(@WindowCallback(),#Window)
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow