|
|
1.1 root 1: /**************************************************************************\
2: * polydraw.c -- sample program demonstrating PolyDraw().
3: *
4: * The user is able to place control points on the screen, and then
5: * drag them. The PolyDraw() call is made to dynamically show the
6: * resulting curve.
7: \**************************************************************************/
8:
9: #include <windows.h>
10: #include "polydraw.h"
11:
12:
13:
14: /**************************************************************************\
15: *
16: * function: WinMain()
17: *
18: * input parameters: c.f. generic sample
19: *
20: \**************************************************************************/
21: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
22: LPSTR lpCmdLine, int nCmdShow)
23: {
24: HANDLE hInst;
25: HWND hwndMain;
26: MSG msg;
27:
28: UNREFERENCED_PARAMETER( lpCmdLine );
29:
30:
31: /* Check for previous instance. If none, then register class. */
32: if (!hPrevInstance) {
33: WNDCLASS wc;
34:
35: wc.style = CS_VREDRAW;
36: wc.lpfnWndProc = (WNDPROC)MainWndProc;
37:
38: wc.cbClsExtra = 0;
39: wc.cbWndExtra = 0;
40: wc.hInstance = hInstance;
41: wc.hIcon = LoadIcon(hInstance, "polydrawIcon");
42: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
43: wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
44: wc.lpszMenuName = NULL;
45: wc.lpszClassName = "polydraw";
46:
47: if (!RegisterClass(&wc)) return (FALSE);
48: } /* class registered o.k. */
49:
50:
51: /* Create the main window. Return false if CreateWindow() fails */
52: hInst = hInstance;
53:
54: hwndMain = CreateWindow(
55: "polydraw",
56: "PolyDraw",
57: WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
58: CW_USEDEFAULT,
59: CW_USEDEFAULT,
60: CW_USEDEFAULT,
61: CW_USEDEFAULT,
62: NULL,
63: NULL,
64: hInstance,
65: NULL);
66:
67: if (!hwndMain) return (FALSE);
68: ShowWindow(hwndMain, nCmdShow);
69: UpdateWindow(hwndMain);
70:
71:
72: /* Loop getting messages and dispatching them. */
73: while (GetMessage(&msg,NULL, NULL, NULL)) {
74: TranslateMessage(&msg);
75: DispatchMessage(&msg);
76: }
77:
78: return (msg.wParam);
79: }
80:
81:
82:
83: /**************************************************************************\
84: *
85: * function: MainWndProc()
86: *
87: * input parameters: normal window procedure parameters.
88: *
89: * global variables: none.
90: *
91: * static variables:
92: * svPoints[] - array that stores the points for the GDI calls.
93: * svTypes[] - array of bytes to store the type for the PolyDraw() calls.
94: * svIndex - when tracking, the index of the point we are modifying.
95: * svNumDown - the number of points currently in the client area.
96: * hPen* - Pens to draw the lines, curves, or erase with.
97: *
98: * The PolyDraw() function is different from PolyBezier in that the current
99: * point is taken to be the first point, and the first point passed in in
100: * the array is actually the second point in the bezier or line or whatever,
101: * thus ...
102: * PolyDraw (hdc, &svPoints[1], &svTypes[1], svNumDown);
103: * instead of ...
104: * PolyDraw (hdc, svPoints, svTypes, svNumDown+1);
105: *
106: \**************************************************************************/
107: LRESULT MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
108: {
109: static HANDLE hPenGrey, hPenLine, hPenpolydraw;
110: static POINT svPoints [MAXPOINTS];
111: static BYTE svTypes [MAXPOINTS];
112: static int svNumDown;
113: static int svIndex;
114:
115: switch (message) {
116:
117:
118: /**********************************************************************\
119: * WM_CREATE
120: *
121: * Initialize the static variables.
122: * Then create three pens for drawing with later.
123: \**********************************************************************/
124: case WM_CREATE:
125: svNumDown = NONE;
126: svIndex = NONE;
127: hPenLine = CreatePen (PS_SOLID, 1, (COLORREF) 0x0100000f);
128: hPenpolydraw = CreatePen (PS_SOLID, 1, (COLORREF) 0x01000005);
129: hPenGrey = CreatePen (PS_SOLID, 1, (COLORREF) 0x01000007);
130: break;
131:
132:
133: /**********************************************************************\
134: * WM_DESTROY
135: *
136: * Complement of the WM_CREATE message. Delete the pens that were
137: * created and then call postquitmessage.
138: \**********************************************************************/
139: case WM_DESTROY:
140: DeleteObject (hPenLine);
141: DeleteObject (hPenpolydraw);
142: DeleteObject (hPenGrey);
143:
144: PostQuitMessage(0);
145: break;
146:
147:
148:
149:
150: /**********************************************************************\
151: * WM_LBUTTONDOWN
152: *
153: * Hittest to see if the user is selecting an existing point.
154: * If not, check for point overflow.
155: * If o.k. then add a new point to the current list.
156: \**********************************************************************/
157: case WM_LBUTTONDOWN: {
158: int i;
159: RECT rectNear;
160:
161: /* Construct a rectangle around the mouse point. */
162: rectNear.left = LOWORD(lParam) - HITSIZE;
163: rectNear.right = LOWORD(lParam) + HITSIZE;
164: rectNear.top = HIWORD(lParam) - HITSIZE;
165: rectNear.bottom = HIWORD(lParam) + HITSIZE;
166:
167: /* step through all points so far. hittest mouse location against
168: * each one. If we hit one, set index, capture mouse and exit
169: * window procedure.
170: */
171: for (i = 0; i<= svNumDown; i++) {
172: if (PtInRect (&rectNear, svPoints[i])) {
173: svIndex = i;
174: SetCapture (hwnd);
175: return NULL;
176: }
177: }
178:
179: /* we did not hit an old point, watch for overflow. */
180: if (svNumDown == (MAXPOINTS-1)) {
181: MessageBox (hwnd,
182: "Points may be dragged with left mouse button.",
183: "No more points allowed",
184: MB_OK | MB_ICONSTOP);
185: return NULL;
186: }
187:
188: /* don't have old point, still room for more. Put down one more. */
189: if (GetCapture() != hwnd) {
190: svNumDown++;
191: svPoints[svNumDown].x = LOWORD(lParam);
192: svPoints[svNumDown].y = HIWORD(lParam);
193:
194: /* set the type value in the array dependent upon keyboard state. */
195: if (wParam & MK_SHIFT) svTypes [svNumDown] = PT_MOVETO;
196: else if (wParam & MK_CONTROL) svTypes [svNumDown] = PT_BEZIERTO;
197: else svTypes [svNumDown] = PT_LINETO;
198:
199: InvalidateRect (hwnd, NULL, TRUE);
200: }
201:
202: }break;
203:
204:
205: /**********************************************************************\
206: * WM_MOUSEMOVE
207: *
208: * If the curve is tracking the mouse, the erase the old curve by drawing
209: * over it with the grey pen. Redraw the new curves with the proper pens.
210: \**********************************************************************/
211: case WM_MOUSEMOVE: {
212: if (GetCapture() == hwnd) {
213: HDC hdc;
214:
215: hdc = GetDC (hwnd);
216: MoveToEx (hdc, svPoints[0].x, svPoints[0].y, NULL);
217:
218: /* Erase the old lines and curves. */
219: SelectObject(hdc, hPenGrey);
220: Polyline (hdc, svPoints, svNumDown+1);
221: PolyDraw (hdc, &svPoints[1], &svTypes[1], svNumDown);
222:
223: /* Change the point to match the new mouse position. */
224: svPoints[svIndex].x = LOWORD(lParam);
225: svPoints[svIndex].y = HIWORD(lParam);
226:
227: MoveToEx (hdc, svPoints[0].x, svPoints[0].y, NULL);
228: SelectObject(hdc, hPenLine);
229: Polyline (hdc, svPoints, svNumDown+1);
230: SelectObject(hdc, hPenpolydraw);
231: PolyDraw (hdc, &svPoints[1], &svTypes[1], svNumDown);
232:
233: ReleaseDC (hwnd, hdc);
234: }
235: }break;
236:
237:
238:
239: /**********************************************************************\
240: * WM_LBUTTONUP
241: *
242: * Finished tracking. Release the mouse capture, and force repaint.
243: \**********************************************************************/
244: case WM_LBUTTONUP:
245: if (GetCapture() == hwnd) {
246: SetCapture (NULL);
247: InvalidateRect (hwnd, NULL, FALSE);
248: }
249: break;
250:
251:
252: /**********************************************************************\
253: * WM_RBUTTONDOWN
254: *
255: * Re-Initialize the static variables, and force a repaint
256: \**********************************************************************/
257: case WM_RBUTTONDOWN:
258: svNumDown = NONE;
259: svIndex = NONE;
260: InvalidateRect (hwnd, NULL, TRUE);
261: break;
262:
263:
264:
265: /**********************************************************************\
266: * WM_PAINT
267: *
268: * Write the instructions at the bottom of the window. (Note that these
269: * lines may be erased by user MOUSEMOVE actions.) Draw the polyline
270: * then draw the PolyDraw.
271: \**********************************************************************/
272: case WM_PAINT: {
273: HDC hdc;
274: PAINTSTRUCT ps;
275: RECT rect;
276: int height,x,y;
277:
278: hdc = BeginPaint(hwnd, &ps);
279:
280: /* set the background mode, the write out the 4 instruction strings. */
281: SetBkMode (hdc, TRANSPARENT);
282: height = GetSystemMetrics (SM_CYCAPTION);
283: GetClientRect (hwnd, &rect);
284: x = rect.left + 10;
285: y = rect.bottom - 4*height;
286: TextOut (hdc, x,y, instructions0,sizeof(instructions0)-1);
287: y = rect.bottom - 3*height;
288: TextOut (hdc, x,y, instructions1,sizeof(instructions1)-1);
289: y = rect.bottom - 2*height;
290: TextOut (hdc, x,y, instructions2,sizeof(instructions2)-1);
291: y = rect.bottom - 1*height;
292: TextOut (hdc, x,y, instructions3,sizeof(instructions3)-1);
293:
294:
295: /* Move to the first point in the array and then call polydraw */
296: MoveToEx (hdc, svPoints[0].x, svPoints[0].y, NULL);
297:
298: SelectObject(hdc, hPenLine);
299: Polyline (hdc, svPoints, svNumDown+1);
300: SelectObject(hdc, hPenpolydraw);
301: PolyDraw (hdc, &svPoints[1], &svTypes[1], svNumDown);
302:
303: EndPaint (hwnd, &ps);
304: } return FALSE;
305:
306:
307: default:
308: return (DefWindowProc(hwnd, message, wParam, lParam));
309: }
310: return (NULL);
311: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.