Last updated: 19. 1.1998, 23: 3
<* +M2EXTENSIONS *> MODULE Multi1; (*--------------------------------------- MULTI1.C --- Multitasking Demo (c) Charles Petzold, 1996 Multi1.mod --- Translation to XDS Modula-2 (c) Peter Stadler, 1997 ---------------------------------------*) IMPORT Windows; IMPORT SYSTEM; IMPORT Lib; IMPORT TimeConv; IMPORT RealMath; VAR cyChar : INTEGER; CONST szAppName = "Multi1"; VAR hwnd : Windows.HWND; msg : Windows.MSG; wc : Windows.WNDCLASSEX; VAR iNum1 : INTEGER; iLine1 : INTEGER; cyClient1 : INTEGER; iNum2 : INTEGER; iLine2 : INTEGER; cyClient2 : INTEGER; iNum3 : INTEGER; iLine3 : INTEGER; cyClient3 : INTEGER; iNext3 : INTEGER; cxClient4 : INTEGER; cyClient4 : INTEGER; hwndChild : ARRAY[0..3] OF Windows.HWND; TYPE CHILD = ARRAY[0..5] OF CHAR; CHILDPROC = ARRAY[0..3] OF Windows.HINSTANCE; CHILDCLASS = ARRAY[0..3] OF CHILD; CONST szChildClass = CHILDCLASS { "Child1", "Child2", "Child3", "Child4" }; (*++++*****************************************************************) PROCEDURE MaxInt (a,b : INTEGER) : INTEGER; (**********************************************************************) BEGIN IF(a>b) THEN RETURN a; ELSE RETURN b; END; END MaxInt; (*++++*****************************************************************) PROCEDURE MinInt (a,b : INTEGER) : INTEGER; (**********************************************************************) BEGIN IF(a>b) THEN RETURN b; ELSE RETURN a; END; END MinInt; (**********************************************************************) PROCEDURE CheckBottom (hwnd : Windows.HWND; cyClient : INTEGER; iLine : INTEGER) : INTEGER; (**********************************************************************) BEGIN IF (iLine * cyChar + cyChar > cyClient) THEN Windows.InvalidateRect (hwnd, NIL, TRUE); Windows.UpdateWindow (hwnd); iLine := 0; END; RETURN iLine; END CheckBottom; (* Window 1: Display increasing sequence of numbers *) (* ************************************************ *) (*++++*****************************************************************) PROCEDURE [Windows.CALLBACK] WndProc1(hwnd : Windows.HWND; (**********************************************************************) iMsg : Windows.UINT; wParam : Windows.WPARAM; lParam : Windows.LPARAM) : Windows.LRESULT; VAR szBuffer : ARRAY[0..15] OF CHAR; hdc : Windows.HDC; BEGIN CASE (iMsg) OF | Windows.WM_SIZE : cyClient1 := Windows.HIWORD (lParam); RETURN 0; | Windows.WM_TIMER : IF (iNum1 < 0) THEN iNum1 := 0; END; iLine1 := CheckBottom (hwnd, cyClient1, iLine1); Windows.wsprintf (szBuffer, "%d", iNum1); INC(iNum1); hdc := Windows.GetDC (hwnd); Windows.TextOut (hdc, 0, iLine1 * cyChar, szBuffer, LENGTH(szBuffer)); Windows.ReleaseDC (hwnd, hdc); INC(iLine1); RETURN 0; ELSE RETURN Windows.DefWindowProc (hwnd, iMsg, wParam, lParam); END; END WndProc1; (* Window 2: Display increasing sequence of prime numbers *) (* ****************************************************** *) (*++++*****************************************************************) PROCEDURE [Windows.CALLBACK] WndProc2(hwnd : Windows.HWND; (**********************************************************************) iMsg : Windows.UINT; wParam : Windows.WPARAM; lParam : Windows.LPARAM) : Windows.LRESULT; VAR szBuffer : ARRAY[0..15] OF CHAR; hdc : Windows.HDC; i,iSqrt : INTEGER; BEGIN CASE (iMsg) OF | Windows.WM_SIZE : cyClient2 := Windows.HIWORD (lParam); RETURN 0; | Windows.WM_TIMER : REPEAT INC(iNum2); IF (iNum2 < 0) THEN iNum2 := 0; END; iSqrt := VAL(INTEGER,RealMath.sqrt (FLOAT(iNum2))); i := 2; LOOP IF (iNum2 MOD i = 0) THEN EXIT; END; INC(i); IF(i>iSqrt) THEN EXIT; END; END; UNTIL (i > iSqrt); iLine2 := CheckBottom (hwnd, cyClient2, iLine2); Windows.wsprintf (szBuffer, "%d", iNum2); hdc := Windows.GetDC (hwnd); Windows.TextOut (hdc, 0, iLine2 * cyChar, szBuffer, LENGTH(szBuffer)); Windows.ReleaseDC (hwnd, hdc); INC(iLine2); RETURN 0; ELSE RETURN Windows.DefWindowProc (hwnd, iMsg, wParam, lParam); END; END WndProc2; (* Window 3: Display increasing sequence of Fibonacci numbers *) (* *********************************************************- *) (*++++*****************************************************************) PROCEDURE [Windows.CALLBACK] WndProc3(hwnd : Windows.HWND; (**********************************************************************) iMsg : Windows.UINT; wParam : Windows.WPARAM; lParam : Windows.LPARAM) : Windows.LRESULT; VAR szBuffer : ARRAY[0..15] OF CHAR; hdc : Windows.HDC; iTemp : INTEGER; BEGIN CASE (iMsg) OF | Windows.WM_SIZE : cyClient3 := Windows.HIWORD (lParam); RETURN 0; | Windows.WM_TIMER : IF (iNum3 < 0) THEN iNum3 := 0; iNext3 := 1; END; iLine3 := CheckBottom (hwnd, cyClient3, iLine3); Windows.wsprintf (szBuffer, "%d", iNum3); hdc := Windows.GetDC (hwnd); Windows.TextOut (hdc, 0, iLine3 * cyChar, szBuffer, LENGTH(szBuffer)); Windows.ReleaseDC (hwnd, hdc); iTemp := iNum3; iNum3 := iNext3; iNext3 := iNext3+iTemp; INC(iLine3); RETURN 0; ELSE RETURN Windows.DefWindowProc (hwnd, iMsg, wParam, lParam); END; END WndProc3; (* Window 4: Display circles of random radii *) (* ***************************************-- *) (*++++*****************************************************************) PROCEDURE [Windows.CALLBACK] WndProc4(hwnd : Windows.HWND; (**********************************************************************) iMsg : Windows.UINT; wParam : Windows.WPARAM; lParam : Windows.LPARAM) : Windows.LRESULT; VAR hdc : Windows.HDC; iDiameter: INTEGER; BEGIN CASE (iMsg) OF | Windows.WM_SIZE : cxClient4 := Windows.LOWORD (lParam); cyClient4 := Windows.HIWORD (lParam); RETURN 0; | Windows.WM_TIMER : Windows.InvalidateRect (hwnd, NIL, TRUE); Windows.UpdateWindow (hwnd); iDiameter := SYSTEM.CAST(INTEGER,Lib.RANDOM(1000) MOD VAL(CARDINAL,MaxInt(1,MinInt(cxClient4,cyClient4)))); hdc := Windows.GetDC (hwnd); Windows.Ellipse (hdc, (cxClient4 - iDiameter) DIV 2, (cyClient4 - iDiameter) DIV 2, (cxClient4 + iDiameter) DIV 2, (cyClient4 + iDiameter) DIV 2); Windows.ReleaseDC (hwnd, hdc); RETURN 0; ELSE RETURN Windows.DefWindowProc (hwnd, iMsg, wParam, lParam); END; END WndProc4; (* Main window to create child windows *) (* *********************************-- *) CONST ChildProc = CHILDPROC { SYSTEM.CAST(Windows.HINSTANCE,WndProc1), SYSTEM.CAST(Windows.HINSTANCE,WndProc2), SYSTEM.CAST(Windows.HINSTANCE,WndProc3), SYSTEM.CAST(Windows.HINSTANCE,WndProc4) }; (*++++*****************************************************************) PROCEDURE [Windows.CALLBACK] WndProc (hwnd : Windows.HWND; (**********************************************************************) iMsg : Windows.UINT; wParam : Windows.WPARAM; lParam : Windows.LPARAM) : Windows.LRESULT; VAR hInstance : Windows.HINSTANCE; i : INTEGER; cxClient : INTEGER; cyClient : INTEGER; wc : Windows.WNDCLASSEX; rc : CARDINAL; BEGIN CASE (iMsg) OF | Windows.WM_CREATE : hInstance := SYSTEM.CAST(Windows.HINSTANCE,Windows.GetWindowLong (hwnd, Windows.GWL_HINSTANCE)); wc.cbSize := SIZE (wc); wc.style := Windows.CS_HREDRAW + Windows.CS_VREDRAW; wc.cbClsExtra := 0; wc.cbWndExtra := 0; wc.hInstance := hInstance; wc.hIcon := NIL; wc.hCursor := Windows.LoadCursor (NIL, Windows.IDC_ARROW); wc.hbrBackground := SYSTEM.CAST(Windows.HBRUSH, Windows.GetStockObject (Windows.WHITE_BRUSH)); wc.lpszMenuName := NIL; wc.hIconSm := NIL; FOR i := 0 TO 4-1 DO wc.lpfnWndProc := SYSTEM.CAST(Windows.WNDPROC,ChildProc[i]); wc.lpszClassName := SYSTEM.ADR(szChildClass[i]); rc := Windows.RegisterClassEx(wc); hwndChild[i] := Windows.CreateWindow (szChildClass[i], "", Windows.WS_CHILDWINDOW + Windows.WS_BORDER + Windows.WS_VISIBLE, 0, 0, 0, 0, hwnd, SYSTEM.CAST(Windows.HMENU,i), hInstance, NIL); END; cyChar := Windows.HIWORD (Windows.GetDialogBaseUnits ()); Windows.SetTimer (hwnd, 1, 10, NIL); RETURN 0; | Windows.WM_SIZE : cxClient := Windows.LOWORD (lParam); cyClient := Windows.HIWORD (lParam); FOR i := 0 TO 4-1 DO IF(i>1) THEN Windows.MoveWindow (hwndChild[i], (i REM 2) * cxClient DIV 2, (1*cyClient DIV 2), cxClient DIV 2, cyClient DIV 2, TRUE); ELSE Windows.MoveWindow (hwndChild[i], (i REM 2) * cxClient DIV 2, (0 * cyClient DIV 2), cxClient DIV 2, cyClient DIV 2, TRUE); END; END; RETURN 0; | Windows.WM_TIMER : FOR i := 0 TO 4-1 DO Windows.SendMessage (hwndChild[i], Windows.WM_TIMER, wParam, lParam); END; RETURN 0; | Windows.WM_CHAR : IF (wParam = 27) (* '\x1B'*) THEN Windows.DestroyWindow (hwnd); END; RETURN 0; | Windows.WM_DESTROY : Windows.KillTimer (hwnd, 1); Windows.PostQuitMessage (0); RETURN 0; ELSE RETURN Windows.DefWindowProc (hwnd, iMsg, wParam, lParam); END; END WndProc; (*++++*****************************************************************) PROCEDURE InitApplication () : BOOLEAN; (**********************************************************************) VAR rc : CARDINAL; BEGIN wc.cbSize := SIZE(wc); wc.style := Windows.CS_HREDRAW + Windows.CS_VREDRAW; wc.lpfnWndProc := WndProc; wc.cbClsExtra := 0; wc.cbWndExtra := 0; wc.hInstance := Windows.MyInstance(); wc.hIcon := Windows.LoadIcon (NIL, Windows.IDI_APPLICATION); wc.hCursor := Windows.LoadCursor (NIL, Windows.IDC_ARROW); wc.hbrBackground := SYSTEM.CAST(Windows.HBRUSH, Windows.GetStockObject (Windows.WHITE_BRUSH)); wc.lpszMenuName := NIL; wc.lpszClassName := SYSTEM.ADR(szAppName); wc.hIconSm := Windows.LoadIcon (NIL,Windows.IDI_APPLICATION); rc := Windows.RegisterClassEx(wc); RETURN rc#0; END InitApplication; (*++++*****************************************************************) PROCEDURE InitMainWindow () : BOOLEAN; (**********************************************************************) BEGIN hwnd := Windows.CreateWindow ( szAppName, (* window class name *) "Multitasking Demo: Translation to XDS Modula-2", (* window caption *) Windows.WS_OVERLAPPEDWINDOW, (* window style *) Windows.CW_USEDEFAULT, (* initial x position *) Windows.CW_USEDEFAULT, (* initial y position *) Windows.CW_USEDEFAULT, (* initial x size *) Windows.CW_USEDEFAULT, (* initial y size *) NIL, (* parent window handle *) NIL, (* window menu handle *) wc.hInstance, (* program instance handle *) NIL); (* creation parameters *) IF hwnd = NIL THEN RETURN FALSE; END; Windows.ShowWindow (hwnd, Windows.SW_SHOWDEFAULT); Windows.UpdateWindow (hwnd); RETURN TRUE; END InitMainWindow; (* CONST ChildProc = CHILDPROC { SYSTEM.CAST(Windows.HINSTANCE,WndProc1), SYSTEM.CAST(Windows.HINSTANCE,WndProc2), SYSTEM.CAST(Windows.HINSTANCE,WndProc3), SYSTEM.CAST(Windows.HINSTANCE,WndProc4) };*) BEGIN Lib.RANDOMIZE; iNum2 := 1; iNum3 := 0; iNext3 := 1; IF InitApplication() AND InitMainWindow() THEN WHILE (Windows.GetMessage(msg,NIL,0,0)) DO Windows.TranslateMessage(msg); Windows.DispatchMessage(msg); END; END; END Multi1.