|
|
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.