// // ALGAUGE.CPP // // Source file for ArchiveLib 2.0 // // Copyright (c) Greenleaf Software, Inc. 1994-1996 // All Rights Reserved // // CONTENTS // // class ALGauge // ALGauge::ALGauge() // int ALGaugeInit() // void ALGauge::gaugePaint() // long ForceRepaint() // gaugeWndProc() // // DESCRIPTION // // This file contains all of the source code for the ALGauge object included // in this library. This is not really a part of ArchiveLib, it is // included strictly for the purposes of demos. This code is directly // derived from code that Microsoft posted on CIS. // // REVISION HISTORY // // May 20, 1994 1.0A : First release // // July 11, 1994 1.0B : Modified the callback function to use AL_EXPORT // instead of _export. This lets me build this // properly under NT. // // February 14, 1996 2.0A : New release // #include "arclib.h" #if !defined( AL_IBM ) #pragma hdrstop #endif #define STRICT #include #include "algauge.h" // // class ALGauge // // DESCRIPTION // // This class is confined entirely to this file. To use this control, // you need to call the initialization routine. The initialization // routine registers the gauge class. Whenever a new gauge object // is created, a WM_CREATE message is sent to the window procedure. // WM_CREATE then creates an instance of ALGauge. The ALGauge // object keeps track of everything about the particular gauge. // The user of the gauge doesn't get to see this class, since his or her // interface to the object goes strictly through messages to the // object. // // DATA MEMBERS // // static dwDefaultTextColor // static dwDefaultBackgroundColor // When a new ALGauge object is created, it // is assigned these colors. In theory, you // can change these colors later with the // right message. // // static szClassName One instance of the class name. // // static iRegistered This guy is used to keep track of whether // the class has been registered with Windows. // // iRange The range of a gauge is normally 100, meaning // it can have a value ranging from 0 to 100. // // iPosition The current position of the gauge, normally // set between 0 and iRange. // // iOrientation This is set to one of four possible // enumerated constants, indication which // way the gauge fills, left to right, // top to bottom, bottom to top, or right // to left. // // hFont The font that that text will be displayed // in. // // dwTextColor The color the text will be displayed in. // // dwBackgroundColor The background color of the box. // // MEMBER FUNCTIONS // // ALGauge() The constructor. The end user never // gets to call this dude. // // gaugePaint() This guy gets called from WM_PAINT. // // REVISION HISTORY // // May 20, 1994 1.0A : First release // // February 14, 1996 2.0A : New release // // I'm not entirely sure why we need the _far declaration on the class. // Watcom doesn't like it, so I am trying it without. Since the // pointer is a far pointer anyway, shouldn't this work without the // _far type modifier on the class? #if defined( AL_WATCOM ) || defined( AL_FLAT_MODEL ) class ALGauge { /* Tag protected class */ #else class _far ALGauge { #endif public : ALGauge(); void gaugePaint( HWND hwnd ); static DWORD dwDefaultTextColor; static DWORD dwDefaultBackgroundColor; static char *szClassName; static int iRegistered; int iRange; int iPosition; ALGaugeOrientation iOrientation; HFONT hFont; DWORD dwTextColor; DWORD dwBackgroundColor; }; // // The static variables for class ALGauge // DWORD ALGauge::dwDefaultTextColor = 0; DWORD ALGauge::dwDefaultBackgroundColor = 0; int ALGauge::iRegistered = 0; char * ALGauge::szClassName = "ALGauge"; /* internal function prototypes */ LONG AL_EXPORT CALLBACK gaugeWndProc( HWND, UINT, WPARAM, LPARAM ); // // NAME // // ALGauge::ALGauge() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ // // SHORT DESCRIPTION // // Constructor for an ALGauge object. // // C++ SYNOPSIS // // #include "arclib.h" // #include "algauge.h" // // ALGauge::ALGauge(); // // C SYNOPSIS // // None, this is an internal C++ function. // // VB SYNOPSIS // // None, this is an internal C++ function. // // DELPHI SYNOPSIS // // None, this is an internal C++ function. // // ARGUMENTS // // None. // // DESCRIPTION // // The constructor is called from the WndProc when the window is first // created. By initializing the member variables, we are all set for // the WM_PAINT. // // Please be sure to keep track of the fact that objects of class ALGauge // are strictly for internal use by ArchiveLib. If you want to use an // ALGauge object, your ownly interface is through your Resource Editor // and the initialization function. In reality, the class is simply a // handy place to hold a bunch of data regarding the gauge window. // // RETURNS // // Nothing. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // ALGauge::ALGauge() /* Tag protected function */ { iRange = 100; iPosition = 0; iOrientation = ALGaugeOrientLeftToRight; dwTextColor = dwDefaultTextColor; dwBackgroundColor = dwDefaultBackgroundColor; } // // NAME // // ALGaugeInit() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ C // // SHORT DESCRIPTION // // Initialize an ArchiveLib ALGuage object. // // C++ SYNOPSIS // // #include "arclib.h" // #include "algauge.h" // // extern "C" // int ALGaugeInit( HINSTANCE hInstance, // HINSTANCE hPrevInstance ); // // C SYNOPSIS // // #include "arclib.h" // #include "algauge.h" // // int ALGaugeInit( HINSTANCE hInstance, // HINSTANCE hPrevInstance ); // // VB SYNOPSIS // // None, can't drop controls on a VB form. // // DELPHI SYNOPSIS // // None, don't know how to integrate an ALGauge object into Delphi. // // ARGUMENTS // // hInstance : The instance handle of the running program, as was // passed to WinMain() // // hPrevInstance : The previous instance handle. See my comments // about this below. A non-zero value here keeps // me from attempting to register the class. // // // DESCRIPTION // // This function is the only function you have to call to initialize // the ALGauge objects. It registers the class and sets up the // WndProc for this type of object. This code is for the most // part either a copy of or closely related to the original Microsoft // code on CIS. // // Looking over this function right now, while I am documenting it, I can // see that I probably shouldn't be dinking with the hPrevInstance // parameter. The standalone program that demonstrated this class // would have used that to prevent itself from registering twice. // At least when inside the DLL, I prevent that by checking the // iRegistered member. // // RETURNS // // 1 for success, 0 for failure. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // extern "C" AL_LINKAGE int AL_FUNCTION ALGaugeInit( HINSTANCE hInstance, /* Tag public function */ HINSTANCE hPrevInstance ) { WNDCLASS wc; HDC hdc; if ( ALGauge::iRegistered ) return 1; if ( hPrevInstance == 0 ) { wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hIcon = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = ALGauge::szClassName; wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wc.hInstance = hInstance; #ifdef AL_BUILDING_DLL wc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW; #else wc.style = CS_HREDRAW | CS_VREDRAW; #endif wc.lpfnWndProc = (WNDPROC) gaugeWndProc; wc.cbClsExtra = 0; #if defined ( AL_WATCOM ) || defined( AL_FLAT_MODEL ) wc.cbWndExtra = sizeof( ALGauge * ); #else wc.cbWndExtra = sizeof( ALGauge _far * ); #endif if ( !RegisterClass( &wc ) ) return 0; } hdc = CreateIC( "DISPLAY", NULL, NULL, NULL ); if ( !hdc ) { UnregisterClass( ALGauge::szClassName, hInstance ); return 0; } // // Select colors based on whether this is mono or color // if ( GetDeviceCaps( hdc, BITSPIXEL ) == 1 && GetDeviceCaps( hdc, PLANES ) == 1 ) { ALGauge::dwDefaultTextColor = RGB(255, 255, 255); ALGauge::dwDefaultBackgroundColor = RGB(0, 0, 0); } else { ALGauge::dwDefaultTextColor = RGB(0, 0, 255); ALGauge::dwDefaultBackgroundColor = RGB(255, 255, 255); } DeleteDC(hdc); return ( ALGauge::iRegistered = 1); } // // NAME // // ALGauge::gaugePaint() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ // // SHORT DESCRIPTION // // Interna // // C++ SYNOPSIS // // #include "arclib.h" // #include "algauge.h" // // void ALGauge::gaugePaint( HWND hwnd ); // // C SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // VB SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // DELPHI SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // ARGUMENTS // // hwnd : The handle of the control hat is being painted. // // DESCRIPTION // // This guy is called when the window gets a WM_PAINT message. How // does that work when this is a member function? Easy, when the // window was created, we made a new ALGauge object, and stored its // address in the window long word. // // This is mostly Microsoft code. I worked it over a little bit to // get it to work with the ALGauge class, instead of using a bunch // of static variables. I had to muck with it a little bit more to // get it to work with Win32s instead of Win16, but that was an easy bit. // // // RETURNS // // Nothing. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // void ALGauge::gaugePaint( HWND hwnd ) /* Tag protected function */ { RECT rc1; RECT rc2; HFONT hLastFont; PAINTSTRUCT ps; char ach[ 6 ]; BeginPaint( hwnd, &ps); HDC hdc = ps.hdc; SetTextColor( hdc, dwTextColor ); SetBkColor( hdc, dwBackgroundColor ); hLastFont = (HFONT) SelectObject( hdc, hFont ); /* draw black rectangle for gauge */ GetClientRect(hwnd, &rc1); FrameRect( hdc, &rc1, (HBRUSH) GetStockObject( BLACK_BRUSH ) ); InflateRect( &rc1, -2, -2 ); rc2 = rc1; /* get the range and position, make sure they are valid */ if ( iRange <= 0 ) iRange = 1; if ( iPosition > iRange ) iPosition = iRange; else if ( iPosition < 0 ) iPosition = 0; /* compute the actual size of the gauge */ int dx = rc1.right - rc1.left; int dy = rc1.bottom - rc1.top; int wGomerX = (WORD)((DWORD)iPosition * dx / iRange ); int wGomerY = (WORD)((DWORD)iPosition * dy / iRange ); /* get the orientation and mung rects accordingly */ switch ( iOrientation ) { case ALGaugeOrientRightToLeft : rc1.left = rc2.right = (short int ) ( rc1.right - wGomerX ); break; case ALGaugeOrientBottomToTop : rc1.top = rc2.bottom = (short int) ( rc1.bottom - wGomerY ); break; case ALGaugeOrientTopToBottom : rc1.bottom = rc2.top += wGomerY; break; case ALGaugeOrientLeftToRight : default: rc1.right = rc2.left += wGomerX; break; } /* switch () */ /* select the correct font */ /* build up a string to blit out--ie the meaning of life: "42%" */ wsprintf(ach, "%3d%%", (WORD)((DWORD) iPosition * 100 / iRange ) ); SIZE size; GetTextExtentPoint( hdc, ach, wGomerX = lstrlen(ach), &size ); /* Draw the finished (ie the percent done) side of box. If * ZYZG_WW_POSITION is 42, (in range of 0 to 100) this ExtTextOut * draws the meaning of life (42%) bar. */ ExtTextOut( hdc, (short int) (( dx - size.cx ) / 2 + 1 ), // 1 for the fram (short int ) (( dy - size.cy ) / 2 + 1 ), ETO_OPAQUE | ETO_CLIPPED, &rc2, ach, (short int) wGomerX, NULL); /* Reverse fore and back colors for drawing the undone (ie the non- * finished) side of the box. */ SetBkColor( hdc, dwTextColor ); SetTextColor( hdc, dwBackgroundColor ); ExtTextOut( hdc, (short int) (( dx - size.cx ) / 2 + 1), // 1 for the frame (short int) (( dy - size.cy ) / 2 + 1), ETO_OPAQUE | ETO_CLIPPED, &rc1, ach, (short int) wGomerX, NULL ); SelectObject( hdc, hLastFont ); EndPaint( hwnd, &ps ); } // // NAME // // ForceRepaint() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ // // SHORT DESCRIPTION // // Forces a repaint on the given window. // // C++ SYNOPSIS // // #include "arclib.h" // #include "algauge.h" // // long ForceRepaint( HWND hwnd ); // // C SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // VB SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // DELPHI SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // ARGUMENTS // // hwnd : The handle of the bar gauge control. // // DESCRIPTION // // Several of the messages that can be sent to the gauge control change // things enough that we want to repaint. Those routines can call // this guy to force it to happen. // // RETURNS // // 0L, always. So what is the point of having a return? Not sure, // I was just copying it. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // long ForceRepaint( HWND hwnd ) /* Tag protected function */ { RECT rc; GetClientRect(hwnd, &rc); InflateRect( &rc, ~1, ~1 ); InvalidateRect( hwnd, &rc, FALSE ); UpdateWindow( hwnd ); return 0L; } // // NAME // // gaugeWndProc() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ // // SHORT DESCRIPTION // // The Windows procedure for ALGauge controls. // // C++ SYNOPSIS // // #include "arclib.h" // #include "algauge.h" // // LONG gaugeWndProc( HWND hwnd, // UINT uMsg, // WPARAM wParam, // LPARAM lParam ); // // C SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // VB SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // DELPHI SYNOPSIS // // None, this is an internal support routine for ALGauge objects. // // ARGUMENTS // // hwnd : Standard argument for Windows procedure // // uMsg : Standard argument for Windows procedure // // wParam : Standard argument for Windows procedure // // lParam : Standard argument for Windows procedure // // DESCRIPTION // // This is the windows procedure for the ALGauge class. In the // demos for ArchiveLib, we pretty much are just going to use // the WM_CREATE and WM_PAINT messages. In theory you could send // all these other messages, but that hasn't been tested. In fact, // looking at the code just now, I believe all the messages that // can be used to set the position, font, etc, should all be part // of the WM_COMMAND case, but that isn't even in there Try to // remember that this is just demo code! // // RETURNS // // varies, see code. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // // // There is a lot of code in here that is #ifdefed to let me declare the // class as a far object. I'm not sure if that is necessary or not. At // one time I was sure it was, but I am able to work with it under // Watcom in small model. // LONG AL_EXPORT CALLBACK gaugeWndProc( HWND hwnd, /* Tag protected function */ UINT uMsg, WPARAM wParam, LPARAM lParam ) { // // After the window has been created, the pointer to the ALGauge object // is kept in the windows long word. I get it here so everyone else // can have access to it. // #if defined ( AL_WATCOM ) || defined( AL_FLAT_MODEL ) ALGauge *pgauge = (ALGauge *) GetWindowLong( hwnd, 0 ); #else ALGauge _far *pgauge = (ALGauge _far *) GetWindowLong( hwnd, 0 ); #endif switch (uMsg) { // // When I get the WM_CREATE message, I create a new ALGauge object, then // put its address in the Windows long word. // case WM_CREATE: #if defined( AL_SYMANTEC ) || defined( AL_WATCOM ) || defined( AL_FLAT_MODEL ) // Not sure about this yet pgauge = new ALGauge; #else pgauge = new _far ALGauge; #endif if ( pgauge == 0 ) return (0L); SetWindowLong( hwnd, 0, (LONG) pgauge ); SendMessage( hwnd, WM_SETFONT, NULL, 0L ); break; case WM_DESTROY: if ( pgauge ) #if defined( AL_SYMANTEC ) && !defined( AL_LARGE_DATA ) delete (void _near *) pgauge; #else delete pgauge; #endif break; case ALGaugeGetPosition : return pgauge->iPosition; case ALGaugeGetRange : return pgauge->iRange; case ALGaugeGetOrientation : return pgauge->iOrientation; case ALGaugeGetForegroundColor : return pgauge->dwTextColor; case ALGaugeGetBackgroundColor: return pgauge->dwBackgroundColor; case ALGaugeSetBackgroundColor : pgauge->dwBackgroundColor = lParam; return 0L; case ALGaugeSetForegroundColor : pgauge->dwTextColor = lParam; return 0L; case ALGaugeSetPosition : pgauge->iPosition = wParam; return ForceRepaint( hwnd ); case ALGaugeSetRange : pgauge->iRange = wParam; return ForceRepaint( hwnd ); case ALGaugeSetOrientation : pgauge->iOrientation = (ALGaugeOrientation) wParam; return ForceRepaint ( hwnd ); case ALGaugeSetDeltaPosition : pgauge->iPosition += (signed) wParam; return ForceRepaint( hwnd ); case WM_PAINT : pgauge->gaugePaint( hwnd ); return (0L); case WM_GETFONT : if ( pgauge->hFont == GetStockObject(SYSTEM_FONT) ) return NULL; else return (WORD) pgauge->hFont; case WM_SETFONT : if ( wParam == 0 ) pgauge->hFont = (HFONT) GetStockObject( SYSTEM_FONT ); else pgauge->hFont = (HFONT) wParam; /* redraw if indicated in message */ if ( (BOOL) lParam ) { InvalidateRect( hwnd, NULL, TRUE ); UpdateWindow( hwnd ); } return (0L); } return ( DefWindowProc( hwnd, uMsg, wParam, lParam ) ); }