Last updated: 15. 1.1998, 21:42
<*/NOWARN:F*>
MODULE OwnerDrw;
(*----------------------------------------------
OWNERDRW.C --- Owner-Draw Button Demo Program
(c) Charles Petzold, 1996
OwnerDrw.mod --- Translation to Stony Brook Modula-2
(c) Peter Stadler, 1998
----------------------------------------------*)
IMPORT WIN32;
IMPORT WINX;
IMPORT WINGDI;
IMPORT WINUSER;
IMPORT SYSTEM;
CONST
IDC_SMALLER = 1;
IDC_LARGER = 2;
VAR
hInst : WIN32.HINSTANCE;
CONST
szAppName = "OwnerDrw";
VAR
hwnd : WIN32.HWND;
msg : WINUSER.MSG;
wc : WINUSER.WNDCLASSEX;
VAR
hwndSmaller : WIN32.HWND;
hwndLarger : WIN32.HWND;
cxClient : INTEGER;
cyClient : INTEGER;
cxChar : INTEGER;
cyChar : INTEGER;
BTN_WIDTH : INTEGER;
BTN_HEIGHT : INTEGER;
(**********************************************************************)
PROCEDURE Triangle (hdc : WIN32.HDC; pt : ARRAY OF WIN32.POINT);
(**********************************************************************)
BEGIN
WINGDI.SelectObject (hdc, WINGDI.GetStockObject (WINGDI.BLACK_BRUSH));
WINGDI.Polygon (hdc, pt, 3);
WINGDI.SelectObject (hdc, WINGDI.GetStockObject (WINGDI.WHITE_BRUSH));
END Triangle;
<*/PUSH*>
%IF WIN32 %THEN
<*/CALLS:WIN32SYSTEM*>
%ELSE
<*/CALLS:WINSYSTEM*>
%END
(*++++*****************************************************************)
PROCEDURE WndProc (hwnd : WIN32.HWND;
(**********************************************************************)
iMsg : WIN32.UINT;
wParam : WIN32.WPARAM;
lParam : WIN32.LPARAM) : WIN32.LRESULT [EXPORT];
VAR
cx : INTEGER;
cy : INTEGER;
rc : WIN32.RECT;
pdis : WINUSER.LPDRAWITEMSTRUCT;
pt : ARRAY[0..2] OF WIN32.POINT;
BEGIN
CASE (iMsg) OF
| WINUSER.WM_CREATE :
cxChar := WINUSER.LOWORD (WINUSER.GetDialogBaseUnits ());
cyChar := WINUSER.HIWORD (WINUSER.GetDialogBaseUnits ());
BTN_WIDTH := 8*cxChar;
BTN_HEIGHT := 4*cyChar;
(* Create the owner-draw pushbuttons *)
hwndSmaller := WINUSER.CreateWindow ("button", "",
WINUSER.WS_CHILD BOR WINUSER.WS_VISIBLE BOR WINUSER.BS_OWNERDRAW,
0, 0, BTN_WIDTH, BTN_HEIGHT,
hwnd, SYSTEM.CAST(WIN32.HMENU,IDC_SMALLER), hInst, NIL);
hwndLarger := WINUSER.CreateWindow ("button", "",
WINUSER.WS_CHILD BOR WINUSER.WS_VISIBLE BOR WINUSER.BS_OWNERDRAW,
0, 0, BTN_WIDTH, BTN_HEIGHT,
hwnd, SYSTEM.CAST(WIN32.HMENU,IDC_LARGER), hInst, NIL);
RETURN 0;
| WINUSER.WM_SIZE :
cxClient := WINUSER.LOWORD (lParam);
cyClient := WINUSER.HIWORD (lParam);
(* Move the buttons to the new center *)
WINUSER.MoveWindow (hwndSmaller, cxClient DIV 2 - 3 * BTN_WIDTH DIV 2,
cyClient DIV 2 - BTN_HEIGHT DIV 2,
BTN_WIDTH, BTN_HEIGHT, TRUE);
WINUSER.MoveWindow (hwndLarger, cxClient DIV 2 + BTN_WIDTH DIV 2,
cyClient DIV 2 - BTN_HEIGHT DIV 2,
BTN_WIDTH, BTN_HEIGHT, TRUE);
RETURN 0;
| WINUSER.WM_COMMAND :
WINUSER.GetWindowRect (hwnd, rc);
(* Make the window 10% smaller or larger *)
CASE (wParam) OF
| IDC_SMALLER :
rc.left := rc.left + cxClient DIV 20;
rc.right := rc.right - cxClient DIV 20;
rc.top := rc.top + cyClient DIV 20;
rc.bottom := rc.bottom - cyClient DIV 20;
| IDC_LARGER :
rc.left := rc.left - cxClient DIV 20;
rc.right := rc.right + cxClient DIV 20;
rc.top := rc.top - cyClient DIV 20;
rc.bottom := rc.bottom + cyClient DIV 20;
ELSE
END;
WINUSER.MoveWindow (hwnd, rc.left, rc.top, rc.right - rc.left,
rc.bottom - rc.top, TRUE);
RETURN 0;
| WINUSER.WM_DRAWITEM :
pdis := SYSTEM.CAST(WINUSER.LPDRAWITEMSTRUCT,lParam);
(* Fill area with white and frame it black *)
WINUSER.FillRect (pdis^.hDC, pdis^.rcItem,
SYSTEM.CAST(WIN32.HBRUSH,WINGDI.GetStockObject (WINGDI.WHITE_BRUSH)));
WINUSER.FrameRect (pdis^.hDC, pdis^.rcItem,
SYSTEM.CAST(WIN32.HBRUSH,WINGDI.GetStockObject (WINGDI.BLACK_BRUSH)));
(* Draw inward and outward black triangles *)
cx := pdis^.rcItem.right - pdis^.rcItem.left;
cy := pdis^.rcItem.bottom - pdis^.rcItem.top ;
CASE (pdis^.CtlID) OF
| IDC_SMALLER :
pt[0].x := 3 * cx DIV 8; pt[0].y := 1 * cy DIV 8;
pt[1].x := 5 * cx DIV 8; pt[1].y := 1 * cy DIV 8;
pt[2].x := 4 * cx DIV 8; pt[2].y := 3 * cy DIV 8;
Triangle (pdis^.hDC, pt);
pt[0].x := 7 * cx DIV 8; pt[0].y := 3 * cy DIV 8;
pt[1].x := 7 * cx DIV 8; pt[1].y := 5 * cy DIV 8;
pt[2].x := 5 * cx DIV 8; pt[2].y := 4 * cy DIV 8;
Triangle (pdis^.hDC, pt);
pt[0].x := 5 * cx DIV 8; pt[0].y := 7 * cy DIV 8;
pt[1].x := 3 * cx DIV 8; pt[1].y := 7 * cy DIV 8;
pt[2].x := 4 * cx DIV 8; pt[2].y := 5 * cy DIV 8;
Triangle (pdis^.hDC, pt);
pt[0].x := 1 * cx DIV 8; pt[0].y := 5 * cy DIV 8;
pt[1].x := 1 * cx DIV 8; pt[1].y := 3 * cy DIV 8;
pt[2].x := 3 * cx DIV 8; pt[2].y := 4 * cy DIV 8;
Triangle (pdis^.hDC, pt);
| IDC_LARGER :
pt[0].x := 5 * cx DIV 8; pt[0].y := 3 * cy DIV 8;
pt[1].x := 3 * cx DIV 8; pt[1].y := 3 * cy DIV 8;
pt[2].x := 4 * cx DIV 8; pt[2].y := 1 * cy DIV 8;
Triangle (pdis^.hDC, pt);
pt[0].x := 5 * cx DIV 8; pt[0].y := 5 * cy DIV 8;
pt[1].x := 5 * cx DIV 8; pt[1].y := 3 * cy DIV 8;
pt[2].x := 7 * cx DIV 8; pt[2].y := 4 * cy DIV 8;
Triangle (pdis^.hDC, pt);
pt[0].x := 3 * cx DIV 8; pt[0].y := 5 * cy DIV 8;
pt[1].x := 5 * cx DIV 8; pt[1].y := 5 * cy DIV 8;
pt[2].x := 4 * cx DIV 8; pt[2].y := 7 * cy DIV 8;
Triangle (pdis^.hDC, pt);
pt[0].x := 3 * cx DIV 8; pt[0].y := 3 * cy DIV 8;
pt[1].x := 3 * cx DIV 8; pt[1].y := 5 * cy DIV 8;
pt[2].x := 1 * cx DIV 8; pt[2].y := 4 * cy DIV 8;
Triangle (pdis^.hDC, pt);
ELSE
END;
(* Invert the rectangle if the button is selected *)
IF (pdis^.itemState BAND WINUSER.ODS_SELECTED=1) THEN
WINUSER.InvertRect (pdis^.hDC, pdis^.rcItem);
END;
(* Draw a focus rectangle if the button has the focus *)
IF (pdis^.itemState BAND WINUSER.ODS_FOCUS=1) THEN
pdis^.rcItem.left := pdis^.rcItem.left + cx DIV 16;
pdis^.rcItem.top := pdis^.rcItem.top + cy DIV 16;
pdis^.rcItem.right := pdis^.rcItem.right - cx DIV 16;
pdis^.rcItem.bottom := pdis^.rcItem.bottom - cy DIV 16;
WINUSER.DrawFocusRect (pdis^.hDC, pdis^.rcItem);
END;
RETURN 0;
| WINUSER.WM_DESTROY :
WINUSER.PostQuitMessage (0);
RETURN 0;
ELSE
RETURN WINUSER.DefWindowProc (hwnd, iMsg, wParam, lParam);
END;
END WndProc;
<*/POP*>
(*++++*****************************************************************)
PROCEDURE InitApplication () : BOOLEAN;
(**********************************************************************)
VAR
rc : CARDINAL;
BEGIN
hInst := WINX.Instance;
wc.cbSize := SIZE(wc);
wc.style := WINUSER.CS_HREDRAW BOR WINUSER.CS_VREDRAW;
wc.lpfnWndProc := WndProc;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
wc.hInstance := WINX.Instance;
wc.hIcon := WINUSER.LoadIcon (NIL, WINUSER.IDI_APPLICATION^);
wc.hCursor := WINUSER.LoadCursor (NIL, WINUSER.IDC_ARROW^);
wc.hbrBackground := SYSTEM.CAST(WIN32.HBRUSH,WINGDI.GetStockObject(WINGDI.WHITE_BRUSH));
wc.lpszMenuName := SYSTEM.ADR(szAppName);
wc.lpszClassName := SYSTEM.ADR(szAppName);
wc.hIconSm := WINUSER.LoadIcon (NIL,WINUSER.IDI_APPLICATION^);
rc := WINUSER.RegisterClassEx(wc);
RETURN rc#0;
END InitApplication;
(*++++*****************************************************************)
PROCEDURE InitMainWindow () : BOOLEAN;
(**********************************************************************)
BEGIN
hwnd := WINUSER.CreateWindow (
szAppName, (* window class name *)
"Owner-Draw Button Demo: Translation to Stony Brook Modula-2",
(* window caption *)
WINUSER.WS_OVERLAPPEDWINDOW, (* window style *)
WINUSER.CW_USEDEFAULT, (* initial x position *)
WINUSER.CW_USEDEFAULT, (* initial y position *)
WINUSER.CW_USEDEFAULT, (* initial x size *)
WINUSER.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;
WINUSER.ShowWindow (hwnd, WINUSER.SW_SHOWDEFAULT);
WINUSER.UpdateWindow (hwnd);
RETURN TRUE;
END InitMainWindow;
BEGIN
IF InitApplication() AND InitMainWindow() THEN
WHILE (WINUSER.GetMessage(msg,NIL,0,0)) DO
WINUSER.TranslateMessage(msg);
WINUSER.DispatchMessage(msg);
END;
END;
END OwnerDrw.