|
|
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: STATUS.C
14: *
15: * Status line handler.
16: *
17: * Functions:
18: *
19: * StatusInit()
20: * StatusCreate()
21: * StatusHeight()
22: * StatusAlloc()
23: * StatusAddItem()
24: * StatusCreateTools()
25: * StatusDeleteTools()
26: * StatusWndProc()
27: * StatusResize()
28: * StatusCalcHeight()
29: * StatusCalcWidth()
30: * StatusGetItem()
31: * LowerRect()
32: * RaiseRect()
33: * StatusPaint()
34: * BottomRight()
35: * TopLeft()
36: * StatusButtonDown()
37: * StatusButtonUp()
38: * InitDC()
39: *
40: * Comments:
41: *
42: ****************************************************************************/
43:
44: #include <windows.h>
45: #include <string.h>
46:
47: #include "gutils.h"
48:
49:
50: /* --- data structures ------------------------------------------------- */
51: #define SF_MAXLABEL 80 /* no more than 80 in an item within the bar */
52: /* Is this adequate for long pathnames on a
53: hi-res screen?
54: */
55:
56: typedef struct statel {
57: int type; /* SF_BUTTON or SF_STATIC */
58: int flags; /* SF_VAR => variable width
59: SF_LEFT=> left aligned (else right)
60: SF_RAISE=> paint as 'raised' 3d rect
61: SF_LOWER=> paint as lowered 3D rect
62: SF_SZMIN=>together with SF_VAR
63: allows minimum size for
64: var sized item
65: SF_SZMAX=>see SZMIN and use nouse
66: */
67: int id; /* control id */
68: int width; /* width of control in chars */
69: char text[SF_MAXLABEL+1]; /* null-term string for label */
70:
71: RECT rc; /* used by status.c */
72: } STATEL, FAR * PSTATEL;
73:
74: typedef struct itemlist {
75: int nitems;
76: PSTATEL statels;
77:
78: int selitem; /* used by status.c */
79: BOOL isselected; /* used by status.c */
80: } ILIST, FAR * PILIST;
81:
82: /* prototypes of routines in this module */
83:
84: void StatusCreateTools(void);
85: void StatusDeleteTools(void);
86: long APIENTRY StatusWndProc(HWND, UINT, UINT, LONG);
87: void StatusResize(HWND hWnd, PILIST pilist);
88: int StatusCalcHeight(HWND hWnd, PSTATEL ip);
89: int StatusCalcWidth(HWND hWnd, PSTATEL ip);
90: PSTATEL StatusGetItem(PILIST plist, int id);
91: void LowerRect(HDC hDC, LPRECT rcp);
92: void RaiseRect(HDC hDC, LPRECT rcp);
93: void StatusPaint(HWND hWnd, PILIST iplistp);
94: void BottomRight(HDC hDC, LPRECT rcp, HPEN hpen, BOOL bCorners);
95: void TopLeft(HDC hDC, LPRECT rcp, HPEN hpen, BOOL bCorners);
96: void StatusButtonDown(HDC hDC, PSTATEL ip);
97: void StatusButtonUp(HDC hDC, PSTATEL ip);
98: void InitDC(HDC hdc);
99:
100:
101: /*--global data---------------------------------------------------------*/
102:
103: HPEN hpenHilight, hpenLowlight;
104: HPEN hpenBlack, hpenNeutral;
105: HBRUSH hbrBackground; /* pieces and board */
106: HFONT hFont;
107: int status_charheight, status_charwidth;
108:
109: /* default pt size for font (tenths of a pt) */
110: #define DEF_PTSIZE 80
111:
112: /***************************************************************************
113: * Function: StatusInit
114: *
115: * Purpose:
116: *
117: * Create window class
118: */
119: BOOL
120: StatusInit(HANDLE hInstance)
121: {
122: WNDCLASS wc;
123: BOOL resp;
124: TEXTMETRIC tm;
125: HDC hDC;
126:
127:
128: StatusCreateTools();
129:
130: wc.style = CS_HREDRAW|CS_VREDRAW|CS_GLOBALCLASS;
131: wc.lpfnWndProc = (WNDPROC) StatusWndProc;
132: wc.cbClsExtra = 0;
133: wc.cbWndExtra = sizeof(HANDLE);
134: wc.hInstance = hInstance;
135: wc.hIcon = NULL;
136: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
137: wc.hbrBackground = hbrBackground;
138: wc.lpszClassName = (LPSTR) "gdstatusclass";
139: wc.lpszMenuName = NULL;
140:
141: resp = RegisterClass(&wc);
142:
143: hDC = GetDC(NULL);
144: InitDC(hDC);
145: GetTextMetrics(hDC, &tm);
146: status_charheight = (int)(tm.tmHeight + tm.tmExternalLeading);
147: status_charwidth = (int)tm.tmAveCharWidth;
148: ReleaseDC(NULL, hDC);
149:
150: return(resp);
151: }
152:
153: /*
154: /***************************************************************************
155: * Function: StatusCreate
156: *
157: * Purpose:
158: *
159: * Create and show the window
160: */
161: HWND APIENTRY
162: StatusCreate(HANDLE hInst, HWND hParent, int id, LPRECT rcp, HANDLE hmem)
163: {
164:
165: HWND hWnd;
166:
167: /* create a child window of status class */
168:
169:
170: hWnd = CreateWindow("gdstatusclass",
171: NULL,
172: WS_CHILD | WS_VISIBLE,
173: rcp->left,
174: rcp->top,
175: (rcp->right - rcp->left),
176: (rcp->bottom - rcp->top),
177: hParent,
178: (HANDLE) id,
179: hInst,
180: (LPVOID) hmem);
181:
182: return(hWnd);
183: }
184:
185: /***************************************************************************
186: * Function: StatusHeight
187: *
188: * Purpose:
189: *
190: * Return default height of this window
191: */
192: int APIENTRY
193: StatusHeight(HANDLE hmem)
194: /* The window has a number of items which are arranged horizontally,
195: so the window height is the maximum of the individual heights
196: */
197: {
198: PILIST plist;
199: int i;
200: int sz;
201: int maxsize = 0;
202:
203: plist = (PILIST) GlobalLock(hmem);
204: if (plist != NULL) {
205: for (i = 0; i<plist->nitems; i++) {
206: sz = StatusCalcHeight(NULL, &plist->statels[i]);
207: maxsize = max(sz, maxsize);
208: }
209: }
210: GlobalUnlock(hmem);
211: if (maxsize > 0) {
212: return(maxsize + 4);
213: } else {
214: return(status_charheight + 4);
215: }
216: }
217:
218: /***************************************************************************
219: * Function: StatusAlloc
220: *
221: * Purpose:
222: *
223: * Alloc the plist struct and return handle to caller
224: */
225: HANDLE FAR PASCAL
226: StatusAlloc(int nitems)
227: {
228: HANDLE hmem;
229: PILIST pilist;
230: LPSTR chp;
231:
232: hmem = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,
233: sizeof(ILIST) + (sizeof(STATEL) * nitems));
234: chp = GlobalLock(hmem);
235: if (chp == NULL) {
236: return(NULL);
237: }
238:
239: pilist = (PILIST) chp;
240: pilist->nitems = nitems;
241: pilist->statels = (PSTATEL) &chp[sizeof(ILIST)];
242: GlobalUnlock(hmem);
243:
244: return(hmem);
245: }
246:
247:
248: /***************************************************************************
249: * Function: StatusAddItem
250: *
251: * Purpose:
252: *
253: * Insert an item into the plist
254: */
255: BOOL FAR PASCAL
256: StatusAddItem(HANDLE hmem, int itemnr, int type, int flags, int id,
257: int width, LPSTR text)
258: {
259: PILIST pilist;
260: PSTATEL pel;
261:
262: pilist = (PILIST) GlobalLock(hmem);
263: if ((pilist == NULL) || (itemnr >= pilist->nitems)) {
264: GlobalUnlock(hmem);
265: return(FALSE);
266: }
267: pel = &pilist->statels[itemnr];
268: pel->type = type;
269: pel->flags = flags;
270: pel->id = id;
271: pel->width = width;
272: if (text == NULL) {
273: pel->text[0] = '\0';
274: } else {
275: lstrcpy(pel->text, text);
276: }
277:
278:
279: GlobalUnlock(hmem);
280: return(TRUE);
281: }
282:
283: /***************************************************************************
284: * Function: InitDC
285: *
286: * Purpose:
287: *
288: * Initialize colors and font
289: */
290: void
291: InitDC(HDC hdc)
292: {
293: SetBkColor(hdc, RGB(192,192,192));
294: SelectObject(hdc, hbrBackground);
295: SelectObject(hdc, hFont);
296: }
297:
298:
299: /***************************************************************************
300: * Function: StatusCreateTools
301: *
302: * Purpose:
303: *
304: * Create Pens and brushes
305: */
306: void
307: StatusCreateTools()
308: {
309: LOGFONT lf;
310: HDC hdc;
311: int scale;
312:
313: hbrBackground = CreateSolidBrush(RGB(192,192,192));
314: hpenHilight = CreatePen(0, 1, RGB(255, 255, 255));
315: hpenLowlight = CreatePen(0, 1, RGB(128, 128, 128));
316: hpenNeutral = CreatePen(0, 1, RGB(192, 192, 192));
317: hpenBlack = CreatePen(0, 1, RGB(0, 0, 0));
318:
319: hdc = GetDC(NULL);
320: scale = GetDeviceCaps(hdc, LOGPIXELSY);
321: ReleaseDC(NULL, hdc);
322:
323: lf.lfHeight = -MulDiv(DEF_PTSIZE, scale, 720);
324: lf.lfWidth = 0;
325: lf.lfEscapement = 0;
326: lf.lfOrientation = 0;
327: lf.lfWeight = FW_REGULAR;
328: lf.lfItalic = 0;
329: lf.lfUnderline = 0;
330: lf.lfStrikeOut = 0;
331: lf.lfCharSet = ANSI_CHARSET;
332: lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
333: lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
334: lf.lfQuality = PROOF_QUALITY;
335: lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
336: lf.lfFaceName[0] = '\0';
337: #ifdef COMPLEX
338: hFont = CreateFontIndirect(&lf);
339: #else
340: hFont = GetStockObject(SYSTEM_FONT);
341: #endif
342:
343:
344:
345: }
346:
347: /***************************************************************************
348: * Function: StatusDeleteTools
349: *
350: * Purpose:
351: *
352: * Delete brushes and pens
353: */
354: void
355: StatusDeleteTools()
356: {
357: DeleteObject(hbrBackground);
358: DeleteObject(hpenHilight);
359: DeleteObject(hpenLowlight);
360: DeleteObject(hpenBlack);
361: DeleteObject(hpenNeutral);
362:
363: #ifdef COMPLEX
364: DeleteObject(hFont);
365: #endif
366: }
367:
368: /***************************************************************************
369: * Function: StatusWndProc
370: *
371: * Purpose:
372: *
373: * Main winproc for status windows
374: *
375: * handles create/destroy and paint requests
376: */
377:
378: long FAR PASCAL
379: StatusWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam)
380: {
381: HANDLE hitems;
382: PSTATEL ip;
383: PILIST plist;
384: CREATESTRUCT FAR * cp;
385: int i;
386: HDC hDC;
387: RECT rc;
388: POINT pt;
389:
390: switch(message) {
391:
392: case WM_CREATE:
393: cp = (CREATESTRUCT FAR *) lParam;
394: hitems = (HANDLE) (LONG) cp->lpCreateParams;
395: SetWindowLong(hWnd, 0, (LONG)hitems);
396: plist = (PILIST) GlobalLock(hitems);
397: if (plist != NULL) {
398: plist->selitem = -1;
399: GlobalUnlock(hitems);
400: }
401: break;
402:
403: case WM_SIZE:
404: hitems = (HANDLE) GetWindowLong(hWnd, 0);
405: plist = (PILIST) GlobalLock(hitems);
406: if (plist != NULL) {
407: StatusResize(hWnd, plist);
408: GlobalUnlock(hitems);
409: }
410: break;
411:
412: case WM_PAINT:
413: hitems = (HANDLE) GetWindowLong(hWnd, 0);
414: plist = (PILIST) GlobalLock(hitems);
415: StatusPaint(hWnd, plist);
416: GlobalUnlock(hitems);
417:
418: break;
419:
420: case WM_LBUTTONUP:
421: hitems = (HANDLE) GetWindowLong(hWnd, 0);
422: plist = (PILIST) GlobalLock(hitems);
423: pt.x = LOWORD(lParam);
424: pt.y = HIWORD(lParam);
425:
426: if (plist == NULL) {
427: break;
428: }
429: if (plist->selitem != -1) {
430: ip = &plist->statels[plist->selitem];
431: if (plist->isselected) {
432: hDC = GetDC(hWnd);
433: InitDC(hDC);
434: StatusButtonUp(hDC, ip);
435: ReleaseDC(hWnd, hDC);
436: }
437: plist->selitem = -1;
438: ReleaseCapture();
439: if (PtInRect(&ip->rc, pt)) {
440: SendMessage(GetParent(hWnd), WM_COMMAND,
441: MAKELONG(ip->id, WM_LBUTTONUP), (LONG)hWnd);
442: }
443: }
444: GlobalUnlock(hitems);
445: break;
446:
447: case WM_LBUTTONDOWN:
448: hitems = (HANDLE) GetWindowLong(hWnd, 0);
449: plist = (PILIST) GlobalLock(hitems);
450: if (plist == NULL) {
451: break;
452: }
453: pt.x = LOWORD(lParam);
454: pt.y = HIWORD(lParam);
455: if (plist->selitem == -1) {
456: for (i = 0; i< plist->nitems; i++) {
457: ip = &plist->statels[i];
458: if (PtInRect(&ip->rc, pt)) {
459: if (ip->type != SF_BUTTON) {
460: break;
461: }
462: plist->selitem = i;
463: SetCapture(hWnd);
464:
465: plist->isselected = TRUE;
466: hDC = GetDC(hWnd);
467: InitDC(hDC);
468: StatusButtonDown(hDC, ip);
469: ReleaseDC(hWnd, hDC);
470: break;
471: }
472: }
473: }
474: GlobalUnlock(hitems);
475: break;
476:
477: case WM_MOUSEMOVE:
478: hitems = (HANDLE) GetWindowLong(hWnd, 0);
479: plist = (PILIST) GlobalLock(hitems);
480: if (plist == NULL) {
481: break;
482: }
483: pt.x = LOWORD(lParam);
484: pt.y = HIWORD(lParam);
485: if (plist->selitem != -1) {
486: ip = &plist->statels[plist->selitem];
487: if (PtInRect(&ip->rc, pt)) {
488: if (!plist->isselected) {
489: hDC = GetDC(hWnd);
490: InitDC(hDC);
491: StatusButtonDown(hDC, ip);
492: ReleaseDC(hWnd, hDC);
493: plist->isselected = TRUE;
494: }
495: } else {
496: if(plist->isselected) {
497: hDC = GetDC(hWnd);
498: InitDC(hDC);
499: StatusButtonUp(hDC, ip);
500: ReleaseDC(hWnd, hDC);
501: plist->isselected = FALSE;
502: }
503: }
504: }
505: GlobalUnlock(hitems);
506: break;
507:
508:
509: case WM_DESTROY:
510:
511: hitems = (HANDLE) GetWindowLong(hWnd, 0);
512: GlobalUnlock(hitems);
513: GlobalFree(hitems);
514:
515: SetWindowLong(hWnd, 0, 0L);
516: break;
517:
518: case SM_NEW:
519: hitems = (HANDLE) GetWindowLong(hWnd, 0);
520: if (hitems != NULL) {
521: GlobalFree(hitems);
522: }
523: hitems = (HANDLE) wParam;
524: if (hitems == NULL) {
525: SetWindowLong(hWnd, 0, 0L);
526: InvalidateRect(hWnd, NULL, TRUE);
527: break;
528: }
529: plist = (PILIST) GlobalLock(hitems);
530: if (plist == NULL) {
531: SetWindowLong(hWnd, 0, 0L);
532: InvalidateRect(hWnd, NULL, TRUE);
533: break;
534: }
535: plist->selitem = -1;
536: StatusResize(hWnd, plist);
537: GlobalUnlock(hitems);
538: SetWindowLong(hWnd, 0, (LONG)hitems);
539: InvalidateRect(hWnd, NULL, TRUE);
540: break;
541:
542: case SM_SETTEXT:
543: hitems = (HANDLE) GetWindowLong(hWnd, 0);
544: if (hitems == NULL) {
545: break;
546: }
547: plist = (PILIST) GlobalLock(hitems);
548: ip = StatusGetItem(plist, wParam);
549: if (ip != NULL) {
550: if (lParam == 0) {
551: ip->text[0] = '\0';
552: } else {
553: strncpy(ip->text, (LPSTR) lParam, SF_MAXLABEL);
554: ip->text[SF_MAXLABEL] = '\0';
555: }
556:
557: /* if this is a variable width field, we need to redo
558: * all size calcs in case the field width has changed.
559: * in that case, we need to repaint the entire window
560: * and not just this field - so set rc to indicate the
561: * area to be redrawn.
562: */
563: if (ip->flags & SF_VAR) {
564: StatusResize(hWnd, plist);
565: GetClientRect(hWnd, &rc);
566: RedrawWindow(hWnd, &rc, NULL,
567: RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW);
568: } else {
569: /* instead of just invalidating the window, we can
570: * force the window to be repainted now. This is
571: * essential for status updates during a busy
572: * loop when no messages are being processed,
573: * but we should still update the user on what's
574: * happening.
575: */
576: RedrawWindow(hWnd, &ip->rc, NULL,
577: RDW_INVALIDATE|RDW_NOERASE|RDW_UPDATENOW);
578: }
579:
580: }
581: GlobalUnlock(hitems);
582: break;
583:
584: default:
585: return(DefWindowProc(hWnd, message, wParam, lParam));
586: }
587: return 0;
588: }
589:
590: /***************************************************************************
591: * Function: StatusResize
592: *
593: * Purpose:
594: *
595: * Position the labels and buttons within the status window
596: */
597: void
598: StatusResize(HWND hWnd, PILIST iplistp)
599: {
600: RECT rc;
601: int curpos_right, curpos_left;
602: int height, width;
603: int i;
604: PSTATEL ip;
605:
606:
607: if (iplistp == NULL) {
608: return;
609: }
610: GetClientRect(hWnd, &rc);
611: curpos_left = rc.left + status_charwidth / 2;
612: curpos_right = rc.right - (status_charwidth / 2);
613:
614: /* loop through all items setting their position rects.
615: * items are flagged as being left or right. We place them
616: * in order starting at the left and the right, with a single
617: * char's width between each item
618: */
619: for (i = 0; i < iplistp->nitems; i++) {
620: ip = &iplistp->statels[i];
621:
622: width = StatusCalcWidth(hWnd, ip);
623: height = StatusCalcHeight(hWnd, ip);
624: ip->rc.top = (rc.bottom - height) / 2;
625: ip->rc.bottom = ip->rc.top + height;
626:
627: /* see if this item fits. Items that partially fit
628: * are placed reduced in size.
629: */
630: if (ip->flags & SF_LEFT) {
631:
632: if (curpos_left+width >= curpos_right) {
633: /* doesn't completely fit-does it partly? */
634: if ((curpos_left + 1) >= curpos_right){
635:
636: /* no - this item does not fit */
637: ip->rc.left = 0;
638: ip->rc.right = 0;
639: } else {
640: /* partial fit */
641: ip->rc.left = curpos_left;
642: ip->rc.right = curpos_right - 1;
643: curpos_left = curpos_right;
644: }
645: } else {
646: /* complete fit */
647: ip->rc.left = curpos_left;
648: ip->rc.right = curpos_left + width;
649: curpos_left += width + 1;
650: }
651: } else {
652:
653: /* same size check for right-aligned items */
654: if (curpos_right-width <= curpos_left) {
655:
656: /* partial fit ? */
657: if (curpos_right <= curpos_left+1) {
658: ip->rc.left = 0;
659: ip->rc.right = 0;
660: } else {
661: /* yes - partial fit */
662: ip->rc.left = curpos_left + 1;
663: ip->rc.right = curpos_right;
664: curpos_right = curpos_left;
665: }
666: } else {
667: /* complete fit */
668: ip->rc.right = curpos_right;
669: ip->rc.left = curpos_right - width;
670: curpos_right -= (width + 1);
671: }
672: }
673: }
674: }
675:
676:
677: /***************************************************************************
678: * Function: StatusPaint
679: *
680: * Purpose:
681: *
682: * Paint the status window
683: */
684: void
685: StatusPaint(HWND hWnd, PILIST iplistp)
686: {
687: RECT rc;
688: HDC hDC;
689: PAINTSTRUCT ps;
690: int i;
691: PSTATEL ip;
692: HPEN hpenOld;
693:
694: GetClientRect(hWnd, &rc);
695: hDC = BeginPaint(hWnd, &ps);
696: InitDC(hDC);
697:
698: RaiseRect(hDC, &rc);
699: if (iplistp == NULL) {
700: EndPaint(hWnd, &ps);
701: return;
702: }
703: for (i =0; i < iplistp->nitems; i++) {
704: ip = &iplistp->statels[i];
705:
706: if (ip->rc.left == ip->rc.right) {
707: continue;
708: }
709: if (ip->type == SF_STATIC) {
710: if (ip->flags & SF_RAISE) {
711: RaiseRect(hDC, &ip->rc);
712: } else if (ip->flags & SF_LOWER) {
713: LowerRect(hDC, &ip->rc);
714: }
715: rc = ip->rc;
716: rc.left += (status_charwidth / 2);
717: rc.right--;
718: rc.top++;
719: rc.bottom--;
720: hpenOld = SelectObject(hDC, hpenNeutral);
721: Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
722: SelectObject(hDC, hpenOld);
723: DrawText(hDC, ip->text, lstrlen(ip->text), &rc,
724: DT_LEFT | DT_VCENTER);
725: } else {
726: StatusButtonUp(hDC, ip);
727: }
728: }
729:
730: EndPaint(hWnd, &ps);
731: }
732:
733: /***************************************************************************
734: * Function: RaiseRect
735: *
736: * Purpose:
737: *
738: */
739: void
740: RaiseRect(HDC hDC, LPRECT rcp)
741: {
742: TopLeft(hDC, rcp, hpenHilight, FALSE);
743: BottomRight(hDC, rcp, hpenLowlight, FALSE);
744: }
745:
746: /***************************************************************************
747: * Function: LowerRect
748: *
749: * Purpose:
750: *
751: */
752: void
753: LowerRect(HDC hDC, LPRECT rcp)
754: {
755: TopLeft(hDC, rcp, hpenLowlight, FALSE);
756: BottomRight(hDC, rcp, hpenHilight, FALSE);
757: }
758:
759: /***************************************************************************
760: * Function: StatusButtonUp
761: *
762: * Purpose:
763: *
764: */
765: void
766: StatusButtonUp(HDC hDC, PSTATEL ip)
767: {
768: RECT rc;
769: HPEN hpenOld;
770:
771: rc = ip->rc;
772: TopLeft(hDC, &rc, hpenBlack, TRUE);
773: BottomRight(hDC, &rc, hpenBlack, FALSE);
774:
775: rc.top++;
776: rc.bottom--;
777: rc.left++;
778: rc.right--;
779: TopLeft(hDC, &rc, hpenHilight, FALSE);
780: BottomRight(hDC, &rc, hpenLowlight, TRUE);
781:
782: rc.top++;
783: rc.bottom--;
784: rc.left++;
785: rc.right--;
786: BottomRight(hDC, &rc, hpenLowlight, TRUE);
787: rc.bottom--;
788: rc.right--;
789: hpenOld = SelectObject(hDC, hpenNeutral);
790: Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
791: SelectObject(hDC, hpenOld);
792: DrawText(hDC, ip->text, lstrlen(ip->text), &rc, DT_CENTER | DT_VCENTER);
793: }
794:
795: /***************************************************************************
796: * Function: StatusButtonDown
797: *
798: * Purpose:
799: *
800: */
801: void
802: StatusButtonDown(HDC hDC, PSTATEL ip)
803: {
804: RECT rc;
805: HPEN hpenOld;
806:
807: rc = ip->rc;
808: TopLeft(hDC, &rc, hpenBlack, TRUE);
809: BottomRight(hDC, &rc, hpenBlack, FALSE);
810:
811: rc.top++;
812: rc.bottom--;
813: rc.left++;
814: rc.right--;
815: TopLeft(hDC, &rc, hpenLowlight, TRUE);
816: rc.top++;
817: rc.left++;
818: TopLeft(hDC, &rc, hpenNeutral, TRUE);
819: rc.top++;
820: rc.left++;
821: TopLeft(hDC, &rc, hpenNeutral, TRUE);
822: rc.top++;
823: rc.left++;
824: hpenOld = SelectObject(hDC, hpenNeutral);
825: Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
826: SelectObject(hDC, hpenOld);
827: DrawText(hDC, ip->text, lstrlen(ip->text), &rc, DT_CENTER | DT_VCENTER);
828: }
829:
830: /***************************************************************************
831: * Function: TopLeft
832: *
833: * Purpose:
834: *
835: */
836: void
837: TopLeft(HDC hDC, LPRECT rcp, HPEN hpen, BOOL bCorners)
838: {
839: HPEN hpenOld;
840: int x, y;
841:
842: hpenOld = SelectObject(hDC, hpen);
843: x = rcp->right - 1;
844: y = rcp->bottom;
845: if (!bCorners) {
846: x--;
847: y--;
848: }
849: MoveToEx(hDC, x, rcp->top, NULL);
850: LineTo(hDC, rcp->left, rcp->top);
851: LineTo(hDC, rcp->left, y);
852: SelectObject(hDC, hpenOld);
853: }
854:
855: /***************************************************************************
856: * Function: BottomRight
857: *
858: * Purpose:
859: *
860: */
861: void
862: BottomRight(HDC hDC, LPRECT rcp, HPEN hpen, BOOL bCorners)
863: {
864: HPEN hpenOld;
865: int x, y;
866:
867: hpenOld = SelectObject(hDC, hpen);
868: x = rcp->left - 1;
869: y = rcp->top;
870: if (!bCorners) {
871: x++;
872: y++;
873: }
874: MoveToEx(hDC, rcp->right-1, y, NULL);
875: LineTo(hDC, rcp->right-1, rcp->bottom-1);
876: LineTo(hDC, x, rcp->bottom-1);
877: SelectObject(hDC, hpenOld);
878: }
879:
880: /***************************************************************************
881: * Function: StatusGetItem
882: *
883: * Purpose:
884: *
885: */
886: PSTATEL
887: StatusGetItem(PILIST plist, int id)
888: {
889: int i;
890:
891: if (plist == NULL) {
892: return(NULL);
893: }
894: for (i = 0; i < plist->nitems; i++) {
895: if (plist->statels[i].id == id) {
896: return(&plist->statels[i]);
897: }
898: }
899: return(NULL);
900: }
901:
902: /***************************************************************************
903: * Function: StatusCalcWidth
904: *
905: * Purpose:
906: *
907: * Calculate the width of a given field. This is the width in characters
908: * multiplied by the average character width, plus a few units for
909: * borders.
910: *
911: * If SF_VAR is set, this field size varies depending on the text, so
912: * we use GetTextExtent for the field size. If SF_VAR is selected, the caller
913: * can specify that the size is not to exceed the (width * avecharwidth)
914: * size (using SF_SZMAX) or that it is not be less than it (SF_SZMIN).
915: */
916: int
917: StatusCalcWidth(HWND hWnd, PSTATEL ip)
918: {
919: int ch_size, t_size;
920: SIZE sz;
921: HDC hDC;
922:
923: ch_size = ip->width * status_charwidth;
924: if (ip->flags & SF_VAR) {
925: hDC = GetDC(hWnd);
926: InitDC(hDC);
927: GetTextExtentPoint(hDC, ip->text, lstrlen(ip->text), &sz);
928: ReleaseDC(hWnd, hDC);
929: t_size = sz.cx;
930:
931: /*
932: * check this size against min/max size if
933: * requested
934: */
935:
936: if (ip->flags & SF_SZMIN) {
937: if (ch_size > t_size) {
938: t_size = ch_size;
939: }
940: }
941: if (ip->flags & SF_SZMAX) {
942: if (ch_size < t_size) {
943: t_size = ch_size;
944: }
945: }
946: ch_size = t_size;
947: }
948:
949: if (ch_size != 0) {
950: if (ip->type == SF_BUTTON) {
951: return(ch_size+6);
952: } else {
953: return(ch_size+4);
954: }
955: } else {
956: return(0);
957: }
958: }
959:
960: /***************************************************************************
961: * Function: StatusCalcHeight
962: *
963: * Purpose:
964: *
965: * Calculate the height of a given field
966: */
967: int
968: StatusCalcHeight(HWND hWnd, PSTATEL ip)
969: {
970: int size;
971:
972: size = status_charheight;
973: if (ip->type == SF_BUTTON) {
974: return(size + 6);
975: } else {
976: return(size + 2);
977: }
978: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.