News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Window with vertical scroll bar

Started by RuiLoureiro, September 07, 2010, 01:18:27 PM

Previous topic - Next topic

RuiLoureiro

Hi,
    I create a window with CreateWindowEx
    with main style
    MAIN_STYLE equ WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN or WS_HSCROLL or WS_VSCROLL
    This is it creates a window that has a horizontal scroll bar and
    has a vertical scroll bar.
    What i want is to print text into that window line by line using TextOut
    but i cannot use the vertical scroll bar to show the last printed line.
    So i think it cannot be done by this way: vertical scroll bar doesnt do anything.
    How can i solve the problem ?
    Could you help me ? Could you show me an example ?
    Thanks
    RuiLoureiro

Tedd

You'd need to tell a scrollbar how 'big' it should be (how big the 'page' it's scrolling is.)
And the scrollbar doesn't actually scroll anything, all it does is notify its position to the parent; the parent window is then responsible for moving the contents appropriately.

If you only want to display text, save yourself trouble and use a plain edit box (or rich-edit if you need fancy text.)
If you want something more complex, you should probably be creating your own custom control and set that as a child of the main window. The custom control should then also create and manage its own scrollbar (set its size and respond to its notifications.)
No snowflake in an avalanche feels responsible.

RuiLoureiro

Thanks Tedd

          I want to try to understand how the scroll bar works.
          I process WM_VSCROLL
          I used invoke  SetScrollInfo, _hWnd, SB_VERT, addr _si, TRUE
          to set nMin, nMax, nPage, nPos and
          I test SB_THUMBTRACK, SB_LINEUP, SB_LINEDOWN, SB_BOTTOM, SB_TOP
          and SB_THUMBPOSITION and nothing happen. I cannot set the scrool
          bar in any position. Simply, i dont know how it works.
          I tryed many thinks and nothing. Something is wrong ! Tiil now

Thanks

akane

Hello,
the code below is an copy-cleanup-paste from my image processing program. There was also drag-drop scrolling, but it is not included here, for clearity.
This pseudocode should be clear enough to learn from it, I think, and hope it is :)

The value 32 used in SB_LINE* cases should be adjusted as you like.

proc SetupScrollbar(hwnd, barId, TotalNumberOfItems, MaxNumberOfItemsPerPage, HideScroll)
SCROLLINFO si
; example:
; TotalNumberOfItems = bitmap width or height
; MaxNumberOfItemsPerPage = imageControl width or height

si.cbSize = len(si)
si.fMask  = SIF_PAGE | SIF_RANGE

si.nMin  = 0
si.nPage = MaxNumberOfItemsPerPage
si.nMax  = TotalNumberOfItems
if (HideScroll) then si.nPage = si.nMax+1
SetScrollInfo(hwnd, barId, si, TRUE)
endproc


; WM_MOUSEWHEEL
proc OnMouseWheel(hwnd, wParam)
SCROLLINFO si

if (GetScroll(hwnd, SB_VERT, si))
si.nPos -= SIGNED_HIWORD(wParam)
SetScroll(hwnd, SB_VERT, si)
InvalidateRect(hwnd, NULL, FALSE)
endif
endproc


; WM_HSCROLL
proc OnHScroll(hwnd, wParam)
SCROLLINFO si

if (GetScroll(hwnd, SB_HORZ, si))
select (LOWORD(wParam))
case SB_LEFT
si.nPos = 0
case SB_RIGHT
si.nPos = si.nMax
case SB_LINELEFT
si.nPos -= 32
case SB_LINERIGHT
si.nPos += 32
case SB_PAGELEFT
si.nPos -= si.nPage
case SB_PAGERIGHT
si.nPos += si.nPage
case SB_THUMBTRACK
si.nPos = HIWORD(wParam)
endselect
SetScroll(hwnd, SB_HORZ, si)
InvalidateRect(hwnd, NULL, FALSE)
endif
endproc


; WM_VSCROLL
proc OnVScroll(hwnd, wParam)
SCROLLINFO si

if (GetScroll(hwnd, SB_VERT, si))
select (LOWORD(wParam))
case SB_TOP
si.nPos = 0
case SB_BOTTOM
si.nPos = si.nMax
case SB_LINEUP
si.nPos -= 32
case SB_LINEDOWN
si.nPos += 32
case SB_PAGEUP
si.nPos -= si.nPage
case SB_PAGEDOWN
si.nPos += si.nPage
case SB_THUMBTRACK
si.nPos = HIWORD(wParam)
endselect
SetScroll(hwnd, SB_VERT, si)
InvalidateRect(hwnd, NULL, FALSE)
endif
endproc


proc SetScroll(hwnd, barId, si)

if (si.nPos < si.nMin) then si.nPos = si.nMin
if (si.nPos > si.nMax) then si.nPos = si.nMax

si.fMask = SIF_POS
SetScrollInfo(hwnd, barId, si, TRUE)
endproc


proc GetScroll(hwnd, barId, si),BOOL
si.cbSize = len(SCROLLINFO)
si.fMask  = SIF_PAGE | SIF_POS | SIF_RANGE
return GetScrollInfo(hwnd, barId, &si)
endproc


For your needs, nMax and nPage for vertical scrollbar should be set to eg. number of ALL lines and maximum number of visible lines. If you would like to have smoth scrolling, multiply both values by the height of a line (TEXTMETRIC.tmHeight). Horizontal scrollbar (nMax and nPage) should be set to the width of the largest line in pixels (GetTextExtentPoint32) and the width of your control client area width.

RuiLoureiro

Hello Akane !  :wink

              Many thanks to you !
              What you post seems to be clear to me
              I have no time now to test it in my prog
              If i have something to say, tomorrow i will say
