Sign in to follow this  
Eriond

[Win32]Problems with horizontal scrolling

Recommended Posts

Eriond    187
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[i];
				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).

Share this post


Link to post
Share on other sites
Evil Steve    2017
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()?

Share this post


Link to post
Share on other sites
Eriond    187
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this