]> git.saurik.com Git - wxWidgets.git/blob - src/msw/gaugemsw.cpp
Separated out Win95 versions of gauge, slider; added wxTabCtrl::GetCurFocus
[wxWidgets.git] / src / msw / gaugemsw.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gaugemsw.cpp
3 // Purpose: wxGaugeMSW class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "gauge.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/defs.h"
25 #endif
26
27 #if USE_GAUGE
28
29 #include "wx/msw/gaugemsw.h"
30 #include "wx/msw/private.h"
31
32 /* gas gauge graph control messages--class "zYzGauge" */
33 #define ZYZG_SETRANGE (WM_USER + 0)
34 #define ZYZG_GETRANGE (WM_USER + 1)
35 #define ZYZG_SETPOSITION (WM_USER + 2)
36 #define ZYZG_GETPOSITION (WM_USER + 3)
37 #define ZYZG_SETORIENTATION (WM_USER + 4)
38 #define ZYZG_GETORIENTATION (WM_USER + 5)
39 #define ZYZG_SETFGCOLOR (WM_USER + 6)
40 #define ZYZG_GETFGCOLOR (WM_USER + 7)
41 #define ZYZG_SETBKCOLOR (WM_USER + 8)
42 #define ZYZG_GETBKCOLOR (WM_USER + 9)
43 #define ZYZG_SETWIDTH3D (WM_USER + 10)
44 #define ZYZG_GETWIDTH3D (WM_USER + 11)
45 #define ZYZG_SETBEZELFACE (WM_USER + 12)
46 #define ZYZG_GETBEZELFACE (WM_USER + 13)
47 #define ZYZG_SETDELTAPOS (WM_USER + 14)
48
49
50 /* orientations for ZYZG_WW_ORIENTATION */
51 #define ZYZG_ORIENT_LEFTTORIGHT 0
52 #define ZYZG_ORIENT_RIGHTTOLEFT 1
53 #define ZYZG_ORIENT_BOTTOMTOTOP 2
54 #define ZYZG_ORIENT_TOPTOBOTTOM 3
55
56 /* gauge styles */
57 #define ZYZGS_3D 0x8000L /* control will be 3D */
58
59 /* public function prototypes */
60 BOOL FAR PASCAL gaugeInit(HINSTANCE hInstance);
61
62 #if !USE_SHARED_LIBRARY
63 IMPLEMENT_DYNAMIC_CLASS(wxGaugeMSW, wxControl)
64 #endif
65
66 bool wxGaugeMSW::Create(wxWindow *parent, const wxWindowID id,
67 const int range,
68 const wxPoint& pos,
69 const wxSize& size,
70 const long style,
71 const wxValidator& validator,
72 const wxString& name)
73 {
74 static bool wxGaugeMSWInitialised = FALSE;
75
76 if ( !wxGaugeMSWInitialised )
77 {
78 if (!gaugeInit((HWND) wxGetInstance()))
79 wxFatalError("Cannot initalize Gauge library");
80 wxGaugeMSWInitialised = TRUE;
81 }
82
83 SetName(name);
84 SetValidator(validator);
85
86 if (parent) parent->AddChild(this);
87 m_rangeMax = range;
88
89 SetBackgroundColour(parent->GetDefaultBackgroundColour()) ;
90 SetForegroundColour(parent->GetDefaultForegroundColour()) ;
91
92 m_windowStyle = style;
93
94 if ( id == -1 )
95 m_windowId = (int)NewControlId();
96 else
97 m_windowId = id;
98
99 int x = pos.x;
100 int y = pos.y;
101 int width = size.x;
102 int height = size.y;
103
104 long msFlags = WS_CHILD | WS_VISIBLE | WS_TABSTOP;
105 msFlags |= ZYZGS_3D;
106
107 HWND wx_button =
108 CreateWindowEx(MakeExtendedStyle(m_windowStyle), "zYzGauge", NULL, msFlags,
109 0, 0, 0, 0, (HWND) parent->GetHWND(), (HMENU)m_windowId,
110 wxGetInstance(), NULL);
111
112 m_hWnd = (WXHWND)wx_button;
113
114 // Subclass again for purposes of dialog editing mode
115 SubclassWin((WXHWND)wx_button);
116
117 int wOrient = 0;
118
119 if (m_windowStyle & wxGA_HORIZONTAL)
120 wOrient = ZYZG_ORIENT_LEFTTORIGHT;
121 else
122 wOrient = ZYZG_ORIENT_BOTTOMTOTOP;
123
124 SendMessage(wx_button, ZYZG_SETORIENTATION, wOrient, 0);
125 SendMessage(wx_button, ZYZG_SETRANGE, range, 0);
126
127 SendMessage((HWND) GetHWND(), ZYZG_SETFGCOLOR, 0, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue()));
128 SendMessage((HWND) GetHWND(), ZYZG_SETBKCOLOR, 0, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue()));
129
130 SetFont(* parent->GetFont());
131
132 if (width == -1)
133 width = 50;
134 if (height == -1)
135 height = 50;
136 SetSize(x, y, width, height);
137
138 ShowWindow((HWND) GetHWND(), SW_SHOW);
139
140 return TRUE;
141 }
142
143 void wxGaugeMSW::SetSize(const int x, const int y, const int width, const int height, const int sizeFlags)
144 {
145 int currentX, currentY;
146 GetPosition(&currentX, &currentY);
147 int x1 = x;
148 int y1 = y;
149 int w1 = width;
150 int h1 = height;
151
152 if (x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
153 x1 = currentX;
154 if (y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
155 y1 = currentY;
156
157 // If we're prepared to use the existing size, then...
158 if (width == -1 && height == -1 && ((sizeFlags & wxSIZE_AUTO) != wxSIZE_AUTO))
159 {
160 GetSize(&w1, &h1);
161 }
162
163 // Deal with default size (using -1 values)
164 if (w1<=0)
165 w1 = DEFAULT_ITEM_WIDTH;
166
167 if (h1<=0)
168 h1 = DEFAULT_ITEM_HEIGHT;
169
170 MoveWindow((HWND) GetHWND(), x1, y1, w1, h1, TRUE);
171
172 #if WXWIN_COMPATIBILITY
173 GetEventHandler()->OldOnSize(width, height);
174 #else
175 wxSizeEvent event(wxSize(width, height), m_windowId);
176 event.eventObject = this;
177 GetEventHandler()->ProcessEvent(event);
178 #endif
179 }
180
181 void wxGaugeMSW::SetShadowWidth(const int w)
182 {
183 SendMessage((HWND) GetHWND(), ZYZG_SETWIDTH3D, w, 0);
184 }
185
186 void wxGaugeMSW::SetBezelFace(const int w)
187 {
188 SendMessage((HWND) GetHWND(), ZYZG_SETBEZELFACE, w, 0);
189 }
190
191 void wxGaugeMSW::SetRange(const int r)
192 {
193 m_rangeMax = r;
194
195 SendMessage((HWND) GetHWND(), ZYZG_SETRANGE, r, 0);
196 }
197
198 void wxGaugeMSW::SetValue(const int pos)
199 {
200 m_gaugePos = pos;
201
202 SendMessage((HWND) GetHWND(), ZYZG_SETPOSITION, pos, 0);
203 }
204
205 int wxGaugeMSW::GetShadowWidth(void) const
206 {
207 return (int) SendMessage((HWND) GetHWND(), ZYZG_GETWIDTH3D, 0, 0);
208 }
209
210 int wxGaugeMSW::GetBezelFace(void) const
211 {
212 return (int) SendMessage((HWND) GetHWND(), ZYZG_GETBEZELFACE, 0, 0);
213 }
214
215 int wxGaugeMSW::GetRange(void) const
216 {
217 return (int) SendMessage((HWND) GetHWND(), ZYZG_GETRANGE, 0, 0);
218 }
219
220 int wxGaugeMSW::GetValue(void) const
221 {
222 return (int) SendMessage((HWND) GetHWND(), ZYZG_GETPOSITION, 0, 0);
223 }
224
225 void wxGaugeMSW::SetForegroundColour(const wxColour& col)
226 {
227 m_foregroundColour = col ;
228 SendMessage((HWND) GetHWND(), ZYZG_SETFGCOLOR, 0, RGB(col.Red(), col.Green(), col.Blue()));
229 }
230
231 void wxGaugeMSW::SetBackgroundColour(const wxColour& col)
232 {
233 m_backgroundColour = col ;
234 SendMessage((HWND) GetHWND(), ZYZG_SETBKCOLOR, 0, RGB(col.Red(), col.Green(), col.Blue()));
235 }
236
237
238 /** zyz3d.c
239 *
240 * DESCRIPTION:
241 * This module contains functions for creating nifty 3D borders
242 * around controls like zYzGauge.
243 *
244 * HISTORY:
245 * 3/14/91 cjp put in this comment
246 * 6/19/92 cjp touched it a bit
247 *
248 ** cjp */
249 // COPYRIGHT:
250 //
251 // (C) Copyright Microsoft Corp. 1992. All rights reserved.
252 //
253 // You have a royalty-free right to use, modify, reproduce and
254 // distribute the Sample Files (and/or any modified version) in
255 // any way you find useful, provided that you agree that
256 // Microsoft has no warranty obligations or liability for any
257 // Sample Application Files which are modified.
258 //
259
260
261 /* get the includes we need */
262 #include <windows.h>
263
264 /* misc. control flag defines */
265 #define DRAW3D_IN 0x0001
266 #define DRAW3D_OUT 0x0002
267
268 #define DRAW3D_TOPLINE 0x0004
269 #define DRAW3D_BOTTOMLINE 0x0008
270 #define DRAW3D_LEFTLINE 0x0010
271 #define DRAW3D_RIGHTLINE 0x0020
272
273
274 /* public function prototypes */
275 void FAR PASCAL Draw3DFaceFrame(HDC, LPRECT, WORD);
276 void FAR PASCAL Draw3DRect(HDC, LPRECT, WORD, WORD);
277 void FAR PASCAL Draw3DLine(HDC, WORD, WORD, WORD, WORD, WORD);
278
279
280 /** void FAR PASCAL Draw3DFaceFrame(HDC hdc, LPRECT rc, WORD wWidth)
281 *
282 * DESCRIPTION:
283 * This function draws a flat frame with the current button-face
284 * color.
285 *
286 * ARGUMENTS:
287 * HDC hdc : The DC to draw into.
288 *
289 * LPRECT rc : The containing rect for the new frame.
290 *
291 * WORD wWidth : The width of the frame to draw.
292 *
293 * RETURN (void FAR PASCAL):
294 * The frame will have been drawn into the DC.
295 *
296 * NOTES:
297 *
298 ** cjp */
299
300 void FAR PASCAL Draw3DFaceFrame(HDC hdc, LPRECT rc, WORD wWidth)
301 {
302 RECT rc1;
303 DWORD rgbOld;
304
305 /* don't go through a bunch of work if we don't have to */
306 if (!wWidth)
307 return;
308
309 /* set up color to be button-face color--so it may not be gray */
310 rgbOld = SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
311
312 /* perform CopyRect w/o bloody windows style overhead */
313 rc1 = *rc;
314
315 /* top */
316 rc1.top = rc->top;
317 rc1.left = rc->left;
318 rc1.bottom = rc->top + wWidth;
319 rc1.right = rc->right;
320
321 /* blast it out */
322 ExtTextOut(hdc, rc1.left, rc1.top, ETO_OPAQUE, &rc1, NULL, 0, NULL);
323
324 /* right */
325 rc1.left = rc->right - wWidth;
326 rc1.bottom = rc->bottom;
327
328 /* blast this part now */
329 ExtTextOut(hdc, rc1.left, rc1.top, ETO_OPAQUE, &rc1, NULL, 0, NULL);
330
331 /* left */
332 rc1.left = rc->left;
333 rc1.right = rc->left + wWidth;
334
335 /* and another part */
336 ExtTextOut(hdc, rc1.left, rc1.top, ETO_OPAQUE, &rc1, NULL, 0, NULL);
337
338 /* bottom */
339 rc1.right = rc->right;
340 rc1.top = rc->bottom - wWidth;
341
342 /* finish it off */
343 ExtTextOut(hdc, rc1.left, rc1.top, ETO_OPAQUE, &rc1, NULL, 0, NULL);
344
345 /* restore the old bk color */
346 SetBkColor(hdc, rgbOld);
347 } /* Draw3DFaceFrame() */
348
349
350 /** void FAR PASCAL Draw3DRect(HDC, LPRECT, WORD, WORD)
351 *
352 * DESCRIPTION:
353 * Draws a 3D rectangle that is shaded. wFlags can be used to
354 * control how the rectangle looks.
355 *
356 * ARGUMENTS:
357 * HDC hdc : Handle to the device context that will be
358 * used to display the rectangle.
359 *
360 * RECT rect : A rectangle describing the dimensions of
361 * the rectangle in device coordinates.
362 *
363 * WORD wShadowWidth : Width of the shadow in device coordinates.
364 *
365 * WORD wFlags : The following flags may be passed to describe
366 * the style of the rectangle:
367 *
368 * DRAW3D_IN : The shadow is drawn such that
369 * the box appears to be sunk in to the screen.
370 * This is default if 0 is passed.
371 *
372 * DRAW3D_OUT : The shadow is drawn such that
373 * the box appears to be sticking out of the
374 * screen.
375 *
376 * RETURN (void FAR PASCAL):
377 * The 3D looking rectangle will have been drawn into the DC.
378 *
379 * NOTES:
380 *
381 ** cjp */
382
383 void FAR PASCAL Draw3DRect(HDC hdc, LPRECT lpRect,
384 WORD wShadowWidth, WORD wFlags)
385 {
386 /* sanity check--don't work if you don't have to! */
387 if (!wShadowWidth || !RectVisible(hdc, lpRect))
388 return;
389
390 /* draw the top line */
391 Draw3DLine(hdc, lpRect->left, lpRect->top,
392 lpRect->right - lpRect->left,
393 wShadowWidth, DRAW3D_TOPLINE | wFlags);
394
395 /* right line */
396 Draw3DLine(hdc, lpRect->right, lpRect->top,
397 lpRect->bottom - lpRect->top,
398 wShadowWidth, DRAW3D_RIGHTLINE | wFlags);
399
400 /* bottom line */
401 Draw3DLine(hdc, lpRect->left, lpRect->bottom,
402 lpRect->right - lpRect->left,
403 wShadowWidth, DRAW3D_BOTTOMLINE | wFlags);
404
405 /* left line */
406 Draw3DLine(hdc, lpRect->left, lpRect->top,
407 lpRect->bottom - lpRect->top,
408 wShadowWidth, DRAW3D_LEFTLINE | wFlags);
409 } /* Draw3DRect() */
410
411
412 /** void FAR PASCAL Draw3DLine(HDC hdc, WORD x, WORD y, WORD nLen,
413 *
414 * DESCRIPTION:
415 * Draws a 3D line that can be used to make a 3D box.
416 *
417 * ARGUMENTS:
418 * HDC hdc : Handle to the device context that will be
419 * used to display the 3D line.
420 *
421 * WORD x, y : Coordinates of the beginning of the line.
422 * These coordinates are in device units and
423 * represent the _outside_ most point. Horiz-
424 * ontal lines are drawn from left to right and
425 * vertical lines are drawn from top to bottom.
426 *
427 * WORD wShadowWidth : Width of the shadow in device coordinates.
428 *
429 * WORD wFlags : The following flags may be passed to
430 * describe the style of the 3D line:
431 *
432 * DRAW3D_IN : The shadow is drawn such that
433 * the box appears to be sunk in to the screen.
434 * This is default if 0 is passed.
435 *
436 * DRAW3D_OUT : The shadow is drawn such that
437 * the box appears to be sticking out of the
438 * screen.
439 *
440 * DRAW3D_TOPLINE, _BOTTOMLINE, _LEFTLINE, and
441 * _RIGHTLINE : Specifies that a "top",
442 * "Bottom", "Left", or"Right" line is to be
443 * drawn.
444 *
445 * RETURN (void FAR PASCAL):
446 * The line will have been drawn into the DC.
447 *
448 * NOTES:
449 *
450 ** cjp */
451
452 void FAR PASCAL Draw3DLine(HDC hdc, WORD x, WORD y, WORD nLen,
453 WORD wShadowWidth, WORD wFlags)
454 {
455 HBRUSH hOldBrush;
456 HPEN hOldPen;
457 BOOL fDark;
458 POINT Point[ 4 ]; /* define a polgon with 4 points */
459
460 /* if width is zero, don't do nothin'! */
461 if (!wShadowWidth)
462 return;
463
464 /* define shape of polygon--origin is always the same */
465 Point[0].x = x;
466 Point[0].y = y;
467
468 /* To do this we'll simply draw a polygon with four sides, using
469 * the appropriate brush. I dare you to ask me why this isn't a
470 * switch/case!
471 */
472 if (wFlags & DRAW3D_TOPLINE)
473 {
474 /* across to right */
475 Point[1].x = x + nLen - (wShadowWidth == 1 ? 1 : 0);
476 Point[1].y = y;
477
478 /* down/left */
479 Point[2].x = x + nLen - wShadowWidth;
480 Point[2].y = y + wShadowWidth;
481
482 /* accross to left */
483 Point[3].x = x + wShadowWidth;
484 Point[3].y = y + wShadowWidth;
485
486 /* select 'dark' brush if 'in'--'light' for 'out' */
487 fDark = (wFlags & DRAW3D_IN) ? TRUE : FALSE;
488 }
489
490 /* possibly the bottom? */
491 else if (wFlags & DRAW3D_BOTTOMLINE)
492 {
493 /* across to right */
494 Point[1].x = x + nLen;
495 Point[1].y = y;
496
497 /* up/left */
498 Point[2].x = x + nLen - wShadowWidth;
499 Point[2].y = y - wShadowWidth;
500
501 /* accross to left */
502 Point[3].x = x + wShadowWidth;
503 Point[3].y = y - wShadowWidth;
504
505 /* select 'light' brush if 'in' */
506 fDark = (wFlags & DRAW3D_IN) ? FALSE : TRUE;
507 }
508
509 /* ok, it's gotta be left? */
510 else if (wFlags & DRAW3D_LEFTLINE)
511 {
512 /* down */
513 Point[1].x = x;
514 Point[1].y = y + nLen - (wShadowWidth == 1 ? 1 : 0);
515
516 /* up/right */
517 Point[2].x = x + wShadowWidth;
518 Point[2].y = y + nLen - wShadowWidth;
519
520 /* down */
521 Point[3].x = x + wShadowWidth;
522 Point[3].y = y + wShadowWidth;
523
524 /* select 'dark' brush if 'in'--'light' for 'out' */
525 fDark = (wFlags & DRAW3D_IN) ? TRUE : FALSE;
526 }
527
528 /* well maybe it's for the right side? */
529 else if (wFlags & DRAW3D_RIGHTLINE)
530 {
531 /* down */
532 Point[1].x = x;
533 Point[1].y = y + nLen;
534
535 /* up/left */
536 Point[2].x = x - wShadowWidth;
537 Point[2].y = y + nLen - wShadowWidth;
538
539 /* up */
540 Point[3].x = x - wShadowWidth;
541 Point[3].y = y + wShadowWidth;
542
543 /* select 'light' brush if 'in' */
544 fDark = (wFlags & DRAW3D_IN) ? FALSE : TRUE;
545 }
546
547 /* bad drugs? */
548 else return;
549
550 /* select NULL_PEN for no borders */
551 hOldPen = SelectObject(hdc, GetStockObject(NULL_PEN));
552
553 /* select the appropriate color for the fill */
554 if (fDark)
555 hOldBrush = SelectObject(hdc, GetStockObject(GRAY_BRUSH));
556 else
557 hOldBrush = SelectObject(hdc, GetStockObject(WHITE_BRUSH));
558
559 /* finally, draw the dern thing */
560 Polygon(hdc, (LPPOINT)&Point, 4);
561
562 /* restore what we killed */
563 SelectObject(hdc, hOldBrush);
564 SelectObject(hdc, hOldPen);
565 } /* Draw3DLine() */
566
567 /** EOF: zyz3d.c **/
568
569 /** zyzgauge.c
570 *
571 * DESCRIPTION:
572 * Yet another 'Gas Gauge Custom Control.' This control gives you
573 * a 'progress bar' class (named zYzGauge) for use in your applications.
574 * You can set the range, position, font, color, orientation, and 3d
575 * effect of the gauge by sending messages to the control.
576 *
577 * Before you can use this control, you MUST first export the window
578 * procedure for the control (or define it with the _export keyword):
579 *
580 * EXPORTS gaugeWndProc
581 *
582 * You then need initialize the class before you use it:
583 *
584 * if (!gaugeInit(hInstance))
585 * die a horrible death
586 * else
587 * you are good to go
588 *
589 * The colors used by the control default to black and white if you
590 * are running on a mono-display. They default to blue and white
591 * if you are on a color display. You enable the 3D effect by setting
592 * the ZYZGS_3D style flag in the styles field of the control (like
593 * any other control).
594 *
595 * To select your own colors, you can send the ZYZG_SETFGCOLOR and
596 * ZYZG_SETBKCOLOR messages to set the foreground (percent done) and
597 * background (percent not done) colors. The lParam is the RGB()
598 * value--wParam is ignored.
599 *
600 * In all of the following ZYZG_??? messages, the arguments are
601 * WORDS. If you are setting parameters, the value is sent as
602 * the wParam (lParam is ignored). If you are getting parameters,
603 * the value is returned as a LONG and should be cast to a *signed*
604 * integer.
605 *
606 * To set the depth of the 3D effect (if enabled), you can send the
607 * ZYZG_SETBEZELFACE and ZYZG_SETWIDTH3D messages. The bezel face
608 * is the flat top on the 3D border--its color will be that of the
609 * button-face. The 3D width is the width of the bezel itself; inside
610 * and outside. The light color is white, the dark color is gray.
611 * Both widths *can* be zero--both default to 2 which looks to me.
612 *
613 * The range of the control can be set by sending the ZYZG_SETRANGE
614 * message to the control. It can be any integer from 1 to 32767.
615 * What this specifies is the number of pieces that create a whole.
616 * The default is 100. You can get the current range setting by
617 * sending the ZYZG_GETRANGE message to the control.
618 *
619 * The position (number of pieces out of the whole have been used) is
620 * set with the ZYZG_SETPOSITION message. It can be any integer from
621 * 0 to the current range setting of the control--it will be clipped
622 * if the position is out of bounds. The default position is 0. You
623 * can get the current position at any time with the ZYZG_GETPOSITION
624 * message.
625 *
626 * You can also set the range using a delta from the current range.
627 * This is done by sending the ZYZG_SETDELTAPOS message with wParam
628 * set to a _signed_ integer value within the range of the control.
629 *
630 * The font used for the percentage text can be set using the standard
631 * WM_SETFONT message. You can get the current font at any time with
632 * the WM_GETFONT message.
633 *
634 * The orientation can be left to right, right to left, bottom to top,
635 * or top to bottom. Whatever suits your needs. You set this by
636 * sending the ZYZG_ORIENTATION message to the control with one of
637 * the following values (default is ZYZG_ORIENT_LEFTTORIGHT):
638 *
639 * ZYZG_ORIENT_LEFTTORIGHT (0)
640 * ZYZG_ORIENT_RIGHTTOLEFT (1)
641 * ZYZG_ORIENT_BOTTOMTOTOP (2)
642 * ZYZG_ORIENT_TOPTOBOTTOM (3)
643 *
644 * HISTORY:
645 * 3/12/91 cjp put in this comment
646 * 6/19/92 cjp touched it a bit
647 *
648 ** cjp */
649 // COPYRIGHT:
650 //
651 // (C) Copyright Microsoft Corp. 1992. All rights reserved.
652 //
653 // You have a royalty-free right to use, modify, reproduce and
654 // distribute the Sample Files (and/or any modified version) in
655 // any way you find useful, provided that you agree that
656 // Microsoft has no warranty obligations or liability for any
657 // Sample Application Files which are modified.
658 //
659
660
661 /* get the includes we need */
662 #ifndef __GNUWIN32__
663 #include <malloc.h>
664 #endif
665 #include <stdio.h>
666 #include <string.h>
667 #include <stdlib.h>
668 // #include "zyz3d.h"
669 // #include "zyzgauge.h"
670
671
672 /* static global variables */
673 static char gszzYzGaugeClass[] = "zYzGauge";
674
675
676 /* window word position definitions */
677 #define ZYZG_WW_PZYZGAUGE 0
678 /* #define ZYZG_WW_EXTRABYTES 2 */
679 #define ZYZG_WW_EXTRABYTES 4
680
681
682 /* control block structure typedef */
683 typedef struct tZYZGAUGE
684 {
685 WORD wRange;
686 WORD wPosition;
687 WORD wOrientation;
688 WORD wWidth3D;
689 WORD wWidthBezelFace;
690 HFONT hFont;
691 DWORD rgbTextColor;
692 DWORD rgbBkColor;
693
694 } ZYZGAUGE, *PZYZGAUGE, FAR *LPZYZGAUGE;
695
696
697 /* some default values for the control */
698 #define ZYZG_DEF_RANGE 100
699 #define ZYZG_DEF_POSITION 0
700 #define ZYZG_DEF_ORIENTATION ZYZG_ORIENT_LEFTTORIGHT
701 #define ZYZG_DEF_WIDTH3D 2
702 #define ZYZG_DEF_BEZELFACE 2
703
704
705
706 /* the default settings for drawing colors--display dependent */
707 static DWORD rgbDefTextColor;
708 static DWORD rgbDefBkColor;
709 static BOOL fSupport3D;
710
711 #if !defined(APIENTRY) // NT defines APIENTRY, 3.x not
712 #define APIENTRY FAR PASCAL
713 #endif
714
715 #ifdef __WIN32__
716 #define _EXPORT /**/
717 #else
718 #define _EXPORT _export
719 typedef signed short int SHORT ;
720 #endif
721
722 /* internal function prototypes */
723 static void PASCAL gaugePaint(HWND, HDC);
724 /* LRESULT FAR PASCAL */
725 LRESULT APIENTRY _EXPORT gaugeWndProc(HWND, UINT, WPARAM, LPARAM);
726
727
728
729 /** BOOL FAR PASCAL gaugeInit(HINSTANCE hInstance)
730 *
731 * DESCRIPTION:
732 * Registers the window class for the zYzGauge control. Performs
733 * other initialization for the zYzGauge text control. This must
734 * be done before the zYzGauge control is used--or it will fail
735 * and your dialog box will not open!
736 *
737 * ARGUMENTS:
738 * HINSTANCE hInstance : Instance handle to register class with.
739 *
740 * RETURN (BOOL FAR):
741 * The return value is TRUE if the zYzGauge class was successfully
742 * registered. It is FALSE if the initialization fails.
743 *
744 * NOTES:
745 *
746 ** cjp */
747
748 //#pragma alloc_text(init, gaugeInit)
749
750 BOOL FAR PASCAL gaugeInit(HINSTANCE hInstance)
751 {
752 static BOOL fRegistered = FALSE;
753 WNDCLASS wc;
754 HDC hdc;
755
756 /* assume already registered if not first instance */
757 if (fRegistered)
758 return (TRUE);
759
760 /* fill in the class structure for the zyzgauge control */
761 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
762 wc.hIcon = NULL;
763 wc.lpszMenuName = NULL;
764 wc.lpszClassName = gszzYzGaugeClass;
765 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
766 wc.hInstance = hInstance;
767
768 #ifdef ZYZGAUGE_DLL
769 wc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
770 #else
771 wc.style = CS_HREDRAW | CS_VREDRAW;
772 #endif
773
774 wc.lpfnWndProc = gaugeWndProc;
775 wc.cbClsExtra = 0;
776 wc.cbWndExtra = ZYZG_WW_EXTRABYTES;
777
778 /* attempt to register it--return FALSE if fail */
779 if (!RegisterClass(&wc))
780 return (FALSE);
781
782 /* Get a DC to determine whether device is mono or not, and set
783 * default foreground/background colors as appropriate.
784 */
785 if ((hdc = CreateIC("DISPLAY", NULL, NULL, 0L)))
786 {
787 /* check for mono-display */
788 if ((GetDeviceCaps(hdc, BITSPIXEL) == 1) &&
789 (GetDeviceCaps(hdc, PLANES) == 1))
790 {
791 /* using a mono DC--white foreground, black background */
792 rgbDefTextColor = RGB(255, 255, 255);
793 rgbDefBkColor = RGB(0, 0, 0);
794 }
795
796 /* good! we have color: blue foreground, white background */
797 else
798 {
799 rgbDefTextColor = RGB(0, 0, 255);
800 rgbDefBkColor = RGB(255, 255, 255);
801 }
802
803 /* need at _least_ 8 for two shades of gray (>=VGA) */
804 fSupport3D = (GetDeviceCaps(hdc, NUMCOLORS) >= 8) ? TRUE : FALSE;
805
806 /* get rid of the DC (IC) */
807 DeleteDC(hdc);
808 }
809
810 /* uh-oh... can't get DC (IC)... fail */
811 else
812 {
813 /* unregister the class */
814 UnregisterClass(gszzYzGaugeClass, hInstance);
815 return (FALSE);
816 }
817
818 /* return success */
819 return (fRegistered = TRUE);
820 } /* gaugeInit() */
821
822
823 /** static void PASCAL gaugePaint(HWND hwnd, HDC hdc)
824 *
825 * DESCRIPTION:
826 * This function is responsible for painting the zYzGauge control.
827 *
828 * ARGUMENTS:
829 * HWND hwnd : The window handle for the gauge.
830 *
831 * HDC hdc : The DC for the gauge's window.
832 *
833 * RETURN (void):
834 * The control will have been painted.
835 *
836 * NOTES:
837 *
838 ** cjp */
839
840 static void PASCAL gaugePaint(HWND hwnd, HDC hdc)
841 {
842 PZYZGAUGE pgauge;
843 WORD iRange, iPos;
844 WORD Offset = 1;
845 DWORD dwExtent;
846 RECT rc1, rc2;
847 HFONT hFont;
848 char ach[ 6 ];
849 WORD dx, dy, wGomerX, wGomerY;
850 /* Win32s has no GetTextExtent(); let's try GetTextExtentPoint() instead,
851 * which needs a SIZE* parameter */
852 #if defined(__WIN32__)
853 SIZE size;
854 #endif
855
856 /* get pointer to the control's control block */
857 // pgauge = (PZYZGAUGE)GetWindowWord(hwnd, ZYZG_WW_PZYZGAUGE);
858 pgauge = (PZYZGAUGE)GetWindowLong(hwnd, ZYZG_WW_PZYZGAUGE);
859
860 /* set the colors into for the gauge into the control */
861 SetTextColor(hdc, pgauge->rgbTextColor);
862 SetBkColor(hdc, pgauge->rgbBkColor);
863
864 /* draw black rectangle for gauge */
865 GetClientRect(hwnd, &rc1);
866
867 /* draw a black border on the _outside_ */
868 FrameRect(hdc, &rc1, GetStockObject(BLACK_BRUSH));
869
870 /* we want to draw _just inside_ the black border */
871 InflateRect(&rc1, -1, -1);
872
873 /* one line thick so far... */
874 // Offset = (WORD) 1;
875
876 /* for 3D stuff, we need to have at least two shades of gray */
877 if ((GetWindowLong(hwnd, GWL_STYLE) & ZYZGS_3D) && fSupport3D)
878 {
879 Draw3DRect(hdc, &rc1, pgauge->wWidth3D, DRAW3D_OUT);
880 InflateRect(&rc1, ~(pgauge->wWidth3D), ~(pgauge->wWidth3D));
881
882 Draw3DFaceFrame(hdc, &rc1, pgauge->wWidthBezelFace);
883 InflateRect(&rc1, ~(pgauge->wWidthBezelFace), ~(pgauge->wWidthBezelFace));
884
885 Draw3DRect(hdc, &rc1, pgauge->wWidth3D, DRAW3D_IN);
886 InflateRect(&rc1, ~(pgauge->wWidth3D), ~(pgauge->wWidth3D));
887
888 /* draw a black border on the _inside_ */
889 FrameRect(hdc, &rc1, GetStockObject(BLACK_BRUSH));
890
891 /* we want to draw _just inside_ the black border */
892 InflateRect(&rc1, -1, -1);
893
894 /* add all the other pixels into the border width */
895 Offset += (2 * pgauge->wWidth3D) + pgauge->wWidthBezelFace + 1;
896 }
897
898 /* dup--one rc for 'how much filled', one rc for 'how much empty' */
899 rc2 = rc1;
900
901 /* get the range--make sure it's a valid range */
902 if ((iRange = pgauge->wRange) <= 0)
903 iRange = 1;
904
905 /* get the position--greater than 100% would be bad */
906 if ((iPos = pgauge->wPosition) > iRange)
907 iPos = iRange;
908
909 /* compute the actual size of the gauge */
910 dx = rc1.right - rc1.left;
911 dy = rc1.bottom - rc1.top;
912 wGomerX = (WORD)((DWORD)iPos * dx / iRange);
913 wGomerY = (WORD)((DWORD)iPos * dy / iRange);
914
915 /* get the orientation and munge rects accordingly */
916 switch (pgauge->wOrientation)
917 {
918 case ZYZG_ORIENT_RIGHTTOLEFT:
919 rc1.left = rc2.right = rc1.right - wGomerX;
920 break;
921
922 case ZYZG_ORIENT_BOTTOMTOTOP:
923 rc1.top = rc2.bottom = rc1.bottom - wGomerY;
924 break;
925
926 case ZYZG_ORIENT_TOPTOBOTTOM:
927 rc1.bottom = rc2.top += wGomerY;
928 break;
929
930 default:
931 rc1.right = rc2.left += wGomerX;
932 break;
933 } /* switch () */
934
935 /* select the correct font */
936 hFont = SelectObject(hdc, pgauge->hFont);
937
938 /* build up a string to blit out--ie the meaning of life: "42%" */
939 wsprintf(ach, "%3d%%", (WORD)((DWORD)iPos * 100 / iRange));
940 /* Win32s has no GetTextExtent(); let's try GetTextExtentPoint() instead */
941 #if defined(__WIN32__)
942 GetTextExtentPoint(hdc, ach, wGomerX = lstrlen(ach), &size);
943 dwExtent = size.cx;
944 #else
945 dwExtent = GetTextExtent(hdc, ach, wGomerX = lstrlen(ach));
946 #endif
947
948
949 /* Draw the finished (ie the percent done) side of box. If
950 * ZYZG_WW_POSITION is 42, (in range of 0 to 100) this ExtTextOut
951 * draws the meaning of life (42%) bar.
952 */
953 ExtTextOut(hdc, (dx - LOWORD(dwExtent)) / 2 + Offset,
954 (dy - HIWORD(dwExtent)) / 2 + Offset,
955 ETO_OPAQUE | ETO_CLIPPED, &rc2, ach, wGomerX, NULL);
956
957 /* Reverse fore and back colors for drawing the undone (ie the non-
958 * finished) side of the box.
959 */
960 SetBkColor(hdc, pgauge->rgbTextColor);
961 SetTextColor(hdc, pgauge->rgbBkColor);
962
963 ExtTextOut(hdc, (dx - LOWORD(dwExtent)) / 2 + Offset,
964 (dy - HIWORD(dwExtent)) / 2 + Offset,
965 ETO_OPAQUE | ETO_CLIPPED, &rc1, ach, wGomerX, NULL);
966
967 /* unselect the font */
968 SelectObject(hdc, hFont);
969 } /* gaugePaint() */
970
971
972 /** LRESULT FAR PASCAL gaugeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
973 *
974 * DESCRIPTION:
975 * This is the control's window procedure. Its purpose is to handle
976 * special messages for this custom control.
977 *
978 * The special control messages for the gauge control are:
979 *
980 * ZYZG_SETRANGE : Sets the range of the gauge. In other
981 * words, the number of parts that make a
982 * whole.
983 *
984 * ZYZG_GETRANGE : Returns the current range of the gauge.
985 *
986 * ZYZG_SETORIENTATION : Sets the orientation of the gauge. This
987 * can be one of the ZYZG_ORIENT_?? msgs.
988 *
989 * ZYZG_GETORIENTATION : Gets the current orientation of the
990 * gauge.
991 *
992 * ZYZG_SETPOSITION : Sets the current position of the gauge.
993 * In other words, how many pieces of the
994 * whole have been used.
995 *
996 * ZYZG_GETPOSITION : Gets the current position of the gauge.
997 *
998 * ZYZG_SETDELTAPOS : Sets the position of the gauge +/- the
999 * specified amount.
1000 *
1001 * ZYZG_SETFGCOLOR : Sets the foreground (percent done) color.
1002 *
1003 * ZYZG_GETFGCOLOR : Gets the foreground (percent done) color.
1004 *
1005 * ZYZG_SETBKCOLOR : Sets the background (percent not done)
1006 * color.
1007 *
1008 * ZYZG_GETBKCOLOR : Gets the background (percent not done)
1009 * color.
1010 *
1011 * WM_SETFONT : Sets the font to use for the percentage
1012 * text of the gauge.
1013 *
1014 * WM_GETFONT : Gets the current font in use by the
1015 * gauge.
1016 *
1017 * NOTES:
1018 *
1019 ** cjp */
1020
1021 /* LRESULT FAR PASCAL */
1022
1023 LRESULT APIENTRY _EXPORT gaugeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1024 {
1025 HFONT hFont;
1026 PAINTSTRUCT ps;
1027 PZYZGAUGE pgauge;
1028 RECT rc;
1029
1030 // pgauge = (PZYZGAUGE)GetWindowWord(hwnd, ZYZG_WW_PZYZGAUGE);
1031 pgauge = (PZYZGAUGE)GetWindowLong(hwnd, ZYZG_WW_PZYZGAUGE);
1032
1033 /* break to get DefWindowProc() */
1034 switch (uMsg)
1035 {
1036 case WM_CREATE:
1037 /* need to allocate a control block */
1038 // pgauge = (PZYZGAUGE)LocalAlloc(LPTR, sizeof(ZYZGAUGE));
1039 pgauge = (PZYZGAUGE)malloc(sizeof(ZYZGAUGE));
1040 if (!pgauge)
1041 return (0L);
1042
1043 /* hang on to this control block */
1044 // SetWindowWord(hwnd, ZYZG_WW_PZYZGAUGE, (WORD)pgauge);
1045 SetWindowLong(hwnd, ZYZG_WW_PZYZGAUGE, (LONG)pgauge);
1046
1047 /* fill control block with defaults */
1048 pgauge->wRange = ZYZG_DEF_RANGE;
1049 pgauge->wPosition = ZYZG_DEF_POSITION;
1050 pgauge->wOrientation = ZYZG_DEF_ORIENTATION;
1051 pgauge->wWidth3D = ZYZG_DEF_WIDTH3D;
1052 pgauge->wWidthBezelFace = ZYZG_DEF_BEZELFACE;
1053 pgauge->rgbTextColor = rgbDefTextColor;
1054 pgauge->rgbBkColor = rgbDefBkColor;
1055
1056 /* use system font */
1057 SendMessage(hwnd, WM_SETFONT, (WPARAM)NULL, 0L);
1058
1059 /* go to DefWindowProc() to finish the job */
1060 break;
1061
1062 case WM_DESTROY:
1063 /* get rid of the control's memory */
1064 if (pgauge)
1065 // LocalFree((HANDLE)pgauge);
1066 free(pgauge);
1067 break;
1068
1069 case ZYZG_GETPOSITION:
1070 return (pgauge->wPosition);
1071
1072 case ZYZG_GETRANGE:
1073 return (pgauge->wRange);
1074
1075 case ZYZG_GETORIENTATION:
1076 return (pgauge->wOrientation);
1077
1078 case ZYZG_GETWIDTH3D:
1079 return (pgauge->wWidth3D);
1080
1081 case ZYZG_GETBEZELFACE:
1082 return (pgauge->wWidthBezelFace);
1083
1084 case ZYZG_GETBKCOLOR:
1085 return (pgauge->rgbTextColor);
1086
1087 case ZYZG_GETFGCOLOR:
1088 return (pgauge->rgbBkColor);
1089
1090 case ZYZG_SETBKCOLOR:
1091 pgauge->rgbBkColor = lParam;
1092 return (0L);
1093
1094 case ZYZG_SETFGCOLOR:
1095 pgauge->rgbTextColor = lParam;
1096 return (0L);
1097
1098
1099 case ZYZG_SETPOSITION:
1100 pgauge->wPosition = wParam;
1101
1102 zyzgForceRepaint:
1103 GetClientRect(hwnd, &rc);
1104 if ((GetWindowLong(hwnd, GWL_STYLE) & ZYZGS_3D) && fSupport3D)
1105 {
1106 wParam = (2 * pgauge->wWidth3D) +
1107 pgauge->wWidthBezelFace + 2;
1108 }
1109
1110 else
1111 wParam = 1;
1112
1113 InflateRect(&rc, ~(wParam), ~(wParam));
1114 InvalidateRect(hwnd, &rc, FALSE);
1115 UpdateWindow(hwnd);
1116 return (0L);
1117
1118 case ZYZG_SETRANGE:
1119 pgauge->wRange = wParam;
1120 goto zyzgForceRepaint;
1121
1122 case ZYZG_SETORIENTATION:
1123 pgauge->wOrientation = wParam;
1124 goto zyzgForceRepaint;
1125
1126 case ZYZG_SETWIDTH3D:
1127 pgauge->wWidth3D = wParam;
1128
1129 zyzgForceRepaint3D:
1130 InvalidateRect(hwnd, NULL, FALSE);
1131 UpdateWindow(hwnd);
1132 return (0L);
1133
1134 case ZYZG_SETBEZELFACE:
1135 pgauge->wWidthBezelFace = wParam;
1136 goto zyzgForceRepaint3D;
1137
1138 case ZYZG_SETDELTAPOS:
1139 /* Watcom doesn't like the following line so removing typecasts */
1140 /* (int)pgauge->wPosition += (int)wParam; */
1141 pgauge->wPosition += wParam;
1142 goto zyzgForceRepaint;
1143
1144 case WM_PAINT:
1145 BeginPaint(hwnd, &ps);
1146 gaugePaint(hwnd, ps.hdc);
1147 EndPaint(hwnd, &ps);
1148 return (0L);
1149
1150 case WM_GETFONT:
1151 hFont = pgauge->hFont;
1152
1153 /* if system font, then return NULL handle */
1154 return (long)((hFont == GetStockObject(SYSTEM_FONT)) ? NULL : hFont);
1155
1156 case WM_SETFONT:
1157 /* if NULL hFont, use system font */
1158 if (!(hFont = (HFONT)wParam))
1159 hFont = GetStockObject(SYSTEM_FONT);
1160
1161 pgauge->hFont = hFont;
1162
1163 /* redraw if indicated in message */
1164 if ((BOOL)lParam)
1165 {
1166 InvalidateRect(hwnd, NULL, TRUE);
1167 UpdateWindow(hwnd);
1168 }
1169 return (0L);
1170 } /* switch () */
1171
1172 /* let the dialog mangler take care of this message */
1173 return (DefWindowProc(hwnd, uMsg, wParam, lParam));
1174 } /* gaugeWndProc() */
1175
1176
1177 /** EOF: zyzgauge.c **/
1178
1179 #endif // USE_GAUGE