To create a MapInfo Pro add-in in python:
- 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
- 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.
- 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