mm3Mountain 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.