Software Customization

Areas that need customization:

  • Basic Application: company name, company website, custom application caption, copyright, company code, application mutex.
  • Product List (found in DataModule).
  • Graphics: resource DLL (splash, icon), AboutBox (logic), SplashForm (logic).
  • Documentation: splash, product matrix, content.
  • Utilities: ezControl Center (menu entries, logo, website), ezBackup, Autorun.
  • Build: updated entries in WiseInstaller/InnoSetup, FinalBuilder, CD image template.
  • Web Update script: update entries in GetCompanyPrefix() function found in file /var/www/html/downloads/ezfit-config.inc.php on the webserver (ssh user@www.audina.net).

Customizing the Application Basics

Create a file custom.cfg:

Company=My Company, Inc.
Copyright=Copyright © 2007, My Company, Inc.
Website=http://www.example.com
Software Caption=Sample Application
Custom Application Caption=Sample Caption
CCny=001
Mutex=ezMyCompanyOneCopy

In the application, load those values:

unit dbmod;
 
interface
  ...
const
  CustomDataFolder = 'data\';
  CustomCfgFile    = 'custom.cfg';
var
  ezAppSettings: TStrings;
  ...
 
procedure TDatamod.DataModuleCreate(Sender: TObject);
begin
  ezAppSettings := TStringList.Create();
 
  ezAppSettings.LoadFromFile(ExtractFilePath(Application.ExeName)+CustomDataFolder+CustomCfgFile);
  lbl_ezCompany           := ezAppSettings.GetValue('Company');
  lbl_ezSoftwareCaption   := ezAppSettings.GetValue('Software Caption');
  lbl_ezCopyright         := ezAppSettings.GetValue('Copyright');
  lbl_ezWebsite           := ezAppSettings.GetValue('Website');
  lbl_ezCustomAppCaption  := ezAppSettings.GetValue('Custom Application Caption');
  lbl_ezCustomCompanyCode := ezAppSettings.GetValue('CCny');
  if trim(lbl_ezCustomCompanyCode) = '' then lbl_ezCustomCompanyCode := '001';
  if length(lbl_ezCustomAppCaption) > 0 then lbl_ezCustomAppCaption := ' - '+lbl_ezCustomAppCaption;
  ...
end;

Encrypting Data

Sometimes customization data needs to be encrypted to avoid third-parties from tapering with it. To encrypt these values, use custom component TEncryptStr.

To decrypt the data so that it is ready for use, use something like this:

procedure TDatamod.ezAppSettingsDecryption(Sender: TObject);
var
  i: integer;
begin
  // decode values just loaded, and store them back into ezAppSettings
  for i:=0 to ezAppSettings.Items.count-1 do begin
    ezAppSettings.Items.ValueFromIndex[i] := EncryptStr1.DecodeVigenere(EncryptStr1.Key, ezAppSettings.GetValueFromIndex(i));
  end;
end;

Customizing the Product List

Create a text file called prodlist.cfg, formatted as:

product name=product code
Intuition 2=prod_Intuition2
Intuition 2FC (Feedback Canceller)=prod_Intuition2FC
Intuition 4=prod_Intuition4
Intuition 4+=prod_Intuition4Plus
Intuition 4AD (Adaptive Directionality)=prod_Intune
Intuition Directional=prod_Intuition4D
Sparo (Open Ear OTE, 4 Channels)=prod_Sparo
Sparo AD (Open Ear OTE, 4 Channels)=prod_SparoAD
Sparo 2  (Open Ear OTE, 2 Channels)=prod_Sparo2
...

A list of product short names is a good idea as well. Create a file prodlist-short.cfg:

Intuition 2=prod_Intuition2
Intuition 2FC=prod_Intuition2FC
Intuition 4=prod_Intuition4
Intuition 4+=prod_Intuition4Plus
Intuition 4AD=prod_Intune
Intuition D=prod_Intuition4D
Sparo=prod_Sparo
Sparo AD=prod_SparoAD
Sparo 2=prod_Sparo2
...

Load the product values in the application:

unit dbmod;
 
interface
  ...
const
  CustomDataFolder       = 'data\';
  CustomProdListFile     = 'prodlist.cfg';
  CustomProdLstShortFile = 'prodlist-short.cfg';
var
  ezProductList : TStrings;
  ...
 
procedure TDatamod.DataModuleCreate(Sender: TObject);
begin
  ezProductList := TStringList.Create();
  ezProductList.LoadFromFile(ExtractFilePath(Application.ExeName)+CustomDataFolder+CustomProdListFile,      // longnames list
                             ExtractFilePath(Application.ExeName)+CustomDataFolder+CustomProdLstShortFile); // shortnames list
end;

Use the product names just by referring to their respective product codes. For example:

procedure TfrmMain.InitialSetup();
begin
  lbl_Intuition_4     := Datamod.ezProductList.GetShortNamefromValue('prod_Intuition4');
  lbl_Intuition_4D    := Datamod.ezProductList.GetShortNamefromValue('prod_Intuition4D');
  lbl_Intuition_4Plus := Datamod.ezProductList.GetShortNamefromValue('prod_Intuition4Plus');
  lbl_Sparo           := Datamod.ezProductList.GetShortNamefromValue('prod_Sparo');
  lbl_Sparo_2         := Datamod.ezProductList.GetShortNamefromValue('prod_Sparo2');
  lbl_Sparo_AD        := Datamod.ezProductList.GetShortNamefromValue('prod_SparoAD');
