Creating a Python Add-in - MapInfo_Pro - 2023

MapInfo Pro Help

Product type
Software
Portfolio
Locate
Product family
MapInfo
Product
MapInfo > MapInfo Pro
Version
2023
ft:locale
en-US
Product name
MapInfo Pro
ft:title
MapInfo Pro Help
First publish date
1985
ft:lastEdition
2023-09-12
ft:lastPublication
2023-09-12T16:39:16.995000
To create a MapInfo Pro add-in in python:
  1. Use one of the existing python add-in templates to start with your add-in. The MapBasic version 2019 installation contains two python add-in templates for creating a simple MapInfo Pro add-in or a layout custom frame add-in in python.
    • SAMPLES\RIBBONINTERFACE\Python\py_addin_templates\Simple
    • SAMPLES\RIBBONINTERFACE\Python\py_addin_templates\CustomFrame
  2. Copy one of the add-in templates listed above and start modifying it.
    • Start with renaming the files (PY and MB) to your add-in name.
    • Rename module reference as per your new file names.
    • Check for all TODO in python code and modify the code as per your requirement.
  3. Once the code is completed, you can run the main python file directly in MapInfo Pro. If your add-in does not have a corresponding .mbx file, a new one with the same base filename as the .py file will be created next to it. This means that the location must be write-able. You can also create, customize and compile the template .mb file.
Note: The name of the MapBasic MB file should be the same as the main python module file. Also, the class below should be present in the main Python module file to load the add-in.
# this class is needed with same name in order to load the python add-in and can be copied
# as it is when creating another add-in.
class main():
    def __init__(self, imapinfopro):
        self._pro = imapinfopro

    def load(self):
        try:
            # uncomment these lines to debug the python script using VSCODE
            # Debug in VSCODE with Python: Attach configuration

            #ptvsd.enable_attach()
            #ptvsd.wait_for_attach()
            #ptvsd.break_into_debugger()

            if self._pro:
                # obtain the handle to current application if needed
                self.thisApplication = self._pro.GetMapBasicApplication(os.path.splitext(__file__)[0] + ".mbx")

        except Exception as e:
            print("Failed to load: {}".format(e))


    def unload(self):
        try:
            print("Unloading")
            self._pro.Ribbon.Tabs['TabMap'].Groups[0].Controls.Remove(self._button)
        except Exception as e:
            print("Failed to unload: {}".format(e))

    def __del__(self):
        self._pro = None
        pass

    def addin_name(self) -> str:
        return "Hello Python Add-in"

    def addin_description(self) -> str:
        return "Hello Python Add-in Description"

    def addin_defaultcommandtext(self) -> str:
        return "Hello Python Add-in Default Command"

    def addin_defaultcommand(self):
        self.on_hello_button_clicked(self)

    def addin_imageuri(self) -> str:
        return join(dirname(__file__), "images/copyright16.png")

Loading a MapInfo Pro Python Add-in

To Load a python addin in MapInfo Pro, you need to create a startup MapBasic script which will load the Python module and start executing it. The following sample mapbasic script templates can be used as is or can be modified for loading a Python add-in in MapInfo Pro.
'MBX Template for Simple Python Addin
'*****************************************************************************
'       Copyright 2020 Precisely
'       All rights reserved.
'****************************************************************************/
Include "mapbasic.def"
Include "IMapInfoPro.def"
Include "ResStrng.def"

Declare Method PyAddinAbout Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_About(ByVal p1 as This)
Declare Method PyAddinHelp Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_Help(ByVal p1 as This)
Declare Method PyAddinDefaultCommand Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_DefaultCommand(ByVal p1 as This)
Declare Method PyAddinVersion Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_Version(ByVal p1 as This) As String
Declare Method PyAddinName Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_Name(ByVal p1 as This) As String
Declare Method PyAddinDescription Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_Description(ByVal p1 as This) As String
Declare Method PyAddinImageUri Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_ImageUri(ByVal p1 as This) As String
Declare Method PyAddinHideRunningProgram Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_HideRunningProgram(ByVal p1 as This) As Logical
Declare Method PyAddinProcessCommandUri Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_ProcessCommandUri(ByVal p1 as This, ByVal commandUri as String) As Logical
Declare Method PyAddinDefaultCommandText Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_DefaultCommandText(ByVal p1 as This) As String

Declare Sub EndHandler
Declare Sub Main

