Here's something to start with. Usage code in attached zip. Flicker, etc are left up to you to deal with as described in link by Codeplug.
Code:
static LRESULT CALLBACK ScrollerProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
return 0;
case WM_DESTROY:
return 0;
case WM_VSCROLL:
SetWindowLong(hwnd, 0, wParam); /* Save scroll position provided in wParam */
InvalidateRect(hwnd, NULL, TRUE);
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
TCHAR szWndText[8192];
GetClientRect(hwnd, &rc);
rc.top -= GetWindowLong(hwnd, 0); /* Move top of text up by scroll position */
GetWindowText(hwnd, szWndText, 8192);
BeginPaint(hwnd, &ps);
DrawText(ps.hdc, szWndText, lstrlen(szWndText), &rc, DT_CENTER);
EndPaint(hwnd, &ps);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
BOOL ScrollerRegister(void)
{
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof (WNDCLASSEX);
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(LONG); /* Room to save scroll position */
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = ScrollerProc;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = SCROLLER_CLASS;
wc.hIconSm = NULL;
return RegisterClassEx(&wc);
}
BOOL ScrollerUnregister(void)
{
return UnregisterClass(SCROLLER_CLASS, GetModuleHandle(NULL));
}