end;

Customizing the Application Graphics

  • Create logos, splash images, and icons, then place them in a subfolder called images.
  • Create a resource DLL with the logos, splash images, and application icons. For example, in splashres.rc:
    SPLASH_AUDINAT     BITMAP "images\splash-audinat.bmp"
    SPLASH_AUDITIVA    BITMAP "images\splash-auditiva.bmp"
    SPLASH_AUDITIVADK  BITMAP "images\splash-auditivadk.bmp"
    SPLASH_AURI        BITMAP "images\splash-auri.bmp"
    SPLASH_BTE675DP    BITMAP "images\splash-bte675dp.bmp"
    SPLASH_HEARINGCENTRAL BITMAP "images\splash-hearingcentral.bmp"
    SPLASH_NEWSON      BITMAP "images\splash-newson.bmp"
    SPLASH_NORTHEY     BITMAP "images\splash-northey.bmp"
    SPLASH_SONITECH    BITMAP "images\splash-sonitech.bmp"
    SPLASH_PHSI        BITMAP "images\splash-phsi.bmp"
    SPLASH_TRANSEAR    BITMAP "images\splash-transear.bmp"
    SPLASH_VISTAHIA    BITMAP "images\splash-vistahia.bmp"
    ICON_AUDINA     ICON "images\icon-audina.ico"
    ICON_AUDINADE   ICON "images\icon-audina.ico"
    ICON_AUDINAT    ICON "images\icon-audinat.ico"
    ICON_AUDITIVA   ICON "images\icon-ezfit.ico"
    ICON_AUDITIVADK ICON "images\icon-ezfit.ico"
    ICON_AURI       ICON "images\icon-ezfit.ico"
    ICON_BTE675DP   ICON "images\icon-bte.ico"
    ICON_HEARINGCENTRAL ICON "images\icon-ezfit.ico"
    ICON_NEWSON     ICON "images\icon-newson.ico"
    ICON_NORTHEY    ICON "images\icon-ezfit.ico"
    ICON_PHSI       ICON "images\icon-ezfit.ico"
    ICON_SONITECH   ICON "images\icon-ezfit.ico"
    ICON_TRANSEAR   ICON "images\icon-transear.ico"
    ICON_VISTAHIA   ICON "images\icon-vistahia.ico"
  • NOTE: The order of the resources is critical if icon indexes are used during application installation. The installer will see indexes in the same order that icons are listed in the resource file. For example:
    //--------------------------------------------------------------
    // Icon numbering (required by WiseInstaller/InnoSetup)
    // IMPORTANT: Icon numbering is dependent on alphabetical order
    //--------------------------------------------------------------
    // 0  = ICON_AUDINA         ICON "icon-audina.ico"
    // 1  = ICON_AUDINADE       ICON "icon-audina.ico"
    // 2  = ICON_AUDINAT        ICON "icon-audinat.ico"
    // 3  = ICON_AUDITIVA       ICON "icon-ezfit.ico"
    // 4  = ICON_AUDITIVADK     ICON "icon-ezfit.ico"
    // 5  = ICON_AURI           ICON "icon-ezfit.ico"
    // 6  = ICON_BTE675DP       ICON "icon-bte.ico"
    // 7  = ICON_HEARINGCENTRAL ICON "icon-ezfit.ico"
    // 8  = ICON_NEWSON         ICON "icon-newson.ico"
    // 9  = ICON_NORTHEY        ICON "icon-ezfit.ico"
    // 10 = ICON_PHSI           ICON "icon-ezfit.ico"
    // 11 = ICON_SONITECH       ICON "icon-ezfit.ico"
    // 12 = ICON_TRANSEAR       ICON "icon-transear.ico"
    // 13 = ICON_VISTAHIA       ICON "icon-vistahia.ico"
    
    //--------------------------------------------------------------
    // NOTE: Do not forget to update custom scripts in:
    //<drive>:\programming\audina\installation\scripts\ezfit4\Firebirdsupport\customized
    //<drive>:\programming\audina\installation\scripts\ezfit4\innosetup
    // For example: In WiseInstaller, auditiva.txt  ==>  _APPICONNUM_=3
    //              In InnoSetup, Auditiva ==> AppIconIdx=3
    // Any new customization requires that these files and their corresponding
    // icon number match.
    //--------------------------------------------------------------
  • Define Company Codes. For example, in ezConst.pas:
      // Audina customization clients code (CCny)
      client_Audina          = 001;   // reserved
      client_Audifone        = 002;   // http://www.audifone.com
      client_Auritone        = 003;   // http://www.auritone.com.ar
      client_Acoustics       = 004;
      client_AudinaKorea     = 005;
      client_Newson          = 006;
      client_TransEar        = 007;   // http://www.transear.com (http://www.eartech.com)
      client_Auditiva        = 008;   // http://www.audina.net
      client_Northey         = 009;
      client_VistaHIA        = 010;   // http://www.vistahearing.net
      client_Sonitech        = 011;
      client_AudiNat         = 012;   // http://www.audinat.com.mx
      client_Auri            = 013;   // http://www.audi.dk
      client_HearingCentral  = 014;   // http://www.hearingcentral.com
      client_BTE675DPFitting = 015;   // no website
      client_AuditivaDenmark = 016;   // http://www.audina.net
      client_AudinaGermany   = 017;   // http://www.audina-hoersysteme.de
      client_PHSI            = 018;   // http://www.phsimd.com
  • Load the resource DLL, selecting the custom images based on the Company Code (see Customizing Application Basics). For example, in frmSplash.pas:
    procedure TfrmSplash.FormActivate(Sender: TObject);
    var
      hResource : THandle;
      CustomCompanyCode: integer;
    begin
      // load application settings
      ezAppSettings.LoadFromFile(ExtractFilePath(Application.ExeName)+'data\ezfit.cfg');
     
      if not TryStrToInt(ezAppSettings.GetValue('CCny'), CustomCompanyCode) then CustomCompanyCode:=001;
     
      if (CustomCompanyCode <> client_Audina) then begin
        // show customized splash
         hResource := LoadLibrary('Splash.DLL');
         try
           case CustomCompanyCode of
             client_Audina: //--- Audina -------------------------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_AUDINA');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_AUDINA');
               end;
     
             client_AudinaGermany: //--- Audina Germany ----------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_AUDINADE');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_AUDINA');
               end;
     
             client_AudiNat: //--- Audi-nat Mexico ---------------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_AUDINAT');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_AUDINAT');
               end;
     
             client_Auditiva: //--- Auditiva ---------------------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_AUDITIVA');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_AUDITIVA');
               end;
     
             client_AuditivaDenmark: //--- Auditiva (Denmark) ----------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_AUDITIVADK');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_AUDITIVADK');
               end;
     
             client_Auri: //--- Auri HoreCenter (Denmark) --------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_AURI');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_AURI');
               end;
     
             client_BTE675DPFitting: //--- BTE675DPFitting -------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_BTE675DP');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_BTE675DP');
               end;
     
             client_HearingCentral: //--- HearingCentral.com -----------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_HEARINGCENTRAL');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_HEARINGCENTRAL');
               end;
     
             client_Newson: //--- Newson -------------------------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_NEWSON');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_NEWSON');
               end;
     
             client_Northey: //--- Northey -----------------------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_NORTHEY');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_NORTHEY');
               end;
     
             client_Sonitech: //--- Sonitech Hearing Center ------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_SONITECH');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_SONITECH');
               end;
     
             client_PHSI: //--- PHSI -----------------------------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_PHSI');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_PHSI');
               end;
     
             client_TransEar: //--- TransEar ---------------------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_TRANSEAR');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_TRANSEAR');
               end;
     
             client_VistaHIA: //--- Vista Hearing Instruments & Audiology ----------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_VISTAHIA');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_VISTAHIA');
               end;
     
             else //--- default ----------------------------------------------------
               begin
                 Image1.Picture.Bitmap.LoadFromResourceName(hResource, 'SPLASH_AUDINA');
                 Application.Icon.Handle := LoadIcon(hResource, 'ICON_AUDINA');
               end;
           end; {endcase}
         finally
           FreeLibrary(hResource);
         end;
      end;
     
    end;