Declare Sub AddIn_About
Declare Sub AddIn_Help
Declare Sub AddIn_DefaultCommand
Declare Function AddIn_Name() As String
Declare Function AddIn_Description() As String
Declare Function AddIn_ImageUri() As String
Declare Function AddIn_Version() As String
Declare Function AddIn_AssemblyName() As String
Declare Function AddIn_ClassName() As String
Declare Function AddIn_HideRunningProgram() As Logical
Declare Function AddIn_ProcessCommandUri(ByVal commandUri as String) As Logical
Declare Function AddIn_DefaultCommandText() As String

Global mapinfoApplication as This
Global mbAddIn as This

Sub Main
    onerror goto ErrorTrap

        if (SystemInfo(SYS_INFO_MIPLATFORM) = MIPLATFORM_WIN64) then
            if (SystemInfo(SYS_INFO_MAPINFO_INTERFACE) = MIINTERFACE_RIBBON) then
                goto ContinueSample
            end if
        end if

    InvalidScenario:
        Note "This sample can only work with 64-bit Ribbon Interface UX."
        goto Done
    ContinueSample:

    dim app_name as string
    app_name = ApplicationName$()
    app_name = Left$(app_name,len(app_name) - 4)

    dim str_file as string
    str_file = ApplicationDirectory$() + app_name + ".str"
    If FileExists(str_file) Then
        If LoadStrings(str_file) = FALSE Then
            Note GetResString(IDS_Res_Load_Error) + ApplicationDirectory$() + app_name + ".str"
            Exit Sub
        End If
    End If

    mapinfoApplication = SYSTEMINFO(SYS_INFO_IMAPINFOAPPLICATION)
    mbAddIn = New_PythonAddin()

    if mbAddIn <> 0 Then
        call InitializePyAddin(mbAddIn, mapinfoApplication, ApplicationDirectory$() + ApplicationName$())
    End if

    Done:
    Exit Sub

    ErrorTrap:
        Note "Main: " + Str$(err()) + ": " + Error$()
        Resume done

End Sub

Sub EndHandler
    If mapinfoApplication <> 0 and mbAddIn <> 0 Then
        call UnloadPyAddin(mbAddIn)
    End If
    mbAddIn = NULL_PTR
    mapinfoApplication = NULL_PTR
End Sub

Sub AddIn_About
    call PyAddinAbout(mbAddIn)
End Sub

Sub AddIn_Help
    call PyAddinHelp(mbAddIn)
End Sub

Sub AddIn_DefaultCommand
    call PyAddinDefaultCommand(mbAddIn)
End Sub

Function AddIn_Version() As String
    AddIn_Version = PyAddinVersion(mbAddIn)
End Function

Function AddIn_Name() As String
    AddIn_Name = PyAddinName(mbAddIn)
End Function

Function AddIn_Description() As String
    AddIn_Description = PyAddinDescription(mbAddIn)
End Function

Function AddIn_ImageUri() As String
    AddIn_ImageUri = PyAddinImageUri(mbAddIn)
End Function

Function AddIn_HideRunningProgram() As Logical
    AddIn_HideRunningProgram = PyAddinHideRunningProgram(mbAddIn)
End Function

Function AddIn_DefaultCommandText() As String
    Addin_DefaultCommandText= PyAddinDefaultCommandText(mbAddIn)
End Function

Function AddIn_ProcessCommandUri(ByVal commandUri as String) As Logical
    AddIn_ProcessCommandUri = PyAddinProcessCommandUri(mbAddIn, commandUri)
End Function
'MBX Template for Layout Custom Frame Python Addin
'*****************************************************************************
'       Copyright 2020 Precisely.
'       All rights reserved.
'****************************************************************************/
Include "mapbasic.def"
Include "IMapInfoPro.def"
Include "ResStrng.def"

Declare Method PyAddinAbout Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_About(ByVal p1 as This)
Declare Method PyAddinHelp Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_Help(ByVal p1 as This)
Declare Method PyAddinDefaultCommand Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_DefaultCommand(ByVal p1 as This)
Declare Method PyAddinVersion Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_Version(ByVal p1 as This) As String
Declare Method PyAddinName Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_Name(ByVal p1 as This) As String
Declare Method PyAddinDescription Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_Description(ByVal p1 as This) As String
Declare Method PyAddinImageUri Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_ImageUri(ByVal p1 as This) As String
Declare Method PyAddinHideRunningProgram Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_HideRunningProgram(ByVal p1 as This) As Logical
Declare Method PyAddinProcessCommandUri Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_ProcessCommandUri(ByVal p1 as This, ByVal commandUri as String) As Logical
Declare Method PyAddinDefaultCommandText Class "MapInfo.Types.PythonAddinLoader" Lib "MapInfo.Types.dll" Alias AddIn_DefaultCommandText(ByVal p1 as This) As String

