|
|
1.1.1.2 ! root 1: ! 2: /******************************************************************************\ ! 3: * This is a part of the Microsoft Source Code Samples. ! 4: * Copyright (C) 1993 Microsoft Corporation. ! 5: * All rights reserved. ! 6: * This source code is only intended as a supplement to ! 7: * Microsoft Development Tools and/or WinHelp documentation. ! 8: * See these sources for detailed information regarding the ! 9: * Microsoft samples programs. ! 10: \******************************************************************************/ ! 11: 1.1 root 12: /******************************************************************************\ 13: * 14: * MODULE: PAINT.C 15: * 16: * PURPOSE: Given an HDC and a pointer to a bounding rectangle 17: * draw all graphics/fonts based on the flags set in 18: * the dwGraphicsOptions global variable. 19: * 20: * FUNTIONS: Paint - main painting routine 21: * GetFirstGraphicSlot- computes bounding rect of 1st 22: * graphic 23: * GetNextGraphicSlot - computes bounding rect of next 24: * graphic 25: * DrawFonts - draws enumerated fonts 26: * BuildFontList - builds a list of fonts of fonts 27: * supported by a given DC 28: * MyEnumFaces - enumerates the font facenames 29: * supported by a given DC 30: * MyEnumCopy - copies LOGFONT & TEXTMETRIC info 31: * to a global variable 32: * MyEnumCount - counts total number of fonts 33: * supported by a given DC 34: * FreeFontList - frees a (BuildFontList-) font list 35: * 36: * COMMENTS: Most of the font-enumeration code "lifted" from NTF.EXE 37: * sample. For more complete documentation have a look a 38: * that. 39: * 40: \******************************************************************************/ 41: 42: #include <windows.h> 43: #include <string.h> 44: #include "common.h" 45: #include "paint.h" 46: 47: 48: 49: /******************************************************************************\ 50: * 51: * FUNCTION: Paint 52: * 53: * INPUTS: hdc - device context to paint 54: * lpRect - bounding rectangle of device to paint 55: * 56: * RETURNS: TRUE if painting went ok, or 57: * FALSE if error while painting 58: * 59: \******************************************************************************/ 60: 61: BOOL Paint (HDC hdc, LPRECT lpRect) 62: { 63: RECT rect; 64: HPEN hpenSave; 65: RECTI ri; 66: 67: if (gdwGraphicsOptions & DRAWAXIS) 68: { 69: 70: // 71: // draw axis 72: // 73: 74: rect = *lpRect; 75: 76: hpenSave = SelectObject (hdc, GetStockObject (BLACK_PEN)); 77: 78: // 79: // if giMapMode == MM_TEXT, MM_ANISOTROPIC then (0,0) is upper left corner 80: // 81: 82: if (giMapMode == MM_TEXT || giMapMode == MM_ANISOTROPIC) 83: { 84: MoveToEx (hdc, rect.left - glcyMenu/2, rect.bottom, NULL); 85: LineTo (hdc, rect.left, rect.bottom + glcyMenu/2); 86: LineTo (hdc, rect.left + glcyMenu/2, rect.bottom); 87: 88: MoveToEx (hdc, rect.left, rect.bottom + glcyMenu/2, NULL); 89: LineTo (hdc, rect.left, rect.top); 90: LineTo (hdc, rect.right + glcyMenu/2, rect.top); 91: 92: MoveToEx (hdc, rect.right, rect.top - glcyMenu/2, NULL); 93: LineTo (hdc, rect.right + glcyMenu/2, rect.top); 94: LineTo (hdc, rect.right, rect.top + glcyMenu/2); 95: } 96: 97: // 98: // else (0,0) is lower left corner 99: // 100: 101: else 102: { 103: MoveToEx (hdc, rect.left - glcyMenu/2, rect.bottom, NULL); 104: LineTo (hdc, rect.left, rect.bottom + glcyMenu/2); 105: LineTo (hdc, rect.left + glcyMenu/2, rect.bottom); 106: 107: MoveToEx (hdc, rect.left, rect.bottom + glcyMenu/2, NULL); 108: LineTo (hdc, rect.left, rect.top); 109: LineTo (hdc, rect.right + glcyMenu/2, rect.top); 110: 111: MoveToEx (hdc, rect.right, rect.top + glcyMenu/2, NULL); 112: LineTo (hdc, rect.right + glcyMenu/2, rect.top); 113: LineTo (hdc, rect.right, rect.top - glcyMenu/2); 114: } 115: } 116: 117: SelectObject (hdc, hpenSave); 118: 119: // 120: // look at bits in gdwGraphicsOptions & determine which graphics to draw 121: // 122: 123: if (gdwGraphicsOptions & ENUMFONTS) 124: { 125: DrawFonts (hdc, lpRect); 126: return TRUE; 127: } 128: 129: giDeltaX = (int) ((lpRect->right - BORDER) / NUM_GRAPHICS_XSLOTS); 130: giDeltaY = (int) ((lpRect->bottom - lpRect->top - BORDER) 131: / NUM_GRAPHICS_YSLOTS); 132: 133: GetFirstGraphicSlot (lpRect, &ri); 134: 135: if (gdwGraphicsOptions & ARC) 136: { 137: Arc (hdc, ri.left, ri.top, ri.right, ri.bottom, 138: ri.left, ri.top, ri.right-10, ri.bottom-10); 139: GetNextGraphicSlot (&ri); 140: } 141: 142: if (gdwGraphicsOptions & ELLIPSE) 143: { 144: Ellipse (hdc, ri.left, ri.top, ri.right, ri.bottom); 145: GetNextGraphicSlot (&ri); 146: } 147: 148: if (gdwGraphicsOptions & LINETO) 149: { 150: int i; 151: 152: for (i = PS_SOLID; i <= PS_DASHDOTDOT; i++) 153: { 154: MoveToEx (hdc, ri.left, ri.top + (i+1)*giDeltaY/7, NULL); 155: LineTo (hdc, ri.right, ri.top + (i+1)*giDeltaY/7); 156: } 157: GetNextGraphicSlot (&ri); 158: } 159: 160: if (gdwGraphicsOptions & PIE) 161: { 162: Pie (hdc, ri.left, ri.top, ri.right, ri.bottom, 163: ri.left, ri.top, ri.right-10, ri.bottom-10); 164: GetNextGraphicSlot (&ri); 165: } 166: 167: if (gdwGraphicsOptions & PLG_BLT) 168: { 169: HBITMAP hbm; 170: BITMAP bm; 171: HDC hdcMem; 172: POINT ap[3]; 173: 174: hbm = LoadBitmap (ghInst, "printer"); 175: hdcMem = CreateCompatibleDC (hdc); 176: SelectObject (hdcMem, hbm); 177: 178: GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm); 179: 180: // 181: // special case here because PlgBlt requires coordinates 182: // of upper left, upper right, & lower left 183: // 184: 185: ap[0].x = (LONG) (ri.left + (ri.right - ri.left)/4); 186: ap[0].y = (LONG) (ri.top + (ri.bottom - ri.top)/4); 187: ap[1].x = (LONG) ri.right; 188: ap[1].y = (LONG) ri.top; 189: ap[2].x = (LONG) ri.left; 190: ap[2].y = (LONG) ri.bottom; 191: 192: PlgBlt (hdc, ap, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, NULL, 0, 0); 193: 194: DeleteDC(hdcMem); 195: GetNextGraphicSlot (&ri); 196: 197: } 198: 199: if (gdwGraphicsOptions & POLYBEZIER) 200: { 201: POINT ap[4]; 202: 203: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top; 204: ap[1].x = (LONG) ri.left; ap[1].y = (LONG) ri.bottom; 205: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top; 206: ap[3].x = (LONG) ri.right; ap[3].y = (LONG) ri.bottom; 207: 208: PolyBezier (hdc, ap, 4); 209: GetNextGraphicSlot (&ri); 210: } 211: 212: if (gdwGraphicsOptions & POLYGON) 213: { 214: POINT ap[5]; 215: 216: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top; 217: ap[1].x = (LONG) ri.right; ap[1].y = (LONG) ri.bottom; 218: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top; 219: ap[3].x = (LONG) ri.left; ap[3].y = (LONG) ri.bottom; 220: ap[4].x = (LONG) ri.left; ap[4].y = (LONG) ri.top; 221: 222: Polygon (hdc, ap, 4); 223: GetNextGraphicSlot (&ri); 224: } 225: 226: if (gdwGraphicsOptions & POLYLINE) 227: { 228: POINT ap[4]; 229: 230: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top; 231: ap[1].x = (LONG) ri.left; ap[1].y = (LONG) ri.bottom; 232: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top; 233: ap[3].x = (LONG) ri.right; ap[3].y = (LONG) ri.bottom; 234: 235: Polyline (hdc, ap, 4); 236: GetNextGraphicSlot (&ri); 237: } 238: 239: if (gdwGraphicsOptions & POLYPOLYGON) 240: { 241: POINT ap[8]; 242: int ai[2] = { 4, 4 }; 243: 244: ap[0].x = (LONG) ri.left; 245: ap[0].y = (LONG) ri.top; 246: ap[1].x = (LONG) (ri.left + giDeltaX/4); 247: ap[1].y = (LONG) ri.top; 248: ap[2].x = (LONG) (ri.left + giDeltaX/4); 249: ap[2].y = (LONG) (ri.top + giDeltaY/4); 250: ap[3].x = (LONG) ri.left; 251: ap[3].y = (LONG) (ri.top + giDeltaY/4); 252: ap[4].x = (LONG) (ri.right - 2*giDeltaX/3); 253: ap[4].y = (LONG) (ri.bottom - 2*giDeltaY/3); 254: ap[5].x = (LONG) ri.right; 255: ap[5].y = (LONG) (ri.bottom - 2*giDeltaY/3); 256: ap[6].x = (LONG) ri.right; 257: ap[6].y = (LONG) ri.bottom; 258: ap[7].x = (LONG) (ri.right - 2*giDeltaX/3); 259: ap[7].y = (LONG) ri.bottom; 260: 261: PolyPolygon (hdc, ap, ai, 2); 262: GetNextGraphicSlot (&ri); 263: } 264: 265: if (gdwGraphicsOptions & RECTANGLE) 266: { 267: Rectangle (hdc, ri.left, ri.top, ri.right, ri.bottom); 268: GetNextGraphicSlot (&ri); 269: } 270: 271: if (gdwGraphicsOptions & ROUNDRECT) 272: { 273: RoundRect (hdc, ri.left, ri.top, ri.right, ri.bottom, 15, 25); 274: GetNextGraphicSlot (&ri); 275: } 276: 277: if (gdwGraphicsOptions & STRETCH_BLT) 278: { 279: HBITMAP hbm; 280: BITMAP bm; 281: HDC hdcMem; 282: 283: hbm = LoadBitmap (ghInst, "printer"); 284: hdcMem = CreateCompatibleDC (hdc); 285: SelectObject (hdcMem, hbm); 286: 287: GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm); 288: 289: StretchBlt (hdc, ri.left, ri.top, ri.right-ri.left, 290: ri.bottom - ri.top, hdcMem, 0, 0, 291: bm.bmWidth, bm.bmHeight, SRCCOPY); 292: 293: DeleteDC(hdcMem); 294: GetNextGraphicSlot (&ri); 295: 296: } 297: 298: return TRUE; 299: } 300: 301: 302: 303: /******************************************************************************\ 304: * 305: * FUNCTION: GetFirstGraphicSlot 306: * 307: * INPUTS: pri - pointer to a RECTI 308: * 309: \******************************************************************************/ 310: 311: void GetFirstGraphicSlot (LPRECT lpRect, PRECTI pri) 312: { 313: pri->left = BORDER; 314: pri->top = lpRect->top + BORDER; 315: pri->right = giDeltaX; 316: pri->bottom = giDeltaY; 317: 318: giColumn = 1; 319: } 320: 321: 322: 323: /******************************************************************************\ 324: * 325: * FUNCTION: GetNextGraphicSlot 326: * 327: * INPUTS: pri - pointer to a RECTI 328: * 329: \******************************************************************************/ 330: 331: void GetNextGraphicSlot (PRECTI pri) 332: { 333: if (++giColumn <= NUM_GRAPHICS_XSLOTS) 334: { 335: pri->left += giDeltaX; 336: pri->right += giDeltaX; 337: } 338: else 339: { 340: giColumn = 1; 341: 342: pri->left = BORDER; 343: pri->top += giDeltaY; 344: pri->right = giDeltaX; 345: pri->bottom += giDeltaY; 346: } 347: } 348: 349: 350: 351: /******************************************************************************\ 352: * 353: * FUNCTION: DrawFonts 354: * 355: * INPUTS: hdc - device context to enumerate from & draw on 356: * pRect - pointer to bounding rect to draw fonts in 357: * 358: * LOCAL VARS: i, j - loop variables 359: * xText - starting x position to draw text 360: * yText - starting y position to draw text 361: * iMaxStrLen - length in pels of string to draw 362: * 363: \******************************************************************************/ 364: 365: void DrawFonts (HDC hdc, LPRECT lpRect) 366: { 367: int i, j, xText, yText, iMaxStrLen = 0; 368: PARFONTS paf; 369: 370: paf = BuildFontList (hdc); 371: 372: xText = yText = 2; 373: 374: // 375: // set the appropriate text align mode depending on 376: // whether we're drawing from top down or bottom up 377: // 378: 379: if (giMapMode == MM_TEXT | giMapMode == MM_ANISOTROPIC) 380: 381: SetTextAlign (hdc, TA_TOP); 382: 383: else 384: 385: SetTextAlign (hdc, TA_BOTTOM); 386: 387: for (i = 0; i < nFaces; i++) 388: { 389: for (j = 0; j < (paf + i)->nFonts; j++) 390: { 391: HFONT hFont, hSaveFont; 392: SIZE size; 393: POINT LogPtExtent; 394: 395: LogPtExtent.x = lpRect->right; 396: LogPtExtent.y = lpRect->bottom; 397: 398: hFont = CreateFontIndirect ((paf + i)->lf + j); 399: 400: hSaveFont = SelectObject (hdc, hFont); 401: 402: TextOut (hdc, xText, yText, ((paf + i)->lf + j)->lfFaceName, 403: strlen(((paf + i)->lf + j)->lfFaceName)); 404: 405: GetTextExtentPoint (hdc, ((paf + i)->lf + j)->lfFaceName, 406: strlen(((paf+i)->lf+j)->lfFaceName), 407: &size); 408: size.cx += 2; 409: iMaxStrLen = iMaxStrLen > (int)size.cx ? iMaxStrLen: (int) size.cx; 410: 411: if (!(i == (nFaces - 1) && j == ((paf + i)->nFonts - 1))) 412: { 413: TEXTMETRIC *pNextTM; 414: 415: pNextTM = j < ((paf+i)->nFonts-1) ? 416: (paf+i)->tm+j+1 : (paf+i+1)->tm; 417: 418: // 419: // add in the height of the face name we just drew 420: // 421: 422: yText += (int) ((paf + i)->tm + j)->tmHeight; 423: 424: // 425: // if the next facename will be drawn outside the bounding rect then 426: // start at first line of next column 427: // 428: 429: if (yText + (int) pNextTM->tmHeight > (int) LogPtExtent.y) 430: { 431: yText = 2; 432: xText += iMaxStrLen + 2; 433: iMaxStrLen = 0; 434: } 435: } 436: 437: SelectObject (hdc, hSaveFont); 438: DeleteObject (hFont); 439: 440: if (xText > (int) LogPtExtent.x) 441: { 442: if (GetDeviceCaps (hdc, TECHNOLOGY) & DT_RASDISPLAY) 443: { 444: // 445: // If we're drawing to the screen & have run out of 446: // room then tell user how many fonts there are left 447: // (that we haven't displayed) 448: // 449: 450: int k; 451: int iFontsLeft = (paf + i)->nFonts - j - 1; 452: char buf[40]; 453: SIZE size; 454: 455: 456: for (k = i + 1; k < nFaces; k++) 457: 458: iFontsLeft += (paf + k)->nFonts; 459: 460: wsprintf (buf, "%ld more display fonts (not listed)", 461: iFontsLeft); 462: 463: GetTextExtentPoint (hdc, buf, strlen(buf), &size); 464: 465: if ((xText = lpRect->right - size.cx) < glcyMenu + 1) 466: 467: xText = glcyMenu/2 + 1; 468: 469: TextOut (hdc, xText, lpRect->bottom, buf, strlen(buf)); 470: 471: goto done_enumfonts; 472: } 473: 474: else 475: { 476: // 477: // Else we're drawing to a printer & have filled up 478: // the first page. If there's any fonts left to draw 479: // then start a new page. 480: // 481: 482: if (!(i == nFaces - 1 && j == (paf + i)->nFonts - 1)) 483: { 484: EndPage (hdc); 485: xText = yText = 2; 486: StartPage (hdc); 487: } 488: } 489: } 490: } 491: } 492: 493: done_enumfonts: 494: 495: FreeFontList (paf); 496: } 497: 498: 499: 500: 501: /* In the callback functions for the enumerations, there is a limited 502: * ability to pass in parameters. For that reason, declare the following 503: * global variables to be used by any of the call back functions. 504: * 505: * HDC hdcGlobal; 506: * PARFONTS parFontsGlobal; 507: * int iFace,jFont; 508: * int nFaces; 509: * 510: * 511: * General call structure: 512: * 513: * BuildFontList 514: * EnumFonts 515: * MyEnumCount 516: * LocalAlloc 517: * EnumFonts 518: * MyEnumFaces 519: * EnumFonts 520: * MyEnumCount 521: * LocalAlloc 522: * LocalAlloc 523: * LocalAlloc 524: * EnumFonts 525: * MyEnumCopy 526: */ 527: 528: 529: 530: /******************************************************************************\ 531: * 532: * FUNCTION: BuildFontList 533: * 534: * GLOBAL VARS: (see above) 535: * 536: \******************************************************************************/ 537: 538: PARFONTS BuildFontList (HDC hdcIn) 539: { 540: nFaces = 0; 541: 542: hdcGlobal = hdcIn; 543: 544: // 545: // count the total number of face names. 546: // 547: 548: EnumFonts (hdcGlobal, NULL, (FONTENUMPROC)MyEnumCount, (LPARAM)&nFaces); 549: 550: // 551: // allocate the pointer to the array of PArFont structures. 552: // 553: 554: parFontsGlobal = (PARFONTS) LocalAlloc (LPTR, sizeof(ARFONTS) * (nFaces+1)); 555: 556: // 557: // step through all fonts again. For each one fill a LOGFONT and 558: // a TEXTMETRIC stucture. 559: // 560: 561: iFace = 0; 1.1.1.2 ! root 562: EnumFonts (hdcGlobal, NULL, (FONTENUMPROC)MyEnumFaces, 0); 1.1 root 563: 564: return parFontsGlobal; 565: } 566: 567: 568: 569: /******************************************************************************\ 570: * 571: * FUNCTION: MyEnumFaces 572: * 573: * GLOBAL VARS: (see above) 574: * 575: \******************************************************************************/ 576: 577: int CALLBACK MyEnumFaces (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs, 578: DWORD fFontType, LPVOID lpData) 579: { 580: int nFonts; 581: 582: nFonts = 0; 583: EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (FONTENUMPROC)MyEnumCount, 584: (LPARAM)&nFonts); 585: 586: parFontsGlobal[iFace].lf = (LOGFONT *) LocalAlloc (LPTR, 587: sizeof(LOGFONT) * 588: nFonts); 589: parFontsGlobal[iFace].tm = (TEXTMETRIC *) LocalAlloc (LPTR, 590: sizeof(TEXTMETRIC) * 591: nFonts); 592: parFontsGlobal[iFace].Type = (int *) LocalAlloc (LPTR, 593: sizeof(int) * 594: nFonts); 595: 596: if ((parFontsGlobal[iFace].lf == NULL) || 597: (parFontsGlobal[iFace].tm == NULL) || 598: (parFontsGlobal[iFace].Type == NULL)) 599: { 600: ErrMsgBox ("LocalAlloc failed", ERR_MOD_NAME); 601: return FALSE; 602: } 603: 604: parFontsGlobal[iFace].nFonts = nFonts; 605: 606: jFont = 0; 1.1.1.2 ! root 607: EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (FONTENUMPROC)MyEnumCopy, 0); 1.1 root 608: 609: iFace++; 610: 611: return TRUE; 612: } 613: 614: 615: 616: /******************************************************************************\ 617: * 618: * FUNCTION: MyEnumCopy 619: * 620: * GLOBAL VARS: (see above) 621: * 622: \******************************************************************************/ 623: 624: int CALLBACK MyEnumCopy (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs, 625: DWORD fFontType, LPVOID lpData) 626: { 627: LOGFONT *lplf; 628: TEXTMETRIC *lptm; 629: int *pType; 630: 631: lplf = parFontsGlobal[iFace].lf; 632: lptm = parFontsGlobal[iFace].tm; 633: pType = parFontsGlobal[iFace].Type; 634: 635: lplf[jFont] = *lpLogFont; 636: lptm[jFont] = *lpTEXTMETRICs; 637: pType[jFont] = fFontType; 638: 639: jFont++; 640: return TRUE; 641: } 642: 643: 644: 645: /******************************************************************************\ 646: * 647: * FUNCTION: MyEnumCount 648: * 649: * GLOBAL VARS: (see above) 650: * 651: \******************************************************************************/ 652: 653: int CALLBACK MyEnumCount (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs, 654: DWORD fFontType, LPVOID lpData) 655: { 656: (*(LPINT)lpData)++; 657: return TRUE; 658: } 659: 660: 661: 662: /******************************************************************************\ 663: * 664: * FUNCTION: FreeFontList 665: * 666: * INPUTS: paf - pointer to ARFONTS struct to free 667: * 668: \******************************************************************************/ 669: 670: void FreeFontList (PARFONTS paf) 671: { 672: int i; 673: 674: for (i = 0; i < nFaces; i++) 675: { 676: LocalFree (LocalHandle ((LPSTR) ((paf + i)->lf ))); 677: LocalFree (LocalHandle ((LPSTR) ((paf + i)->tm ))); 678: LocalFree (LocalHandle ((LPSTR) ((paf + i)->Type))); 679: } 680: LocalFree (LocalHandle ((LPSTR) paf)); 681: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.