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