Declare Sub EndHandler
Declare Sub Main

Declare Sub AddIn_About
Declare Sub AddIn_Help
Declare Sub AddIn_DefaultCommand
Declare Function AddIn_Name() As String
Declare Function AddIn_Description() As String
Declare Function AddIn_ImageUri() As String
Declare Function AddIn_Version() As String
Declare Function AddIn_AssemblyName() As String
Declare Function AddIn_ClassName() As String
Declare Function AddIn_HideRunningProgram() As Logical
Declare Function AddIn_ProcessCommandUri(ByVal commandUri as String) As Logical
Declare Function AddIn_DefaultCommandText() As String

Global mapinfoApplication as This
Global mbAddIn as This

Sub Main
    onerror goto ErrorTrap

        if (SystemInfo(SYS_INFO_MIPLATFORM) = MIPLATFORM_WIN64) then
            if (SystemInfo(SYS_INFO_MAPINFO_INTERFACE) = MIINTERFACE_RIBBON) then
                goto ContinueSample
            end if
        end if

    InvalidScenario:
        Note "This sample can only work with 64-bit Ribbon Interface UX."
        goto Done
    ContinueSample:

    dim app_name as string
    app_name = ApplicationName$()
    app_name = Left$(app_name,len(app_name) - 4)

    dim str_file as string
    str_file = ApplicationDirectory$() + app_name + ".str"
    If FileExists(str_file) Then
        If LoadStrings(str_file) = FALSE Then
            Note GetResString(IDS_Res_Load_Error) + ApplicationDirectory$() + app_name + ".str"
            Exit Sub
        End If
    End If

    mapinfoApplication = SYSTEMINFO(SYS_INFO_IMAPINFOAPPLICATION)
    mbAddIn = New_PythonCustomFrameAddin()

    if mbAddIn <> 0 Then
        call InitializePyAddin(mbAddIn, mapinfoApplication, ApplicationDirectory$() + ApplicationName$())
    End if

    Done:
    Exit Sub

    ErrorTrap:
        Note "Main: " + Str$(err()) + ": " + Error$()
        Resume done

End Sub

Sub EndHandler
    If mapinfoApplication <> 0 and mbAddIn <> 0 Then
        call UnloadPyAddin(mbAddIn)
    End If
    mbAddIn = NULL_PTR
    mapinfoApplication = NULL_PTR
End Sub

Sub AddIn_About
    call PyAddinAbout(mbAddIn)
End Sub

Sub AddIn_Help
    call PyAddinHelp(mbAddIn)
End Sub

Sub AddIn_DefaultCommand
    call PyAddinDefaultCommand(mbAddIn)
End Sub

Function AddIn_Version() As String
    AddIn_Version = PyAddinVersion(mbAddIn)
End Function

Function AddIn_Name() As String
    AddIn_Name = PyAddinName(mbAddIn)
End Function

Function AddIn_Description() As String
    AddIn_Description = PyAddinDescription(mbAddIn)
End Function

Function AddIn_ImageUri() As String
    AddIn_ImageUri = PyAddinImageUri(mbAddIn)
End Function

Function AddIn_AssemblyName() As String
    Addin_AssemblyName = "MapInfo.Types"
End Function

Function AddIn_ClassName() As String
    Addin_ClassName = "MapInfo.Types.PythonCustomFrameAddinLoader"
End Function

Function AddIn_HideRunningProgram() As Logical
    AddIn_HideRunningProgram = PyAddinHideRunningProgram(mbAddIn)
End Function

Function AddIn_DefaultCommandText() As String
    Addin_DefaultCommandText= PyAddinDefaultCommandText(mbAddIn)
End Function

Function AddIn_ProcessCommandUri(ByVal commandUri as String) As Logical
    AddIn_ProcessCommandUri = PyAddinProcessCommandUri(mbAddIn, commandUri)
End Function