Using Microsoft's COM or OLE technology, many customers have create full applications the embed maps and other pro windows into their own applications. Other have use COM to connect to Pro, either visible or in the background to customize the UI or to automate tasks from other applications. Typically these were done via C++, Visual Basic, VB script, or .NET.
This approach was de-emphasized but not eliminated for a while during the transition to 64 bit versions of Pro. Recently starting with version 2019.2 the development team has been putting more effort restoring the ability to embed maps, browser and certain tool windows, largely to support customers migrating their applications to newer version of Pro.
One benefit of this for Python developers is that there are several good Python libraries for interacting with COM technologies to open up using Pro in this manner via Python.
I am attaching two sample python scripts that demonstrate this to make you aware of the possibilities. Note that these will not work completely correctly until 2019.3 is released later this year.
The samples will also be added to the PythonQuickStart app available in the MapInfo Marketplace.
-Bob
Here is the code from one of the samples:
import os
os.environ['QT_USE_NATIVE_WINDOWS'] = "1"
import win32com.client
import win32com.server.util
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QHBoxLayout, QVBoxLayout, QPushButton, QGridLayout
from PyQt5 import QtGui
class MIOLECallback:
def __init__(self, pro):
self._pro = pro
_public_methods_ = ['WindowContentsChanged', 'SetStatusText' , 'MenuItemHandler', 'SayHello']
def WindowContentsChanged(self, windowId: int):
self._pro.Do('print "WindowContentsChanged {}"'.format(windowId))
def SetStatusText(self, message: str):
self._pro.Do('print "SetStatusText: {}"'.format(message))
def MenuItemHandler(self, commandInfo: str):
self._pro.Do('print "MenuItemHandler: {}"'.format(commandInfo))
def SayHello(self, commandInfo: str):
self._pro.Do('print "Hello {}"'.format(commandInfo))
class CustomQTDialog(QDialog):
def __init__(self, *args, **kwargs):
super(CustomQTDialog, self).__init__(*args, **kwargs)
self._pro = win32com.client.Dispatch("MapInfo.Application.x64")
callback = win32com.server.util.wrap(MIOLECallback(self._pro))
self._pro.RegisterCallback(callback)
self.setWindowTitle("Python IntegratedMapping")
self.resize(300, 300)
vlayout = QVBoxLayout()
self._cLayout = QVBoxLayout()
vlayout.addLayout(self._cLayout)
hlayout = QHBoxLayout()
b2 = QPushButton()
b2.setText("Show MapInfo Pro")
b2.clicked.connect(self.button_action_pro_visible)
hlayout.addWidget(b2)
vlayout.addLayout(hlayout)
self.setLayout(vlayout)
def button_action_pro_visible(self):
if self._pro:
phwnd = int(self._pro.Eval("SystemInfo(SYS_INFO_MAPINFOWND)"))
self._pro.Do("Set Application Window {}".format(phwnd))
self._pro.Do('Alter ButtonPad "SpatialCreateBar" Add PushButton Calling OLE "SayHello" Large HelpMsg "Hello\\nSay Hello" Tab "TabSpatial" ')
self._pro.Do("Alter Menu \"MapperShortcut\" Add \"Custom Item\" ID 10000 calling OLE \"MenuItemHandler\"")
self._pro.Do("Alter Menu \"MapperShortcut\" add \"Layer Control\" ID 8001 calling 801")
self._pro.Visible = True
def __del__(self):
if self._pro:
self._pro = None
def application():
app = QApplication(sys.argv)
try:
qtdlg = CustomQTDialog()
qtdlg.exec_()
finally:
app.exit()
if __name__ == '__main__':
application()
------------------------------
Bob Fortin
Software Architect and Distinguished Engineer
MapInfo Pro Development Team
------------------------------