File:  [OS/2 SDKs] / pmsdk / samples / petzold / chap14 / sqbtn.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:28:28 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: pmsdk-1989, HEAD
Microsoft OS/2 SDK PM 02-24-1989

/*----------------------------------------------------------------
   SQBTN.C -- Contains window procedure for square 3D push button
  ----------------------------------------------------------------*/

#define INCL_WIN
#define INCL_GPI
#include <os2.h>
#include <malloc.h>
#include <string.h>

#define LCID_ITALIC 1L

               /*--------------------------------------------------
                  Structure for storing data unique to each window
		 --------------------------------------------------*/
typedef struct
     {
     PSZ  pszText ;
     BOOL fHaveCapture ;
     BOOL fHaveFocus ;
     BOOL fInsideRect ;
     BOOL fSpaceDown ;
     }
     SQBTN ;

typedef SQBTN FAR *PSQBTN ;

MRESULT EXPENTRY SqBtnWndProc (HWND, USHORT, MPARAM, MPARAM) ;
VOID             DrawButton   (HWND, HPS, PSQBTN) ;

HAB  hab ;

          /*--------------------------------------------------------
             RegisterSqBtnClass function available to other modules
            --------------------------------------------------------*/

BOOL RegisterSqBtnClass (HAB habIn)
     {
     hab = habIn ;

     return WinRegisterClass (hab, "SqBtn", SqBtnWndProc,
                              CS_SIZEREDRAW, sizeof (PSQBTN)) ;
     }

          /*-------------------------------------------
             String functions that accept far pointers
            -------------------------------------------*/

USHORT fstrlen (PCHAR pch)
     {
     USHORT usLen ;
     for (usLen = 0 ; pch[usLen] ; usLen++) ;
     return usLen ;
     }

PCHAR fstrcpy (PCHAR pchDst, PCHAR pchSrc)
     {
     USHORT usIndex ;
     for (usIndex = 0 ; pchDst[usIndex] = pchSrc[usIndex] ; usIndex++) ;
     return pchDst ;
     }

          /*-------------------------------
             SqBtnWndProc window procedure
            -------------------------------*/

