home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / bio / wndproc.c < prev   
Encoding:
C/C++ Source or Header  |  1990-07-09  |  17.4 KB  |  527 lines

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