Annotation of pmsdk/samples/petzold/chap11/sqbtn.c, revision 1.1.1.1

1.1       root        1: /*----------------------------------------------------------------
                      2:    SQBTN.C -- Contains window procedure for square 3D push button
                      3:   ----------------------------------------------------------------*/
                      4: 
                      5: #define INCL_WIN
                      6: #define INCL_GPI
                      7: #include <os2.h>
                      8: #include <malloc.h>
                      9: #include <string.h>
                     10: 
                     11: #define LCID_ITALIC 1L
                     12: 
                     13:                /*--------------------------------------------------
                     14:                   Structure for storing data unique to each window
                     15:                 --------------------------------------------------*/
                     16: typedef struct
                     17:      {
                     18:      PSZ  pszText ;
                     19:      BOOL fHaveCapture ;
                     20:      BOOL fHaveFocus ;
                     21:      BOOL fInsideRect ;
                     22:      BOOL fSpaceDown ;
                     23:      }
                     24:      SQBTN ;
                     25: 
                     26: typedef SQBTN FAR *PSQBTN ;
                     27: 
                     28: MRESULT EXPENTRY SqBtnWndProc (HWND, USHORT, MPARAM, MPARAM) ;
                     29: VOID             DrawButton   (HWND, HPS, PSQBTN) ;
                     30: 
                     31: HAB  hab ;
                     32: 
                     33:           /*--------------------------------------------------------
                     34:              RegisterSqBtnClass function available to other modules
                     35:             --------------------------------------------------------*/
                     36: 
                     37: BOOL RegisterSqBtnClass (HAB habIn)
                     38:      {
                     39:      hab = habIn ;
                     40: 
                     41:      return WinRegisterClass (hab, "SqBtn", SqBtnWndProc,
                     42:                               CS_SIZEREDRAW, sizeof (PSQBTN)) ;
                     43:      }
                     44: 
                     45:           /*-------------------------------------------
                     46:              String functions that accept far pointers
                     47:             -------------------------------------------*/
                     48: 
                     49: USHORT fstrlen (PCHAR pch)
                     50:      {
                     51:      USHORT usLen ;
                     52:      for (usLen = 0 ; pch[usLen] ; usLen++) ;
                     53:      return usLen ;
                     54:      }
                     55: 
                     56: PCHAR fstrcpy (PCHAR pchDst, PCHAR pchSrc)
                     57:      {
                     58:      USHORT usIndex ;
                     59:      for (usIndex = 0 ; pchDst[usIndex] = pchSrc[usIndex] ; usIndex++) ;
                     60:      return pchDst ;
                     61:      }
                     62: 
                     63:           /*-------------------------------
                     64:              SqBtnWndProc window procedure
                     65:             -------------------------------*/
                     66: 
                     67: MRESULT EXPENTRY SqBtnWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
                     68:      {
                     69:      BOOL          fTestInsideRect ;
                     70:      HPS           hps ;
                     71:      PCREATESTRUCT pcrst ;
                     72:      POINTL        ptl ;
                     73:      PSQBTN        pSqBtn ;
                     74:      PWNDPARAMS    pwprm ;
                     75:      RECTL         rcl ;
                     76: 
                     77:      pSqBtn = WinQueryWindowPtr (hwnd, 0) ;
                     78: 
                     79:      switch (msg)
                     80:           {
                     81:           case WM_CREATE:
                     82:                pSqBtn = _fmalloc (sizeof (SQBTN)) ;
                     83: 
                     84:                          // Initialize structure
                     85: 
                     86:                pSqBtn->fHaveCapture = FALSE ;
                     87:                pSqBtn->fHaveFocus   = FALSE ;
                     88:                pSqBtn->fInsideRect  = FALSE ;
                     89:                pSqBtn->fSpaceDown   = FALSE ;
                     90: 
                     91:                          // Get window text from creation structure
                     92: 
                     93:                pcrst = (PCREATESTRUCT) PVOIDFROMMP (mp2) ;
                     94: 
                     95:                pSqBtn->pszText = _fmalloc (1 + fstrlen (pcrst->pszText)) ;
                     96:                fstrcpy (pSqBtn->pszText, pcrst->pszText) ;
                     97: 
                     98:                WinSetWindowPtr (hwnd, 0, pSqBtn) ;
                     99:                return 0 ;
                    100: 
                    101:           case WM_SETWINDOWPARAMS:
                    102:                pwprm = (PWNDPARAMS) PVOIDFROMMP (mp1) ;
                    103: 
                    104:                          // Get window text from window parameter structure
                    105: 
                    106:                if (pwprm->fsStatus & WPM_TEXT)
                    107:                     {
                    108:                     _ffree (pSqBtn->pszText) ;
                    109:                     pSqBtn->pszText = _fmalloc (1 + pwprm->cchText) ;
                    110:                     fstrcpy (pSqBtn->pszText, pwprm->pszText) ;
                    111:                     }
                    112:                return 1 ;
                    113: 
                    114:           case WM_QUERYWINDOWPARAMS:
                    115:                pwprm == (PWNDPARAMS) PVOIDFROMMP (mp1) ;
                    116: 
                    117:                          // Set window parameter structure fields
                    118: 
                    119:                if (pwprm->fsStatus & WPM_CCHTEXT)
                    120:                     pwprm->cchText = fstrlen (pSqBtn->pszText) ;
                    121: 
                    122:                if (pwprm->fsStatus & WPM_TEXT)
                    123:                     fstrcpy (pwprm->pszText, pSqBtn->pszText) ;
                    124: 
                    125:                if (pwprm->fsStatus & WPM_CBPRESPARAMS)
                    126:                     pwprm->cbPresParams = 0 ;
                    127: 
                    128:                if (pwprm->fsStatus & WPM_PRESPARAMS)
                    129:                     pwprm->pPresParams = NULL ;
                    130: 
                    131:                if (pwprm->fsStatus & WPM_CBCTLDATA)
                    132:                     pwprm->cbCtlData = 0 ;
                    133: 
                    134:                if (pwprm->fsStatus & WPM_CTLDATA)
                    135:                     pwprm->pCtlData = NULL ;
                    136: 
                    137:                return 1 ;
                    138: 
                    139:           case WM_BUTTON1DOWN:
                    140:                WinSetFocus (HWND_DESKTOP, hwnd) ;
                    141:                WinSetCapture (HWND_DESKTOP, hwnd) ;
                    142:                pSqBtn->fHaveCapture = TRUE ;
                    143:                pSqBtn->fInsideRect  = TRUE ;
                    144:                WinInvalidateRect (hwnd, NULL, FALSE) ;
                    145:                return 0 ;
                    146: 
                    147:           case WM_MOUSEMOVE:
                    148:                if (!pSqBtn->fHaveCapture)
                    149:                     break ;
                    150: 
                    151:                WinQueryWindowRect (hwnd, &rcl) ;
                    152:                ptl.x = MOUSEMSG(&msg)->x ;
                    153:                ptl.y = MOUSEMSG(&msg)->y ;
                    154: 
                    155:                          // Test if mouse pointer is still in window
                    156: 
                    157:                fTestInsideRect = WinPtInRect (hab, &rcl, &ptl) ;
                    158: 
                    159:                if (pSqBtn->fInsideRect != fTestInsideRect)
                    160:                     {
                    161:                     pSqBtn->fInsideRect = fTestInsideRect ;
                    162:                     WinInvalidateRect (hwnd, NULL, FALSE) ;
                    163:                     }
                    164:                break ;
                    165: 
                    166:           case WM_BUTTON1UP:
                    167:                if (!pSqBtn->fHaveCapture)
                    168:                     break ;
                    169: 
                    170:                WinSetCapture (HWND_DESKTOP, NULL) ;
                    171:                pSqBtn->fHaveCapture = FALSE ;
                    172:                pSqBtn->fInsideRect  = FALSE ;
                    173: 
                    174:                WinQueryWindowRect (hwnd, &rcl) ;
                    175:                ptl.x = MOUSEMSG(&msg)->x ;
                    176:                ptl.y = MOUSEMSG(&msg)->y ;
                    177: 
                    178:                          // Post WM_COMMAND if mouse pointer is in window
                    179: 
                    180:                if (WinPtInRect (hab, &rcl, &ptl))
                    181:                     WinPostMsg (WinQueryWindow (hwnd, QW_OWNER, FALSE),
                    182:                          WM_COMMAND,
                    183:                          MPFROMSHORT (WinQueryWindowUShort (hwnd, QWS_ID)),
                    184:                          MPFROM2SHORT (CMDSRC_OTHER, TRUE)) ;
                    185: 
                    186:                WinInvalidateRect (hwnd, NULL, FALSE) ;
                    187:                return 0 ;
                    188: 
                    189:           case WM_ENABLE:
                    190:                WinInvalidateRect (hwnd, NULL, FALSE) ;
                    191:                return 0 ;
                    192: 
                    193:           case WM_SETFOCUS:
                    194:                pSqBtn->fHaveFocus = SHORT1FROMMP (mp2) ;
                    195:                WinInvalidateRect (hwnd, NULL, FALSE) ;
                    196:                return 0 ;
                    197: 
                    198:           case WM_CHAR:
                    199:                if (!(CHARMSG(&msg)->fs & KC_VIRTUALKEY) ||
                    200:                      CHARMSG(&msg)->vkey != VK_SPACE    ||
                    201:                      CHARMSG(&msg)->fs & KC_PREVDOWN)
                    202:                     break ;
                    203: 
                    204:                          // Post WM_COMMAND when space bar is released
                    205: 
                    206:                if (!(CHARMSG(&msg)->fs & KC_KEYUP))
                    207:                     pSqBtn->fSpaceDown = TRUE ;
                    208:                else
                    209:                     {
                    210:                     pSqBtn->fSpaceDown = FALSE ;
                    211:                     WinPostMsg (WinQueryWindow (hwnd, QW_OWNER, FALSE),
                    212:                          WM_COMMAND,
                    213:                          MPFROMSHORT (WinQueryWindowUShort (hwnd, QWS_ID)),
                    214:                          MPFROM2SHORT (CMDSRC_OTHER, FALSE)) ;
                    215:                     }
                    216:                WinInvalidateRect (hwnd, NULL, FALSE) ;
                    217:                return 0 ;
                    218: 
                    219:           case WM_PAINT:
                    220:                hps = WinBeginPaint (hwnd, NULL, NULL) ;
                    221:                DrawButton (hwnd, hps, pSqBtn) ;
                    222:                WinEndPaint (hps) ;
                    223:                return 0 ;
                    224: 
                    225:           case WM_DESTROY:
                    226:                _ffree (pSqBtn->pszText) ;
                    227:                _ffree (pSqBtn) ;
                    228:                return 0 ;
                    229:           }
                    230:      return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
                    231:      }
                    232: 
                    233:           /*--------------------------------------------------------
                    234:              Draws filled and outlined polygon (used by DrawButton)
                    235:             --------------------------------------------------------*/
                    236: 
                    237: VOID Polygon (HPS hps, LONG lPoints, POINTL aptl[], LONG lColor)
                    238:      {
                    239:                // Draw interior in specified color
                    240: 
                    241:      GpiSavePS (hps) ;
                    242:      GpiSetColor (hps, lColor) ;
                    243: 
                    244:      GpiBeginArea (hps, BA_NOBOUNDARY | BA_ALTERNATE) ;
                    245:      GpiMove (hps, aptl) ;
                    246:      GpiPolyLine (hps, lPoints - 1, aptl + 1) ;
                    247:      GpiEndArea (hps) ;
                    248: 
                    249:      GpiRestorePS (hps, -1L) ;
                    250: 
                    251:                // Draw boundary in default color
                    252: 
                    253:      GpiMove (hps, aptl + lPoints - 1) ;
                    254:      GpiPolyLine (hps, lPoints, aptl) ;
                    255:      }
                    256: 
                    257:           /*---------------------
                    258:              Draws Square Button
                    259:             ---------------------*/
                    260: 
                    261: VOID DrawButton (HWND hwnd, HPS hps, PSQBTN pSqBtn)
                    262:      {
                    263:      FATTRS      fat ;
                    264:      FONTMETRICS fm ;
                    265:      HDC         hdc ;
                    266:      LONG        lColor, lHorzRes, lVertRes, cxEdge, cyEdge ;
                    267:      POINTL      aptl[10], aptlTextBox[TXTBOX_COUNT], ptlShadow, ptlText ;
                    268:      RECTL       rcl ;
                    269: 
                    270:                // Find 2 millimeter edge width in pixels
                    271: 
                    272:      hdc = GpiQueryDevice (hps) ;
                    273:      DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &lHorzRes) ;
                    274:      DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION,   1L, &lVertRes) ;
                    275: 
                    276:      cxEdge = lHorzRes / 500 ;
                    277:      cyEdge = lVertRes / 500 ;
                    278: 
                    279:                // Set up coordinates for drawing the button
                    280: 
                    281:      WinQueryWindowRect (hwnd, &rcl) ;
                    282: 
                    283:      aptl[0].x = 0 ;                    aptl[0].y = 0 ;
                    284:      aptl[1].x = cxEdge ;               aptl[1].y = cyEdge ;
                    285:      aptl[2].x = rcl.xRight - cxEdge ;  aptl[2].y = cyEdge ;
                    286:      aptl[3].x = rcl.xRight - 1 ;       aptl[3].y = 0 ;
                    287:      aptl[4].x = rcl.xRight - 1 ;       aptl[4].y = rcl.yTop - 1 ;
                    288:      aptl[5].x = rcl.xRight - cxEdge ;  aptl[5].y = rcl.yTop - cyEdge ;
                    289:      aptl[6].x = cxEdge ;               aptl[6].y = rcl.yTop - cyEdge ;
                    290:      aptl[7].x = 0 ;                    aptl[7].y = rcl.yTop - 1 ;
                    291:      aptl[8].x = 0 ;                    aptl[8].y = 0 ;
                    292:      aptl[9].x = cxEdge ;               aptl[9].y = cyEdge ;
                    293: 
                    294:                // Paint edges at bottom and right side
                    295: 
                    296:      GpiSetColor (hps, CLR_BLACK) ;
                    297:      lColor = (pSqBtn->fInsideRect || pSqBtn->fSpaceDown) ?
                    298:                               CLR_PALEGRAY : CLR_DARKGRAY ;
                    299:      Polygon (hps, 4L, aptl + 0, lColor) ;
                    300:      Polygon (hps, 4L, aptl + 2, lColor) ;
                    301: 
                    302:                // Paint edges at top and left side
                    303: 
                    304:      lColor = (pSqBtn->fInsideRect || pSqBtn->fSpaceDown) ?
                    305:                               CLR_DARKGRAY : CLR_WHITE ;
                    306:      Polygon (hps, 4L, aptl + 4, lColor) ;
                    307:      Polygon (hps, 4L, aptl + 6, lColor) ;
                    308: 
                    309:                // Paint interior area
                    310: 
                    311:      GpiSavePS (hps) ;
                    312:      GpiSetColor (hps, (pSqBtn->fInsideRect || pSqBtn->fSpaceDown) ?
                    313:                               CLR_DARKGRAY : CLR_PALEGRAY) ;
                    314:      GpiMove (hps, aptl + 1) ;
                    315:      GpiBox (hps, DRO_FILL, aptl + 5, 0L, 0L) ;
                    316:      GpiRestorePS (hps, -1L) ;
                    317:      GpiBox (hps, DRO_OUTLINE, aptl + 5, 0L, 0L) ;
                    318: 
                    319:                // If button has focus, use italic font
                    320: 
                    321:      GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm) ;
                    322: 
                    323:      if (pSqBtn->fHaveFocus)
                    324:           {
                    325:           fat.usRecordLength  = sizeof fat ;
                    326:           fat.fsSelection     = FATTR_SEL_ITALIC ;
                    327:           fat.lMatch          = 0 ;
                    328:           fat.idRegistry      = fm.idRegistry ;
                    329:           fat.usCodePage      = fm.usCodePage ;
                    330:           fat.lMaxBaselineExt = fm.lMaxBaselineExt ;
                    331:           fat.lAveCharWidth   = fm.lAveCharWidth ;
                    332:           fat.fsType          = 0 ;
                    333:           fat.fsFontUse       = 0 ;
                    334:           strcpy (fat.szFacename, fm.szFacename) ;
                    335: 
                    336:           GpiCreateLogFont (hps, NULL, LCID_ITALIC, &fat) ;
                    337:           GpiSetCharSet (hps, LCID_ITALIC) ;
                    338:           }
                    339:                // Calculate text position
                    340: 
                    341:      GpiQueryTextBox (hps, (LONG) fstrlen (pSqBtn->pszText), pSqBtn->pszText,
                    342:                            TXTBOX_COUNT, aptlTextBox) ;
                    343: 
                    344:      ptlText.x = (rcl.xRight - aptlTextBox[TXTBOX_CONCAT].x) / 2 ;
                    345:      ptlText.y = (rcl.yTop   - aptlTextBox[TXTBOX_TOPLEFT].y -
                    346:                                aptlTextBox[TXTBOX_BOTTOMLEFT].y) / 2 ;
                    347: 
                    348:      ptlShadow.x = ptlText.x + fm.lAveCharWidth   / 3 ;
                    349:      ptlShadow.y = ptlText.y - fm.lMaxBaselineExt / 8 ;
                    350: 
                    351:                // Display text shadow in black, and text in white
                    352: 
                    353:      GpiSetColor (hps, CLR_BLACK) ;
                    354:      GpiCharStringAt (hps, &ptlShadow, (LONG) fstrlen (pSqBtn->pszText),
                    355:                                        pSqBtn->pszText) ;
                    356:      GpiSetColor (hps, CLR_WHITE) ;
                    357:      GpiCharStringAt (hps, &ptlText, (LONG) fstrlen (pSqBtn->pszText),
                    358:                                      pSqBtn->pszText) ;
                    359: 
                    360:                // X out button if the window is not enabled
                    361: 
                    362:      if (!WinIsWindowEnabled (hwnd))
                    363:           {
                    364:           GpiMove (hps, aptl + 1) ;
                    365:           GpiLine (hps, aptl + 5) ;
                    366:           GpiMove (hps, aptl + 2) ;
                    367:           GpiLine (hps, aptl + 6) ;
                    368:           }
                    369:                // Clean up
                    370: 
                    371:      if (pSqBtn->fHaveFocus)
                    372:           {
                    373:           GpiSetCharSet (hps, LCID_DEFAULT) ;
                    374:           GpiDeleteSetId (hps, LCID_ITALIC) ;
                    375:           }
                    376:      }

unix.superglobalmegacorp.com

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