MRESULT EXPENTRY SqBtnWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
     {
     BOOL          fTestInsideRect ;
     HPS           hps ;
     PCREATESTRUCT pcrst ;
     POINTL        ptl ;
     PSQBTN        pSqBtn ;
     PWNDPARAMS    pwprm ;
     RECTL         rcl ;

     pSqBtn = WinQueryWindowPtr (hwnd, 0) ;

     switch (msg)
          {
          case WM_CREATE:
               pSqBtn = _fmalloc (sizeof (SQBTN)) ;

                         // Initialize structure

               pSqBtn->fHaveCapture = FALSE ;
               pSqBtn->fHaveFocus   = FALSE ;
               pSqBtn->fInsideRect  = FALSE ;
               pSqBtn->fSpaceDown   = FALSE ;

                         // Get window text from creation structure

               pcrst = (PCREATESTRUCT) PVOIDFROMMP (mp2) ;

               pSqBtn->pszText = _fmalloc (1 + fstrlen (pcrst->pszText)) ;
               fstrcpy (pSqBtn->pszText, pcrst->pszText) ;

               WinSetWindowPtr (hwnd, 0, pSqBtn) ;
               return 0 ;

          case WM_SETWINDOWPARAMS:
               pwprm = (PWNDPARAMS) PVOIDFROMMP (mp1) ;

                         // Get window text from window parameter structure

               if (pwprm->fsStatus & WPM_TEXT)
                    {
                    _ffree (pSqBtn->pszText) ;
                    pSqBtn->pszText = _fmalloc (1 + pwprm->cchText) ;
                    fstrcpy (pSqBtn->pszText, pwprm->pszText) ;
                    }
               return 1 ;

          case WM_QUERYWINDOWPARAMS:
               pwprm == (PWNDPARAMS) PVOIDFROMMP (mp1) ;

                         // Set window parameter structure fields

               if (pwprm->fsStatus & WPM_CCHTEXT)
                    pwprm->cchText = fstrlen (pSqBtn->pszText) ;

               if (pwprm->fsStatus & WPM_TEXT)
                    fstrcpy (pwprm->pszText, pSqBtn->pszText) ;

               if (pwprm->fsStatus & WPM_CBPRESPARAMS)
                    pwprm->cbPresParams = 0 ;

               if (pwprm->fsStatus & WPM_PRESPARAMS)
                    pwprm->pPresParams = NULL ;

               if (pwprm->fsStatus & WPM_CBCTLDATA)
                    pwprm->cbCtlData = 0 ;

               if (pwprm->fsStatus & WPM_CTLDATA)
                    pwprm->pCtlData = NULL ;

               return 1 ;

          case WM_BUTTON1DOWN:
               WinSetFocus (HWND_DESKTOP, hwnd) ;
               WinSetCapture (HWND_DESKTOP, hwnd) ;
               pSqBtn->fHaveCapture = TRUE ;
               pSqBtn->fInsideRect  = TRUE ;
               WinInvalidateRect (hwnd, NULL, FALSE) ;
               return 0 ;

          case WM_MOUSEMOVE:
               if (!pSqBtn->fHaveCapture)
                    break ;

               WinQueryWindowRect (hwnd, &rcl) ;
               ptl.x = MOUSEMSG(&msg)->x ;
               ptl.y = MOUSEMSG(&msg)->y ;

                         // Test if mouse pointer is still in window

               fTestInsideRect = WinPtInRect (hab, &rcl, &ptl) ;

               if (pSqBtn->fInsideRect != fTestInsideRect)
                    {
                    pSqBtn->fInsideRect = fTestInsideRect ;
                    WinInvalidateRect (hwnd, NULL, FALSE) ;
                    }
               break ;

          case WM_BUTTON1UP:
               if (!pSqBtn->fHaveCapture)
                    break ;

               WinSetCapture (HWND_DESKTOP, NULL) ;
               pSqBtn->fHaveCapture = FALSE ;
               pSqBtn->fInsideRect  = FALSE ;

               WinQueryWindowRect (hwnd, &rcl) ;
               ptl.x = MOUSEMSG(&msg)->x ;
               ptl.y = MOUSEMSG(&msg)->y ;

                         // Post WM_COMMAND if mouse pointer is in window

               if (WinPtInRect (hab, &rcl, &ptl))
                    WinPostMsg (WinQueryWindow (hwnd, QW_OWNER, FALSE),
                         WM_COMMAND,
                         MPFROMSHORT (WinQueryWindowUShort (hwnd, QWS_ID)),
                         MPFROM2SHORT (CMDSRC_OTHER, TRUE)) ;

               WinInvalidateRect (hwnd, NULL, FALSE) ;
               return 0 ;

          case WM_ENABLE:
               WinInvalidateRect (hwnd, NULL, FALSE) ;
               return 0 ;

          case WM_SETFOCUS:
               pSqBtn->fHaveFocus = SHORT1FROMMP (mp2) ;
               WinInvalidateRect (hwnd, NULL, FALSE) ;
               return 0 ;

          case WM_CHAR:
               if (!(CHARMSG(&msg)->fs & KC_VIRTUALKEY) ||
                     CHARMSG(&msg)->vkey != VK_SPACE    ||
                     CHARMSG(&msg)->fs & KC_PREVDOWN)
                    break ;

                         // Post WM_COMMAND when space bar is released

               if (!(CHARMSG(&msg)->fs & KC_KEYUP))
                    pSqBtn->fSpaceDown = TRUE ;
               else
                    {
                    pSqBtn->fSpaceDown = FALSE ;
                    WinPostMsg (WinQueryWindow (hwnd, QW_OWNER, FALSE),
                         WM_COMMAND,
                         MPFROMSHORT (WinQueryWindowUShort (hwnd, QWS_ID)),
                         MPFROM2SHORT (CMDSRC_OTHER, FALSE)) ;
                    }
               WinInvalidateRect (hwnd, NULL, FALSE) ;
               return 0 ;

          case WM_PAINT:
               hps = WinBeginPaint (hwnd, NULL, NULL) ;
               DrawButton (hwnd, hps, pSqBtn) ;
               WinEndPaint (hps) ;
               return 0 ;

          case WM_DESTROY:
               _ffree (pSqBtn->pszText) ;
               _ffree (pSqBtn) ;
               return 0 ;
          }
     return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
     }

          /*--------------------------------------------------------
             Draws filled and outlined polygon (used by DrawButton)
            --------------------------------------------------------*/

VOID Polygon (HPS hps, LONG lPoints, POINTL aptl[], LONG lColor)
     {
               // Draw interior in specified color

     GpiSavePS (hps) ;
     GpiSetColor (hps, lColor) ;

     GpiBeginArea (hps, BA_NOBOUNDARY | BA_ALTERNATE) ;
     GpiMove (hps, aptl) ;
     GpiPolyLine (hps, lPoints - 1, aptl + 1) ;
     GpiEndArea (hps) ;

     GpiRestorePS (hps, -1L) ;

               // Draw boundary in default color

     GpiMove (hps, aptl + lPoints - 1) ;
     GpiPolyLine (hps, lPoints, aptl) ;
     }

          /*---------------------
             Draws Square Button
            ---------------------*/