Thanks
RuiLoureiro

RuiLoureiro

Akane, hello
             The procedures works perfectly.
             Your help was great !  :wink
             But i have one doubt here:

             What is SIGNED_HIWORD(wParam) ?
Quote
proc OnMouseWheel(hwnd, wParam)
   SCROLLINFO si
   if (GetScroll(hwnd, SB_VERT, si))
      si.nPos -= SIGNED_HIWORD(wParam)
      SetScroll(hwnd, SB_VERT, si)
      InvalidateRect(hwnd, NULL, FALSE)
   endif
endproc
RuiLoureiro

akane

Signed, also sign-extended word to dword using movsx.

Short example: movsx eax, word ptr [wParam+2]

Long example:mov eax,[wParam]
shr eax,16
movsx eax,ax

RuiLoureiro

Akane,
         First, many thanks for all
         Without your help i would have many more problems.
         
         On my prog «OnMouseWheel» doesnt work correctly
         I have a list with records.
         One screen are 30 records or 13 records (2 cases)
         To show the records i have 3 variables: Fst, Lst, End=Total number of records
         Each screen starts at the record number Fst and ends in Lst
         When i move the mouse wheel towards me: Fst=Fst+1 and Lst=Lst+1
         and the vertical scrool bar moves only 1 towards bottom

         Another problem: how do you know if we move the vertical scrool bar
         towards up or towards down after we process SB_THUMBTRACK to
         call the correct procedure to print he records ? It moves the
         bar correctly but we need to know if up or down.
         
         I use this, and it works perfectly
         (it moves one record up or one record down )

Quote
OnMouseWheel        proc    wParam:DWORD

                    invoke  GetVScroll           
                    cmp     eax, TRUE
                    je      short @F
                    ret
                    ;
@@:              mov     eax, _si.nPos
                    cmp     word ptr [wParam+2], 0   
                    jg      short @F

                    add     eax, 2
                   
@@:              sub     eax, 1
                    mov     _si.nPos, eax
                   
                    invoke    SetVScroll       
                    invoke    InvalidateRect, _hWnd, NULL, FALSE
                    ret
OnMouseWheel        endp

        where GetVScroll and SetVScroll are these
        (my window handle is _hWnd and _si is SCROLLINFO)
Quote
GetVScroll          proc   

                    mov     _si.cbSize, sizeof SCROLLINFO
                    mov     _si.fMask, SIF_PAGE or SIF_POS or SIF_RANGE
                    invoke  GetScrollInfo, _hWnd, SB_VERT, addr _si
                    ;
                    ; If the function retrieved any values, the return value is TRUE
                    ret
GetVScroll          endp
; ------------------------------------------------------
SetVScroll          proc   

                    mov     eax, _si.nMin
                    cmp     _si.nPos, eax
                    jge     short @F
                    ;
                    mov     _si.nPos, eax                   

@@:              mov     eax, _si.nMax
                    cmp     _si.nPos, eax
                    jle     short @F
                    ;
                    mov     _si.nPos, eax

@@:              invoke  SetScrollInfo, _hWnd, SB_VERT, addr _si, TRUE
                    ; The return value is the current position of the scroll box
                    ret
SetVScroll          endp

Thanks again
RuiLoureiro

akane

case SB_THUMBTRACK
si.nPos = HIWORD(wParam)


I think you don't need these two lines (in two procs), because si.nPos is already initialized to new scroll position (GetScroll). Scroll position in wParam is limited to probably signed, 16-bit numbers.

To get the direction, subtract si.nPos AFTER calling GetScroll, from si.nPos BEFORE calling GetScroll. The "before" value should be A positive value should indicate scrolling to right/down, and a negative to left/up. If you are using globally defined SCROLLINFO, this should be easy to implement.
push si.nPos ; globally allocated
invoke GetScroll ...
pop edx
sub edx,si.nPos ; edx = old_pos - new_pos; if negative then scrolling down/right. Check in SB_THUMBTRACK


WM_MOUSEWHEEL
Quote from: MSDNwParam
The high-order word indicates the distance the wheel is rotated, expressed in multiples or divisions of WHEEL_DELTA, which is 120. A positive value indicates that the wheel was rotated forward, away from the user
If you convert the high-order word to +1 or -1 (just divide it by WHEEL_DELTA) and multiply it by the value returned by reference from SystemParametersInfo(SPI_GETWHEELSCROLLLINES), you'll get the direction and number of lines for text scrolling.

RuiLoureiro

Akane,
        Thanks for reply
Quote
If you convert the high-order word to +1 or -1 (just divide it by WHEEL_DELTA)
and multiply it by the value returned by reference from
SystemParametersInfo(SPI_GETWHEELSCROLLLINES), you'll get the direction and
number of lines for text scrolling.
        How can we get WHEELSCROLLLINES from SystemParametersInfo ?
        invoke  SystemParametersInfo, SPI_GETWHEELSCROLLLINES, 0, addr Info, 0 ?
        I have no information about this in Plataform SDK
       
        thanks

EDIT: i tryed invoke  SystemParametersInfo, SPI_GETWHEELSCROLLLINES, 0, addr Info, 0
      and i got Info=3. I am using 1 (scroll only one line and the result is
      perfect ). I tested 3 and it doesnt work correctly

RuiLoureiro         

akane

Yup, the syntax is ok.
The default value is 3, and I prefer the value 6, for a bit faster scrolling - see control panel/mouse/wheel.
If you are planning to share your program, using SPI_GETWHEELSCROLLLINES (on systems above win95) is highly recommended, to respect target user settings.