// // WINMON.CPP // // Source file for ArchiveLib 2.0 // // Copyright (c) Greenleaf Software, Inc. 1994-1996 // All Rights Reserved // // CONTENTS // // ALWindowsMessage::operator new() // ALWindowsMessage::ALWindowsMessage() // newALWindowsMessage() // ALWindowsMessage::Progress() // ALWindowsMessage::ArchiveOperation() // ALWindowsMessage::~ALWindowsMessage() // // DESCRIPTION // // This file contains all the code to support the ALWindowsMessage // monitor class. This monitor class is good for updating progress // bars and things like that. // // REVISION HISTORY // // May 21, 1994 1.0A : First release // // February 14, 1996 2.0A : New release // #include "arclib.h" #if !defined( AL_IBM ) #pragma hdrstop #endif #include "glengn.h" #include "winmon.h" #include "wildcard.h" // // NAME // // ALWindowsMessage::operator new() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ // // SHORT DESCRIPTION // // Memory allocator used when ArchiveLib resides in a 16 bit DLL. // // C++ SYNOPSIS // // #include "arclib.h" // #include "winmon.h" // // void * ALWindowsMessage::operator new( size_t size ) // // C SYNOPSIS // // None. // // VB SYNOPSIS // // None. // // DELPHI SYNOPSIS // // None. // // ARGUMENTS // // size : The number of bytes that the compiler has decided will be // necessary to construct a new ALWindowsMessage object. // // DESCRIPTION // // When using a DLL, it is easy to get into a dangerous situation when // creating objects whose ctor and dtor are both in the DLL. The problem // arises because when you create an object using new, the memory for // the object will be allocated from the EXE. However, when you destroy // the object using delete, the memory is freed inside the DLL. Since // the DLL doesn't really own that memory, bad things can happen. // // But, you say, won't the space just go back to the Windows heap regardless // of who tries to free it? Maybe, but maybe not. If the DLL is using // a subsegment allocation scheme, it might do some sort of local free // before returning the space to the windows heap. That is the point where // you could conceivably cook your heap. // // By providing our own version of operator new inside this class, we // ensure that all memory allocation for the class will be done from // inside the DLL, not the EXE calling the DLL. // // RETURNS // // A pointer to some memory that should have been pulled out of the // heap for the DLL. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // #if defined( AL_BUILDING_DLL ) void AL_DLL_FAR * AL_PROTO ALWindowsMessage::operator new( size_t size ) /* Tag protected function */ { return ::new char[ size ]; } #endif // // NAME // // ALWindowsMessage::ALWindowsMessage() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ C VB Delphi // // SHORT DESCRIPTION // // Create a new ALWindowsMessage monitor. // // C++ SYNOPSIS // // #include "arclib.h" // #include "winmon.h" // // ALWindowsMessage::ALWindowsMessage( ALMonitorType monitor_type, // HWND progress_text_window, // ALWindowsMessageType message_type, // HWND progress_number_window, // UINT windows_message = 0 ); // // C SYNOPSIS // // #include "arclib.h" // #include "winmon.h" // // hALMonitor newALWindowsMessage( enum ALMonitorType monitor_type, // HWND progress_text_window, // enum ALWindowsMessageType message_type, // HWND progress_number_window, // UINT windows_message ); // // VB SYNOPSIS // // Declare Function newALWindowsMessage Lib "AL20LW" // (ByVal monitor_type%, // ByVal progress_text_window%, // ByVal message_type%, // ByVal progress_number_window%, // ByVal windows_message%) As Long // // DELPHI SYNOPSIS // // function newALWindowsMessage( monitor_type : Integer; // progress_text_window : HWnd; // message_type : Integer; // progress_number_window : HWnd; // windows_message : Integer ) : hALMonitor; // // ARGUMENTS // // monitor_type : AL_MONITOR_OBJECTS or AL_MONITOR_JOBS // // progress_text_window : The handle of the window that is going to // receive text messages during the archiving // process. // // message_type : AL_SEND_RATIO or AL_SEND_BYTE_COUNT // // progress_number_window : The window that is going to receive the // number, which will either be the byte // count or the percent complete ratio. // // windows_message : The message that will be sent to the // progress number window. When the message // is sent, the number is sent in LPARAM // and WPARAM, so take your pick. If this // number is set to 0, the message is instead // sent as test using the set text call. // // DESCRIPTION // // This constructor has an easy job. It accepts five parameters. // Four of them just get copied into data members, the fifth gets // passed up to the constructor for the base class. // // This type of monitor is used in Windows programs. Our examples // make use of it frequently. It sends text messages to edit or static // text controls, and sends numbers to either text controls or custom // controls. We use it to dink with our ALGauge control. // // RETURNS // // When this function is called from C/VB/Delphi it returns an ALMonitor // handle, which is actually a pointer to the object. In C++, a pointer // is returned when the object is allocated using new. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // AL_PROTO ALWindowsMessage::ALWindowsMessage( ALMonitorType monitor_type, /* Tag public function */ HWND progress_text_window, ALWindowsMessageType message_type, HWND progress_number_window, UINT windows_message /* = 0 */ ) : ALMonitor( monitor_type ) { mhMessageWindowHandle = progress_text_window; mhNumberWindowHandle = progress_number_window; miMessage = windows_message; mMessageType = message_type; } #if !defined( AL_NO_C ) extern "C" AL_LINKAGE hALMonitor AL_FUNCTION newALWindowsMessage( enum ALMonitorType monitor_type, /* Tag public function */ HWND progress_text_window, enum ALWindowsMessageType message_type, HWND progress_number_window, UINT windows_message ) { ALWindowsMessage *monitor; monitor = new ALWindowsMessage( monitor_type, progress_text_window, message_type, progress_number_window, windows_message ); return (hALMonitor) monitor; } #endif // // NAME // // ALWindows::Progress() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ // // SHORT DESCRIPTION // // The progress routine for the Windows message monitor. // // C++ SYNOPSIS // // #include "arclib.h" // #include "winmon.h" // // void ALWindowsMessage::Progress( long object_tell, // ALStorage &object ); // // C SYNOPSIS // // None, this is a protected member function for internal use. // // VB SYNOPSIS // // None, this is a protected member function for internal use. // // DELPHI SYNOPSIS // // None, this is a protected member function for internal use. // // ARGUMENTS // // object_tell : The current offset within the object being processed. // Since this function is always called from inside // ALStorage::Yield(), the location will always be known. // // object : The object being compressed, extracted, copied, or // whatever. // // // DESCRIPTION // // While an archiving operation is in progress, this monitor function // will get called sometimes. It gets called by the Yield() function // inside the ALStorage object. The Yield function figures out what // the current offset is inside the storage object, and passes that // as a parameter. // // Taking that all into account, this routine has to figure out what // sort of message to send to the window that is getting the progress // update. Basically, there are two options we have to consider. First, // we have to figure out whether we are sending the byte count or // the ratio (the percent of the job/object that we have done.) Second, // we have to see if there is a windows message or not. If there is // a windows message, we send the number with SendMessage(). Otherwise // we format it into ASCII text and send it using SetWindowText(). // SetWindowText() works good for edit controls and the like. // // In case you are wondering, we don't have to take into account whether // we are monitoring individual objects or an entire job. That is because // that is figured out in the Progress() function in the base class, // which we call at the start of this function. It calculates the correct // values of mlByteCount and miRatio based on which type of monitoring // we are doing, then leaves it up to us here to figure out how and where // to send the data. // // // RETURNS // // Nothing. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // void AL_PROTO ALWindowsMessage::Progress( long object_tell, /* Tag public function */ ALStorage AL_DLL_FAR & object ) { char buf[ 18 ]; // // This guy figures out what the current byte count and ratio are // ALMonitor::Progress( object_tell, object ); if ( mhNumberWindowHandle == 0 ) return; switch ( mMessageType ) { case AL_SEND_BYTE_COUNT : // // Send the byte count using either SendMessage() or SetWindowText() // if ( miMessage == 0 ) { wsprintf( buf, "%ld", mlByteCount ); SetWindowText( mhNumberWindowHandle, buf ); } else SendMessage( mhNumberWindowHandle, (short int) miMessage, 0, mlByteCount ); break; case AL_SEND_RATIO : // // Send the progress ratio using SendMessage() or SetWindowText() // if ( miMessage == 0 ) { wsprintf( buf, "%d%%", miRatio ); SetWindowText( mhNumberWindowHandle, buf ); } else SendMessage( mhNumberWindowHandle, (short int) miMessage, (short int) miRatio, miRatio ); default : break; } } // // NAME // // ALWindowsMessage::ArchiveOperation() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ // // SHORT DESCRIPTION // // Update user interface elements after an archiving operation. // // C++ SYNOPSIS // // #include "arclib.h" // #include "winmon.h" // // void ALWindowsMessage::ArchiveOperation( ALArchiveOperation operation, // ALArchive *archive, // ALEntry *job ); // // C SYNOPSIS // // None, this is a protected member function for internal use. // // VB SYNOPSIS // // None, this is a protected member function for internal use. // // DELPHI SYNOPSIS // // None, this is a protected member function for internal use. // // ARGUMENTS // // operation : One of the values from the enumerated type ALArchiveOperation. // It is simply a list of possible operations that the archive // operation might take, such as opening a file, closing a // file, etc. // // archive : A pointer to the archive object currently being worked on. // // job : A pointer to an ALEntry object that defines the ALStorage // object presently being worked on. // // DESCRIPTION // // During the course of an Archiving operation, the functions in // ALArchive will get the urge to spit out a message. They do // so by calling this member function. All of the messages should // be self-explanatory. // // It would make a lot of sense to move the message formatting up into // the base class so I didn't have to duplicate this effort in every // derived class. // // RETURNS // // Nothing. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // #ifdef AL_FLAT_MODEL #define CHAR_PTR char * #else #define CHAR_PTR char _far * #endif void AL_PROTO ALWindowsMessage::ArchiveOperation( ALArchiveOperation operation, /* Tag public function */ ALArchive AL_DLL_FAR *archive, ALEntry AL_DLL_FAR *job ) { if ( mhMessageWindowHandle == 0 ) return; char buf[ 81 ]; switch ( operation ) { case AL_ARCHIVE_OPEN : wsprintf( buf, "Opening %s", (CHAR_PTR) archive->GetStorageObject()->mName.GetSafeName() ); break; case AL_ARCHIVE_CLOSE : wsprintf( buf, "Closing %s", (CHAR_PTR) archive->GetStorageObject()->mName.GetSafeName() ); break; case AL_EXTRACTION_OPEN : wsprintf( buf, "Extracting %s", (CHAR_PTR) job->mpStorageObject->mName.GetSafeName() ); break; case AL_INSERTION_OPEN : wsprintf( buf, "Inserting %s", (CHAR_PTR) job->mpStorageObject->mName.GetSafeName() ); break; case AL_COPY_OPEN : wsprintf( buf, "Copying %s", (CHAR_PTR) job->mpStorageObject->mName.GetSafeName() ); break; case AL_EXTRACTION_CLOSE : case AL_INSERTION_CLOSE : case AL_COPY_CLOSE : case AL_END_DIRECTORY_WRITE : case AL_END_DIRECTORY_READ : strcpy( buf, "Done" ); break; case AL_START_DIRECTORY_WRITE : strcpy( buf, "Writing directory" ); break; case AL_START_DIRECTORY_READ : strcpy( buf, "Reading directory" ); break; } SetWindowText( mhMessageWindowHandle, buf ); } // // NAME // // ALWindowsMessage::~ALWindowsMessage() // // PLATFORMS/ENVIRONMENTS // // Windows // C++ // // SHORT DESCRIPTION // // The Windows monitor object destructor. // // C++ SYNOPSIS // // #include "arclib.h" // #include "winmon.h" // // ALWindowsMessage::~ALWindowsMessage(); // // C SYNOPSIS // // None, C programmers should call the base class dtor, deleteALMonitor(). // // VB SYNOPSIS // // None, C programmers should call the base class dtor, deleteALMonitor(). // // DELPHI SYNOPSIS // // None, C programmers should call the base class dtor, deleteALMonitor(). // // ARGUMENTS // // None. // // DESCRIPTION // // An examination of the code shown here should satisfy you that this // destructor has nothing to do. // // RETURNS // // Nothing. // // EXAMPLE // // SEE ALSO // // REVISION HISTORY // // February 14, 1996 2.0A : New release // AL_PROTO ALWindowsMessage::~ALWindowsMessage() /* Tag public function */ { AL_ASSERT( GoodTag(), "~ALWindowsMessage: attempt to delete invalid object" ); }