madNVAssistant Unit

The "madNVAssistant" unit is used by madExcept to show thread safe assistants to the end user. Each assistant consists of one or more forms, which are shown until the end user either aborts one of the forms, or until all steps/forms of the assistant are through.

A full list of what is contained in the whole unit can be found in the madNVAssistant Reference.

The assistant is managed through an interfaced named "INVAssistant". The only way to get an instance of such an interface is indirectly through the IMESettings interface. The single most interesting method of the "INVAssistant" interface is the "ShowModal" method:

  INVAssistant = interface ['{14A3AFE4-B39F-4745-8F85-08FFABE8771C}'];

  TNVModalResult = (nvmInvalid, nvmOk, nvmSkip, nvmCancel);

function INVAssistant.ShowModal (parentWindow: dword = 0) : TNVModalResult;

// Example:

There are some more properties, which are more or less interesting. E.g. you can retrieve the exception interface, in case the assistant was created from an exception context. Plus you can set and get a "Data" pointer, which you can use for any purpose you like.

  TNVAction = (nvaFormCreate, nvaFormShow, nvaFormClose, nvaItemEvent);

  TNVActionHandler = procedure (form: INVForm; action: TNVAction; item: INVItem; exception: IMEException);

property INVAssistant.Title       : string;
property INVAssistant.FormCount   : integer;
property INVAssistant.Forms       [index : integer] : INVForm;
property INVAssistant.Form        [name  : string ] : INVForm;
property INVAssistant.ModalResult : TNVModalResult;
property INVAssistant.OnAction    : TNVActionHandler;
property INVAssistant.Exception   : IUnknown;  // can be typecasted to IMEException
property INVAssistant.Data        : pointer;

Each step/form of an assistant is represented by an "INVForm" interface. The only way to get an "INVForm" interface instance is indirectly through either the INVAssistant interface or the TNVActionHandler callback.

  INVForm = interface ['{9C62303F-3C4A-4E2F-9C14-74C518871995}'];

The only situation where it makes sense for you to even touch the "INVForm" interface is probably inside of an TNVActionHandler event. During that event it might make sense for you to access the forms controls and to do something with them.

You can either enumerate through all controls by using the "ItemCount" and "Items" properties. Or you can directly access any controls by referencing them via their type and name. Finally you can directly access the three default main buttons that belong to each form.

property INVForm.ItemCount : integer;
property INVForm.Items     [index: integer] : INVItem;

// Example:
for i1 := 0 to form.ItemCount - 1 do
  form.Items[i1].Enabled := false;

function INVForm.nvEdit     (item: string) : INVEdit;
function INVForm.nvLabel    (item: string) : INVLabel;
function INVForm.nvButton   (item: string) : INVButton;
function INVForm.nvCheckBox (item: string) : INVCheckBox;
function INVForm.nvImage    (item: string) : INVImage;

property INVForm.ContinueButton : INVButton;
property INVForm.SkipButton     : INVButton;
property INVForm.CancelButton   : INVButton;

// Example:
form.ContinueButton.Enabled := form.nvEdit('NameEdit').Text <> '';

As with the INVAssistant interface, the "INVForm" interface also has some more properties, which will probably be less exciting to you. Here's a list just for the sake of completeness:

property INVForm.Assistant     : INVAssistant;
property INVForm.Name          : string;
property INVForm.Title         : string;
property INVForm.Message       : string;
property INVForm.Handle        : dword;
property INVForm.Timer         : dword;
property INVForm.ModalResult   : TNVModalResult;
property INVForm.ActiveControl : string;
property INVForm.OnAction      : TNVActionHandler;
property INVForm.Exception     : IUnknown;  // can be typecasted to IMEException
property INVForm.Data          : pointer;

The controls are all descendants of the basic "INVItem" interface and thus share some general properties & methods, e.g. the control "Name" and the "Enabled" state.

  INVItem = interface ['{36EE4E77-B6B3-41D0-ABA7-3D9B90847EC0}'];

property INVItem.Name    : string;
property INVItem.Handle  : dword;
property INVItem.TabStop : boolean;
property INVUtem.Spacing : integer;
property INVItem.Enabled : boolean;

procedure INVItem.SetFocus;

The label control is fairly easy. It only adds the property "Caption" to the INVItem basic interface.

  INVLabel = interface (INVItem) ['{EA968486-7DA2-486F-9D40-DE0B7BDECBEC}'];

property INVLabel.Caption : string;

For button controls you can specify a "MinWidth". If the button "Caption" needs more space than you entered in "MinWidth", the real width is auto adjusted to the width needed to draw the full "Caption".

  INVButton = interface (INVItem) ['{20E07644-4788-4FDF-8F90-B62C0E61E20B}'];

property INVButton.Caption  : string;
property INVButton.MinWidth : integer;

The check box control is slightly more complex. It has a "Caption" and a "Checked" property, just like the VCL check box component. Additionally it has a property named "OutputName". If you write a name in here, the check box value (that is "yes" or "no") is added to the bug report header under the name specified by "OutputName". If you leave the field empty, the check box value is not added to the bug report header.

  INVCheckBox = interface (INVItem) ['{34E76977-C2B5-4819-B8F6-B6170089A03C}'];

property INVCheckBox.Caption : string;
property INVCheckBox.Checked : boolean;

property INVCheckBox.OutputName : string;

The edit control can behave as either an edit box or a memo field, depending on how the "Lines" property is set. If "Lines" is greater than 1, we have a memo control. The property "Optional" defines whether the user must fill this edit/memo control before he may forward to the next assistant step. If "Optional" is false, the continue button is automatically disabled, as long as the edit/memo control contains no text or invalid text. You can specify whether an edit control has valid content by settings the "Valid" property. It makes sense to do that in an INVForm.OnAction event handler. If the "Colored" property is true, the edit/memo field is colored in green or red, depending on whether the content is valid. Otherwise it is colored black.

If the "OutputName" property is filled, the edit/memo text is written to the bug report. Depending on how "OutputType" is set, the edit/memo text is either added to the bug report header, or stored into a seperate bug report section.

  INVEdit = interface (INVItem) ['{22AC205D-0FED-425B-BEBB-9FBAB850C1DC}'];

property INVEdit.Lines    : integer;
property INVEdit.Optional : boolean;
property INVEdit.Text     : string;
property INVEdit.Colored  : boolean;
property INVEdit.Valid    : boolean;

  TOutputType = (otHeader, otOwnSection);

property INVEdit.OutputName : string;
property INVEdit.OutputType : TOutputType;

The image control can load an image "File_" from harddisk, or you can manually fill the image by writing to the "Bitmap" property. If you specify the "Width" and "Height" properties at design time, the image is zoomed (if necessary) to fit your wishes. When zooming the aspect ratio of the image is maintained, though. So if you specify e.g. a "Width" and "Height" of e.g. 200 pixels each and then enter a bitmap with 800x600 pixels, the final size of the image will be 200x150 pixels. If you leave "Width" and "Height" empty at design time, the optimal size of the image is auto calculated.

  INVImage = interface (INVItem) ['{A0DE7AC1-F790-4BDB-B6B2-453AF25A6B7B}'];

property INVImage.File_     : string;
property INVImage.Bitmap    : INVBitmap;
property INVImage.Clickable : boolean;
property INVImage.Border    : boolean;
property INVImage.Width     : integer;
property INVImage.Height    : integer;