jps services
  • Home Page
  • GIS Training Courses
    • QGIS Training Courses
    • ArcGIS Training Courses
    • MapInfo Pro Training Courses >
      • MapBasic Training Course
  • About
  • Blog

Updating MapBasic menu based legacy code to a ribbon based interface

11/9/2017

0 Comments

 
The PrintLayout program provided by Egge-Jan Pollé on his website is a code sample which iterates through polygons in a map in order to create individual maps from a selection of departmental polygons. This code has the potential to be updated into an atlas like program for general use within MapInfo Pro.
As a first step let’s review what the PrintLayout offers in functionality terms. If you download and extract the folders you are given both the .mb and .mbx files together with folders and a map of France. The screen shot below shows the make up of the files.

Picture
The MBExtensions.dll provides extra date functionality regarding date formats and there is an explanation within the code concerning this option. There are two folders Output and Tables. The code puts any created maps into the Output folder. The Tables folder contains a map of France.
If you run the program in any recent version of MapInfo Pro the program will still run, but as legacy code as shown in the following screen shot:-
Picture
The program has a menu based interface which can be updated to a ribbon interface as will be shortly shown. If you click on the first menu option provided by the Print Layout sample code a dialogue box checks to let the user save any open tables. A new map of France displays then a list box option appears as shown in the following screen shot.
Picture
This MultiListBox option lists all the Regions of France and provides options to print a selection, or if required, all of them. There are also options to choose between A4 and A3 paper sizes. Selecting several Regions will result in the program automatically creating maps of the relevant departments for those regions. The maps will then be saved in the Output folder. Here is an example of the printout for Alsace.
Picture
The first thing to note about this program is that all the information is hard coded. The program currently only works with a specific map of France and related data such as the company information which is already in written into the code. If you want to use a different map and update the company data then the program has to be re-compiled for the updates to take effect. So as mentioned before, this program is an excellent template for creating an atlas program but will need more than a ribbon interface for it to be viable for general use.
The following code covers all the procedures and functions in the program.

Declare Sub Main
Declare Sub MLB
Declare Sub PrintLayoutDefaultSettings
Declare Sub CreateMaps
Declare Sub LayoutPortrait
Declare Sub LayoutLandscape
Declare Sub MLBOKButton
Declare Sub SelectAllFromMLB
Declare Sub HighLightSelectedRegions
Declare Sub PopulateRegionsArray
Declare Sub About
Declare Sub End_Program

'Function to check whether a table is open or not
Declare Function TableIsOpen (ByVal sTabName As String) As Logica

' ///// Class "MBExtensions.MBDateAndTime" /////
' Allows you to retreive information from a MapBasic Date (i.e. YYYYMMDD) or
' DateTime (i.e. YYYYMMDDHHMMSSFFF) string

' Convert the string to it's equivalent long date string representation
' (depends on Control Panel > Regional and Language Options)
Declare Method RegionalLongDate
Class "MBExtensions.MBDateAndTime"
Lib "MBExtensions.dll" (ByVal sDateString as string) As String

The Main procedure contains the menu based code sample which will be updated to a ribbon based interface in due course.

The following variables are assigned as follows:-

sOutputFolder = ApplicationDirectory$() + "Output\"

sTabFile = ApplicationDirectory$() + "Tables\FR_Départements2006.TAB"
sTable = PathToTableName$(sTabFile)
sColA = "Nom_Région"
sColB = "Nom_Département"
In order to use the program with another table, in this case the States table, we need to update the code as follows:-

sTabFile = ApplicationDirectory$() + "Tables\STATES.TAB" ' "Tables\FR_Départements2006.TAB"
sTable = PathToTableName$(sTabFile)
sColA = "State_Name" '"Nom_Région"
'sColB = "Nom_Département"

The above code allocates sTabFile to the States table and changes the State_Name to sColA. The sColB and information about the French map are disabled as they are only valid for the original code.
Open the STATES table from the MapInfo Trial Data folder and then save a copy in the Tables folder. The Tables folder should now match the next screen shot:-
Picture
In the MLB procedure changes are made to reflect the use of the States map:-

If CommandInfo(CMD_INFO_DLG_OK) Then

   For l = 1 To Ubound(iRegionsSelectedArray)
   sRegion = sRegionsArray(iRegionsSelectedArray(l))
   sRegionTitle = "Map of " + sRegionsArray(iRegionsSelectedArray(l))
   '  "Les départements de la région " + sRegionsArray(iRegionsSelectedArray(l))
   Call CreateMaps
   Next

End If

Some original code is again commented out. Note that the only change is to the variable sRegionTitle.
Similarly the PrintLayoutDefaultSettings is updated with relevant company details as follows:-

