|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.