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