'*********************************************************************************************
Sub PrintLayoutDefaultSettings
'*********************************************************************************************
OnError Goto ErrorHandler
sPrintDate = CurDate()
sPrintDate = RegionalLongDate(sPrintDate)
sCopyrightText = Chr$(169) + Chr$(32) + Year(CurDate()) + " - JPS Services"
' " - My wonderful team"
sFont = "Arial"
sAddressArray(1) = "JPS Services" '"My own company name"
sAddressArray(2) = "Southport" '"My own company address"
sAddressArray(3) = "07857 692628" '"My own company phone number"
sAddressArray(4) = "info@jpsservices.org.uk" '"My own company email address"
sAddressArray(5) = '"www.jpsservices.org.uk" '"My own company website"

Exit Sub
'---------------------------
ErrorHandler:
Note Error$()
End Sub PrintLayoutDefaultSettings

In the CreateMaps the following code puts a company logo into the printed map. To update it choose an appropriate logo and overwrite the default and create a tab file for your own logo.

Open Table ApplicationDirectory$() + "My_own_company_logo.TAB"
Map From My_own_company_logo
iLogoWindowID = WindowID(FrontWindow())

Further in the code we need make a change as we do not need ColB when iterating through each State chosen in the States table.

Map From RegionSelected
iMapWindowID = WindowID(FrontWindow())

If iOrientation = 1 Then
Set Window FrontWindow() Position (0,0) units "cm" Width 19*fMp units "cm" Height 24.5*fMp units "cm"
ElseIf iOrientation = 2 Then
Set Window FrontWindow() Position (0,0) units "cm" Width 27.7*fMp units "cm" Height 15.8*fMp units "cm"
End If
Set Map Window iMapWindowID Zoom Entire Layer RegionSelected
'sCommand = "Set Map Window " + iMapWindowID + " Layer RegionSelected Label With " + sColB + " Auto Retry On"
sCommand = "Set Map Window " + iMapWindowID + " Layer RegionSelected Label With " + sColA + " Auto Retry On"
Now we have made these changes we should be able to compile and run the program with the States map. When compiled and run we should see similar to the following:-
Picture
The MultiListBox now shows the American States data from the browser information for the State_Name column. If we choose Delaware and select Print we will obtain a map similar to the following:-
Picture
If we zoom in to the bottom of the map we can see that we now have data relevant to a specific organisation.
Picture
The next stage is to upgrade the code to the ribbon interface. Before creating the ribbon interface we should look at the various elements of the program to review the way the various parts work together to automatically create a map or series of maps.
Sub Main
As mentioned this program holds the menu based code and some variables are initialised.

Sub MLB
This program creates a dialogue box which includes a MultiListBox box. Hence MLB as the name of the procedure. At the beginning of the code block an explanation is given regarding the ReadControlValue(). The code checks for an open table and whether there are any selections. After this PopulateRegionsArray is called.

Then for each selection the CreateMaps procedure is called.

PrintLayoutDefaultSettings
Here the various settings are used to populate each map.

Sub CreateMaps
This procedure creates the individual maps from, in this example, the States chosen by the user.

LayoutPortrait and LayoutLandscape
These two procedures create either a portrait or landscape layout for the maps depending on the user’s choice.

Sub MLBOK Button
Checks whether a State has been selected. Assigns the ReadControlValues.

Sub SelectAllFromMLB
Selects or deselects all the states.

Sub HighLightSelectedRegions
This procedure highlights any state which is selected by the user.

Sub PopulateRegionsArray
This procedure creates the array containing, in this example, all the States which will populate the MLB MultiListBox.

Sub About
Dialog box explaining the purpose of the program as well as its author.

Sub End_Program
Checks whether you want to close the program

Function TableIsOpen
Checks for whether a table is open or not and returns a logical True or False.

Method RegionalLongDate
The purpose of this method RegionalLongDate is covered within the program code.

Upgrading to the ribbon interface involves creating a definition file, a .mbp project file and modules for each of the functions and procedures. Additionally, we need to add several more folders to our project. One folder is named mb code to contain the modules, another Images for ribbon icons and then one more named Library which is saved within the mb code folder.

When created the set up should look like the following screen shot:-
Picture
Next we need to create a definition file and put all the relevant Includes, Definitions, Functions, Procedures and Variables needed for the program.

Here is the PrintLayout.def:-
'************************************************************************************
'** Project
'**
'** Definition file
'**
'** Author: Joseph Short
'** Date: 9th September 2017
'** Version: AppVersion (see below)
'************************************************************************************
Include "MAPBASIC.DEF"
Include "ICONS.DEF"
Include "MENU.DEF"
Include "Enums.def"
Include "Library\RIBBONLib.def"
Include "Library\MAPPERLib.def"

