home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
w3_prog
/
ddjwin.arj
/
STATE.ASC
< prev
next >
Wrap
Text File
|
1991-11-14
|
17KB
|
407 lines
_PROGRAMMING WINDOWS USING STATE TABLES_
by Michael A. Bertrand and William R. Welch
[LISTING ONE]
/***********DRAW.H : header file for DRAW.C **************************/
#define WAITING 0 /* the possible values for variable iState in */
#define DRAWING 1 /* Tool() are WAITING and DRAWING */
/* These constants are the possible values for iMenuChoice, the variable
* recording the user's menu choice. The old menu choice must be stored
* so the check mark can be removed from the menu when a new menu choice
* is made. Do not change. */
#define IDM_RECT 100
#define IDM_ROUND_RECT 101
#define IDM_ELLIPSE 102
#define IDM_LINE 103
#define IDM_ABOUT 104
/* These constants are the possible values for iFigType, the variable
* recording the current FIGURE, as chosen through the menu. The value is
* also stored in the iType field in faList[] and is used to determine
* which drawing function is called upon from DrawFig[], the array of
* pointers to functions; since these values are indices into an array,
* starting at 0, they may not be changed. */
#define FT_RECT (IDM_RECT - IDM_RECT)
#define FT_ROUND_RECT (IDM_ROUND_RECT - IDM_RECT)
#define FT_ELLIPSE (IDM_ELLIPSE - IDM_RECT)
#define FT_LINE (IDM_LINE - IDM_RECT)
/* maximum number of FIGUREs in faList[] */
#define MAX_FIGS 1000
/* FIGUREs in faList[]: rectangle, rounded rectangle, ellipse, line */
typedef struct
{ int iType;
RECT rsCoord;
} FIGURE;
/* global variables */
FIGURE faList[MAX_FIGS]; /* List of FIGUREs */
int iListSize; /* tally number of displayed FIGUREs */
HANDLE hInst; /* current instance */
RECT rClient; /* client area in scr coords for ClipCursor() */
/* function prototypes */
long FAR PASCAL WndProc(HWND hWnd, unsigned iMessage, WORD wParam,
LONG lParam);
void NEAR PASCAL Tool(HWND hWnd, unsigned iMessage, LONG lParam,int iFigType);
BOOL FAR PASCAL DrawRoundRect(HDC hDC, int x1, int y1, int x2, int y2);
BOOL FAR PASCAL DrawLine(HDC hDC, int x1, int y1, int x2, int y2);
BOOL FAR PASCAL AboutDraw(HWND hDlg, unsigned message, WORD wParam,
LONG lParam);
/* DrawFig[] is an array of pointers to FAR PASCAL functions, each with parms
* (HDC,int,int,int,int) and returning BOOL. Note Rectangle() and Ellipse() are
* MS Windows GDI calls, while DrawRoundRect() and DrawLine() are our calls. */
BOOL (FAR PASCAL *DrawFig[4])(HDC hDC, int x1, int y1, int x2, int y2)
= {Rectangle, DrawRoundRect, Ellipse, DrawLine};
[LISTING TWO]
/******* DRAW.C by Michael A. Bertrand and William R. Welch. *******/
#include <windows.h>
#include "draw.h"
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine,
int nCmdShow)
/* hInstance : current instance handle
* hPrevInstance : previous instance handle
* lpszCmdLine : current command line
* nCmdShow : display either window or icon
*/
{ static char szAppName [] = "Draw";
static char szIconName[] = "DrawIcon";
static char szMenuName[] = "DrawMenu";
HWND hWnd; /* handle to WinMain's window */
MSG msg; /* message dispached to window */
WNDCLASS wc; /* for registering window */
/* Save instance handle in global var so can use for "About" dialog box. */
hInst = hInstance;
if (!hPrevInstance) /* Register application window class. */
{ wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc; /* function to get window's messages */
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, szIconName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = szMenuName; /* menu resource in RC file */
wc.lpszClassName = szAppName; /* name used in call to CreateWindow() */
if (!RegisterClass(&wc))
return(FALSE);
}
/* Initialize specific instance. */
hWnd = CreateWindow(szAppName, /* window class */
szAppName, /* window caption */
WS_OVERLAPPEDWINDOW, /* normal window style */
CW_USEDEFAULT, /* initial x-position */
CW_USEDEFAULT, /* initial y-position */
CW_USEDEFAULT, /* initial x-size */
CW_USEDEFAULT, /* initial y-size */
NULL, /* parent window handle */
NULL, /* window menu handle */
hInstance, /* program instance handle */
NULL); /* create parameters */
ShowWindow(hWnd, nCmdShow); /* display the window */
UpdateWindow(hWnd); /* update client area; send WM_PAINT */
/* Read msgs from app que and dispatch them to appropriate win function.
* Continues until GetMessage() returns NULL when it receives WM_QUIT. */
while (GetMessage(&msg, NULL, NULL, NULL))
{ TranslateMessage(&msg); /* process char input from keyboard */
DispatchMessage(&msg); /* pass message to window function */
}
return(msg.wParam);
}
/****************************************************************/
long FAR PASCAL WndProc(HWND hWnd,unsigned iMessage, WORD wParam, LONG lParam)
/* IN: hWnd : handle to window
* iMessage : message type
* wParam : drawing tool selected from menu (when WM_COMMAND msg)
* lParam : mouse coords (x == loword, y == hiword) */
{ static int iMenuChoice = IDM_RECT; /* default menu choice */
static int iFigType = FT_RECT; /* default figure type */
HDC hDC; /* must generate our own handle to DC to draw */
HMENU hMenu; /* handle for drop down menu */
PAINTSTRUCT ps; /* needed when receive WM_PAINT message */
int ndx; /* to traverse faList[] when draw it */
FARPROC lpProcAbout; /* pointer to "AboutDraw" function */
POINT pt; /* for ClientToScreen() */
switch(iMessage)
{ case WM_SIZE: /*convert client coords to scrn coords for ClipCursor()*/
pt.x = pt.y = 0;
ClientToScreen(hWnd, &pt);
rClient.left = pt.x;
rClient.top = pt.y;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
ClientToScreen(hWnd, &pt);
rClient.right = pt.x;
rClient.bottom = pt.y;
break;
case WM_COMMAND:
switch(wParam)
{ case IDM_RECT:
case IDM_ROUND_RECT:
case IDM_ELLIPSE:
case IDM_LINE:
/* New FIGURE chosen by user : uncheck old choice and check new
* choice on menu; reset iMenuChoice according to user choice. */
hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, iMenuChoice, MF_UNCHECKED);
CheckMenuItem(hMenu, iMenuChoice = wParam, MF_CHECKED);
/* User has chosen new FIGURE : set iFigType accordingly. */
iFigType = iMenuChoice - IDM_RECT;
break; /* case IDM_LINE ... */
case IDM_ABOUT:
/* "About" chosen by user : call "AboutDraw" function. */
lpProcAbout = MakeProcInstance(AboutDraw, hInst);
DialogBox (hInst, "AboutDraw", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break; /* IDM_ABOUT */
} /* switch(wParam) */
break; /* WM_COMMAND */
case WM_LBUTTONDOWN:
case WM_MOUSEMOVE:
case WM_LBUTTONUP:
/* Mouse events passed on to Tool() for processing. */
Tool(hWnd, iMessage, lParam, iFigType);
break; /* WM_LBUTTONDOWN... */
case WM_PAINT:
/* Repaint window when resized. */
hDC = BeginPaint(hWnd, &ps);
/* Draw list of FIGUREs. */
for (ndx = 0; ndx < iListSize; ndx++)
DrawFig[faList[ndx].iType](hDC, faList[ndx].rsCoord.left,
faList[ndx].rsCoord.top,
faList[ndx].rsCoord.right,
faList[ndx].rsCoord.bottom);
EndPaint(hWnd, &ps);
break; /* WM_PAINT */
case WM_DESTROY:
/* Destroy window when application terminated. */
PostQuitMessage(0);
break; /* WM_DESTROY */
default:
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
} /* switch(iMessage) */
return(0L);
}
/****************************************************************/
void NEAR PASCAL Tool(HWND hWnd, unsigned iMessage, LONG lParam, int iFigType)
/* Process mouse event and draw.
* IN: hWnd : handle to window
* iMessage : mouse event (WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP)
* lParam : mouse coords (x == loword, y == hiword)
*/
{ static int x1, y1; /* coordinates of button-down point */
static int x2, y2; /* coordinates of mouse */
static int iState; /* WAITING or DRAWING */
HDC hDC; /* must generate our own handle to DC to draw */
switch(iMessage)
{ case WM_LBUTTONDOWN:
/* Protect array from overflow : if array full, notify and out. */
if (iListSize == MAX_FIGS)
{ MessageBox(hWnd,"Figure array full","Note",MB_ICONEXCLAMATION|MB_OK);
break; /* WM_LBUTTONDOWN */
}
/* If not drawing, reset iState and store button-down point. */
if (iState == WAITING)
{ ClipCursor(&rClient); /* restrict cursor */
iState = DRAWING; /* starting drag */
x1 = x2 = LOWORD(lParam); /* store user point in statics */
y1 = y2 = HIWORD(lParam);
}
break; /* WM_LBUTTONDOWN */
case WM_MOUSEMOVE:
/* If drawing, erase old figure and draw new one at mouse. */
if (iState == DRAWING)
{ hDC = GetDC(hWnd);
SetROP2(hDC, R2_NOTXORPEN); /* draw in XOR */
DrawFig[iFigType](hDC, x1, y1, x2, y2); /* erase old */
x2 = LOWORD(lParam); /* get 2nd user pt */
y2 = HIWORD(lParam);
DrawFig[iFigType](hDC, x1, y1, x2, y2); /* draw new */
ReleaseDC(hWnd, hDC);
}
break; /* WM_MOUSEMOVE */
case WM_LBUTTONUP:
/* If drawing, write in COPY mode and store in faList[]. */
if (iState == DRAWING)
{ ClipCursor(NULL); /* no longer restrict cursor */
iState = WAITING; /* ending draw */
hDC = GetDC(hWnd);
SetROP2(hDC, R2_COPYPEN); /* COPY pen for final FIGURE */
DrawFig[iFigType](hDC, x1, y1, x2, y2); /* draw FIGURE */
ReleaseDC(hWnd, hDC);
faList[iListSize].iType = iFigType; /* put FIGURE in faList[] */
faList[iListSize].rsCoord.left = x1;
faList[iListSize].rsCoord.top = y1;
faList[iListSize].rsCoord.right = x2;
faList[iListSize].rsCoord.bottom = y2;
iListSize++; /* bump tally, since just added figure to list */
}
break; /* WM_LBUTTONUP */
} /* switch(iMessage) */
}
/****************************************************************/
BOOL FAR PASCAL DrawRoundRect(HDC hDC, int x1, int y1, int x2, int y2)
/* IN: hDC : display context in which to draw
* x1, y1 : coordinates of first corner
* x2, y2 : coordinates of second corner
* RET: returns BOOL for consistency with GDI's Rectangle() and Ellipse()
* NOTE: GDI's RoundRect() is used to draw, but RoundRect() requires x-
* and y-diameters of ellipse used for rounding. This routine sets
* the common diameter equal to half the smallest side, then calls
* RoundRect(). Array DrawFig[] contains a pointer to this function.
*/
{ int dx, dy; /* sides of rectangle, as positive values */
int diameter; /* diameter of circle used for rounding */
dx = (x1 < x2) ? (x2 - x1) : (x1 - x2); /* x-side of rect (positive) */
dy = (y1 < y2) ? (y2 - y1) : (y1 - y2); /* y-side of rect (positive) */
diameter = (dx < dy) ? dx/2 : dy/2; /* half smallest side */
RoundRect(hDC, x1, y1, x2, y2, diameter, diameter); /* call GDI */
return(TRUE);
}
/****************************************************************/
BOOL FAR PASCAL DrawLine(HDC hDC, int x1, int y1, int x2, int y2)
/*
* IN: hDC : display context in which to draw
* x1, y1 : coordinates of first endpoint
* x2, y2 : coordinates of second endpoint
* RET: returns BOOL for consistency w/GDI's Rectangle() and Ellipse().
* NOTE: Array DrawFig[] contains a pointer to this function.
*/
{ MoveTo(hDC, x1, y1); /* MoveTo() and LineTo() are GDI calls. */
LineTo(hDC, x2, y2);
return(TRUE);
}
/****************************************************************/
BOOL FAR PASCAL AboutDraw(HWND hDlg,unsigned iMessage,WORD wParam,LONG lParam)
/* Application's "About" dialog box function.
* IN: hDlg : handle to dialog box
* iMessage : message type
* wParam : auxiliary message info (act on IDOK, IDCANCEL)
* lParam : unused
* RET: Return TRUE if processed appropriate message, FALSE otherwise.
*/
{ switch (iMessage)
{ case WM_INITDIALOG: /* initialize dialog box */
return (TRUE);
case WM_COMMAND: /* received a command */
/* IDOK if OK box selected; IDCANCEL if system menu close command */
if (wParam == IDOK || wParam == IDCANCEL)
{ EndDialog(hDlg, TRUE); /* exit dialog box */
return(TRUE); /* did proccess message */
}
break; /* WM_COMMAND */
} /* switch (iMessage) */
return (FALSE); /* did not process message */
}
[LISTING THREE]
#*************** DRAW : Make file for DRAW.C ***************************
# To make program : NMAKE DRAW
# Linker and Resource Compiler: draw.exe depends on draw.obj draw.def draw.res
# Linker options as follows :
# /A:16 : align on paragraphs
# /CO : add symbol information to EXE for CodeView
# /NOD : don't search default libs (use only those in link response file)
draw.exe: draw.obj draw.def draw.res
link /A:16 /CO /NOD draw,,, libw slibcew, draw.def
rc draw.res
# Microsoft C Compiler : draw.obj contingent on draw.c, draw.h
# Compiler options as follows :
# -c : compile only
# -Gs : remove stack probe before function calls
# -Gw : for MS Windows
# -Od : disable code optimization to help with debugging
# -W3 : highest warning level (flags ANSI incompatibilities)
# -AS : small model
# -Zp : pack structures (required by MS Windows)
# -Zi : add symbol information to OBJ for CodeView
draw.obj: draw.c draw.h
cl -c -Gsw -Od -W3 -AS -Zpi draw.c
# Resource Compiler : draw.res contingent on draw.rc, draw.h
draw.res: draw.rc draw.h
rc -r -v draw.rc
[LISTING FOUR]
;;**************DRAW.DEF : Definition file for DRAW.C**************
NAME DRAW
DESCRIPTION 'MS Windows Draw Program (c) 1990 M. Bertrand & W. Welch'
EXETYPE WINDOWS
STUB 'WINSTUB.EXE'
CODE MOVEABLE PRELOAD
DATA MOVEABLE PRELOAD SINGLE
HEAPSIZE 1024
STACKSIZE 4096
EXPORTS WndProc
AboutDraw
[LISTING FIVE]
/************ DRAW.RC : resource file for DRAW.C *******************/
#include "windows.h"
#include "draw.h"
DrawIcon ICON DRAW.ICO
DrawMenu MENU
BEGIN
POPUP "&Tool"
BEGIN
MENUITEM "&Rectangle", IDM_RECT, CHECKED
MENUITEM "R&ounded rectangle", IDM_ROUND_RECT
MENUITEM "&Ellipse", IDM_ELLIPSE
MENUITEM "&Line", IDM_LINE
MENUITEM Separator
MENUITEM "&About Draw...", IDM_ABOUT
END
END
/* "AboutDraw" dialog box contains 3 types of controls :
* CTEXT to display centered text at x-coordinates 8, 24, 40, 56
* ICON to display DRAW's icon at coords relative (20,20)
* DEFPUSHBUTTON to display 32x14 OK push button at coords (60,74)
*/
AboutDraw DIALOG 30, 30, 150, 94
CAPTION "About Draw"
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
BEGIN
CTEXT "Microsoft Windows" -1, 0, 8, 152, 8
CTEXT "Draw" -1, 0, 24, 152, 8
CTEXT "Copyright (c) 1990" -1, 0, 40, 152, 8
CTEXT "Michael A. Bertrand and William R. Welch" -1, 0, 56, 152, 8
ICON "DrawIcon" -1, 20, 20, 19, 26
DEFPUSHBUTTON "&OK" IDOK, 60, 74, 32, 14, WS_GROUP
END