Customizing the User Documentation

#--------------------------------------------------------------------------
# Custom Configuration files and Custom Variables
# Use variables as usual. For example: @CompanyName or \CompanyName
#--------------------------------------------------------------------------
ALIASES = "CompanyName=ACME, Inc." \
          "CompanyNameShort=ACME" \
          "CompanyWebsite=http://www.acme.com" \
          "CompanyLogoJPG=splash01.jpg" \
          "CompanyLogoEPS=splash01.eps" 
@INCLUDE_PATH = includes
@INCLUDE      = customproj.cfg

Add custom values to a custom configuration file. For example, in customproj.cfg:

#--------------------------------------------------------------------------
# Custom Settings
#--------------------------------------------------------------------------
OUTPUT_DIRECTORY  = customoutput\acme
IMAGE_PATH        = images custom\images
ENABLED_SECTIONS  = StandaloneOnly Acme
HTML_HEADER       = includes\header.html
HTML_FOOTER       = includes\footer.html
CHM_FILE          = UserDoc.CHM
 
#--------------------------------------------------------------------------
# Custom Variables
#--------------------------------------------------------------------------
ALIASES = "CompanyName=ACME 2, Inc." \
          "CompanyNameShort=ACME 2" \
          "CompanyWebsite=http://www.acme2.com" \
          "CompanyLogoJPG=ezfit-splash01-acme2.jpg" \
          "CompanyLogoEPS=ezfit-splash01-acme2.eps"

In file 104-hi-swrequirementmatrix.txt, setup list of custom products for the company:

@if Acme1
  ...
@elseif Acme2
  ...
@endif

Customizing External Utilities