Declare Sub Main
Declare Sub MLB
Declare Sub PrintLayoutDefaultSettings
Declare Sub CreateMaps
Declare Sub LayoutPortrait
Declare Sub LayoutLandscape
Declare Sub MLBOKButton
Declare Sub SelectAllFromMLB
Declare Sub HighLightSelectedRegions
Declare Sub PopulateRegionsArray
Declare Sub About
Declare Sub End_Program
Declare Sub Endhandler

'Function to check whether a table is open or not
Declare Function TableIsOpen (ByVal sTabName As String) As Logical

' ///// Class "MBExtensions.MBDateAndTime" /////
' Allows you to retreive information from a MapBasic Date (i.e. YYYYMMDD) or
' DateTime (i.e. YYYYMMDDHHMMSSFFF) string

' Convert the string to it's equivalent long date string representation
' (depends on Control Panel > Regional and Language Options)
Declare Method RegionalLongDate
Class "MBExtensions.MBDateAndTime"
Lib "MBExtensions.dll" (ByVal sDateString as string) As String

Define AppName "Print Layout Ribbon Sample Code"
'Define AppNameMenu "Print &Layout"
Define AppVersion "0.60
'Defining Dialog Width and Height
'This allows you to specify width and height clauses in terms of characters (i.e., Width 30dW, Height 10dH).
Define dW *4 'Four dialog units equals one character in width
Define dH *8 'Eight dialog units equals one character in height
Define MLBID 1001
Define SelectAllMLBID 1002

Global sTabFile, sTable, sColA, sColB, sRegionsArray(), sAddressArray(5), sPrintDate, sCopyrightText, sFont, sRegion, sRegionTitle, sPrinterName, sDocTitle, sPapersize, sOutputFolder as String
Global iRegionsSelectedArray(), iPaperChoice, iPapersize, iLogoWindowID, iMapWindowID, iLayoutWindowID, iLayoutFontSize1, iLayoutFontSize2, iLayoutFontSize3, iLayoutFontSize4, iOrientation as Integer
Global fZoom, fMp, fPaper1, fPaper2, fPaperWidth, fPaperHeight, fHorizontalDistance, fVerticalDistance, fPos1, fPos2 As Float

Next we need to create the ribbon interface module. Here is the code for RibbonPrintLayoutInterface.mb to update the menu based version of PrintLayout.

'************************************************************************************
'** Project
'**
'** Module Sub Main
'**
'** Author: Joseph Short
'** Date: 9th September 2017
'** Version: AppVersion (see below)
'************************************************************************************
Include "PrintLayout.def"
Sub Main
sOutputFolder = ApplicationDirectory$() + "Output\"
sTabFile = ApplicationDirectory$() + "Tables\STATES.TAB" '"Tables\FR_Départements2006.TAB"
sTable = PathToTableName$(sTabFile)
sColA = "State_Name" '"Nom_Région"
'sColB = "Nom_Département"

Dim nCtrlIdx as Integer
Dim sTabName, sGroupName, marrModProgramsNames(), marrModProgramsImages() as Strin

' Check for the existence of the TAB named tabRibbonPrintLayoutApp
sTabName = "tabRibbonPrintLayoutApp"
If NOT RBNTabExists(sTabName) Then
nCtrlIdx = RBNAddTab(sTabName,"Ribbon Print Layout App","F")
If nCtrlIdx = 0 Then
Note "An error occurred whilst adding a new tab called + '" + sTabName + "' to the ribbon"
Exit Sub
End If
End If
sGroupName = "grpRibbonPrintLayoutApp"
If NOT RBNTabGroupExists(sTabName,sGroupName) Then
nCtrlIdx = RBNTabAddGroup(sGroupName, "Ribbon Print Layout",sTabName)
If nCtrlIdx = 0 Then
Exit Sub
End If
End If
ReDim marrModProgramsNames(1)
ReDim marrModProgramsImages(1)
marrModProgramsNames(1) = "Ribbon Print Layout Example"
marrModProgramsImages(1) = ApplicationDirectory$() + "\Images\Output.png"
nCtrlIdx = RBNGroupAddButton("RibbonPrintLayout", marrModProgramsNames(1),"",sTabName,sGroupName)
If nCtrlIdx > 0 Then
' Create and set the button tooltip
Call RBNControlSetToolTipIdx(nCtrlIdx,"Ribbon Print Layout App","Start module '" + marrModProgramsNames(1)+ "'","")
' Set the button icon
Call RBNControlSetIconsIdx(nCtrlIdx,CONTROL_SIZE_LARGE,"",marrModProgramsImages(1))
' Set Custom MapBasic handle to the button
Call RBNControlSetCustomMBXHandlerIdx(nCtrlIdx,"MLB")
End If
ReDim marrModProgramsNames(2)
ReDim marrModProgramsImages(2)
marrModProgramsNames(2) = "About example"
marrModProgramsImages(2) = ApplicationDirectory$() + "\Images\Info.png"
nCtrlIdx = RBNGroupAddButton("Aboutexample", marrModProgramsNames(2),"",sTabName,sGroupName)
If nCtrlIdx > 0 Then
' Create and set the button tooltip
Call RBNControlSetToolTipIdx(nCtrlIdx,"Ribbon Print Layout Example App","Start module '" + marrModProgramsNames(2)+ "'","")
' Set the button icon
Call RBNControlSetIconsIdx(nCtrlIdx,CONTROL_SIZE_LARGE,"",marrModProgramsImages(2))
' Set Custom MapBasic handle to the button
Call RBNControlSetCustomMBXHandlerIdx(nCtrlIdx,"About")
End If
Call RBNNotificationShow("Ribbon Print Layout Sample Code App", "Launching....", Notify_Info, 4000)
End Sub Main

