[Win32]Problems with horizontal scrolling

Started by
3 comments, last by Eriond 19 years, 6 months ago
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	static int charWidth, charHeight, capsWidth, maxWidth;
	static int clientWidth, clientHeight;
	static int verticalScrollPos, horizontalScrollPos;

	switch(msg)
	{
	case WM_CREATE:
		{
			HDC hdc = GetDC(hwnd);
			TEXTMETRIC tm;
			GetTextMetrics(hdc, &tm);

			charWidth = tm.tmAveCharWidth;
			capsWidth = (tm.tmPitchAndFamily & 1 ? 3 : 2) * charWidth / 2;
			charHeight = tm.tmHeight + tm.tmExternalLeading;

			ReleaseDC(hwnd, hdc);

			maxWidth = 40 * charWidth + 22 * capsWidth;
			return 0;
		}

	case WM_SIZE:
		{
			clientWidth = LOWORD(lparam);
			clientHeight = HIWORD(lparam);

			SCROLLINFO si;
			si.cbSize = sizeof(si);
			si.fMask = SIF_RANGE | SIF_PAGE;
			si.nMin = 0;
			si.nMax = NUMLINES - 1;
			si.nPage = clientHeight / charHeight;
			SetScrollInfo(hwnd, SB_VERT, &si, true);

			si.cbSize = sizeof(si);
			si.fMask = SIF_RANGE | SIF_PAGE;
			si.nMin = 0;
			si.nMax = 2 + maxWidth / charWidth;
			si.nPage = clientWidth / charWidth;
			SetScrollInfo(hwnd, SB_HORZ, &si, true);
			return 0;
		}

	case WM_HSCROLL:
		{
			SCROLLINFO si;
			si.cbSize = sizeof(si);
			si.fMask = SIF_ALL;
			GetScrollInfo(hwnd, SB_HORZ, &si);
			horizontalScrollPos = si.nPos;

			switch(LOWORD(wparam))
			{
				case SB_LINELEFT:
					si.nPos -= 1;
					break;

				case SB_LINERIGHT:
					si.nPos += 1;
					break;

				case SB_PAGELEFT:
					si.nPos -= si.nPage;
					break;

				case SB_PAGERIGHT:
					si.nPos += si.nPage;
					break;

				case SB_THUMBPOSITION:
					si.nPos = si.nTrackPos;
					break;

				default:
					break;
			}

			si.fMask = SIF_POS;
			SetScrollInfo(hwnd, SB_HORZ, &si, true);
			GetScrollInfo(hwnd, SB_HORZ, &si);
			if(si.nPos != horizontalScrollPos)
			{
				ScrollWindow(hwnd, 0, charWidth * (horizontalScrollPos - si.nPos), 
							 0, 0);
			}
			return 0;
		}

	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(hwnd, &ps);

			SCROLLINFO si;
			si.cbSize = sizeof(si);
			si.fMask = SIF_POS;

			GetScrollInfo(hwnd, SB_VERT, &si);
			verticalScrollPos = si.nPos;

			GetScrollInfo(hwnd, SB_HORZ, &si);
			horizontalScrollPos = si.nPos;

			int paintBegin = max(0, verticalScrollPos + ps.rcPaint.top / charHeight);
			int paintEnd = min(NUMLINES - 1, 
							   verticalScrollPos + ps.rcPaint.bottom / charHeight);
			
			for(int i = paintBegin; i <= paintEnd; ++i)
			{
				const Sysmetrics& sm = sysmetrics;
				int x = charWidth * (1 - horizontalScrollPos);
				int y = charHeight * (i - verticalScrollPos);

				TextOut(hdc, x, y, sm.label, strlen(sm.label));
				TextOut(hdc, x + 22 * capsWidth, y, 
						sm.desc, strlen(sm.desc));

				SetTextAlign(hdc, TA_RIGHT | TA_TOP);
				string text = str(format("%1%") % GetSystemMetrics(sm.index));

				TextOut(hdc, x + 22 * capsWidth + 40 * charWidth, y,
						text.c_str(), text.size());

				SetTextAlign(hdc, TA_LEFT | TA_TOP);
			}

			EndPaint(hwnd, &ps);
			return 0;
		}

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, msg, wparam, lparam);
}
That's my WndProc, without WM_VSCROLL. Everything looks good until I try to scroll horizontally. Then some of the things from the left side stays in the window and some get overdrawn. If I put another program in from of the window and then switch back to my program, everything looks fine again, so I guessed that the window was not redrawn when scrolling. I have tested putting a UpdateWindow call at the end of WM_HSCROLL but that didn't help either. The code is from ch4 in Programming Windows 5th edition, and in the book no call is made to UpdateWindow in WM_HSCROLL but it is in WM_VSCROLL. I have checked my code many times and have not found anything different from the book's code (except for names on variables).
Advertisement
From the MSDN:
Quote:The area uncovered by ScrollWindow is not repainted, but it is combined into the window's update region. The application eventually receives a WM_PAINT message notifying it that the region must be repainted. To repaint the uncovered area at the same time the scrolling is in action, call the UpdateWindow function immediately after calling ScrollWindow.
So, does it work if you call UpdateWindow()?
Quoting myselft: "I have tested putting a UpdateWindow call at the end of WM_HSCROLL but that didn't help either." :) The thing I don't understand is why there is a UpdateWindow call in VSCROLL but not in HSCROLL in the book's code.
Have you tried explicitly calling Invalidate for your scroll area?

-fel
~ The opinions stated by this individual are the opinions of this individual and not the opinions of her company, any organization she might be part of, her parrot, or anyone else. ~
It worked when I called InvalidateRect(hwnd, 0, true) :D Thanks for your help.

This topic is closed to new replies.

Advertisement