
	======================================================================================
	ReadMe File for TellTail Delphi 5 Component

	Copyright (c) 1999 - 2000 - Michael Kelly - mkelly99@gate.net

	A "One Instance" component with Command Tail Transer
	
	Update: Dec. 4, 1999
	Version 1.008

	See comments at the top of TellTail.pas.  The component has been enhanced to
	automatically create GUID strings when dropped on a form and has events for
	transfering application-defined data in addition to the command tail and
	working directory.

	Note:  	Thanks to Jeff Overcash for permission to steal some of his ideas from
		a similar component he wrote[however the implementation is mine, not a
		cut & paste job! :)]

	See "Notes on implementation:" if you're still unsure what this thing is. :)

	*** Provided as a Freeware, no warranty whatever - USE AT YOUR OWN RISK ***

	Feb. 1, 2000 : 	Fixed TellTail.dcr file so that the glyph loads in the palette
			when the component is installed.
	======================================================================================

	Component Files:

		TellTail.pas - component source
		TellTail.dcr - component resource for palette
		TellTail.bmp - bitmap used for palette glyph
		Readme.txt   - this ReadMe file

	TellTailTest Demo Files:

		A demo showing how to dynamically create and try
		the component before you install it in the palette;
		
		TTTestUnit.dfm - simple form with TMemo to display data
		TTTestUnit.pas - code for the demo

	Note: 	I don't include TellTailTest.dpr since there's no sense hardwiring
		where my modules are into the demo.  Just generate a project and
		name it TellTailTest and add TTTestUnit.pas and TellTail.pas to it
		substituting TTTestUnit.dfm for the default project form.


	Notes on implementation:

	TellTail uses a Memory Mapped File to use one page of system swapfile memory 
	to detect if an instance of the application hosting it is already loaded, and
	if so, to transer the Command Tail and Working Directory of the secondary instance 
	of the application to the main application instance.  The Memory Mapped file is 
	protected by a Named Mutex.  It is not required but I suggest using GUID strings 
	for the names of the Mutex and Memory Mapped File since it guarantees the
	names will be unique.  If dropped on a form the component automatically generates
	GUID strings.  If you create the component dynamically then you need to assign
	names for the Kernel Objects before invoking the component's Execute procedure.


	Installation:

	After testing, to install just copy the TellTail.pas and TellTail.dcr files 
	to the directory where you keep your user packages.  Use the package editor
	to add TellTail.pas to your package and select compile.  If all is well
	you should see a traffic "yield" sign on a page named 'Freeware' in the
	component palette. If you prefer another page edit the Register procedure 
	in TellTail.pas.


	Typical usage:

	Drop the component on the main form of your application.  In your main form's
	OnCreate handler invoke the component's Execute method.  If the component's
	Enabled property is still True then Execute was successful.  You can then
	call the Boolean method InMainInstance to find out if this is the main or 
	secondary instance of the application.  If you are in the main instance then
	you want to use some means to poll if any secondary instance has sent you its
	command tail and working directory.  In this polling function you can call the
	Boolean method CopyData to see if any data was retrieved.  In CopyData the
	component stores the command tail and working directory it copied from the
	shared memory(the Memory Mapped File page in the system swap file.)  To get
	the command tail and working directory strings after CopyData returns True,
	use the GetCommandTail and GetWorkingDir methods.  Both are functions that
	return String.  

	In the secondary instance of the application, once successful copying data to
	shared memory, the component calls Application.Terminate.

	Advanced usage:

	Version 1.008 of TellTail has four event handlers.  Two are to deal with errors
	creating or opening Kernel Objects, and two are for assisting in transfering
	application-defined data from the secondary instance of the application to
	the main instance.  I figured since mapping even one byte of the swapfile
	uses a page then I might as well provide a mechanism to use the whole page.
	On most systems the size of a page in the swapfile is 4K but if you are on
	an Alpha it's 8K, so I account for this in the event for sharing the data.
	One of the parameters lets you know the maximum number of bytes you can
	transfer without getting an access violation.  The way I implemented it,
	the component actually copies the data, so you should be free of access
	violatons on the shared memory page side of the equation(if I got it right
	that is) but on the other side you are responsible that the address and
	size of the data you pass in your TSharedDataEvent handlers are correct.
	See TellTail.pas comments on the TSharedDataEvent declaration and look at
	the demo for one example of how you can use it.
	

	Component Properties and Events:

		Properties

		Enabled:	Boolean; if True and Execute is called, it does its thing.
				Enabled may be reset to False if a problem is encountered
				so it's one of the values you can check after calling Execute
				to see what's up.  Also there are Events and an ErrorCode
				built in to help out when things go wrong.

		MapFileName: 	String;  the name of the Memory Mapped File. (Required)

		MutexName:   	String;  the name of the Named Mutex. (Required)

		MaximizeMainInstance:	Boolean; if True and the main instance happens to
					be minimized then a WM_SYSCOMMAND msg is posted by
					the secondary app instance to restore the window.

		MutexTimeOut:	DWORD; milliseconds to wait for the Mutex.  I set this to 250
				so that the secondary instance will wait 1/4 second before
				giving up trying to get the Mutex and transer the data, but
				you might want to set it to 0 in the main app to reduce the
				chance of slowing down whatever polling you do for data
				transfer detection.  IOW, if InMainInstance returns True you
				can feel good about setting this wait value to 0.

		Name:		String; the name of the Component ref. in your program.

		Events

		OnMapFileFailure:  TNotifyEvent for Memory Mapped File open/create errors. (Optional)

		OnMutexFailure:    TNotifyEvent for Mutex open/create errors. (Optional)

		OnWriteSharedData: TSharedDataEvent called by secondary app instance. (Optional)

		OnReadSharedData:  TSharedDataEvent called by main app instance. (Optional)

		Major Public Methods

		GetErrorCode: function; DWORD; returns 0 for no error and may have a return value
					from GetLastError Win32Api or a component-defined error.

		Execute: procedure; manipulates shared data page then kills the secondary instance
				    if Enabled = True when invoked.  Otherwise it just exits.
				    If successful, ErrorCode = 0 and Enabled = True.
				    If failed, call GetErrorCode for a clue to the reason.

		InMainInstance: function; Boolean; returns True if you are in the main instance and
                                Execute was invoked successfully.

		CopyData: function; Boolean; Invoke only if InMainInstance returns True.
				    Copies the command tail and working directory from
				    shared memory to component variables.  Returns True
				    if data was actually copied.  If no data was waiting
				    returns False.  Use this function to poll if data was
				    transfered from the secondary instance.

		GetCommandTail: function; String; Invoke only if InMainInstance and CopyData
				          return True.  Returns command tail stored by component.

		GetWorkinDir: function; String; Invoke only if InMainInstance and CopyData
					return True.  Returns the path to the secondary instance
					of the application(since it's concievable more than one
					copy of the exe is on the machine.)

	A note on how the info looks when transfered to save you some time:

	The Command Tail means the command line of the secondary
	application instance without the exe program included, so
	if you launch the second app at a Dos prompt like this:
	MyApp "some parm" -x<Enter>
	the Command Tail transefer to the first app instance will be:
	"some parm" -x  (with the quotes included)

	The directory the second app was started from is derived by
	using ExtractFilePath(Application.ExeName) so that you don't get
	short filename format out of a Dos box(no '~' chars to mess with)
	and will be an unquoted string, so if you launch the second app
	from a Dos box in C:\Program Files\MyApp folder, you will get a
	WorkingDir value of:
	C:\PROGRAM FILES\MYAPP\ (no surrounding quotes; with trailing '\')

	For details on the implementation see the large comment heading for
	the TellTail.Execute procedure body.

	That should be enough info to get you going if you look at the demo.
	Hope you enjoy using the TellTail component.

	***  End of ReadMe File  ***
