Code:
/*---------------------------------------------------
Example of GetScrollInfo and SetScrollInfo for
the scroll bar of the created window
---------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int nCmdShow)
{
static TCHAR szAppName[] = TEXT("TestApp");
WNDCLASS wndclass;
MSG msg;
HWND hwnd;
wndclass.style = CS_VREDRAW | CS_HREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hInstance = hInstance;
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("Error registering window class!"),
TEXT("ERROR"), MB_OK);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Test Window"),
WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL,
hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
TEXTMETRIC tm;
static int cyChar, cyClient;
int nVscrollPos, i, iPaintBeg, iPaintEnd, y;
SCROLLINFO si;
switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);
GetTextMetrics(hdc, &tm);
cyChar = tm.tmHeight + tm.tmExternalLeading;
InvalidateRect(hwnd, NULL, TRUE);
ReleaseDC(hwnd, hdc);
return 0;
case WM_SIZE:
cyClient = HIWORD(lParam);
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = 30;
si.nPage = cyClient / cyChar;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
return 0;
case WM_VSCROLL:
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, SB_VERT, &si);
nVscrollPos = si.nPos;
switch (LOWORD(wParam))
{
case SB_LINEDOWN:
si.nPos += 1;
break;
case SB_LINEUP:
si.nPos -= 1;
break;
}
si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
if (nVscrollPos != si.nPos)
{
ScrollWindow(hwnd, 0, cyChar * (nVscrollPos - si.nPos), NULL, NULL);
UpdateWindow(hwnd);
}
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo(hwnd, SB_VERT, &si);
nVscrollPos = si.nPos;
iPaintBeg = max(0, nVscrollPos + ps.rcPaint.top / cyChar);
iPaintEnd = min(50, nVscrollPos + ps.rcPaint.bottom / cyChar);
for (i = iPaintBeg; i <= iPaintEnd; ++i)
{
y = cyChar * (i - nVscrollPos);
TextOut(hdc, 0, y, TEXT("WM_PAINT"), 8);
}
TextOut(hdc, 0, y, TEXT("TEST"), 4);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
And, I attached the .c file so, if you want to download it and see what I'm talking about (it is hard to explain what is going on with the client area during a scroll).