Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Scroll & zoom

Status
Not open for further replies.

LyMc

Programmer
Jun 3, 2003
84
US
I'm writing an app which will draw on a window. The drawing is architectural in scale, out to a maximum size of 10,000x10,000 inches. I'm using centered coordinates sized in 1/10th's of an inch. I want scroll bars and a zoom capability; the zoom will be controlled by the mouse wheel, and will be from 300% to 5%, where 100% means each pixel on the screen is 1/2" on the plan. Obviously, the zoom will raise and lower that value. I need the zoom to work such that if any part of the plan is at the center of the drawing window, zooming in and out will leave that part centered on the screen (I'm sure there has to be a neat name for that capability, but I don't know what it might be...iso-centered, perhaps? :).

I've been experimenting with code to try to cover these requirements, but haven't been able to get it done the way I want it to be. Here is the current code, excerpted from the window process:

Code:
#define PIXPERINCH 2

LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static int			cxClient, cyClient;
	int					zoom;
	SCROLLINFO			si;
	PAINTSTRUCT			ps;
	HDC					hdc;

	switch (message) {

	case WM_CREATE:
		zoom = 1.;
		break;

	case WM_SIZE:
		{
			if (lParam > 0) {
				cxClient = LOWORD (lParam);
				cyClient = HIWORD (lParam);
			}
			si.cbSize = sizeof (si);
			si.fMask  = SIF_RANGE | SIF_PAGE;
			si.nPage  = (int) (cxClient / (5 * PIXPERINCH * opts.de.zoom));
			si.nMin   = -100;
			si.nMax   =  100 + si.nPage;
			SetScrollInfo (hWnd, SB_VERT, &si, TRUE);

			si.cbSize = sizeof (si);
			si.fMask  = SIF_RANGE | SIF_PAGE;
			si.nPage  = (int) (cyClient / (5 * PIXPERINCH * opts.de.zoom));
			si.nMin   = -100;
			si.nMax   =  100 + si.nPage;
			SetScrollInfo (hWnd, SB_HORZ, &si, TRUE);
			InvalidateRect (hWnd, NULL, TRUE);
		}
		break;

	case /*WM_MOUSEWHEEL*/ 0x20a:
		// makes 24 clicks to cover zoom range of .05 to 3.0; about 19% increase/decrease per click.
		zoom *= (pow (1.189, (double) (((short) HIWORD (wParam)) / 120)));
		zoom = __max (.05, __min (opts.de.zoom, 3.0));
		SendMessage (hWnd, WM_SIZE, SIZE_RESTORED, 0);
		return TRUE;

	case WM_VSCROLL:
		si.cbSize = sizeof (si);
		si.fMask = SIF_ALL;
		GetScrollInfo (hWnd, SB_VERT, &si);
		switch (LOWORD (wParam)) {
		case SB_TOP:
			si.nPos = si.nMin;
			break;

		case SB_BOTTOM:
			si.nPos = si.nMax;
			break;

		case SB_LINEUP:
			si.nPos--;
			break;

		case SB_LINEDOWN:
			si.nPos++;
			break;

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

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

		case SB_THUMBTRACK:
			si.nPos = si.nTrackPos;
			break;
		}
		si.fMask = SIF_POS;
		SetScrollInfo (hWnd, SB_VERT, &si, TRUE);
		InvalidateRect (hWnd, NULL, TRUE);
		return TRUE;

	case WM_HSCROLL:
		si.cbSize = sizeof (si);
		si.fMask = SIF_ALL;
		GetScrollInfo (hWnd, SB_HORZ, &si);
		switch (LOWORD (wParam)) {
		case SB_LINELEFT:
			si.nPos--;
			break;

		case SB_LINERIGHT:
			si.nPos++;
			break;

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

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

		case SB_THUMBTRACK:
			si.nPos = si.nTrackPos;
			break;
		}
		si.fMask = SIF_POS;
		SetScrollInfo (hWnd, SB_HORZ, &si, TRUE);
		InvalidateRect (hWnd, NULL, TRUE);
		return TRUE;

	case WM_PAINT:
		hdc = BeginPaint (hWnd = hIn, &ps);
		SetMapMode (hdc, MM_ISOTROPIC);
		SetWindowExtEx (hdc, 100000, 100000, NULL);
		SetViewportExtEx (hdc, xClient / 2, zClient / 2, NULL);
		SetViewportOrgEx (hdc, xClient / 2, zClient / 2, NULL);

		// Scale and translate:
		si.cbSize = sizeof (si);
		si.fMask = SIF_POS;
		GetScrollInfo (hWnd, SB_VERT, &si);
		int zpos = si.nPos;
		si.cbSize = sizeof (si);
		si.fMask = SIF_POS;
		GetScrollInfo (hWnd, SB_HORZ, &si);
		OffsetViewportOrgEx (hdc, -si.nPos * 13, -zpos * 13, NULL);
		ScaleWindowExtEx  (hdc, 1000, (int) (o->de.zoom * 1000.), 
							1000, (int) (o->de.zoom * 1000.), NULL);

		//  Go ahead and draw the image on the window...
		
		EndPaint (hWnd, &ps);
		break;

	case WM_DESTROY:
		PostQuitMessage (0);
		break;

	default:
		return DefWindowProc (hWnd, message, wParam, lParam);
	}
	return 0;
}

Note that there are lots of magic numbers in the code, as I'm trying to make it work reasonably. I would prefer to use constants that are theoretically derived, but I don't know enough about all the possibilities - all I can do is guess at this point. Pointers to tutorials or other matter that expand on what MS says in msdn or the compiler help would be appreciated. Good books about this area? Any hints, or places where I'm obviously barking up the wrong tree?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top