--- pmsdk/samples/bio/wndproc.c 2018/08/09 12:28:13 1.1 +++ pmsdk/samples/bio/wndproc.c 2018/08/09 12:28:34 1.1.1.2 @@ -1,7 +1,49 @@ +/* wndproc.c -- Window handling routines + Created by Microsoft Corporation, 1989 +*/ +#define INCL_GPI +#define INCL_WIN +#include + +#include "bio.h" +#include +#include + +/* Read-only global variables */ +extern HAB hAB; +extern HWND hwndApp; +extern HWND hwndAppFrame, hwndKidFrame; +extern char szAppName[]; +extern PFNWP OldFrameWndProc; + +/* Write-once Global variables */ +LONG Color[] = {CLR_RED, CLR_GREEN, CLR_BLUE}; +FONTMETRICS tmFontInfo; +SHORT cxLegendField; +SHORT cxDateField; +/* parameter used when creating a device context for a memory device */ +PSZ dcdatablk[9] = {(PSZ)0 + ,(PSZ)"DISPLAY" + ,(PSZ)0 + ,(PSZ)0 + ,(PSZ)0 + ,(PSZ)0 + ,(PSZ)0 + ,(PSZ)0 + ,(PSZ)0 + }; + +/* Read-Write global variables */ +double Born; +long Day, SelectDay; +BOOL bKid = TRUE; +BOOL bBorn = TRUE; +RECTL rclClient; +int LinesPerPage; +void BioGetDate(HWND); + /* BioWndProc() - Parent WndProc message processing routine. * -* Created by Microsoft Corp., 1988 -* * Purpose: * WndProc callback function to handle all messages for parent window. * @@ -12,20 +54,20 @@ * mp2 - Extra message-dependent info * * Globals (modified): -* Born - Bithdate in julian days. Read from WIN.INI. -* SelectDay - Current day being tracked, day is highlighted. Is -* in units of days from birth date. Date of present -* day initially used in WM_CREATE. +* Born - Birthdate in julian days. Read from WIN.INI. +* SelectDay - Current day being tracked, day is highlighted. +* Value is days from birthdate. +* Initialized to current day in WM_CREATE processing. * daylight - Defined by environment string TZ. If no such string, * timezone default TZ=PST8PDT used. If daylight field is * used, daylight time correction will occur. See * documentation of tzset() C run-time function. * Day - Day number from date born which is top line being * displayed. Initially three days before SelectDay. -* bKid - Boolean indicating whether child window legend is visible. +* bKid - Boolean indicating whether legend is visible. * bBorn - Boolean indicating whether valid birtdate entered or * defined in WIN.INI. Nothing graphed until valid. -* rectClient - Size of client area defined by WM_SIZE message +* rclClient - Size of client area defined by WM_SIZE message * LinesPerPage - Number of system font lines on client area, defined * by WM_SIZE message handling * Color[] - Set of colored pens used to identify cycles. @@ -35,7 +77,7 @@ * hAB - Handle to the Anchor Block * hwndAppFrame - Window handle of parent window's frame * hwndKidFrame - Handle to child window used for showing/moving legend. -* szAppName[] - RC file program name (Biorhythm). +* szAppName[] - RC file program name (Biorhythm). * * Description: * Handle all messages for the parent window. @@ -45,74 +87,33 @@ * */ -#define INCL_GPI -#define INCL_WIN -#include - -#include "bio.h" -#include -#include - -/* Read-only global variables */ -extern HAB hAB; -extern HWND hwndApp; -extern HWND hwndAppFrame, hwndKidFrame; -extern char szAppName[]; - -/* Write-once Global variables */ -LONG Color[] = {CLR_RED, CLR_GREEN, CLR_BLUE}; -FONTMETRICS tmFontInfo; - -/* Read-Write global variables */ -double Born; -long Day, SelectDay; -BOOL bKid = TRUE; -BOOL bBorn = TRUE; -RECTL rectClient; -int LinesPerPage; - -MRESULT FAR PASCAL BioWndProc( hWnd, message, mp1, mp2 ) +MRESULT CALLBACK BioWndProc( hWnd, message, mp1, mp2 ) HWND hWnd; USHORT message; MPARAM mp1; MPARAM mp2; { - /* Procedures which make up the window class. */ - int year, month, iDay, i; - double day; - HPS hPS; + int iDay, i; + HPS hPS; + HPS hMemPS; RECTL rc; + POINTL ptlTextBox[5]; + SIZEL pgsi; + HDC hdcMem; + HBITMAP hbm; + BITMAPINFOHEADER bmih; + POINTL ptlPoints[3]; switch( message ) { case WM_CREATE: - /* Read in birth date from OS2.INI. Error value is 12-31-1899, - which is out of range for valid entries. */ - year = WinQueryProfileInt( hAB, szAppName, "Year", 1899 ); - month = WinQueryProfileInt( hAB, szAppName, "Month", 12 ); - day = (double)WinQueryProfileInt( hAB, szAppName, "Day", 31 ); - /* Compute date of birth in julian days */ - Born = julian( year, month, day ); - - /* Get time zone environment information */ - tzset(); - /* System clock starts 1-1-1970. Get julian date then and how many - days have elapsed since, so that number of days since birth date - can be determined */ - SelectDay = (long)(julian( 1970, 1, 1.0 ) + - (double)((time(NULL) - timezone + (long)daylight*3600)/86400) - - Born); - - /* If no valid OS2.INI info then automatically bring up dialog box */ - if (year < 1900) { - bBorn = FALSE; - WinPostMsg( hWnd, WM_COMMAND, (MPARAM)MAKEULONG(IDDATES, 0), 0L ); - } + BioGetDate(hWnd); - /* Put date of the day three lines down on display */ + /* Put date of the day three lines down on display */ Day = SelectDay - 3; + /* Initially set elevator */ iDay = (int)(Day/365); WinSendMsg( WinWindowFromID( WinQueryWindow(hWnd,QW_PARENT,FALSE), @@ -121,7 +122,14 @@ MPARAM mp2; /* Get System font text metrics */ hPS = WinGetPS( hWnd ); - GpiQueryFontMetrics( hPS, (LONG)sizeof tmFontInfo, &tmFontInfo ); + GpiQueryFontMetrics( hPS, (LONG)sizeof tmFontInfo, &tmFontInfo ); + /* Get sizes of long strings to be used as yard sticks for sizing + windows and objects. This is necessary because of new system + proportional fonts. */ + GpiQueryTextBox( hPS, 10L, "Emotional ", TXTBOX_COUNT, ptlTextBox ); + cxLegendField = (SHORT)ptlTextBox[TXTBOX_CONCAT].x; + GpiQueryTextBox( hPS, 10L, "W 99-99-99", TXTBOX_COUNT, ptlTextBox ); + cxDateField = (SHORT)ptlTextBox[TXTBOX_CONCAT].x; WinReleasePS( hPS ); break; @@ -131,7 +139,7 @@ MPARAM mp2; case WM_COMMAND: switch (LOUSHORT(mp1)) { - case IDDATES: + case IDM_DATES: if (WinDlgBox( HWND_DESKTOP, hWnd, (PFNWP)BioDlg, NULL, IDD_DATE, NULL )) { WinInvalidateRect( hWnd, NULL, FALSE ); iDay = (int)(Day/365); @@ -140,30 +148,79 @@ MPARAM mp2; } break; - case IDKID: + case IDM_LEGEND: if (bKid = !bKid) { WinSendMsg( WinWindowFromID( hwndAppFrame, FID_MENU), MM_SETITEMATTR, - (MPARAM)MAKEULONG( IDKID, TRUE ), + (MPARAM)MAKEULONG( IDM_LEGEND, TRUE ), (MPARAM)MAKEULONG( MIA_CHECKED, MIA_CHECKED) ); WinShowWindow( hwndKidFrame, TRUE ); } else { WinSendMsg( WinWindowFromID( hwndAppFrame, FID_MENU), MM_SETITEMATTR, - (MPARAM)MAKEULONG( IDKID, TRUE ), + (MPARAM)MAKEULONG( IDM_LEGEND, TRUE ), (MPARAM)MAKEULONG( MIA_CHECKED, 0) ); WinShowWindow( hwndKidFrame, FALSE ); } break; - case IDCOPY: - WinMessageBox( HWND_DESKTOP, hWnd, - (NPCH)"Coming soon to a theatre near you", - (NPCH)"BitBlt to Clipboard", NULL, - MB_OK | MB_ICONEXCLAMATION ); + case IDM_COPY: + /* Get access to clipboard. */ + WinOpenClipbrd( hAB ); + /* Wipe the slate clean. */ + WinEmptyClipbrd( hAB ); + + /* Bitmap header for bitmap the size of the window. */ + pgsi.cx = rclClient.xRight; + pgsi.cy = rclClient.yTop; + bmih.cbFix = 12; + bmih.cx = (USHORT)pgsi.cx; + bmih.cy = (USHORT)pgsi.cy; + bmih.cPlanes = 1; + bmih.cBitCount = 24; + + /* Get a memory dc. */ + hdcMem = DevOpenDC( hAB + , OD_MEMORY + , (PSZ)"*" + , 8L + , (PDEVOPENDATA)dcdatablk + , (HDC)NULL + ); + + /* Get a memory PS that will be used to manipulate image */ + hMemPS = GpiCreatePS( hAB + , hdcMem + , (PSIZEL)&pgsi + , (LONG)PU_PELS | GPIT_MICRO | GPIA_ASSOC + ); + + /* Create a bitmap to hold image */ + hbm = GpiCreateBitmap(hMemPS, &bmih, 0L, (PBYTE)NULL, (PBITMAPINFO)NULL); + /* Select bitmap into PS */ + GpiSetBitmap( hMemPS, hbm ); + /* BitBlt window client area into memory bitmap */ + ptlPoints[0].x = 0; + ptlPoints[0].y = 0; + ptlPoints[1].x = pgsi.cx; + ptlPoints[1].y = pgsi.cy; + ptlPoints[2].x = 0; + ptlPoints[2].y = 0; + hPS = WinGetPS( hWnd ); + GpiBitBlt(hMemPS, hPS, 3L, ptlPoints, ROP_SRCCOPY, BBO_OR); + WinReleasePS( hPS ); + + /* Put bitmap into the clipboard. */ + WinSetClipbrdData( hAB, (ULONG)hbm, CF_BITMAP, CFI_HANDLE ); + + /* Tidy up */ + WinCloseClipbrd( hAB ); + GpiSetBitmap( hMemPS, NULL ); + GpiDestroyPS( hMemPS ); + DevCloseDC( hdcMem ); break; - case IDABOUT: + case IDM_ABOUT: WinDlgBox( HWND_DESKTOP, hWnd, (PFNWP)About, NULL, IDD_ABOUT, NULL ); break; @@ -174,16 +231,34 @@ MPARAM mp2; break; case WM_SIZE: - WinQueryWindowRect( hWnd, &rectClient ); - LinesPerPage = (int)(rectClient.yTop / tmFontInfo.lMaxBaselineExt); + WinQueryWindowRect( hWnd, &rclClient ); + LinesPerPage = (int)(rclClient.yTop / tmFontInfo.lMaxBaselineExt); WinSetWindowPos( hwndKidFrame, NULL, 10, 10, 0, 0, SWP_MOVE ); break; case WM_CHAR: - /* Send keyboard characters to scroll bar to support scrolling, - paging, etc. */ - return WinSendMsg( WinWindowFromID( hwndAppFrame, FID_VERTSCROLL), - message, mp1, mp2 ); + /* Convert keyboard to scroll bar messages to support scrolling, + paging, etc. with keyboard interface. */ + if ( (ULONG)mp1 & KC_KEYUP ) + return WinDefWindowProc( hWnd, message, mp1, mp2 ); + switch (HIUSHORT( mp2 )) { + case VK_UP: + mp2 = (MPARAM)MAKEULONG( 0, SB_LINEUP ); + break; + case VK_DOWN: + mp2 = (MPARAM)MAKEULONG( 0, SB_LINEDOWN ); + break; + case VK_PAGEUP: + mp2 = (MPARAM)MAKEULONG( 0, SB_PAGEUP ); + break; + case VK_PAGEDOWN: + mp2 = (MPARAM)MAKEULONG( 0, SB_PAGEDOWN ); + break; + default: + return WinDefWindowProc( hWnd, message, mp1, mp2 ); + break; + } + return WinSendMsg( hWnd, WM_VSCROLL, mp1, mp2 ); break; case WM_VSCROLL: @@ -191,21 +266,21 @@ MPARAM mp2; if (!bBorn) break; /* Setup for scroll window - full width of client area is scrolled */ - WinCopyRect( hAB, &rc, &rectClient ); + WinCopyRect( hAB, &rc, &rclClient ); switch (HIUSHORT(mp2)) { case SB_LINEUP: /* Update top day of display */ Day--; - rc.yTop = rectClient.yTop - tmFontInfo.lMaxBaselineExt; - rc.yBottom = rectClient.yTop - (LinesPerPage-1) * tmFontInfo.lMaxBaselineExt + 1; + rc.yTop = rclClient.yTop - tmFontInfo.lMaxBaselineExt; + rc.yBottom = rclClient.yTop - (LinesPerPage-1) * tmFontInfo.lMaxBaselineExt + 1; WinScrollWindow( hWnd, 0, (SHORT)-tmFontInfo.lMaxBaselineExt, &rc, NULL, NULL, NULL, SW_INVALIDATERGN ); break; case SB_LINEDOWN: /* Update top day of display */ Day++; - rc.yTop = rectClient.yTop - 2*tmFontInfo.lMaxBaselineExt; - rc.yBottom = rectClient.yTop - (LinesPerPage) * tmFontInfo.lMaxBaselineExt + 1; + rc.yTop = rclClient.yTop - 2*tmFontInfo.lMaxBaselineExt; + rc.yBottom = rclClient.yTop - (LinesPerPage) * tmFontInfo.lMaxBaselineExt + 1; WinScrollWindow( hWnd, 0, (SHORT)tmFontInfo.lMaxBaselineExt, &rc, NULL, NULL, NULL, SW_INVALIDATERGN ); break; @@ -235,24 +310,24 @@ MPARAM mp2; case WM_PAINT: APPPaint( hWnd ); - break; + break; case WM_BUTTON1DOWN: - /* Don't allow any processing until valid birth date entered */ + /* Don't allow any processing until valid birthdate entered */ if (!bBorn) break; /* Unhighlight previously selected line and highlight new line */ - WinCopyRect( hAB, &rc, &rectClient ); + WinCopyRect( hAB, &rc, &rclClient ); hPS = WinGetPS( hWnd ); for(i=0; i<2; i++) { /* Make sure line is visible before (un)highlighting */ if ((SelectDay >= Day) && (SelectDay - Day < LinesPerPage-1)) { - rc.yTop = rectClient.yTop - (int)(SelectDay - Day + 1) * tmFontInfo.lMaxBaselineExt; + rc.yTop = rclClient.yTop - (int)(SelectDay - Day + 1) * tmFontInfo.lMaxBaselineExt; rc.yBottom = rc.yTop - tmFontInfo.lMaxBaselineExt + 1; WinInvertRect( hPS, &rc ); } /* New line to highlight */ - SelectDay = Day + (rectClient.yTop - HIUSHORT(mp1)) / + SelectDay = Day + (rclClient.yTop - HIUSHORT(mp1)) / tmFontInfo.lMaxBaselineExt - 1; } WinReleasePS( hPS ); @@ -260,8 +335,8 @@ MPARAM mp2; /* Draw highlight on selected day */ if ((SelectDay >= Day) && (SelectDay - Day < LinesPerPage - 1)) { - rc.xRight = rectClient.xRight; - rc.xLeft = rectClient.xLeft; + rc.xRight = rclClient.xRight; + rc.xLeft = rclClient.xLeft; } default: return WinDefWindowProc( hWnd, message, mp1, mp2 ); @@ -281,9 +356,6 @@ MPARAM mp2; * mp1 - Extra message-dependent info * mp2 - Extra message-dependent info * -* Globals (modified): -* none -* * Globals (referenced): * hwndApp - Window handle of parent window's client area * tmFontInfo - Text Metric structure defined during WM_CREATE @@ -293,16 +365,12 @@ MPARAM mp2; * Display legend information relating graph line styles to each * cyle: physical, emotional and intellectual. Notifies parent * to hide child if child window is instructed to close by user. -* -* Limits: -* N/A. -* */ /* Read-only global variables */ extern HWND hwndApp; -MRESULT FAR PASCAL KidWndProc( hWnd, message, mp1, mp2 ) +MRESULT CALLBACK KidWndProc( hWnd, message, mp1, mp2 ) HWND hWnd; USHORT message; MPARAM mp1; @@ -315,6 +383,12 @@ MPARAM mp2; switch( message ) { + case WM_CHAR: + /* Convert keyboard to scroll bar messages to support scrolling, + paging, etc. with keyboard interface. */ + WinSendMsg( hwndApp, message, mp1, mp2 ); + break; + case WM_PAINT: hPS = WinBeginPaint( hWnd, NULL, NULL ); @@ -324,7 +398,7 @@ MPARAM mp2; ptl.x = 0; ptl.y = tmFontInfo.lMaxDescender; - GpiCharStringAt( hPS, &ptl, 9L, (PCH)"Physical " ); + GpiCharStringAt( hPS, &ptl, 8L, (PCH)"Physical" ); ptl.y += tmFontInfo.lMaxBaselineExt; GpiCharStringAt( hPS, &ptl, 9L, (PCH)"Emotional" ); ptl.y += tmFontInfo.lMaxBaselineExt; @@ -332,25 +406,121 @@ MPARAM mp2; for (i=0; i<3; i++ ) { GpiSetColor( hPS, Color[i] ); - ptl.x = tmFontInfo.lAveCharWidth * 10; + ptl.x = cxLegendField; ptl.y = i * tmFontInfo.lMaxBaselineExt + tmFontInfo.lMaxBaselineExt/2; GpiMove( hPS, &ptl ); - ptl.x = tmFontInfo.lAveCharWidth * 20; + ptl.x = rc.xRight - tmFontInfo.lAveCharWidth; GpiLine( hPS, &ptl ); } WinEndPaint( hPS ); break; - - case WM_CLOSE: - WinPostMsg( hwndApp, WM_COMMAND, (MPARAM)MAKEULONG(IDKID, 0), 0L ); + case WM_BUTTON1UP: + /* Quick way to make Legend window disappear using mouse. */ + WinPostMsg( hwndApp, WM_COMMAND, (MPARAM)MAKEULONG(IDM_LEGEND, 0), 0L ); break; + case WM_TRANSLATEACCEL: + /* Change window handle. Child window's frame will block + ALT handling, so bypass frame. Return window handle + of main window's client area. Now the ALT key message + handling will be passed on up the chain of windows to + the main window's frame for proper ALT key message + handling. The main window's menu bar will highlight + even if the child window has the focus. */ + return WinDefWindowProc( hwndApp, message, mp1, mp2 ); + break; + default: return WinDefWindowProc( hWnd, message, mp1, mp2 ); break; } return( 0L ); } +/* +*/ + +/* FrameWndProc() - Subclass routine for frame. +* +* Purpose: +* Handle WM_QUERYTRACKINFO message so that a minimum horizontal and +* vertical window size can be controlled. This minimum size keeps +* the tabulated data from overlapping and leaves at least 4 rows +* of data visible. +* +* Arguments: +* hWnd - Handle of Window owning message +* message - Message itself +* mp1 - Extra message-dependent info +* mp2 - Extra message-dependent info +* +* Globals (referenced): +* OldFrameWndProc - Original Frame Window procedure. +* +* Limits: +* N/A +* +*/ + +MRESULT CALLBACK FrameWndProc( hWnd, message, mp1, mp2 ) +HWND hWnd; +USHORT message; +MPARAM mp1; +MPARAM mp2; +{ + switch( message ) + { + case WM_QUERYTRACKINFO: + (*OldFrameWndProc)( hWnd, message, mp1, mp2 ); + /* Limit vertical and horizontal minimum size. Must take into + account menu, title, border and font widths and heights for + device independence. */ + ((PTRACKINFO)mp2)->ptlMinTrackSize.x = cxDateField * 2 + cxDateField/2; + ((PTRACKINFO)mp2)->ptlMinTrackSize.y = + tmFontInfo.lMaxBaselineExt * 5 + + WinQuerySysValue( HWND_DESKTOP, SV_CYMENU ) + + WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) + + WinQuerySysValue( HWND_DESKTOP, SV_CYSIZEBORDER ) * 2 + + WinQuerySysValue( HWND_DESKTOP, SV_CYBORDER ) * 2; + return TRUE; + break; + + default: + return (*OldFrameWndProc)( hWnd, message, mp1, mp2 ); + break; + } + return( 0L ); +} + +void BioGetDate(HWND hWnd) { + int year, month; + double day; + + /* Read in birth date from OS2.INI. Error value is 12-31-1899, + which is out of range for valid entries. */ + year = WinQueryProfileInt( hAB, szAppName, "Year", 1899 ); + month = WinQueryProfileInt( hAB, szAppName, "Month", 12 ); + day = (double)WinQueryProfileInt( hAB, szAppName, "Day", 31 ); + + /* Compute date of birth in julian days */ + Born = julian( year, month, day ); + + /* Get time zone environment information */ + tzset(); + /* + System clock starts 1-1-1970. Get julian date then and how many + days have elapsed since, so that number of days since birth date + can be determined + */ + SelectDay = (long)(julian( 1970, 1, 1.0 ) + + (double)((time(NULL) - timezone + (long)daylight*3600)/86400) - + Born ); + + /* If no valid OS2.INI info then automatically bring up dialog box */ + if (year < 1900) { + bBorn = FALSE; + WinPostMsg( hWnd, WM_COMMAND, (MPARAM)MAKEULONG(IDM_DATES, 0), 0L ); + } +}