Sub Endhandler
'Ask the RibbonHandler to tidy up before the app ends
Call RBNEndHandler
End Sub Endhandler
The other modules can be created by cutting and pasting code from the original PrintLayout.mb. Here is the format for each module. This one creates the About module.
'************************************************************************************
'** Project
'**
'** Module Sub Main
'**
'** Author: Joseph Short
'** Date: 9th September 2017
'** Version: AppVersion
'*******************************************************************************
Include "PrintLayout.def"
'*********************************************************************************************
Sub About
'*********************************************************************************************
Dialog
Title "About " + AppName + " (Version " + AppVersion + ")"
Control StaticText title "This application provides an example of how to use" Position 3dW, 1dH
Control StaticText title "the Ribbon interface in an automated map creation MapBasic application" Position 3dW, 2dH
Control StaticText title Chr$(169) + " 2017 - JPS Services with acknowledgement to Egge-Jan Pollé" Position 35dW, 6dH
Control OKButton Title "&Exit" Calling End_Program
Control CancelButton
End Sub About
When all the modules have been created and compiled the next state is to create the .mbp file. Here is the RibbonPrintLayout.mbp:-
[Link]
Application=..\RibbonPrintLayout.mbx
Module=Library\ARRAYLib.mbo
Module=Library\DEBUGLib.mbo
Module=Library\ERRORLib.mbo
Module=Library\RIBBONLib.mbo
Module=RibbonPrintLayoutInterface.mbo
Module=About.mbo
Module=CreateMaps.mbo
Module=HighlightSelectedRegions.mbo
Module=LayoutLandscape.mbo
Module=LayoutPortrait.mbo
Module=MLB.mbo
Module=MLBOKButton.mbo
Module=PopulateRegionsArray.mbo
Module=PrintLayoutDefaultSettings.mbo
Module=SelectAllFromMLB.mbo
Module=End_Program.mbo
Module=TableIsOpen.mbo
When the program is compiled and linked you can run the resulting RibbonPrintLayout.mbx.
Here is a screenshot of the program:-
Picture
Here is the MultiListBox containing a list of all the States.
Picture
So far we have modified the code so as to be able to use a different map from the original French map provided. We have also changed the Print Layout default settings to be more relevant to a specific organisation.

In the next blog we will go to next stage which involves adding modules which will enable the user to create maps from either a single table or a workspace of their own choice. Additionally a module will be created for a dialogue box to update company details as required rather than having to modify code.
0 Comments

Your comment will be posted after it is approved.


Leave a Reply.

    Author

    Joe Short BSc has been involved with various mapping solutions for over twenty years.  If you are considering implementing a GIS  or have ArcGIS Pro, MapInfo Pro or QGIS training requirements, jps services would be happy to be of assistance to your organisation. 

    Archives

    April 2020
    March 2020
    October 2019
    September 2019
    August 2019
    July 2019
    March 2019
    November 2018
    October 2018
    August 2018
    July 2018
    November 2017
    October 2017
    September 2017
    July 2017
    February 2017
    January 2017
    December 2016
    November 2016
    October 2016
    May 2016
    February 2016
    September 2015
    August 2015
    April 2015
    February 2015
    November 2014
    October 2014
    July 2014
    June 2014
    May 2014
    March 2014
    February 2014
    December 2013
    November 2013
    October 2013
    September 2013
    August 2013
    June 2013
    May 2013
    April 2013
    February 2013
    December 2012
    October 2012
    September 2012
    August 2012
    July 2012

    Categories

    All
    Arc Gis
    Arcview
    Autodesk
    Cad
    Gis Training
    Local Government
    Mapbasic
    Mapinfo
    Quantum Gis
    Relational Databases
    Saga Gis

    RSS Feed