|
|
1.1 root 1: /* wndproc.c -- Window handling routines
2: Created by Microsoft, IBM Corporation, 1990
3: */
4: #define INCL_GPI
5: #define INCL_WIN
6: #include <os2.h>
7:
8: #include "bio.h"
9: #include <time.h>
10: #include <stdio.h>
11:
12: /* Read-only global variables */
13: extern HAB hAB;
14: extern HWND hwndApp;
15: extern HWND hwndAppFrame, hwndKidFrame;
16: extern char szAppName[];
17: extern PFNWP OldFrameWndProc;
18:
19: /* Write-once Global variables */
20: LONG Color[] = {CLR_RED, CLR_GREEN, CLR_BLUE};
21: FONTMETRICS tmFontInfo;
22: SHORT cxLegendField;
23: SHORT cxDateField;
24: /* parameter used when creating a device context for a memory device */
25: PSZ dcdatablk[9] = {(PSZ)0
26: ,(PSZ)"DISPLAY"
27: ,(PSZ)0
28: ,(PSZ)0
29: ,(PSZ)0
30: ,(PSZ)0
31: ,(PSZ)0
32: ,(PSZ)0
33: ,(PSZ)0
34: };
35:
36: /* Read-Write global variables */
37: double Born;
38: long Day, SelectDay;
39: BOOL bKid = TRUE;
40: BOOL bBorn = TRUE;
41: RECTL rclClient;
42: SHORT LinesPerPage;
43:
44: /* BioWndProc() - Parent WndProc message processing routine.
45: *
46: * Purpose:
47: * WndProc callback function to handle all messages for parent window.
48: *
49: * Arguments:
50: * hWnd - Handle of Window owning message
51: * message - Message itself
52: * mp1 - Extra message-dependent info
53: * mp2 - Extra message-dependent info
54: *
55: * Globals (modified):
56: * Born - Birthdate in julian days. Read from WIN.INI.
57: * SelectDay - Current day being tracked, day is highlighted.
58: * Value is days from birthdate.
59: * Initialized to current day in WM_CREATE processing.
60: * daylight - Defined by environment string TZ. If no such string,
61: * timezone default TZ=PST8PDT used. If daylight field is
62: * used, daylight time correction will occur. See
63: * documentation of tzset() C run-time function.
64: * Day - Day number from date born which is top line being
65: * displayed. Initially three days before SelectDay.
66: * bKid - Boolean indicating whether legend is visible.
67: * bBorn - Boolean indicating whether valid birtdate entered or
68: * defined in WIN.INI. Nothing graphed until valid.
69: * rclClient - Size of client area defined by WM_SIZE message
70: * LinesPerPage - Number of system font lines on client area, defined
71: * by WM_SIZE message handling
72: * Color[] - Set of colored pens used to identify cycles.
73: * tmFontInfo - Text Metric structure defined during WM_CREATE
74: *
75: * Globals (referenced):
76: * hAB - Handle to the Anchor Block
77: * hwndAppFrame - Window handle of parent window's frame
78: * hwndKidFrame - Handle to child window used for showing/moving legend.
79: * szAppName[] - RC file program name (Biorhythm).
80: *
81: * Description:
82: * Handle all messages for the parent window.
83: *
84: * Limits:
85: * N/A
86: *
87: */
88:
89:
90: MRESULT EXPENTRY BioWndProc( hWnd, message, mp1, mp2 )
91: HWND hWnd;
92: USHORT message;
93: MPARAM mp1;
94: MPARAM mp2;
95: {
96: SHORT iDay, i;
97: HPS hPS;
98: HPS hMemPS;
99: RECTL rc;
100: POINTL ptlTextBox[5];
101: SIZEL pgsi;
102: HDC hdcMem;
103: HBITMAP hbm;
104: BITMAPINFOHEADER bmih;
105: POINTL ptlPoints[3];
106:
107: switch( message )
108: {
109:
110: case WM_CREATE:
111: BioGetDate(hWnd);
112:
113: /* Put date of the day three lines down on display */
114: Day = SelectDay - 3;
115:
116: /* Initially set elevator */
117: iDay = (int)(Day/365);
118: WinSendMsg( WinWindowFromID( WinQueryWindow(hWnd,QW_PARENT,FALSE),
119: FID_VERTSCROLL),
120: SBM_SETPOS, (MPARAM)MAKEULONG(iDay, 0), 0L );
121:
122: /* Get System font text metrics */
123: hPS = WinGetPS( hWnd );
124: GpiQueryFontMetrics( hPS, (LONG)sizeof tmFontInfo, &tmFontInfo );
125: /* Get sizes of long strings to be used as yard sticks for sizing
126: windows and objects. This is necessary because of new system
127: proportional fonts. */
128: GpiQueryTextBox( hPS, 10L, "Emotional ", TXTBOX_COUNT, ptlTextBox );
129: cxLegendField = (SHORT)ptlTextBox[TXTBOX_CONCAT].x;
130: GpiQueryTextBox( hPS, 10L, "W 99-99-99", TXTBOX_COUNT, ptlTextBox );
131: cxDateField = (SHORT)ptlTextBox[TXTBOX_CONCAT].x;
132: WinReleasePS( hPS );
133: break;
134:
135: case WM_CLOSE:
136: WinPostMsg( hWnd, WM_QUIT, 0L, 0L );
137: break;
138:
139: case WM_COMMAND:
140: switch (LOUSHORT(mp1)) {
141: case IDM_DATES:
142: if (WinDlgBox( HWND_DESKTOP, hWnd, (PFNWP)BioDlg, NULL, IDD_DATE, NULL )) {
143: WinInvalidateRect( hWnd, NULL, FALSE );
144: iDay = (int)(Day/365);
145: WinSendMsg( WinWindowFromID( hwndAppFrame, FID_VERTSCROLL),
146: SBM_SETPOS, (MPARAM)MAKEULONG(iDay, 0), 0L );
147: }
148: break;
149:
150: case IDM_LEGEND:
151: if (bKid = !bKid) {
152: WinSendMsg( WinWindowFromID( hwndAppFrame, FID_MENU),
153: MM_SETITEMATTR,
154: (MPARAM)MAKEULONG( IDM_LEGEND, TRUE ),
155: (MPARAM)MAKEULONG( MIA_CHECKED, MIA_CHECKED) );
156: WinShowWindow( hwndKidFrame, TRUE );
157: } else {
158: WinSendMsg( WinWindowFromID( hwndAppFrame, FID_MENU),
159: MM_SETITEMATTR,
160: (MPARAM)MAKEULONG( IDM_LEGEND, TRUE ),
161: (MPARAM)MAKEULONG( MIA_CHECKED, 0) );
162: WinShowWindow( hwndKidFrame, FALSE );
163: }
164: break;
165:
166: case IDM_COPY:
167: /* Get access to clipboard. */
168: WinOpenClipbrd( hAB );
169: /* Wipe the slate clean. */
170: WinEmptyClipbrd( hAB );
171:
172: /* Bitmap header for bitmap the size of the window. */
173: pgsi.cx = rclClient.xRight;
174: pgsi.cy = rclClient.yTop;
175: bmih.cbFix = 12;
176: bmih.cx = (USHORT)pgsi.cx;
177: bmih.cy = (USHORT)pgsi.cy;
178: bmih.cPlanes = 1;
179: bmih.cBitCount = 24;
180:
181: /* Get a memory dc. */
182: hdcMem = DevOpenDC( hAB
183: , OD_MEMORY
184: , (PSZ)"*"
185: , 8L
186: , (PDEVOPENDATA)dcdatablk
187: , (HDC)NULL
188: );
189:
190: /* Get a memory PS that will be used to manipulate image */
191: hMemPS = GpiCreatePS( hAB
192: , hdcMem
193: , (PSIZEL)&pgsi
194: , (LONG)PU_PELS | GPIT_MICRO | GPIA_ASSOC
195: );
196:
197: /* Create a bitmap to hold image */
198: hbm = GpiCreateBitmap(hMemPS, (PBITMAPINFOHEADER2)&bmih, 0L, NULL, NULL);
199: /* Select bitmap into PS */
200: GpiSetBitmap( hMemPS, hbm );
201: /* BitBlt window client area into memory bitmap */
202: ptlPoints[0].x = 0;
203: ptlPoints[0].y = 0;
204: ptlPoints[1].x = pgsi.cx;
205: ptlPoints[1].y = pgsi.cy;
206: ptlPoints[2].x = 0;
207: ptlPoints[2].y = 0;
208: hPS = WinGetPS( hWnd );
209: GpiBitBlt(hMemPS, hPS, 3L, ptlPoints, ROP_SRCCOPY, BBO_OR);
210: WinReleasePS( hPS );
211:
212: /* Put bitmap into the clipboard. */
213: WinSetClipbrdData( hAB, (ULONG)hbm, CF_BITMAP, CFI_HANDLE );
214:
215: /* Tidy up */
216: WinCloseClipbrd( hAB );
217: GpiSetBitmap( hMemPS, NULL );
218: GpiDestroyPS( hMemPS );
219: DevCloseDC( hdcMem );
220: break;
221:
222: case IDM_ABOUT:
223: WinDlgBox( HWND_DESKTOP, hWnd, (PFNWP)About, NULL,
224: IDD_ABOUT, NULL );
225: break;
226:
227: default:
228: break;
229: }
230: break;
231:
232: case WM_SIZE:
233: WinQueryWindowRect( hWnd, &rclClient );
234: LinesPerPage = (int)(rclClient.yTop / tmFontInfo.lMaxBaselineExt);
235: WinSetWindowPos( hwndKidFrame, NULL, 10, 10, 0, 0, SWP_MOVE );
236: break;
237:
238: case WM_CHAR:
239: /* Convert keyboard to scroll bar messages to support scrolling,
240: paging, etc. with keyboard interface. */
241: if ( (ULONG)mp1 & KC_KEYUP )
242: return WinDefWindowProc( hWnd, message, mp1, mp2 );
243: switch (HIUSHORT( mp2 )) {
244: case VK_UP:
245: mp2 = (MPARAM)MAKEULONG( 0, SB_LINEUP );
246: break;
247: case VK_DOWN:
248: mp2 = (MPARAM)MAKEULONG( 0, SB_LINEDOWN );
249: break;
250: case VK_PAGEUP:
251: mp2 = (MPARAM)MAKEULONG( 0, SB_PAGEUP );
252: break;
253: case VK_PAGEDOWN:
254: mp2 = (MPARAM)MAKEULONG( 0, SB_PAGEDOWN );
255: break;
256: default:
257: return WinDefWindowProc( hWnd, message, mp1, mp2 );
258: break;
259: }
260: return WinSendMsg( hWnd, WM_VSCROLL, mp1, mp2 );
261: break;
262:
263: case WM_VSCROLL:
264: /* Don't allow any processing until valid birth date entered */
265: if (!bBorn) break;
266:
267: /* Setup for scroll window - full width of client area is scrolled */
268: WinCopyRect( hAB, &rc, &rclClient );
269: switch (HIUSHORT(mp2)) {
270: case SB_LINEUP:
271: /* Update top day of display */
272: Day--;
273: rc.yTop = rclClient.yTop - tmFontInfo.lMaxBaselineExt;
274: rc.yBottom = rclClient.yTop - (LinesPerPage-1) * tmFontInfo.lMaxBaselineExt + 1;
275: WinScrollWindow( hWnd, 0, (SHORT)-tmFontInfo.lMaxBaselineExt, &rc,
276: NULL, NULL, NULL, SW_INVALIDATERGN );
277: break;
278: case SB_LINEDOWN:
279: /* Update top day of display */
280: Day++;
281: rc.yTop = rclClient.yTop - 2*tmFontInfo.lMaxBaselineExt;
282: rc.yBottom = rclClient.yTop - (LinesPerPage) * tmFontInfo.lMaxBaselineExt + 1;
283: WinScrollWindow( hWnd, 0, (SHORT)tmFontInfo.lMaxBaselineExt, &rc,
284: NULL, NULL, NULL, SW_INVALIDATERGN );
285: break;
286: case SB_PAGEUP:
287: Day -= (LinesPerPage-1);
288: break;
289: case SB_PAGEDOWN:
290: Day += (LinesPerPage-1);
291: break;
292: case SB_SLIDERPOSITION:
293: /* Set to birthday of each year because 100 year scale maps to
294: default 100 position scroll bar */
295: Day = (long)(LOUSHORT(mp2) * 365.25);
296: break;
297: default:
298: return 0L;
299: }
300: /* Update scroll bar elevator */
301: iDay = (int)(Day/365);
302: WinSendMsg( WinWindowFromID( hwndAppFrame, FID_VERTSCROLL),
303: SBM_SETPOS, (MPARAM)MAKEULONG(iDay, 0), 0L );
304: /* All but LINEUP/DOWN need full repaint of client area */
305: if ((HIUSHORT(mp2) != SB_LINEUP) && (HIUSHORT(mp2) != SB_LINEDOWN ))
306: WinInvalidateRect( hWnd, NULL, FALSE );
307: WinUpdateWindow( hWnd );
308: break;
309:
310: case WM_PAINT:
311: APPPaint( hWnd );
312: break;
313:
314: case WM_BUTTON1DOWN:
315: /* Don't allow any processing until valid birthdate entered */
316: if (!bBorn) break;
317:
318: /* Unhighlight previously selected line and highlight new line */
319: WinCopyRect( hAB, &rc, &rclClient );
320: hPS = WinGetPS( hWnd );
321: for(i=0; i<2; i++) {
322: /* Make sure line is visible before (un)highlighting */
323: if ((SelectDay >= Day) && (SelectDay - Day < LinesPerPage-1)) {
324: rc.yTop = rclClient.yTop - (int)(SelectDay - Day + 1) * tmFontInfo.lMaxBaselineExt;
325: rc.yBottom = rc.yTop - tmFontInfo.lMaxBaselineExt + 1;
326: WinInvertRect( hPS, &rc );
327: }
328: /* New line to highlight */
329: SelectDay = Day + (rclClient.yTop - HIUSHORT(mp1)) /
330: tmFontInfo.lMaxBaselineExt - 1;
331: }
332: WinReleasePS( hPS );
333: break;
334:
335: /* Draw highlight on selected day */
336: if ((SelectDay >= Day) && (SelectDay - Day < LinesPerPage - 1)) {
337: rc.xRight = rclClient.xRight;
338: rc.xLeft = rclClient.xLeft;
339: }
340: default:
341: return WinDefWindowProc( hWnd, message, mp1, mp2 );
342: break;
343: }
344: return( 0L );
345: }
346:
347: /* KidWndProc() - Child WndProc handling legend display.
348: *
349: * Purpose:
350: * WndProc callback function to handle all messages for legend child.
351: *
352: * Arguments:
353: * hWnd - Handle of Window owning message
354: * message - Message itself
355: * mp1 - Extra message-dependent info
356: * mp2 - Extra message-dependent info
357: *
358: * Globals (referenced):
359: * hwndApp - Window handle of parent window's client area
360: * tmFontInfo - Text Metric structure defined during WM_CREATE
361: * Color[] - Set of colored pens used to identify cycles.
362: *
363: * Description:
364: * Display legend information relating graph line styles to each
365: * cyle: physical, emotional and intellectual. Notifies parent
366: * to hide child if child window is instructed to close by user.
367: */
368:
369: /* Read-only global variables */
370: extern HWND hwndApp;
371:
372: MRESULT EXPENTRY KidWndProc( hWnd, message, mp1, mp2 )
373: HWND hWnd;
374: USHORT message;
375: MPARAM mp1;
376: MPARAM mp2;
377: {
378: HPS hPS;
379: RECTL rc;
380: POINTL ptl;
381: SHORT i;
382:
383: switch( message )
384: {
385: case WM_CHAR:
386: /* Convert keyboard to scroll bar messages to support scrolling,
387: paging, etc. with keyboard interface. */
388: WinSendMsg( hwndApp, message, mp1, mp2 );
389: break;
390:
391: case WM_PAINT:
392: hPS = WinBeginPaint( hWnd, NULL, NULL );
393:
394: /* Erase client area */
395: WinQueryWindowRect( hWnd, &rc );
396: WinFillRect( hPS, &rc, CLR_PALEGRAY );
397:
398: ptl.x = 0;
399: ptl.y = tmFontInfo.lMaxDescender;
400: GpiCharStringAt( hPS, &ptl, 8L, (PCH)"Physical" );
401: ptl.y += tmFontInfo.lMaxBaselineExt;
402: GpiCharStringAt( hPS, &ptl, 9L, (PCH)"Emotional" );
403: ptl.y += tmFontInfo.lMaxBaselineExt;
404: GpiCharStringAt( hPS, &ptl, 9L, (PCH)"Intellect" );
405:
406: for (i=0; i<3; i++ ) {
407: GpiSetColor( hPS, Color[i] );
408: ptl.x = cxLegendField;
409: ptl.y = i * tmFontInfo.lMaxBaselineExt +
410: tmFontInfo.lMaxBaselineExt/2;
411: GpiMove( hPS, &ptl );
412: ptl.x = rc.xRight - tmFontInfo.lAveCharWidth;
413: GpiLine( hPS, &ptl );
414: }
415:
416: WinEndPaint( hPS );
417: break;
418:
419: case WM_BUTTON1UP:
420: /* Quick way to make Legend window disappear using mouse. */
421: WinPostMsg( hwndApp, WM_COMMAND, (MPARAM)MAKEULONG(IDM_LEGEND, 0), 0L );
422: break;
423:
424: case WM_TRANSLATEACCEL:
425: /* Change window handle. Child window's frame will block
426: ALT handling, so bypass frame. Return window handle
427: of main window's client area. Now the ALT key message
428: handling will be passed on up the chain of windows to
429: the main window's frame for proper ALT key message
430: handling. The main window's menu bar will highlight
431: even if the child window has the focus. */
432: return WinDefWindowProc( hwndApp, message, mp1, mp2 );
433: break;
434:
435: default:
436: return WinDefWindowProc( hWnd, message, mp1, mp2 );
437: break;
438: }
439: return( 0L );
440: }
441: /*
442: */
443:
444: /* FrameWndProc() - Subclass routine for frame.
445: *
446: * Purpose:
447: * Handle WM_QUERYTRACKINFO message so that a minimum horizontal and
448: * vertical window size can be controlled. This minimum size keeps
449: * the tabulated data from overlapping and leaves at least 4 rows
450: * of data visible.
451: *
452: * Arguments:
453: * hWnd - Handle of Window owning message
454: * message - Message itself
455: * mp1 - Extra message-dependent info
456: * mp2 - Extra message-dependent info
457: *
458: * Globals (referenced):
459: * OldFrameWndProc - Original Frame Window procedure.
460: *
461: * Limits:
462: * N/A
463: *
464: */
465:
466: MRESULT EXPENTRY FrameWndProc( hWnd, message, mp1, mp2 )
467: HWND hWnd;
468: USHORT message;
469: MPARAM mp1;
470: MPARAM mp2;
471: {
472: switch( message )
473: {
474: case WM_QUERYTRACKINFO:
475: (*OldFrameWndProc)( hWnd, message, mp1, mp2 );
476: /* Limit vertical and horizontal minimum size. Must take into
477: account menu, title, border and font widths and heights for
478: device independence. */
479: ((PTRACKINFO)mp2)->ptlMinTrackSize.x = cxDateField * 2 + cxDateField/2;
480: ((PTRACKINFO)mp2)->ptlMinTrackSize.y =
481: tmFontInfo.lMaxBaselineExt * 5 +
482: WinQuerySysValue( HWND_DESKTOP, SV_CYMENU ) +
483: WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) +
484: WinQuerySysValue( HWND_DESKTOP, SV_CYSIZEBORDER ) * 2 +
485: WinQuerySysValue( HWND_DESKTOP, SV_CYBORDER ) * 2;
486: return (MRESULT)TRUE;
487: break;
488:
489: default:
490: return (*OldFrameWndProc)( hWnd, message, mp1, mp2 );
491: break;
492: }
493: return( 0L );
494: }
495: /*
496: */
497:
498: VOID BioGetDate(HWND hWnd)
499: {
500: SHORT year, month;
501: double day;
502:
503: /* Read in birth date from OS2.INI. Error value is 12-31-1899,
504: which is out of range for valid entries. */
505: year = PrfQueryProfileInt( HINI_USERPROFILE, szAppName, "Year", 1899 );
506: month = PrfQueryProfileInt( HINI_USERPROFILE, szAppName, "Month", 12 );
507: day = (double)PrfQueryProfileInt( HINI_USERPROFILE, szAppName, "Day", 31 );
508:
509: /* Compute date of birth in julian days */
510: Born = julian( year, month, day );
511:
512: /* Get time zone environment information */
513: tzset();
514: /*
515: System clock starts 1-1-1970. Get julian date then and how many
516: days have elapsed since, so that number of days since birth date
517: can be determined
518: */
519: SelectDay = (long)(julian( 1970, 1, 1.0 ) +
520: (double)((time(NULL) - timezone + (long)daylight*3600)/86400) -
521: Born );
522:
523: /* If no valid OS2.INI info then automatically bring up dialog box */
524: if (year < 1900) {
525: bBorn = FALSE;
526: WinPostMsg( hWnd, WM_COMMAND, (MPARAM)MAKEULONG(IDM_DATES, 0), 0L );
527: }
528: }
529: /*
530: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.