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