|
|
1.1 ! 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: ! 12: /****************************** Module Header ******************************* ! 13: * Module Name: util.c ! 14: * ! 15: * Contains miscellaneous utility functions for dlgedit. ! 16: * ! 17: * Functions: ! 18: * MyAlloc() ! 19: * MyRealloc() ! 20: * MyFree() ! 21: * IsValue() ! 22: * HasBlanks() ! 23: * valtoi() ! 24: * axtoi() ! 25: * Myitoa() ! 26: * itoax() ! 27: * IsUniqueID() ! 28: * NextID() ! 29: * Message() ! 30: * ClientToScreenRect() ! 31: * ScreenToClientRect() ! 32: * DUToWinPoint() ! 33: * WinToDUPoint() ! 34: * DUToWinRect() ! 35: * WinToDURect() ! 36: * MapDlgClientPoint() ! 37: * MapWindowPoint() ! 38: * MyMapWindowRect() ! 39: * GetChildRect() ! 40: * CenterWindow() ! 41: * FitRectToScreen() ! 42: * ids() ! 43: * PixelsToPointSize() ! 44: * PointSizeToPixels() ! 45: * ! 46: * Comments: ! 47: * ! 48: ****************************************************************************/ ! 49: ! 50: #include "dlgedit.h" ! 51: #include "dlgfuncs.h" ! 52: #include "dlgextrn.h" ! 53: ! 54: #include <stdarg.h> ! 55: #include <ctype.h> ! 56: ! 57: ! 58: #define CBOVERHEAD (sizeof(INT)+sizeof(INT)+sizeof(INT)) ! 59: #define MEMSIGHEAD 0x1234 ! 60: #define MEMSIGTAIL 0x5678 ! 61: ! 62: ! 63: STATICFN BOOL IDUsedByCtrl(INT id); ! 64: ! 65: ! 66: ! 67: /**************************************************************************** ! 68: * MyAlloc ! 69: * ! 70: * Does a local alloc. ! 71: * ! 72: * Arguments: ! 73: * INT cbAlloc - number of bytes to allocate. ! 74: * ! 75: * Returns: ! 76: * ! 77: * A pointer to the memory if succesful; otherwise, NULL. ! 78: * ! 79: ****************************************************************************/ ! 80: ! 81: VOID *MyAlloc( ! 82: INT cbAlloc) ! 83: { ! 84: register HANDLE hMem; ! 85: ! 86: if (hMem = LocalAlloc(LMEM_FIXED, cbAlloc)) { ! 87: return (VOID *)hMem; ! 88: } ! 89: else { ! 90: MessageBeep(0); ! 91: Message(MSG_OUTOFMEMORY); ! 92: ! 93: return NULL; ! 94: } ! 95: } ! 96: ! 97: ! 98: /**************************************************************************** ! 99: * MyRealloc ! 100: * ! 101: * reallocates memory and returns a pointer to the memory block. ! 102: * ! 103: ****************************************************************************/ ! 104: ! 105: VOID *MyRealloc( ! 106: VOID *npMem, ! 107: INT cbNewAlloc) ! 108: { ! 109: npMem = (VOID *)LocalReAlloc((HANDLE)npMem, cbNewAlloc, LMEM_MOVEABLE); ! 110: ! 111: if (!npMem) { ! 112: MessageBeep(0); ! 113: Message(MSG_OUTOFMEMORY); ! 114: ! 115: return NULL; ! 116: } ! 117: ! 118: return npMem; ! 119: } ! 120: ! 121: /**************************************************************************** ! 122: * MyFree ! 123: * ! 124: * Frees the specified memory. ! 125: * ! 126: ****************************************************************************/ ! 127: ! 128: VOID *MyFree( ! 129: VOID *npMem) ! 130: { ! 131: if (LocalFree((HANDLE)npMem)) { ! 132: MessageBeep(0); ! 133: Message(MSG_MEMERROR); ! 134: ! 135: return npMem; ! 136: } ! 137: ! 138: return NULL; ! 139: } ! 140: ! 141: ! 142: ! 143: /************************************************************************ ! 144: * IsValue ! 145: * ! 146: * This function tells you if the string you give it represents a ! 147: * valid value or not. For this purpose, a valid value can only ! 148: * have the ascii characters from '0' to '9' with possibly the ! 149: * first character being '-'. Or be a Hex Number, with 0x preceeding ! 150: * it. ! 151: * ! 152: * Arguments: ! 153: * LPTSTR pszValue = The string to test. ! 154: * ! 155: * Returns: ! 156: * (0 == 0) if szValue represents a value. ! 157: * (c == 0) if szValue does not represent a value where c is ! 158: * non-zero. ! 159: * ! 160: * ! 161: ************************************************************************/ ! 162: ! 163: BOOL IsValue( ! 164: LPTSTR pszValue) ! 165: { ! 166: INT i; ! 167: ! 168: if (pszValue[0] == CHAR_0 && ! 169: (pszValue[1] == CHAR_X || pszValue[1] == CHAR_CAP_X)) { ! 170: for (i = 2; iswxdigit(pszValue[i]); i++) ! 171: ; ! 172: } ! 173: else { ! 174: for (i = 0; iswdigit(pszValue[i]) || ! 175: (i == 0 && pszValue[i] == CHAR_MINUS); i++) ! 176: ; ! 177: } ! 178: ! 179: return (pszValue[i] == 0); ! 180: } ! 181: ! 182: ! 183: ! 184: /************************************************************************ ! 185: * HasBlanks ! 186: * ! 187: * This function returns TRUE if the given string has imbedded ! 188: * blanks in it. ! 189: * ! 190: * Arguments: ! 191: * LPTSTR psz - String to check. ! 192: * ! 193: * ! 194: ************************************************************************/ ! 195: ! 196: BOOL HasBlanks( ! 197: LPTSTR psz) ! 198: { ! 199: while (*psz) ! 200: if (*psz++ == CHAR_SPACE) ! 201: return TRUE; ! 202: ! 203: return FALSE; ! 204: } ! 205: ! 206: ! 207: ! 208: /************************************************************************ ! 209: * valtoi ! 210: * ! 211: * Takes a string and returns its integer representation. ! 212: * This function handles both hex ("0x1234") and decimal ("1234") ! 213: * strings transparently. ! 214: * ! 215: * Arguments: ! 216: * LPTSTR pszValue = The string to convert. ! 217: * ! 218: * ! 219: ************************************************************************/ ! 220: ! 221: INT valtoi( ! 222: LPTSTR pszValue) ! 223: { ! 224: return (pszValue[0] == CHAR_0 && ! 225: (pszValue[1] == CHAR_CAP_X || pszValue[1] == CHAR_X)) ? ! 226: axtoi(&pszValue[2]) : awtoi(pszValue); ! 227: } ! 228: ! 229: ! 230: ! 231: /************************************************************************ ! 232: * axtoi ! 233: * ! 234: * This function converts a null terminated ascii string for a ! 235: * hex number to its integer value. Should just be the number ! 236: * with no preceeding "0x" or trailing "H". Garbage will result ! 237: * if there are non-hex digits in the string. Hex digits are: ! 238: * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, a, b, c, d, e, f. ! 239: * Non-hex digits will be treated like '0'. ! 240: * ! 241: * Arguments: ! 242: * LPTSTR pch = The null terminated hex string. ! 243: * ! 244: * Returns: ! 245: * The integer value represented by the given ascii string. ! 246: * ! 247: ************************************************************************/ ! 248: ! 249: INT axtoi( ! 250: LPTSTR pch) ! 251: { ! 252: register TCHAR ch; ! 253: register INT n = 0; ! 254: ! 255: while((ch = *pch++) != 0) { ! 256: if (iswdigit(ch)) ! 257: ch -= CHAR_0; ! 258: else if (ch >= CHAR_CAP_A && ch <= CHAR_CAP_F) ! 259: ch += (TCHAR)(10 - CHAR_CAP_A); ! 260: else if (ch >= CHAR_A && ch <= CHAR_F) ! 261: ch += (TCHAR)(10 - CHAR_A); ! 262: else ! 263: ch = (TCHAR)0; ! 264: ! 265: n = 16 * n + ch; ! 266: } ! 267: ! 268: return n; ! 269: } ! 270: ! 271: ! 272: ! 273: /************************************************************************ ! 274: * Myitoa ! 275: * ! 276: * This function converts a word to an ascii string. It builds either ! 277: * a decimal string or a hex string, based on whether Hex Mode is on ! 278: * when it is called. ! 279: * ! 280: * Arguments: ! 281: * INT n - The number to convert. ! 282: * LPTSTR psz - The buffer to put the string in, should have at least ! 283: * 17 bytes to take the string. ! 284: * ! 285: ************************************************************************/ ! 286: ! 287: VOID Myitoa( ! 288: INT n, ! 289: LPTSTR psz) ! 290: { ! 291: if (gfHexMode) ! 292: itoax(n, psz); ! 293: else ! 294: itoaw(n, psz, 10); ! 295: } ! 296: ! 297: ! 298: ! 299: /************************************************************************ ! 300: * itoax ! 301: * ! 302: * This function converts an int, 'n', to an ascii string ! 303: * representing it as a 4 digit hex number with "0x" preceeding it. ! 304: * ! 305: * Arguments: ! 306: * INT n = The number to convert. ! 307: * LPTSTR pszBuff = The buffer to put the string in, must ! 308: * be at least 7 characters long to take the string. ! 309: * ! 310: * ! 311: ************************************************************************/ ! 312: ! 313: VOID itoax( ! 314: INT n, ! 315: LPTSTR pszBuff) ! 316: { ! 317: INT i; ! 318: INT j; ! 319: ! 320: pszBuff[0] = CHAR_0; ! 321: pszBuff[1] = CHAR_X; ! 322: ! 323: for (i = 5; i > 1; i--) { ! 324: j = n & 15; ! 325: ! 326: if (j > 9) ! 327: pszBuff[i] = (TCHAR)(j + (CHAR_A - 10)); ! 328: else ! 329: pszBuff[i] = (TCHAR)(j + CHAR_0); ! 330: ! 331: n = n >> 4; ! 332: } ! 333: ! 334: pszBuff[6] = CHAR_NULL; ! 335: } ! 336: ! 337: ! 338: ! 339: /************************************************************************ ! 340: * NextID ! 341: * ! 342: * This function returns the next available id. ! 343: * ! 344: * For dialogs, it starts at 100 and increments by 100. It will not ! 345: * return a value until it finds one that begins a range that is ! 346: * not used by any control in any of the dialogs in the res list. ! 347: * In other words, it is guaranteed that the number returned and ! 348: * the range of the next 99 numbers are not used by any control in ! 349: * any dialog in the current res file. ! 350: * ! 351: * When returning a new id for a control, it usually starts at the ! 352: * dialog base, but if there are any controls, it starts at one higher ! 353: * than the id of the last control in the dialog that does not have ! 354: * one of the special-cased ids (the unused id, IDOK or IDCANCEL). ! 355: * It will find the first available id above this. ! 356: * ! 357: * When returning a default id for a new label, it starts at the dialog ! 358: * base (or 100 if there is not a dialog being edited) and starts ! 359: * searching for the first available one. It guarantees that the ! 360: * id returned is not used by any control in the current dialog, or ! 361: * any other label, or any control in the entire resource list. ! 362: * ! 363: * Arguments: ! 364: * INT idType - The type of id desired: ! 365: * NEXTID_DIALOG = ID for a new dialog. ! 366: * NEXTID_CONTROL = ID for a new control. ! 367: * NEXTID_LABEL = ID for a new label. ! 368: * NPLABEL plHead - The current label list to check for conflicts with. ! 369: * INT idExclude - An id that you specifically want to skip over. ! 370: * Set to zero if you don't care. ! 371: * ! 372: * Returns: ! 373: * The "next" unused id value. ! 374: * ! 375: * ! 376: ************************************************************************/ ! 377: ! 378: INT NextID( ! 379: INT idType, ! 380: NPLABEL plHead, ! 381: INT idExclude) ! 382: { ! 383: INT id; ! 384: ! 385: if (idType == NEXTID_CONTROL) { ! 386: /* ! 387: * Start at the base from the dialog plus one. It is ! 388: * assumed that this routine will not be called for an ! 389: * id for a control if there is not a dialog being ! 390: * edited first. ! 391: */ ! 392: id = gcd.npc->id + 1; ! 393: ! 394: /* ! 395: * Keep looping until an unused id is found. ! 396: */ ! 397: while (!IsUniqueID(id) || FindID(id, plHead) || id == idExclude) ! 398: id++; ! 399: } ! 400: else if (idType == NEXTID_DIALOG) { ! 401: /* ! 402: * Start at 100. ! 403: */ ! 404: id = 100; ! 405: ! 406: /* ! 407: * Keep looping by hundreds until an unused id is found. ! 408: */ ! 409: while (!IsUniqueID(id) || FindID(id, plHead) || id == idExclude) ! 410: id += 100; ! 411: } ! 412: else { ! 413: /* ! 414: * We are looking for a default id for a new label. Start ! 415: * at the dialog base, if there is a dialog being edited. ! 416: */ ! 417: if (gfEditingDlg) ! 418: id = gcd.npc->id + 1; ! 419: else ! 420: id = 100; ! 421: ! 422: /* ! 423: * Keep looping until an unused id is found. The id should ! 424: * not be used by any control in the current dialog, any ! 425: * other label already, or any control in the res file. ! 426: */ ! 427: while (FindID(id, plHead) || FindIDInRes(id) || id == idExclude) ! 428: id++; ! 429: } ! 430: ! 431: /* ! 432: * We found an unused one. Return it. ! 433: */ ! 434: return id; ! 435: } ! 436: ! 437: ! 438: ! 439: /************************************************************************ ! 440: * IDUsedByCtrl ! 441: * ! 442: * This function returns TRUE if the given ID is used by any control ! 443: * in the current dialog. This also counts the text field of W_ICON ! 444: * controls, if they are ordinals. ! 445: * ! 446: * Arguments: ! 447: * INT id = The ID to look for. ! 448: * ! 449: * Returns: ! 450: * TRUE if the id is used, FALSE if not. ! 451: * ! 452: * ! 453: ************************************************************************/ ! 454: ! 455: STATICFN BOOL IDUsedByCtrl( ! 456: INT id) ! 457: { ! 458: register NPCTYPE npc; ! 459: ! 460: for (npc = npcHead; npc; npc = npc->npcNext) { ! 461: if (npc->id == id || ! 462: (npc->pwcd->iType == W_ICON && ! 463: npc->text && ! 464: IsOrd(npc->text) && ! 465: id == (INT)OrdID(npc->text))) ! 466: return TRUE; ! 467: } ! 468: ! 469: return FALSE; ! 470: } ! 471: ! 472: ! 473: ! 474: /************************************************************************ ! 475: * IsUniqueID ! 476: * ! 477: * This function returns TRUE if the given id is unique. A unique ! 478: * id is either the special "unused" id value, or it is an id that ! 479: * is not already assigned to any other control in the current dialog ! 480: * and it is not assigned to any other dialog in the current res list. ! 481: * ! 482: * Note that this routine does NOT look for duplicates in the include ! 483: * file of this id, only for ids that have been used by other controls ! 484: * or dialogs already. ! 485: * ! 486: * Arguments: ! 487: * INT id = The id to verify is unique. ! 488: * ! 489: * Returns: ! 490: * TRUE if the id is "unique", FALSE if it is not. ! 491: * ! 492: * ! 493: ************************************************************************/ ! 494: ! 495: BOOL IsUniqueID( ! 496: INT id) ! 497: { ! 498: ORDINAL ord; ! 499: ! 500: /* ! 501: * If the id is the special unused id, it is considered unique. ! 502: */ ! 503: if (id == IDUNUSED) ! 504: return TRUE; ! 505: ! 506: /* ! 507: * Not unique if another control in the dialog has the same id. ! 508: */ ! 509: if (IDUsedByCtrl(id)) ! 510: return FALSE; ! 511: ! 512: /* ! 513: * Not unique if another dialog has the same id. ! 514: */ ! 515: WriteOrd(&ord, id); ! 516: if (FindDialog((LPTSTR)&ord)) ! 517: return FALSE; ! 518: ! 519: return TRUE; ! 520: } ! 521: ! 522: ! 523: ! 524: /************************************************************************ ! 525: * Message ! 526: * ! 527: * This function puts up a message box with a string indexed by idMsg. ! 528: * ! 529: * Returns: ! 530: * What MessageBox returns. ! 531: * ! 532: ************************************************************************/ ! 533: ! 534: INT Message( ! 535: INT idMsg, ! 536: ...) ! 537: { ! 538: va_list marker; ! 539: INT RetCode; ! 540: TCHAR szT[CCHTEXTMAX]; ! 541: BOOL fDisabledSave; ! 542: ! 543: va_start(marker, idMsg); ! 544: wvsprintf(szT, ids(gamdMessages[idMsg].ids), marker); ! 545: ! 546: fDisabledSave = gfDisabled; ! 547: gfDisabled = TRUE; ! 548: RetCode = MessageBox(NULL, szT, ids(IDS_DLGEDIT), ! 549: (WORD)(gamdMessages[idMsg].fMessageBox | MB_TASKMODAL)); ! 550: gfDisabled = fDisabledSave; ! 551: ! 552: va_end(marker); ! 553: ! 554: return RetCode; ! 555: } ! 556: ! 557: ! 558: ! 559: /************************************************************************ ! 560: * ClientToScreenRect ! 561: * ! 562: * This function converts the coordinates in a rectangle from points ! 563: * relative to the client area into points that are relative to the ! 564: * screen. ! 565: * ! 566: * Arguments: ! 567: * HWND hwnd - Window handle for the conversion. ! 568: * PRECT prc - Pointer to the rectangle to convert. ! 569: * ! 570: * ! 571: ************************************************************************/ ! 572: ! 573: VOID ClientToScreenRect( ! 574: HWND hwnd, ! 575: PRECT prc) ! 576: { ! 577: ClientToScreen(hwnd, (PPOINT)prc); ! 578: ClientToScreen(hwnd, ((PPOINT)prc) + 1); ! 579: } ! 580: ! 581: ! 582: ! 583: /************************************************************************ ! 584: * ScreenToClientRect ! 585: * ! 586: * This function converts the coordinates in a rectangle from points ! 587: * relative to the screen into points that are relative to the given ! 588: * window's client area. ! 589: * ! 590: * Arguments: ! 591: * HWND hwnd - Window handle for the conversion. ! 592: * PRECT prc - Pointer to the rectangle to convert. ! 593: * ! 594: * ! 595: ************************************************************************/ ! 596: ! 597: VOID ScreenToClientRect( ! 598: HWND hwnd, ! 599: PRECT prc) ! 600: { ! 601: ScreenToClient(hwnd, (PPOINT)prc); ! 602: ScreenToClient(hwnd, ((PPOINT)prc) + 1); ! 603: } ! 604: ! 605: ! 606: ! 607: /************************************************************************ ! 608: * DUToWinPoint ! 609: * ! 610: * This function converts the coordinates in the given point from ! 611: * dialog units (DU's) to window units for the current dialog. ! 612: * ! 613: * Arguments: ! 614: * PPOINT ppt - Pointer to the point to convert. ! 615: * ! 616: * ! 617: ************************************************************************/ ! 618: ! 619: VOID DUToWinPoint( ! 620: PPOINT ppt) ! 621: { ! 622: ppt->x = MulDiv(ppt->x, gcd.cxChar, 4); ! 623: ppt->y = MulDiv(ppt->y, gcd.cyChar, 8); ! 624: } ! 625: ! 626: ! 627: ! 628: /************************************************************************ ! 629: * WinToDUPoint ! 630: * ! 631: * This function converts the coordinates in the given point from ! 632: * window points to dialog units (DU's) for the current dialog. ! 633: * ! 634: * Arguments: ! 635: * PPOINT ppt - Pointer to the point to convert. ! 636: * ! 637: * ! 638: ************************************************************************/ ! 639: ! 640: VOID WinToDUPoint( ! 641: PPOINT ppt) ! 642: { ! 643: ppt->x = MulDiv(ppt->x, 4, gcd.cxChar); ! 644: ppt->y = MulDiv(ppt->y, 8, gcd.cyChar); ! 645: } ! 646: ! 647: ! 648: ! 649: /************************************************************************ ! 650: * DUToWinRect ! 651: * ! 652: * This function converts the coordinates in a rectangle from ! 653: * dialog units for the current dialog to window units. ! 654: * ! 655: * Arguments: ! 656: * PRECT prc - Pointer to the rectangle to convert. ! 657: * ! 658: * ! 659: ************************************************************************/ ! 660: ! 661: VOID DUToWinRect( ! 662: PRECT prc) ! 663: { ! 664: DUToWinPoint((PPOINT)prc); ! 665: DUToWinPoint(((PPOINT)prc) + 1); ! 666: } ! 667: ! 668: ! 669: ! 670: /************************************************************************ ! 671: * WinToDURect ! 672: * ! 673: * This function converts the coordinates in a rectangle from ! 674: * window units to dialog units for the current dialog. ! 675: * ! 676: * Arguments: ! 677: * PRECT prc - Pointer to the rectangle to convert. ! 678: * ! 679: * ! 680: ************************************************************************/ ! 681: ! 682: VOID WinToDURect( ! 683: PRECT prc) ! 684: { ! 685: WinToDUPoint((PPOINT)prc); ! 686: WinToDUPoint(((PPOINT)prc) + 1); ! 687: } ! 688: ! 689: ! 690: ! 691: /************************************************************************ ! 692: * MapDlgClientPoint ! 693: * ! 694: * This function converts client points to be relative to the window ! 695: * origin instead, or the other way around. If fFromClient is TRUE, ! 696: * the point is considered to be relative to the client origin in ! 697: * the dialog, and will be converted to a point relative to the ! 698: * window origin instead. ! 699: * ! 700: * If fFromClient is FALSE, the point is considered to be relative ! 701: * to the window origin, and will be mapped to a point that is ! 702: * relative to the client origin. ! 703: * ! 704: * This function assumes that the global grcDlgClient has been ! 705: * previously calculated. It should only be called to map points ! 706: * for the current dialog being edited (for which grcDlgClient has ! 707: * been calculated). ! 708: * ! 709: * Arguments: ! 710: * PPOINT ppt - Pointer to the point to convert. ! 711: * BOOL fFromClient - TRUE if the point is relative to the client origin. ! 712: * ! 713: * ! 714: ************************************************************************/ ! 715: ! 716: VOID MapDlgClientPoint( ! 717: PPOINT ppt, ! 718: BOOL fFromClient) ! 719: { ! 720: if (fFromClient) { ! 721: ppt->x += grcDlgClient.left; ! 722: ppt->y += grcDlgClient.top; ! 723: } ! 724: else { ! 725: ppt->x -= grcDlgClient.left; ! 726: ppt->y -= grcDlgClient.top; ! 727: } ! 728: } ! 729: ! 730: ! 731: ! 732: /************************************************************************ ! 733: * MapWindowPoint ! 734: * ! 735: * This function maps a point from one window to another. The point ! 736: * given is in window coordinates (not client coordinates) and is ! 737: * mapped so that it is relative to the destination window. ! 738: * ! 739: * Arguments: ! 740: * HWND hwndFrom - Source window. ! 741: * HWND hwndTo - Destination window. ! 742: * PPOINT ppt - Pointer to the point to convert. ! 743: * ! 744: * Comments: ! 745: * In Win 3.1 (and NT) the MapWindowPoints call can be used and this one can be removed. ! 746: * It is only needed here for compatibility with Win 3.0. ! 747: * ! 748: ************************************************************************/ ! 749: ! 750: VOID MapWindowPoint( ! 751: HWND hwndFrom, ! 752: HWND hwndTo, ! 753: PPOINT ppt) ! 754: { ! 755: RECT rcFrom; ! 756: RECT rcTo; ! 757: ! 758: GetWindowRect(hwndFrom, &rcFrom); ! 759: GetWindowRect(hwndTo, &rcTo); ! 760: ! 761: ppt->x += rcFrom.left - rcTo.left; ! 762: ppt->y += rcFrom.top - rcTo.top; ! 763: } ! 764: ! 765: ! 766: ! 767: /************************************************************************ ! 768: * MyMapWindowRect ! 769: * ! 770: * This function maps a rectangle from one window to another. The rectangle ! 771: * given is in window coordinates (not client coordinates) and is ! 772: * mapped so that it is relative to the destination window. ! 773: * ! 774: * Arguments: ! 775: * HWND hwndFrom - Source window. ! 776: * HWND hwndTo - Destination window. ! 777: * PRECT prc - Pointer to the rectangle to convert. ! 778: * ! 779: * Comments: ! 780: * In Win 3.1 (and NT) the MapWindowRect call can be used and this one can be removed. ! 781: * It is only needed here for compatibility with Win 3.0. ! 782: ************************************************************************/ ! 783: ! 784: VOID MyMapWindowRect( ! 785: HWND hwndFrom, ! 786: HWND hwndTo, ! 787: PRECT prc) ! 788: { ! 789: RECT rcFrom; ! 790: RECT rcTo; ! 791: ! 792: GetWindowRect(hwndFrom, &rcFrom); ! 793: GetWindowRect(hwndTo, &rcTo); ! 794: ! 795: OffsetRect(prc, rcFrom.left - rcTo.left, rcFrom.top - rcTo.top); ! 796: } ! 797: ! 798: ! 799: ! 800: /************************************************************************ ! 801: * GetChildRect ! 802: * ! 803: * This function returns the client rectangle for a given child control, ! 804: * mapped to its parent window. ! 805: * ! 806: * Arguments: ! 807: * HWND hwndChild - Child window. ! 808: * PRECT prc - Where to return the rectangle. ! 809: * ! 810: ************************************************************************/ ! 811: ! 812: VOID GetChildRect( ! 813: HWND hwndChild, ! 814: PRECT prc) ! 815: { ! 816: HWND hwndParent; ! 817: ! 818: hwndParent = GetParent(hwndChild); ! 819: GetClientRect(hwndChild, prc); ! 820: ClientToScreenRect(hwndChild, prc); ! 821: ScreenToClientRect(hwndParent, prc); ! 822: } ! 823: ! 824: ! 825: ! 826: /************************************************************************ ! 827: * CenterWindow ! 828: * ! 829: * This function centers the given window over its owner. It ensures ! 830: * that the window is entirely within the visible screen, however. ! 831: * If the window does not have an owner, it is centered over the ! 832: * desktop. ! 833: * ! 834: * Arguments: ! 835: * HWND hwnd - The window to center. ! 836: * ! 837: ************************************************************************/ ! 838: ! 839: VOID CenterWindow( ! 840: HWND hwnd) ! 841: { ! 842: RECT rc; ! 843: RECT rcOwner; ! 844: RECT rcCenter; ! 845: HWND hwndOwner; ! 846: ! 847: GetWindowRect(hwnd, &rc); ! 848: ! 849: if (!(hwndOwner = GetWindow(hwnd, GW_OWNER))) ! 850: hwndOwner = GetDesktopWindow(); ! 851: ! 852: GetWindowRect(hwndOwner, &rcOwner); ! 853: ! 854: /* ! 855: * Calculate the starting x,y for the new ! 856: * window so that it would be centered. ! 857: */ ! 858: rcCenter.left = rcOwner.left + ! 859: (((rcOwner.right - rcOwner.left) - ! 860: (rc.right - rc.left)) ! 861: / 2); ! 862: ! 863: rcCenter.top = rcOwner.top + ! 864: (((rcOwner.bottom - rcOwner.top) - ! 865: (rc.bottom - rc.top)) ! 866: / 2); ! 867: ! 868: rcCenter.right = rcCenter.left + (rc.right - rc.left); ! 869: rcCenter.bottom = rcCenter.top + (rc.bottom - rc.top); ! 870: ! 871: FitRectToScreen(&rcCenter); ! 872: ! 873: SetWindowPos(hwnd, NULL, rcCenter.left, rcCenter.top, 0, 0, ! 874: SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); ! 875: } ! 876: ! 877: ! 878: ! 879: /************************************************************************ ! 880: * FitRectToScreen ! 881: * ! 882: * This function ensures that the given rectangle is entirely within ! 883: * the visible screen, adjusting it if necessary. ! 884: * ! 885: * Arguments: ! 886: * PRECT prc - The rectangle. ! 887: * ! 888: ************************************************************************/ ! 889: ! 890: VOID FitRectToScreen( ! 891: PRECT prc) ! 892: { ! 893: INT cxScreen; ! 894: INT cyScreen; ! 895: INT delta; ! 896: ! 897: cxScreen = GetSystemMetrics(SM_CXSCREEN); ! 898: cyScreen = GetSystemMetrics(SM_CYSCREEN); ! 899: ! 900: if (prc->right > cxScreen) { ! 901: delta = prc->right - prc->left; ! 902: prc->right = cxScreen; ! 903: prc->left = prc->right - delta; ! 904: } ! 905: ! 906: if (prc->left < 0) { ! 907: delta = prc->right - prc->left; ! 908: prc->left = 0; ! 909: prc->right = prc->left + delta; ! 910: } ! 911: ! 912: if (prc->bottom > cyScreen) { ! 913: delta = prc->bottom - prc->top; ! 914: prc->bottom = cyScreen; ! 915: prc->top = prc->bottom - delta; ! 916: } ! 917: ! 918: if (prc->top < 0) { ! 919: delta = prc->bottom - prc->top; ! 920: prc->top = 0; ! 921: prc->bottom = prc->top + delta; ! 922: } ! 923: } ! 924: ! 925: ! 926: ! 927: /************************************************************************ ! 928: * ids ! 929: * ! 930: * This function will return a string, given the string id. If this is ! 931: * the first time that the string has been retrieved, memory will be ! 932: * allocated for it and it will be loaded. After it is loaded once, it ! 933: * is then cached in a LPTSTR array and is available for later without ! 934: * having to load it again. ! 935: * ! 936: * Arguments: ! 937: * UINT idString - String ID of the string to retrieve. ! 938: * ! 939: ************************************************************************/ ! 940: ! 941: LPTSTR ids( ! 942: UINT idString) ! 943: { ! 944: static LPTSTR apsz[CSTRINGS]; // String resource array cache. ! 945: LPTSTR psz; ! 946: INT cch; ! 947: ! 948: if (apsz[idString]) ! 949: return apsz[idString]; ! 950: ! 951: if (!(psz = MyAlloc(CCHTEXTMAX * sizeof(TCHAR)))) ! 952: return szEmpty; ! 953: ! 954: if (!(cch = LoadString(ghInst, idString, psz, CCHTEXTMAX))) { ! 955: MyFree(psz); ! 956: return szEmpty; ! 957: } ! 958: ! 959: apsz[idString] = psz = MyRealloc(psz, (cch + 1) * sizeof(TCHAR)); ! 960: ! 961: return (psz ? psz : szEmpty); ! 962: } ! 963: ! 964: ! 965: ! 966: /************************************************************************ ! 967: * PixelsToPointSize ! 968: * ! 969: * This function takes a font height in pixels and converts it to ! 970: * the equivalent point size. Note that the pixel height of a font ! 971: * is actually the tmHeight field of the TEXTMETRIC structure minus ! 972: * the tmInternalLeading value. ! 973: * ! 974: * This function relies on the global gcyPixelsPerInch having been ! 975: * set before it is called. ! 976: * ! 977: * Arguments: ! 978: * INT nPixels - Pixel size to convert to point size. ! 979: * ! 980: ************************************************************************/ ! 981: ! 982: INT PixelsToPointSize( ! 983: INT nPixels) ! 984: { ! 985: return MulDiv(nPixels, 72, gcyPixelsPerInch); ! 986: } ! 987: ! 988: ! 989: ! 990: /************************************************************************ ! 991: * PointSizeToPixels ! 992: * ! 993: * This function takes a given point size and converts it to the ! 994: * equivalent pixel text height. This value can be placed in ! 995: * the TEXTMETRIC structure's tmHeight field if it is made negative ! 996: * first. This will cause a CreateFont call to automatically ! 997: * subtract the internal leading value before creating the font. ! 998: * ! 999: * This function relies on the global gcyPixelsPerInch having been ! 1000: * set before it is called. ! 1001: * ! 1002: * Arguments: ! 1003: * INT nPointSize - Point size to convert to pixels. ! 1004: * ! 1005: ************************************************************************/ ! 1006: ! 1007: INT PointSizeToPixels( ! 1008: INT nPointSize) ! 1009: { ! 1010: return MulDiv(nPointSize, gcyPixelsPerInch, 72); ! 1011: } ! 1012: ! 1013: ! 1014:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.