[comp.windows.ms.programmer] Help! UAE with Petzold's sysmets. ** LONG **

mekdecic@serss0.fiu.edu (Christine Mekdeci) (06/30/91)

I have a question that I hope someone can answer.  The following code
listing comes from pages 101-106 in Petzold's book "Programming Windows".

According to my Turbo Debugger, the program runs fine up to ShowWindow()
(in WinMain) then TD generates an Exception 13 error (memory overwrite
error).  When I run it in Windows it gives me two UAE's.  The first one
kicks me out of sysmets and the second kicks me out of Windows.

I am using the Borland C++ compiler with the Windows application
parameter of all functions exportable and the small memory model.

I gone through the code very carefully.  I don't think I've made any typos
but just in case I've included the source.

Hints anyone?

Posted for George Santamarina.

mekdecic@serss0.fiu.edu

/*---------------------------------------------------------------
	SYSMETS.C -- System Metrics Display Program (Final)
			(c) Charles Petzold, 1990
---------------------------------------------------------------*/

#include <windows.h>
#include "sysmets.h"

long FAR PASCAL WndProc(HWND, WORD, WORD, LONG);


int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
		LPSTR lpszCmdLine, int nCmdShow) {


	static char szAppName[] = "SysMets";
	HWND hwnd;
	MSG msg;
	WNDCLASS wndclass;

	if(!hPrevInstance) {

		wndclass.style		= CS_HREDRAW | CS_VREDRAW;
		wndclass.lpfnWndProc	= WndProc;
		wndclass.cbClsExtra	= 0;
		wndclass.cbWndExtra	= 0;
		wndclass.hInstance	= hInstance;
		wndclass.hIcon		= LoadIcon(NULL, IDI_APPLICATION);
		wndclass.hCursor	= LoadCursor(NULL, IDC_ARROW);
		wndclass.hbrBackground	= GetStockObject(WHITE_BRUSH);
		wndclass.lpszMenuName	= NULL;
		wndclass.lpszClassName	= szAppName;

		RegisterClass(&wndclass);

	}

	hwnd=CreateWindow(szAppName, "System Metrics",
		WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
		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;

}

long FAR PASCAL WndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam) {


	static short cxChar, cxCaps, cyChar, cxClient, cyClient, nMaxWidth,
		     nVscrollPos, nVscrollMax, nHscrollPos, nHscrollMax;
	char szBuffer[10];
	HDC hdc;
	short i, x, y, nPaintBeg, nPaintEnd, nVscrollInc, nHscrollInc;
	PAINTSTRUCT ps;
	TEXTMETRIC tm;

	switch(message) {

		case WM_CREATE:

			hdc = GetDC(hwnd);

			GetTextMetrics(hdc, &tm);
			cxChar = tm.tmAveCharWidth;
			cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;
			cyChar = tm.tmHeight + tm.tmExternalLeading;

			ReleaseDC(hwnd, hdc);

			nMaxWidth = 40 * cxChar + 18 * cxCaps;

			return 0;

		case WM_SIZE:

			cyClient = HIWORD(lParam);
			cxClient = LOWORD(lParam);

			nVscrollMax = max (0, NUMLINES + 2 - cyClient / cyChar);
			nVscrollPos = min (nVscrollPos, nVscrollMax);

			SetScrollRange(hwnd, SB_VERT, 0, nVscrollMax, FALSE);
			SetScrollPos(hwnd, SB_VERT, nVscrollPos, TRUE);

			nHscrollMax = max (0, 2 + (nMaxWidth - cxClient) / cxChar);
			nHscrollPos = min (nHscrollPos, nHscrollMax);

			SetScrollRange(hwnd, SB_HORZ, 0, nHscrollMax, FALSE);
			SetScrollPos(hwnd, SB_HORZ, nHscrollPos, TRUE);

			return 0;

		case WM_VSCROLL:

			switch (wParam) {

				case SB_TOP:
					nVscrollInc = -nVscrollPos;
					break;

				case SB_BOTTOM:
					nVscrollInc = nVscrollMax - nVscrollPos;
					break;

				case SB_LINEUP:
					nVscrollInc = -1;
					break;

				case SB_LINEDOWN:
					nVscrollInc = 1;
					break;

				case SB_PAGEUP:
					nVscrollInc = min (-1, -cyClient / cyChar);
					break;

				case SB_PAGEDOWN:
					nVscrollInc = max (1, cyClient / cyChar);
					break;

				case SB_THUMBTRACK:
					nVscrollInc = LOWORD (lParam) - nVscrollPos;
					break;

				default:
					nVscrollInc=0;

			}

			if (nVscrollInc = max (-nVscrollPos, min (nVscrollInc, nVscrollMax - nVscrollPos))) {
				nVscrollPos += nVscrollInc;
				ScrollWindow (hwnd, 0, -cyChar * nVscrollInc, NULL, NULL);
				SetScrollPos (hwnd, SB_VERT, nVscrollPos, TRUE);
				UpdateWindow (hwnd);
			}

			return 0;

		case WM_HSCROLL:
			switch (wParam) {

				case SB_LINEUP:
					nHscrollInc = -1;
					break;

				case SB_LINEDOWN:
					nHscrollInc = 1;
					break;

				case SB_PAGEUP:
					nHscrollInc = -8;
					break;

				case SB_PAGEDOWN:
					nHscrollInc = 8;
					break;

				case SB_THUMBPOSITION:
					nHscrollInc = LOWORD (lParam) - nHscrollPos;
					break;

				default:
					nHscrollInc=0;

			}

			if (nHscrollInc = max (-nHscrollPos, min (nHscrollInc, nHscrollMax - nHscrollPos))) {
				nHscrollPos += nHscrollInc;
				ScrollWindow (hwnd, -cxChar * nHscrollInc, 0, NULL, NULL);
				SetScrollPos (hwnd, SB_HORZ, nHscrollPos, TRUE);
				UpdateWindow (hwnd);
			}

			return 0;

		case WM_KEYDOWN:

			switch (wParam) {
				case VK_HOME:
					SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0L);
					break;

				case VK_END:
					SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0L);
					break;

				case VK_PRIOR:
					SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0L);
					break;

				case VK_NEXT:
					SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0L);
					break;

				case VK_UP:
					SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0L);
					break;

				case VK_DOWN:
					SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0L);
					break;

				case VK_LEFT:
					SendMessage(hwnd, WM_HSCROLL, SB_PAGEUP, 0L);
					break;

				case VK_RIGHT:
					SendMessage(hwnd, WM_HSCROLL, SB_PAGEDOWN, 0L);
					break;
			}

			return 0;

		case WM_PAINT:

			hdc = BeginPaint(hwnd, &ps);

			nPaintBeg = max (0, nVscrollPos + ps.rcPaint.top / cyChar - 1);
			nPaintEnd = min (NUMLINES, nVscrollPos + ps.rcPaint.bottom / cyChar);

			for (i = nPaintBeg; i < nPaintEnd; i++) {

				x = cxChar * (1 - nHscrollPos);
				y = cyChar * (1 - nVscrollPos + i);

				TextOut(hdc, x, y,
					sysmetrics[i].szLabel,
					lstrlen(sysmetrics[i].szLabel));

				TextOut(hdc, x + 18 * cxCaps, y,
					sysmetrics[i].szDesc,
					lstrlen(sysmetrics[i].szDesc));

				SetTextAlign(hdc, TA_RIGHT | TA_TOP);

				TextOut (hdc, x + 18 * cxCaps + 40 * cxChar, y,
					szBuffer,
					wsprintf(szBuffer, "%5d",
					GetSystemMetrics (sysmetrics[i].nIndex)));

				SetTextAlign(hdc, TA_LEFT | TA_TOP);
			}

			EndPaint(hwnd, &ps);
			return 0;


		case WM_DESTROY:

			PostQuitMessage(0);
			return 0;

	}

	return DefWindowProc(hwnd, message, wParam, lParam);

}

;-------------------------------------
; SYSMETS.DEF module definition file
;-------------------------------------

NAME		SYSMETS

DESCRIPTION     'System Metrics Display (c) Charles Petzold, 1990'
EXETYPE		WINDOWS
CODE		PRELOAD MOVEABLE DISCARDABLE
DATA		PRELOAD MOVEABLE MULTIPLE
HEAPSIZE	1024
STACKSIZE	8192
;EXPORTS		WndProc