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