Mountain
Meadow 3
Technical reference
The ProgramPieces Interface
Overview
Program pieces are code to be called by the MainClass of the main
program. The user can call them by choosing them on the navigation bar or
from menu item selections. They can show a User Control within the program
space of the main form, or can just run plain code with or without
generating their own forms.
For interacting with the main program and accessing data, they are
passed objects with the two interfaces, IMM3Data and IMM3State
Program Piece interface
The IProgramPiece interface defines requirements for all plug-in pieces
for the program. If desired a programmer can create an object that derives
from ProgramPieceBase to include all the implementation of IProgramPiece
automatically. Then they can override only those members that need
specific programming, such as the Label to show or the DiaplayToShow. Or,
they can create a custom class from scratch as long as it implements the
interface. The piece(s) should be compiled into a .NET class library (a
.dll module)
Notice the administrator chooses which program pieces will be loaded,
using the Administrator Console.
Interface members
- MM3Cn and MM3State
- The main program will pass reference to the connnection and state
objects to these properties when they are loaded
- Description
- will be shown to the administrator using the Admin program to explain
what the piece does.
- Label, LabelColor, ShortcutLetter, MenuPath, ShowInNavbar suggestions
- These are all SUGGESTIONS to the administrator for how to load the
pieces into the program, and can be overridden. For example if two
pieces want to be called "Lookup" then the administrator may
rename one of them. These properties are in the .DLL file and show the
administrator what the default values are when they attach them to the
program using the adminiatrator's console. However the values chosen by
the administrator are saved in the database and are used when the
program is actually run.
- Display
- Can be null if this isn't to be shown in the main form's default
space. To create a typical control with Visual Studio, just click
Project, Add User Control, and pick User Control. Typically you will
want to fill the control with a panel that fits in the main form's
space, typically about 706, 514 size. Then drag any other controls onto
that panel. This is something like a MDI (multiple document interface)
Child Form, except that it doesn't inherit from the Form class.
- SelfReference
- This is an optional static reference to the only instance of the class there
is. It is not required by the interface but useful so that the forms and
UserControls and other objects in the program piece's assembly can
reference the ProgramPiece members easily. This is an option only if you
are sure there are no more than one instance of the class going to be made.
The alternative way to provide other objects with this instance is to include
the instance as a parameter to the constructors of other objects.
- void OnCallBeforeShow()
- called before the display is shown, and typically should decide
whether or not to reload data first, based on if the user or patient has
changed, etc.
- void OnCallAfterShow()
- Called after the display is shown, and typically assigns which
control on the UserControl has focus. This is redundant for program
pieces that don't show a display, but both methods will be called
anyway.
- bool OkToChangePages()
- called on the program piece showing its display, asking permission to
switch to another piece and allowing for saving of data first if needed.
- bool OkToChangePatients()
- called on every program piece that is loaded in the program, whether
showing a display or not, asking permission to let user switch to
another patient and allowing for saving of data first if needed.
- bool OkToLogout()
- Called on every program piece loaded in the program, but only if user
tries to logout manually. (See ForcedLogout() for when program times out
for automatic logout or when Windows system tries to close the program).
It requests permission to logout and save data first if needed. Warning:
if this returns 'no' the program cannot close!
- void ForcedLogout()
- IMPORTANT: No dialog boxes or exceptions allowed! This is called when
the timer forces a logout after a period of program inactivity by the
user, or when the program is closed by the operating system, as in
rebooting. It gives the piece a chance to save data first. A dialog box
or an error here could hang up the program and prevent other pieces from
saving their data before shutdown. Saving to database is allowed, but do
not assume any other programs are running, as the operating system may
have already shut them down.
- void Reload()
- User requests reloading data for that piece, or refreshing the page
- void Initialize()
- Programmer may choose to assign values to Label, LabelColor, etc here
as well. Initialize() will be called upon instantiating the object, both
by the client program and by the Admin Console.
- If the program piece has a Diaplay to show it is instantiated in this
initialization method. You should pass it a reference to this program
piece so it can access properties like MM3Data. For example if you have
a program piece called MyProgramPiece and a user control named MyDisplay
you can make a constructor in MyDisplay with the signature ,"public
MyDisplay(MyProgramPiece piece). You can assign it in the Initialize()
method with, "Dispay = new MyDisplay(this);"
- ReceiveMessage()
- receives and processes MM3Message messages from other program pieces
- ReportSections {get;}
- optionally, can return MM3Common.MM3Printing.MM3ReportSection[] array
of report sections to include in reports requested by the user in the
File,Reports menu of the main program.
Considerations to remember in every child form:
- Differentiate X'd Out data from good data!
- Ideally should show errored-out data in strikethrough font and give
user option of showing it or not. At a minimum, do not display it as
good data though.
- Check user's permissions and privacy exclusions!
- Don't show sensitive data if user isn't allowed to see it, and don't
allow them to add or change data if they don't have permission to. See
enumerations UserPermissions and PrivacyFlags in MM3Common for details
- Refresh patient specific data via OnCallBeforeShow() and also
Reload()! Otherwise a patient's data might persist after the program
changes to another patient.
- OnCallBeforeShow() is responsible for resetting lastPatientID and
lastUserID when using pieces inherited from ProgramPieceBase, either by
calling SetLastUser() and SetLastPatient() or by calling
base.OnCallBeforeShow() which does that.
Note about internal program fix for the KeyDown event eating controls:
A glitch in .Net Framework of 2005 makes read-only textboxes eat certain
Ctrl-character sequences, making them fail to fire KeyDown events in
either the textbox or the parent form previewing the keydown event.
The chosen workaround is to make a Windows Message Filter when MainForm
is activated, removing it when MainForm is closed. This filter looks for
Ctrl-<char> sequences which are used to navigate the navigation bar.
However, if you want to trap Ctrl-<char> sequences you can try some
of the other workaround below.
See NotesOnKeyboardGlitches.htm
for more on the glitches
How the Piecer works
The Piecer.cs code reads the program pieces specified in the database
table ProgramPieceInfos into a list called ProgramPieceInfos.
The Piecer makes a menu item in MainForm for each piece, under Tools,
Windows,...
The MainForm shows the labels in its vertical navigation bar of all
program pieces that specify to be shown
The user can click on the vertical nav bar or on the menu item which
will call Piecer.CallProgramPiece(). Or, the code can make that call
directly if desired.
MM3StateClass.CallProgramPiece() makes that piece the active piece and
calls its methods OnCallBeforeShow() and OnCallAfterShow (if the
previously active piece says OkToChangePieces().).
MM3StateClass.CallProgramPiece() has overloads that can pass a string
array of parameters to the program piece, optionally.
Handling the timer's automatic logout
The timer logs a user off after a set number of minutes as a privacy and
security feature of MM3. The piece will receive a call to ForcedLogout(),
but may not ask questions of the user; You may have to default to losing
data or leaving data locks in place until the user logs back in and
decides whether or not to override the locks.