|
|
1.1 ! root 1: /* ! 2: * edpline.c -- polyline editor, for practice in mouse handling ! 3: * ! 4: * Created by Microsoft, IBM Corporation, 1990 ! 5: * ! 6: * DISCLAIMER OF WARRANTIES. The following [enclosed] code is ! 7: * sample code created by Microsoft Corporation and/or IBM ! 8: * Corporation. This sample code is not part of any standard ! 9: * Microsoft or IBM product and is provided to you solely for ! 10: * the purpose of assisting you in the development of your ! 11: * applications. The code is provided "AS IS", without ! 12: * warranty of any kind. Neither Microsoft nor IBM shall be ! 13: * liable for any damages arising out of your use of the sample ! 14: * code, even if they have been advised of the possibility of ! 15: * such damages. ! 16: */ ! 17: #define INCL_DOSMEMMGR ! 18: #define INCL_WINWINDOWMGR ! 19: #define INCL_WINMESSAGEMGR ! 20: #define INCL_WINSWITCHLIST ! 21: #define INCL_WINDIALOGS ! 22: #define INCL_GPIBITMAPS ! 23: #define INCL_GPIPRIMITIVES ! 24: #define INCL_GPITRANSFORMS ! 25: #define INCL_WINMENUS ! 26: #define INCL_WININPUT ! 27: #define INCL_WINFRAMEMGR ! 28: #define INCL_WINCLIPBOARD ! 29: #include <os2.h> ! 30: ! 31: #include <stdio.h> ! 32: #include <stdlib.h> ! 33: ! 34: #include "edpline.h" ! 35: ! 36: ! 37: ! 38: #define abs(x) (((x) > 0) ? (x) : -(x)) ! 39: #define PRIM_POLYLINE 0x0001 ! 40: #define PRIM_POLYFILLET 0x0002 ! 41: #define PRIM_POLYSPLINE 0x0004 ! 42: #define PRIM_POINTARC 0x0008 ! 43: ! 44: ! 45: /************************************************************************ ! 46: * ! 47: * Function declarations ! 48: * ! 49: ************************************************************************/ ! 50: ! 51: /* Private functions */ ! 52: ! 53: VOID cdecl main(VOID); ! 54: BOOL InitGlobals(VOID); ! 55: BOOL InitApp(VOID); ! 56: VOID Close(HWND); ! 57: VOID Command(HWND, USHORT); ! 58: VOID Paint(HPS, BOOL); ! 59: VOID MouseMove(HWND, MPARAM); ! 60: VOID ButtonUp(HWND, USHORT); ! 61: VOID ButtonDown(HWND, USHORT, MPARAM); ! 62: SHORT IsPtInList(PPOINTL); ! 63: SHORT AddPtToList(PPOINTL); ! 64: BOOL IsPtCloseToLine(PPOINTL, PPOINTL, PPOINTL); ! 65: VOID DrawPrimitive(HPS, USHORT); ! 66: VOID DrawPolyLine(HPS); ! 67: VOID DrawPolyFillet(HPS); ! 68: VOID DrawPolySpline(HPS); ! 69: VOID DrawPointArc(HPS); ! 70: VOID DrawControlPoints(HPS, LONG, PPOINTL); ! 71: VOID MyMessageBox(HWND, PSZ); ! 72: VOID SwapLong(PLONG, PLONG); ! 73: ! 74: /* Exported functions */ ! 75: ! 76: MRESULT EXPENTRY WndProc(HWND, USHORT, MPARAM, MPARAM); ! 77: MRESULT EXPENTRY AboutDlgProc(HWND, USHORT, MPARAM, MPARAM); ! 78: ! 79: ! 80: ! 81: /************************************************************************ ! 82: * ! 83: * Global Variables ! 84: * ! 85: ************************************************************************/ ! 86: ! 87: typedef struct ! 88: { ! 89: HAB hab; ! 90: HMQ hMsgQ; ! 91: HWND hwndFrame; ! 92: HWND hwnd; ! 93: ! 94: ULONG flPrim; ! 95: BOOL fDisplayControlPoints; ! 96: SHORT cptl; ! 97: PPOINTL pptl; ! 98: ! 99: SHORT sPtGrabbed; ! 100: BOOL fDragging; ! 101: ! 102: ULONG ulHitPrecision; ! 103: ! 104: HPS hpsMetafile; ! 105: HDC hdcMetafile; ! 106: ULONG hItem; ! 107: SIZEL sizlPage; ! 108: DEVOPENSTRUC dop; ! 109: ! 110: } GLOBALDATA; ! 111: GLOBALDATA global; ! 112: ! 113: ! 114: ! 115: /************************************************************************ ! 116: * ! 117: * main ! 118: * ! 119: * WinInitialize resizes our ring 2 stack, among other things, so ! 120: * we won't GP fault trying to do graphics. WinCreateMsgQueue defines ! 121: * us as a REAL PM app. (as well as the WINDOWAPI statement in the .DEF ! 122: * file...) Call a sub to register our window class and create a window. ! 123: * Loop over messages. Exit cleanly. ! 124: * ! 125: ************************************************************************/ ! 126: ! 127: VOID cdecl ! 128: main() ! 129: { ! 130: QMSG qMsg; ! 131: int iRet = 0; ! 132: ! 133: ! 134: global.hab = WinInitialize(NULL); ! 135: global.hMsgQ = WinCreateMsgQueue(global.hab, 0); ! 136: ! 137: if (InitApp()) ! 138: while (WinGetMsg( global.hab, (PQMSG)&qMsg, (HWND)NULL, 0, 0 )) ! 139: WinDispatchMsg( global.hab, (PQMSG)&qMsg ); ! 140: else ! 141: iRet = -1; ! 142: ! 143: WinDestroyWindow( global.hwndFrame ); ! 144: WinDestroyMsgQueue( global.hMsgQ ); ! 145: WinTerminate( global.hab ); ! 146: DosExit(EXIT_PROCESS, iRet); ! 147: } ! 148: ! 149: ! 150: ! 151: ! 152: /**************************************************************************** ! 153: * ! 154: * InitGlobals ! 155: * ! 156: * Initialize global variables. ! 157: * ! 158: ****************************************************************************/ ! 159: ! 160: BOOL ! 161: InitGlobals() ! 162: { ! 163: global.flPrim = PRIM_POLYLINE; ! 164: global.fDisplayControlPoints = TRUE; ! 165: ! 166: global.cptl = 0 ; ! 167: global.pptl = NULL; ! 168: ! 169: if (DosAllocMem(&global.pptl, ! 170: CPTLMAX * sizeof(POINTL), ! 171: PAG_READ | PAG_WRITE | PAG_COMMIT)) ! 172: return FALSE; ! 173: ! 174: ! 175: global.sPtGrabbed = -1 ; /* Initialize sPtGrabbed as being non-valid */ ! 176: global.fDragging = FALSE; ! 177: global.ulHitPrecision = 0L; ! 178: ! 179: return TRUE; ! 180: } ! 181: ! 182: ! 183: ! 184: /**************************************************************************** ! 185: * ! 186: * InitApp ! 187: * ! 188: * Register application window class and creates standard window. ! 189: * ! 190: ****************************************************************************/ ! 191: ! 192: #define INIT_MENU_ITEM(val, var) \ ! 193: TOGGLE_MENU_ITEM(global.hwndFrame, (val), (var)) ! 194: ! 195: BOOL ! 196: InitApp() ! 197: { ! 198: char szTitle[24]; ! 199: ULONG ctldata; ! 200: PID pid; ! 201: TID tid; ! 202: HSWITCH hsw; ! 203: static SWCNTRL swctl = { 0, 0, 0, 0, 0, SWL_VISIBLE, ! 204: SWL_JUMPABLE, "Edit Polyline", 0 }; ! 205: ! 206: if (!InitGlobals()) ! 207: return FALSE; ! 208: ! 209: ! 210: /* Register Application Window Class */ ! 211: ! 212: WinLoadString( global.hab, NULL, IDS_TITLE, sizeof(szTitle), (PCH)szTitle ); ! 213: if ( !WinRegisterClass( global.hab, (PCH)szTitle, (PFNWP)WndProc, ! 214: CS_SIZEREDRAW, 0 )) ! 215: return FALSE; ! 216: ! 217: ! 218: ! 219: /* Create a window instance of class "PolyLine Editor" */ ! 220: ! 221: ctldata = FCF_STANDARD & ! 222: ~(ULONG)(FCF_ICON | FCF_TASKLIST); ! 223: ! 224: if (global.hwndFrame = WinCreateStdWindow( ! 225: HWND_DESKTOP, /* specify desktop as parent window */ ! 226: WS_VISIBLE, /* window styles */ ! 227: &ctldata, /* frame creation flags */ ! 228: (PCH)szTitle, /* window class name */ ! 229: (PCH)szTitle, /* name appearing in window caption */ ! 230: 0L, /* */ ! 231: (HMODULE)NULL, /* use current executable module id */ ! 232: IDR_EDPLINE, /* menu id */ ! 233: (HWND FAR *)&global.hwnd /* window handle */ ! 234: )) ! 235: { ! 236: INIT_MENU_ITEM(IDM_CTLPOINTS, global.fDisplayControlPoints); ! 237: ! 238: if (global.flPrim & PRIM_POLYLINE) ! 239: CHECK_MENU_ITEM(global.hwndFrame, IDM_POLYLINE); ! 240: if (global.flPrim & PRIM_POLYFILLET) ! 241: CHECK_MENU_ITEM(global.hwndFrame, IDM_POLYFILLET); ! 242: if (global.flPrim & PRIM_POLYSPLINE) ! 243: CHECK_MENU_ITEM(global.hwndFrame, IDM_POLYSPLINE); ! 244: if (global.flPrim & PRIM_POINTARC) ! 245: CHECK_MENU_ITEM(global.hwndFrame, IDM_POINTARC); ! 246: ! 247: ! 248: /* Add ourselves to the switch list. */ ! 249: ! 250: WinQueryWindowProcess(global.hwndFrame, &pid, &tid); ! 251: swctl.hwnd = global.hwndFrame; ! 252: swctl.idProcess = pid; ! 253: hsw = WinAddSwitchEntry(&swctl); ! 254: ! 255: return TRUE; ! 256: } ! 257: return FALSE; ! 258: } ! 259: ! 260: ! 261: ! 262: ! 263: /************************************************************************ ! 264: * ! 265: * WndProc ! 266: * ! 267: * Process messages for the window class. ! 268: * ! 269: ************************************************************************/ ! 270: ! 271: MRESULT EXPENTRY ! 272: WndProc( hwnd, usMsg, mp1, mp2 ) ! 273: HWND hwnd; ! 274: USHORT usMsg; ! 275: MPARAM mp1; ! 276: MPARAM mp2; ! 277: { ! 278: HPS hps; ! 279: ! 280: switch (usMsg) ! 281: { ! 282: case WM_CLOSE: ! 283: Close(hwnd); ! 284: break; ! 285: ! 286: case WM_COMMAND: ! 287: Command(hwnd, LOUSHORT(mp1)); ! 288: break; ! 289: ! 290: case WM_PAINT: ! 291: hps = WinBeginPaint(global.hwnd, NULL, NULL); ! 292: ! 293: if (global.ulHitPrecision == 0L) ! 294: { ! 295: HDC hdc; ! 296: LONG cx; ! 297: ! 298: if (hdc = WinQueryWindowDC(global.hwnd)) { ! 299: DevQueryCaps(hdc, CAPS_MARKER_WIDTH, 1L, &cx); ! 300: global.ulHitPrecision = (cx >> 17) + 1L; ! 301: } else { ! 302: global.ulHitPrecision = 6L; ! 303: } ! 304: } ! 305: Paint(hps, TRUE); ! 306: WinEndPaint(hps); ! 307: break; ! 308: ! 309: case WM_BUTTON1DOWN: ! 310: case WM_BUTTON2DOWN: ! 311: ButtonDown(hwnd, usMsg, mp1); ! 312: break; ! 313: ! 314: case WM_BUTTON1UP: ! 315: case WM_BUTTON2UP: ! 316: ButtonUp(hwnd, usMsg); ! 317: break; ! 318: ! 319: case WM_MOUSEMOVE: ! 320: MouseMove(hwnd, mp1); ! 321: return( (MRESULT)WinDefWindowProc(hwnd, usMsg, mp1, mp2)); ! 322: break; ! 323: ! 324: default: ! 325: return( (MRESULT)WinDefWindowProc(hwnd, usMsg, mp1, mp2)); ! 326: break; ! 327: } ! 328: ! 329: return FALSE; ! 330: } ! 331: ! 332: ! 333: ! 334: ! 335: /************************************************************************ ! 336: * ! 337: * MouseMove ! 338: * ! 339: ************************************************************************/ ! 340: ! 341: VOID ! 342: MouseMove(hwnd, mp1) ! 343: HWND hwnd; ! 344: MPARAM mp1; ! 345: { ! 346: POINTL ptl; ! 347: HPS hps; ! 348: ! 349: if (hwnd == global.hwnd) ! 350: if (global.fDragging) ! 351: { ! 352: ptl.x = (LONG) LOUSHORT(mp1); ! 353: ptl.y = (LONG) HIUSHORT(mp1); ! 354: ! 355: if (global.sPtGrabbed != (SHORT) -1) /* is it a useable number yet? */ ! 356: { ! 357: hps = WinGetPS(hwnd); ! 358: Paint(hps, FALSE); ! 359: ! 360: /* then use it as an offset into the point table */ ! 361: ! 362: *(global.pptl+global.sPtGrabbed) = ptl; ! 363: ! 364: Paint(hps, FALSE); ! 365: WinReleasePS(hps); ! 366: } ! 367: } ! 368: } ! 369: ! 370: ! 371: ! 372: ! 373: /************************************************************************ ! 374: * ! 375: * ButtonUp ! 376: * ! 377: ************************************************************************/ ! 378: ! 379: VOID ! 380: ButtonUp(hwnd, usMsg) ! 381: HWND hwnd; ! 382: USHORT usMsg; ! 383: { ! 384: int i; ! 385: HPS hps; ! 386: ! 387: ! 388: if (hwnd == global.hwnd) ! 389: if (global.fDragging) ! 390: { ! 391: global.fDragging = FALSE; ! 392: if (global.sPtGrabbed != (SHORT) -1) /* is it a useable number yet? */ ! 393: { ! 394: if (usMsg == WM_BUTTON2UP) /* if the right mouse button has been released */ ! 395: { ! 396: hps = WinGetPS(hwnd); ! 397: Paint(hps, FALSE); ! 398: ! 399: if ((i = global.sPtGrabbed) < global.cptl-1) ! 400: while (i < global.cptl-1) ! 401: { ! 402: global.pptl[i] = global.pptl[i+1]; /* shift the points down one */ ! 403: ++i; ! 404: } ! 405: ! 406: --global.cptl; /* and decrement the count of points long */ ! 407: global.sPtGrabbed = -1 ; /* and reset PtGrabbed to non-positive number */ ! 408: ! 409: Paint(hps, FALSE); ! 410: WinReleasePS(hps); ! 411: } ! 412: else /* WM_BUTTON1UP */ ! 413: global.sPtGrabbed = -1 ; /* else just reset PtGrabbed to non-positive number */ ! 414: } ! 415: } ! 416: } ! 417: ! 418: ! 419: ! 420: ! 421: /************************************************************************ ! 422: * ! 423: * ButtonDown ! 424: * ! 425: ************************************************************************/ ! 426: ! 427: VOID ! 428: ButtonDown(hwnd, usMsg, mp1) ! 429: HWND hwnd; ! 430: USHORT usMsg; ! 431: MPARAM mp1; ! 432: { ! 433: POINTL ptl; ! 434: HPS hps; ! 435: SHORT sNewPtGrabbed; ! 436: ! 437: ! 438: if (hwnd == global.hwnd) ! 439: if (!global.fDragging) /* if we wheren't dragging */ ! 440: { ! 441: global.fDragging = TRUE; /* we are now */ ! 442: ! 443: ptl.x = (LONG) LOUSHORT(mp1); /* so get the mouse location */ ! 444: ptl.y = (LONG) HIUSHORT(mp1); /* and store it in ptl */ ! 445: ! 446: if ((sNewPtGrabbed = IsPtInList(&ptl)) != (SHORT) -1) /* if ptl is allready in the list */ ! 447: /* then set sNewPtGrabbed to it's index in the list */ ! 448: global.sPtGrabbed = sNewPtGrabbed; /* and set PtGrabbed to the same index */ ! 449: ! 450: if (usMsg == WM_BUTTON1DOWN) ! 451: { ! 452: hps = WinGetPS(hwnd); ! 453: Paint(hps, FALSE); ! 454: ! 455: if (sNewPtGrabbed == -1) /* if it wasn't in the list */ ! 456: global.sPtGrabbed = AddPtToList(&ptl); /* add it to the list and save it's index */ ! 457: /* in PtGrabbed */ ! 458: else ! 459: global.sPtGrabbed = sNewPtGrabbed; /* unneeded step save as above */ ! 460: ! 461: Paint(hps, FALSE); ! 462: WinReleasePS(hps); ! 463: ! 464: if (global.sPtGrabbed == -1) /* if it couldn't be added to the list */ ! 465: /* then let the user know */ ! 466: ! 467: MyMessageBox(global.hwnd, "Cannot add any more points."); ! 468: } ! 469: } ! 470: } ! 471: ! 472: ! 473: ! 474: ! 475: /************************************************************************ ! 476: * ! 477: * IsPtInList ! 478: * Parameters: PPOINTL ! 479: * Returns: Either index of PPOINTL if POINT is close enough ! 480: * or FALSE if it isn't within ulHitPrecision. ! 481: * ! 482: ************************************************************************/ ! 483: ! 484: SHORT ! 485: IsPtInList(pptl) ! 486: PPOINTL pptl; ! 487: { ! 488: int i; ! 489: ! 490: ! 491: /* try to find pptl in the points we already have */ ! 492: for (i = 0; i < global.cptl; ++i) ! 493: if (((abs(pptl->x - global.pptl[i].x)) ! 494: <= (LONG) global.ulHitPrecision) ! 495: && ((abs(pptl->y - global.pptl[i].y)) ! 496: <= (LONG) global.ulHitPrecision)) ! 497: return (SHORT) i; ! 498: ! 499: /* couldn't find it */ ! 500: return -1 ; ! 501: } ! 502: ! 503: ! 504: ! 505: ! 506: /************************************************************************ ! 507: * ! 508: * AddPtToList ! 509: * ! 510: ************************************************************************/ ! 511: ! 512: SHORT ! 513: AddPtToList(pptl) ! 514: PPOINTL pptl; ! 515: { ! 516: int i, j; ! 517: ! 518: if (global.cptl < CPTLMAX) /* if we aren't to the limit of number of points */ ! 519: { ! 520: /* check for new points lying on a line segment */ ! 521: for (i = 0; i < (global.cptl - 1); ++i) ! 522: /* for each set of adjacent points */ ! 523: /* see if the point is close enough to the line */ ! 524: if (IsPtCloseToLine(&global.pptl[i], &global.pptl[i+1L], pptl)) ! 525: { ! 526: /* if it is, then */ ! 527: for (j = global.cptl; j > i+1 ; --j) ! 528: ! 529: /* slide all points from there to the end of the line ! 530: down toward the end one */ ! 531: ! 532: global.pptl[j] = global.pptl[j - 1]; ! 533: /* and insert the new point into the list */ ! 534: global.pptl[i+1] = *pptl; ! 535: /* and increment the lenth of the list */ ! 536: ++global.cptl; ! 537: return (SHORT) i+1; ! 538: } ! 539: ! 540: /* append the point */ ! 541: ! 542: i = global.cptl; ! 543: global.pptl[i] = *pptl; ! 544: ++global.cptl; ! 545: return (SHORT) i; ! 546: } ! 547: ! 548: return -1; ! 549: } ! 550: ! 551: ! 552: ! 553: ! 554: /************************************************************************ ! 555: * ! 556: * IsPtCloseToLine ! 557: * ! 558: ************************************************************************/ ! 559: ! 560: BOOL ! 561: IsPtCloseToLine(pptl1, pptl2, pptlTest) ! 562: PPOINTL pptl1; ! 563: PPOINTL pptl2; ! 564: PPOINTL pptlTest; ! 565: { ! 566: POINTL ptlLL, ptlUR; ! 567: LONG dx, dy, yIntercept, result; ! 568: ! 569: ! 570: /* find the bounding box of the line segment */ ! 571: ! 572: ptlLL = *pptl1; /* assume line goes lower left to upper right */ ! 573: ptlUR = *pptl2; ! 574: if (pptl1->x > pptl2->x) ! 575: SwapLong(&ptlLL.x, &ptlUR.x); ! 576: if (pptl1->y > pptl2->y) ! 577: SwapLong(&ptlLL.y, &ptlUR.y); ! 578: ! 579: ! 580: /* adjust the bounding box if it's too narrow */ ! 581: ! 582: dx = pptl2->x - pptl1->x; ! 583: if (abs(dx) <= (LONG) (global.ulHitPrecision >> 1)) ! 584: { ! 585: ptlLL.x -= (LONG) (global.ulHitPrecision >> 1); ! 586: ptlUR.x += (LONG) (global.ulHitPrecision >> 1); ! 587: } ! 588: dy = pptl2->y - pptl1->y; ! 589: if (abs(dy) <= (LONG) (global.ulHitPrecision >> 1)) ! 590: { ! 591: ptlLL.y -= (LONG) (global.ulHitPrecision >> 1); ! 592: ptlUR.y += (LONG) (global.ulHitPrecision >> 1); ! 593: } ! 594: ! 595: ! 596: /* see if the test point is in the bounding box of the line segment */ ! 597: ! 598: if ((pptlTest->x >= ptlLL.x) && ! 599: (pptlTest->x <= ptlUR.x) && ! 600: (pptlTest->y >= ptlLL.y) && ! 601: (pptlTest->y <= ptlUR.y)) ! 602: { ! 603: /* test for special cases */ ! 604: ! 605: if (dx == 0) ! 606: { ! 607: if (abs(pptlTest->x - pptl1->x) <= (LONG) global.ulHitPrecision) ! 608: return TRUE; ! 609: else ! 610: return FALSE; ! 611: } ! 612: ! 613: if (dy == 0) ! 614: { ! 615: if (abs(pptlTest->y - pptl1->y) <= (LONG) global.ulHitPrecision) ! 616: return TRUE; ! 617: else ! 618: return FALSE; ! 619: } ! 620: ! 621: ! 622: /* test for general case */ ! 623: ! 624: yIntercept = pptl1->y - (pptl1->x * dy) / dx; ! 625: ! 626: result = pptlTest->y - (pptlTest->x * dy / dx) - yIntercept; ! 627: if (abs(result) <= (LONG) global.ulHitPrecision) ! 628: return TRUE; ! 629: } ! 630: ! 631: return FALSE; ! 632: } ! 633: ! 634: ! 635: ! 636: ! 637: /************************************************************************ ! 638: * ! 639: * SwapLong ! 640: * ! 641: ************************************************************************/ ! 642: ! 643: VOID ! 644: SwapLong(pl1, pl2) ! 645: PLONG pl1, pl2; ! 646: { ! 647: LONG lTmp; ! 648: ! 649: lTmp = *pl1; ! 650: *pl1 = *pl2; ! 651: *pl2 = lTmp; ! 652: } ! 653: ! 654: ! 655: ! 656: ! 657: /************************************************************************ ! 658: * ! 659: * Close ! 660: * ! 661: ************************************************************************/ ! 662: ! 663: VOID ! 664: Close(hwnd) ! 665: HWND hwnd; ! 666: { ! 667: WinPostMsg(hwnd, WM_QUIT, 0L, 0L); ! 668: } ! 669: ! 670: ! 671: ! 672: ! 673: /************************************************************************ ! 674: * ! 675: * Command ! 676: * ! 677: * Dispatches menu commands to the proper handlers. ! 678: * ! 679: ************************************************************************/ ! 680: ! 681: #define UPDATE_MENU_BOOL(var, val) \ ! 682: { \ ! 683: TOGGLE_BOOL((var)); \ ! 684: TOGGLE_MENU_ITEM(global.hwndFrame, (val), (var)); \ ! 685: } ! 686: ! 687: #define UPDATE_MENU_LIST(var, val) \ ! 688: { \ ! 689: UNCHECK_MENU_ITEM(global.hwndFrame, (var)); \ ! 690: (var) = (val); \ ! 691: CHECK_MENU_ITEM(global.hwndFrame, (var)); \ ! 692: } ! 693: ! 694: VOID ! 695: Command(hwnd, id) ! 696: HWND hwnd; ! 697: USHORT id; ! 698: { ! 699: HPS hps; ! 700: BOOL fRedraw = FALSE; ! 701: int rc; ! 702: ! 703: switch (id) ! 704: { ! 705: case IDM_ABOUT: ! 706: rc = WinDlgBox(HWND_DESKTOP, hwnd, AboutDlgProc, NULL, IDD_ABOUT, NULL); ! 707: fRedraw = FALSE; ! 708: break; ! 709: ! 710: case IDM_NOPRIM: ! 711: global.flPrim = 0L; ! 712: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_POLYLINE, 0); ! 713: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_POLYFILLET, 0); ! 714: TOGGLE_MENU_ITEM(global.hwndFrame, IDM_POLYSPLINE, 0); ! 715: fRedraw = TRUE; ! 716: break; ! 717: ! 718: case IDM_POLYLINE: ! 719: global.flPrim ^= PRIM_POLYLINE; ! 720: TOGGLE_MENU_ITEM(global.hwndFrame, id, (global.flPrim & PRIM_POLYLINE)); ! 721: fRedraw = TRUE; ! 722: break; ! 723: ! 724: case IDM_POLYFILLET: ! 725: global.flPrim ^= PRIM_POLYFILLET; ! 726: TOGGLE_MENU_ITEM(global.hwndFrame, id, (global.flPrim & PRIM_POLYFILLET)); ! 727: fRedraw = TRUE; ! 728: break; ! 729: ! 730: case IDM_POLYSPLINE: ! 731: global.flPrim ^= PRIM_POLYSPLINE; ! 732: TOGGLE_MENU_ITEM(global.hwndFrame, id, (global.flPrim & PRIM_POLYSPLINE)); ! 733: fRedraw = TRUE; ! 734: break; ! 735: ! 736: case IDM_POINTARC: ! 737: global.flPrim ^= PRIM_POINTARC; ! 738: TOGGLE_MENU_ITEM(global.hwndFrame, id, (global.flPrim & PRIM_POINTARC)); ! 739: fRedraw = TRUE; ! 740: break; ! 741: ! 742: case IDM_CTLPOINTS: ! 743: UPDATE_MENU_BOOL(global.fDisplayControlPoints, IDM_CTLPOINTS); ! 744: fRedraw = TRUE; ! 745: break; ! 746: ! 747: case IDM_CLEARALL: ! 748: global.cptl = 0L; ! 749: fRedraw = TRUE; ! 750: break; ! 751: ! 752: case IDM_COPY: ! 753: /* ! 754: To put this image on the clipboard, create a Metafile DC. ! 755: ! 756: Associate a presentation space with the DC, then play the ! 757: drawing orders into the metafile. ! 758: */ ! 759: global.dop.pszLogAddress = NULL; ! 760: global.dop.pszDriverName = "DISPLAY"; ! 761: global.dop.pdriv = NULL; ! 762: global.dop.pszDataType = NULL; ! 763: ! 764: global.hdcMetafile = DevOpenDC(global.hab, OD_METAFILE, ! 765: "*", 4L, (PDEVOPENDATA) &global.dop, NULL); ! 766: global.hpsMetafile = GpiCreatePS(global.hab, global.hdcMetafile, ! 767: &global.sizlPage, PU_PELS | GPIA_ASSOC); ! 768: ! 769: Paint(global.hpsMetafile, TRUE); ! 770: /* ! 771: Clean up. A handle to the metafile is obtained when ! 772: calling DevCloseDC(). ! 773: */ ! 774: GpiAssociate(global.hpsMetafile, NULL); ! 775: GpiDestroyPS(global.hpsMetafile); ! 776: global.hItem = (ULONG) DevCloseDC(global.hdcMetafile); ! 777: /* ! 778: Be sure to empty the clipboard of other data. This will ! 779: also empty previous data stored in other formats. ! 780: Then, set the clipboard data with type METAFILE, passing ! 781: the handle to our metafile. ! 782: */ ! 783: if (WinOpenClipbrd(global.hab)) { ! 784: WinEmptyClipbrd(global.hab); ! 785: WinSetClipbrdData(global.hab,global.hItem, CF_METAFILE, CFI_HANDLE); ! 786: WinCloseClipbrd(global.hab); ! 787: } ! 788: break; ! 789: } ! 790: ! 791: if (fRedraw) ! 792: { ! 793: hps = WinGetPS(hwnd); ! 794: Paint(hps, TRUE); ! 795: WinReleasePS(hps); ! 796: } ! 797: } ! 798: ! 799: ! 800: ! 801: ! 802: /************************************************************************ ! 803: * ! 804: * Paint ! 805: * ! 806: ************************************************************************/ ! 807: ! 808: VOID ! 809: Paint(hps, fClearScreen) ! 810: HPS hps; ! 811: BOOL fClearScreen; ! 812: { ! 813: LINEBUNDLE lb; ! 814: RECTL rcl; ! 815: if (fClearScreen) ! 816: { ! 817: /* clear the screen */ ! 818: WinQueryWindowRect(global.hwnd, &rcl); ! 819: GpiBitBlt(hps, NULL, 2L, (PPOINTL) &rcl, ROP_ONE, NULL); ! 820: } ! 821: ! 822: ! 823: if (global.cptl > 0L) ! 824: { ! 825: if (global.fDisplayControlPoints) ! 826: { ! 827: if (fClearScreen) ! 828: /* draw all the control points */ ! 829: DrawControlPoints(hps, global.cptl, global.pptl); ! 830: else if (global.sPtGrabbed != -1L) ! 831: /* draw just the control point that moved */ ! 832: DrawControlPoints(hps, 1L, global.pptl+global.sPtGrabbed); ! 833: } ! 834: ! 835: /* set mix mode to xor */ ! 836: lb.usMixMode = FM_XOR; ! 837: GpiSetAttrs(hps, PRIM_LINE, LBB_MIX_MODE, 0L, &lb); ! 838: ! 839: /* draw the current primitives */ ! 840: ! 841: if (global.flPrim & PRIM_POLYLINE) ! 842: { ! 843: lb.lColor = CLR_BROWN; ! 844: GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb); ! 845: DrawPrimitive(hps, IDM_POLYLINE); ! 846: } ! 847: ! 848: if (global.flPrim & PRIM_POLYFILLET) ! 849: { ! 850: lb.lColor = CLR_DARKCYAN; ! 851: GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb); ! 852: DrawPrimitive(hps, IDM_POLYFILLET); ! 853: } ! 854: ! 855: if (global.flPrim & PRIM_POLYSPLINE) ! 856: { ! 857: lb.lColor = CLR_DARKPINK; ! 858: GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb); ! 859: DrawPrimitive(hps, IDM_POLYSPLINE); ! 860: } ! 861: ! 862: if (global.flPrim & PRIM_POINTARC) ! 863: { ! 864: lb.lColor = CLR_BACKGROUND; ! 865: GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb); ! 866: DrawPrimitive(hps, IDM_POINTARC); ! 867: } ! 868: } ! 869: } ! 870: ! 871: ! 872: ! 873: ! 874: /************************************************************************ ! 875: * ! 876: * DrawPrimitive ! 877: * ! 878: ************************************************************************/ ! 879: ! 880: VOID ! 881: DrawPrimitive(hps, usPrim) ! 882: HPS hps; ! 883: USHORT usPrim; ! 884: { ! 885: switch ( usPrim ) ! 886: { ! 887: case IDM_POLYLINE: ! 888: DrawPolyLine(hps); ! 889: break; ! 890: ! 891: case IDM_POLYFILLET: ! 892: DrawPolyFillet(hps); ! 893: break; ! 894: ! 895: case IDM_POLYSPLINE: ! 896: DrawPolySpline(hps); ! 897: break; ! 898: ! 899: case IDM_POINTARC: ! 900: DrawPointArc(hps); ! 901: break; ! 902: } ! 903: } ! 904: ! 905: ! 906: ! 907: ! 908: /************************************************************************ ! 909: * ! 910: * DrawPolyLine ! 911: * ! 912: ************************************************************************/ ! 913: ! 914: VOID ! 915: DrawPolyLine(hps) ! 916: HPS hps; ! 917: { ! 918: GpiSetCurrentPosition( hps, global.pptl ); ! 919: GpiPolyLine( hps, global.cptl-1, global.pptl+1 ); ! 920: } ! 921: ! 922: ! 923: ! 924: ! 925: /************************************************************************ ! 926: * ! 927: * DrawPolyFillet ! 928: * ! 929: ************************************************************************/ ! 930: ! 931: VOID ! 932: DrawPolyFillet(hps) ! 933: HPS hps; ! 934: { ! 935: if (global.cptl > 2) ! 936: { ! 937: GpiSetCurrentPosition( hps, global.pptl ); ! 938: GpiPolyFillet( hps, global.cptl-1, global.pptl+1 ); ! 939: } ! 940: } ! 941: ! 942: ! 943: ! 944: ! 945: /************************************************************************ ! 946: * ! 947: * DrawPolySpline ! 948: * ! 949: ************************************************************************/ ! 950: ! 951: VOID ! 952: DrawPolySpline(hps) ! 953: HPS hps; ! 954: { ! 955: LONG cptSlack; /* # points in pptl not usable by PolySpline */ ! 956: ! 957: /* GpiPolySpline expects the number of points to be a ! 958: multiple of 3. If we have a non-multiple of three, ! 959: (excluding the first point, which we've used to set ! 960: the current position), only pass the largest multiple ! 961: of three, saving the rest for the next go-round. */ ! 962: ! 963: cptSlack = ((global.cptl-1) % 3) + 1; ! 964: GpiSetCurrentPosition( hps, global.pptl ); ! 965: GpiPolySpline( hps, global.cptl-cptSlack, ! 966: global.pptl+1 ); ! 967: } ! 968: ! 969: ! 970: ! 971: ! 972: /************************************************************************ ! 973: * ! 974: * DrawPointArc ! 975: * ! 976: ************************************************************************/ ! 977: ! 978: VOID ! 979: DrawPointArc(hps) ! 980: HPS hps; ! 981: { ! 982: if (global.cptl >= 3L) ! 983: { ! 984: GpiSetCurrentPosition( hps, global.pptl ); ! 985: GpiPointArc( hps, global.pptl+1 ); ! 986: } ! 987: } ! 988: ! 989: ! 990: ! 991: ! 992: /************************************************************************ ! 993: * ! 994: * DrawControlPoints ! 995: * ! 996: ************************************************************************/ ! 997: ! 998: VOID ! 999: DrawControlPoints(hps, cptl, pptl) ! 1000: HPS hps; ! 1001: LONG cptl; ! 1002: PPOINTL pptl; ! 1003: { ! 1004: MARKERBUNDLE mb; ! 1005: ! 1006: mb.lColor = CLR_TRUE; ! 1007: mb.usMixMode = FM_XOR; ! 1008: GpiSetAttrs(hps, PRIM_MARKER, MBB_COLOR | MBB_MIX_MODE, 0L, &mb); ! 1009: ! 1010: GpiPolyMarker(hps, cptl, pptl); ! 1011: } ! 1012: ! 1013: ! 1014: ! 1015: ! 1016: /************************************************************************ ! 1017: * ! 1018: * MyMessageBox ! 1019: * ! 1020: * Displays a message box with the given string. To simplify matters, ! 1021: * the box will always have the same title ("PolyLine Editor"), will always ! 1022: * have a single button ("Ok"), will always have an exclamation point ! 1023: * icon, and will always be application modal. ! 1024: * ! 1025: ************************************************************************/ ! 1026: ! 1027: VOID ! 1028: MyMessageBox(hWnd, sz) ! 1029: HWND hWnd; ! 1030: PSZ sz; ! 1031: { ! 1032: static char *szTitle = "PolyLine Editor"; ! 1033: ! 1034: WinMessageBox(HWND_DESKTOP, hWnd, sz, szTitle, NULL, ! 1035: MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL); ! 1036: } ! 1037: ! 1038: MRESULT EXPENTRY AboutDlgProc(HWND hDlg, USHORT msg, MPARAM mp1, MPARAM mp2) { ! 1039: /* ! 1040: About... dialog procedure ! 1041: */ ! 1042: switch(msg) { ! 1043: case WM_COMMAND: ! 1044: switch(SHORT1FROMMP(mp1)) { ! 1045: case DID_OK: WinDismissDlg(hDlg, TRUE); break; ! 1046: default: break; ! 1047: } ! 1048: default: return WinDefDlgProc(hDlg, msg, mp1, mp2); ! 1049: } ! 1050: return FALSE; ! 1051: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.