The OS/2 API Project - Scrollbars

By Abram Dancy

Creation
There are two ways to create scrollbars. If the owner window is a standard frame window, you can create scroll bars by specifying the FCF_VERTSCROLL and FCF_HORZSCROLL flags in the third argument to WinCreateStdWindow when you create the frame window. Otherwise, scroll bars can be created with a call to WinCreateWindow, specifying the window class (second argument to WinCreateWindow) as WC_SCROLLBAR, and SBS_VERT or SBS_HORZ as flags (fourth argmument).

When scrollbars are created with the WinCreateStdWindow API, the size and position of the scroll bar can be set with the four coordinate inputs to WinCreateWindow (arguments 5 through 8). The first two arguments specify the position, and the second two specify size. Note that these coordinates are measured relative to the upper left corner of the owner window, not the lower left. The system default width/height of vertical/horizontal scrollbars are specified by SV_CXVSCROLL and SV_CYHSCROLL.

Styles for the scrollbar (specified as flags in the fourth argument of WinCreateWindow) are SBS_VERT, SBS_HORZ, SBS_AUTOTRACK, and SBS_THUMBSIZE. SBS_AUTOTRACK specifies that the slider should be redrawn as it is dragged along in a window. Otherwise an outline of the slider will be dragged and the slider will jump to the new position when the mouse is released. SBS_THUMBSIZE specifies that the scrollbar slider size and range should be set from the data passed in the SBCDATA structure passed to WinCreateWindow. See also SBM_SETTHUMBSIZE.

The owner window will receive WM_VSCROLL and WM_HSCROLL messages when the user interacts with the scroll bar. The owner controls the size and position of the slider, as well as the scale used to describe the slider. The scrollbar position is not updated by the scrollbar itself, but by the owner. The owner should also adjust these parameters in response to WM_SIZE messages, since presumably the amount of data displayed will change relative to the amount of data stored. The owner will also need to reposition the scrollbar to keep it on an edge of the window when the size changes. (May not be the case when scrollbar is created with the FCF_VERTSCROLL flag.)

The slider is controlled by sending messages to the scroll bar window. The SBM_SETPOS message sets the position of the slider. The SBM_SETTHUMBSIZE sets the size of the slider. The SBM_SETSCROLLBAR sets the position of the slider and range of the slider scale. The slider state can be retrieved with the SBM_QUERYPOS message.

Scrollbars can be enabled and disabled with the WinEnableWindow API.

The owner window can retrieve the window handle to the slider by using the WinWindowFromID command. If you created the window with WinCreateWindow, merely pass the ID you used when you created the window. If the FCF_***SCROLL flags were used, you should specify FID_VERTSCROLL or FID_HORZSCROLL.

Scroll Bar Messages

 * SBM_QUERYPOS
 * Message sent to scrollbar window to read the current slider position. Slider position is returned from call to WinSendMsg.


 * SBM_QUERYRANGE
 * Message sent to scrollbar window to read the current slider range. Slider minimum and maximum page is returned from call to WinSendMsg.


 * SBM_SETPOS
 * Message sent to scrollbar window to set the position of the slider within the scrollbar. Set position of slider within a scrollbar. The position of the slider is passed in the first element of the first m-parameter. The range for that position is defined by the SBM_SETSCROLLBAR message. Sample Code:

hwndScroll = WinWindowFromID(hwndOwnder,ID_SCROLL_BAR); /* assuming ID_SCROLL_BAR was used when the scroll bar was created */ WinSendMsg(hwndScroll, SBM_SETPOS,	  MPFROM2SHORT(first_visible_row,0), 0); See also SBM_SETTHUMBSIZE, SBM_SETSCROLLBAR, SBM_QUERYPOS
 * 1) define ID_SCROLL_BAR 0x10


 * SBM_SETTHUMBSIZE:
 * Message sent to scrollbar window to set the size of the slider within the scrollbar. Set the size of the slider within a scrollbar. The size is set the first element to the first m-parameter, and the range of the scrollbar is set with the second m-parameter. If you wish to display 10 lines of a 25 line document you might specify 10 and 25 in the first parameter passed. You might just as well specify 100 and 250. The significance of these parameters is in your hands.Sample Code:

WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE,  MPFROM2SHORT(num_lines_visible,total_lines+1), 0); See also SBM_SETSCROLLBAR SBM_SETPOS SBM_QUERYPOS


 * SBM_SETSCROLLBAR:
 * Message sent to scrollbar window to set the position of the slider and the range used to specify that position. Set the position and range of the slider within a scrollbar. The first parameter passed to the scrollbar window contains the starting position of the slider in the first element. The second parameter passed to the scrollbar window contains the index for the first and last positions of the slider. For a window which is displaying 25 lines of text, 10 lines at a time, you might specify the first position as 1 and the final position as 16. (In position 1, lines 1-10 are visible, and in position 16, lines 16-25 are visible.) This avoids the ridiculous behavior of the scrollbar getting tiny and only one line of text being visible when the slider is dragged to the bottom of the scrollbar (as seen in NR/2 and other OS/2 applications). This would occur if the range of the scrollbar was set to 25.Sample Code:

WinSendMsg(hwndScroll, SBM_SETSCROLLBAR,  MPFROM2SHORT(first_visible_row,0),   MPFROM2SHORT(1, num_rows + 1 - num_rows_per_page); /* if there is not enough data to be scrolled, scrollbar  * should be disabled with WinEnableWindow */

See also SBM_SETPOS SBM_SETTHUMBSIZE SBM_QUERYPOS WinEnableWindow

WM_HSCROLL SB_LINEUP SB_LINEDOWN SB_PAGEUP SB_PAGEDOWN SB_SLIDERPOSITION SB_SLIDERTRACK SB_ENDSCROLL
 * WM_VSCROLL
 * When a vertical scroll bar receives user input, it posts a WM_VSCROLL message to its owner window. The nature of the input is stored in the second element of the second m-parameter. The possible messages are SB_LINEUP, SB_LINEDOWN, SB_PAGEUP, SB_PAGEDOWN, SB_SLIDERPOSITION, SB_SLIDERTRACK, and SB_ENDSCROLL. When the owner receives these messages, it must reposition the slider and redraw its window appropriately. The SB_LINEUP/DOWN and SB_PAGEUP/DOWN messages have rather obvious purposes. The SB_SLIDERTRACK message is issued while the user drags the slider. If the owner can redraw its window fast enough, it can redraw the window in response to this message. The SB_SLIDERPOSITION message is issued when the user releases the slider after dragging. The SB_ENDSCROLL is issued when the user releases the mouse after holding it down on a scrollbar arrow or the scrollbar background. With the SB_SLIDERTRACK and SB_SLIDERPOSITION messages, the new position of the slider is contained in the first element of the second m-parameter.Sample Code:

MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) {  switch (msg) { case WM_VSCROLL: {     int inc; RECTL rectl; HWND hwndScroll; hwndScroll = WinWindowFromID(hwnd,ID_VSCROLL_BAR); switch (SHORT2FROMMP(mp2)) { case SB_LINEUP: inc = -1; break; case SB_LINEDOWN: inc = +1; break; case SB_PAGEUP: inc = MIN(-page_size+1,-1); break; case SB_PAGEDOWN: inc = MAX(page_size-1,+1); break; case SB_SLIDERPOSITION: case SB_SLIDERTRACK: inc = SHORT1FROMMP(mp2)-current_top_line; break; default: return WinDefWindowProc (hwnd,msg,mp1,mp2); }     if (current_top_line+inc < 0) /* Don't scroll back too far */ inc = -current_top_line; else { int largest_top_line; largest_top_line = MAX(0,num_lines-page_size+1); if (current_top_line+inc > largest_top_line) /* Don't scroll forward too far */ inc = largest_top_line - current_top_line; }     current_top_line += inc; /* Retrieve size of visible window so we can redraw it */ WinQueryWindowRect(hwnd,&rectl); if (inc) WinScrollWindow(hwnd, 0L, inc, &rectl, (PRECTL) NULL, 			(HRGN) NULL, (PRECTL) NULL, SW_INVALIDATERGN); /* Update the position of the slider */ WinSendMsg(hwndScroll, SBM_SETPOS, 		 MPFROM2SHORT(current_top_line,0), 0); }   return (MRESULT) TRUE; default: return WinDefWindowProc (hwnd,msg,mp1,mp2); } }

See also:
 * WinScrollWindow
 * WinSendMsg
 * WinWindowFromID
 * SHORT1FROMMP
 * SHORT2FROMMP