VOID DrawButton (HWND hwnd, HPS hps, PSQBTN pSqBtn)
     {
     FATTRS      fat ;
     FONTMETRICS fm ;
     HDC         hdc ;
     LONG        lColor, lHorzRes, lVertRes, cxEdge, cyEdge ;
     POINTL      aptl[10], aptlTextBox[TXTBOX_COUNT], ptlShadow, ptlText ;
     RECTL       rcl ;

               // Find 2 millimeter edge width in pixels

     hdc = GpiQueryDevice (hps) ;
     DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &lHorzRes) ;
     DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION,   1L, &lVertRes) ;

     cxEdge = lHorzRes / 500 ;
     cyEdge = lVertRes / 500 ;

               // Set up coordinates for drawing the button

     WinQueryWindowRect (hwnd, &rcl) ;

     aptl[0].x = 0 ;                    aptl[0].y = 0 ;
     aptl[1].x = cxEdge ;               aptl[1].y = cyEdge ;
     aptl[2].x = rcl.xRight - cxEdge ;  aptl[2].y = cyEdge ;
     aptl[3].x = rcl.xRight - 1 ;       aptl[3].y = 0 ;
     aptl[4].x = rcl.xRight - 1 ;       aptl[4].y = rcl.yTop - 1 ;
     aptl[5].x = rcl.xRight - cxEdge ;  aptl[5].y = rcl.yTop - cyEdge ;
     aptl[6].x = cxEdge ;               aptl[6].y = rcl.yTop - cyEdge ;
     aptl[7].x = 0 ;                    aptl[7].y = rcl.yTop - 1 ;
     aptl[8].x = 0 ;                    aptl[8].y = 0 ;
     aptl[9].x = cxEdge ;               aptl[9].y = cyEdge ;

               // Paint edges at bottom and right side

     GpiSetColor (hps, CLR_BLACK) ;
     lColor = (pSqBtn->fInsideRect || pSqBtn->fSpaceDown) ?
                              CLR_PALEGRAY : CLR_DARKGRAY ;
     Polygon (hps, 4L, aptl + 0, lColor) ;
     Polygon (hps, 4L, aptl + 2, lColor) ;

               // Paint edges at top and left side

     lColor = (pSqBtn->fInsideRect || pSqBtn->fSpaceDown) ?
                              CLR_DARKGRAY : CLR_WHITE ;
     Polygon (hps, 4L, aptl + 4, lColor) ;
     Polygon (hps, 4L, aptl + 6, lColor) ;

               // Paint interior area

     GpiSavePS (hps) ;
     GpiSetColor (hps, (pSqBtn->fInsideRect || pSqBtn->fSpaceDown) ?
                              CLR_DARKGRAY : CLR_PALEGRAY) ;
     GpiMove (hps, aptl + 1) ;
     GpiBox (hps, DRO_FILL, aptl + 5, 0L, 0L) ;
     GpiRestorePS (hps, -1L) ;
     GpiBox (hps, DRO_OUTLINE, aptl + 5, 0L, 0L) ;

               // If button has focus, use italic font

     GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm) ;

     if (pSqBtn->fHaveFocus)
          {
          fat.usRecordLength  = sizeof fat ;
          fat.fsSelection     = FATTR_SEL_ITALIC ;
          fat.lMatch          = 0 ;
          fat.idRegistry      = fm.idRegistry ;
          fat.usCodePage      = fm.usCodePage ;
          fat.lMaxBaselineExt = fm.lMaxBaselineExt ;
          fat.lAveCharWidth   = fm.lAveCharWidth ;
          fat.fsType          = 0 ;
          fat.fsFontUse       = 0 ;
          strcpy (fat.szFacename, fm.szFacename) ;

          GpiCreateLogFont (hps, NULL, LCID_ITALIC, &fat) ;
          GpiSetCharSet (hps, LCID_ITALIC) ;
          }
               // Calculate text position

     GpiQueryTextBox (hps, (LONG) fstrlen (pSqBtn->pszText), pSqBtn->pszText,
                           TXTBOX_COUNT, aptlTextBox) ;

     ptlText.x = (rcl.xRight - aptlTextBox[TXTBOX_CONCAT].x) / 2 ;
     ptlText.y = (rcl.yTop   - aptlTextBox[TXTBOX_TOPLEFT].y -
                               aptlTextBox[TXTBOX_BOTTOMLEFT].y) / 2 ;

     ptlShadow.x = ptlText.x + fm.lAveCharWidth   / 3 ;
     ptlShadow.y = ptlText.y - fm.lMaxBaselineExt / 8 ;

               // Display text shadow in black, and text in white

     GpiSetColor (hps, CLR_BLACK) ;
     GpiCharStringAt (hps, &ptlShadow, (LONG) fstrlen (pSqBtn->pszText),
                                       pSqBtn->pszText) ;
     GpiSetColor (hps, CLR_WHITE) ;
     GpiCharStringAt (hps, &ptlText, (LONG) fstrlen (pSqBtn->pszText),
                                     pSqBtn->pszText) ;

               // X out button if the window is not enabled

     if (!WinIsWindowEnabled (hwnd))
          {
          GpiMove (hps, aptl + 1) ;
          GpiLine (hps, aptl + 5) ;
          GpiMove (hps, aptl + 2) ;
          GpiLine (hps, aptl + 6) ;
          }
               // Clean up

     if (pSqBtn->fHaveFocus)
          {
          GpiSetCharSet (hps, LCID_DEFAULT) ;
          GpiDeleteSetId (hps, LCID_ITALIC) ;
          }
     }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.