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