Skip to main content
1 of 4
Petr Krebs
  • 10.3k
  • 1
  • 23
  • 33

So, in the light of the tips in Kirk's link (ArcMap Automation: Man the Message Pumps!) and the knowledge that IObjectFactory must be used your scenario, here's my take on Python implementation of the discussed workaround. I am not versed in Python, in fact this might only be my fifth piece of Python code or so, if memory serves. If anyone wants to improve it in any way, go ahead.

import ctypes
import threading

class EsriAppMessageHelper(threading.Thread):
    def __init__(self, windowHandle):
        threading.Thread.__init__(self)
        self.running = True
        self.windowHandle = windowHandle

    def stop(self):
        self.running = False

    def run(self):
        while self.running:
            ctypes.windll.user32.SendMessageA(self.windowHandle, 0, 0, 0)
            #print 'WM_NULL to window %d sent' % self.windowHandle

    def __enter__(self):
        self.start()

    def __exit__(self, type, value, traceback):
        self.stop()

Basically, it's a thread which sends WM_NULL (0) messages to the given window. The __enter__ and __exit__ functions support Python's with statement. Here's how it's used (the ArcObjects related functions are taken from this post in a different question):

app = GetApp()    # get the IApplication reference

# WM_NULL messages will be sent from another thread while
# this block is executing
with EsriAppMessageHelper(app.hWnd):

    objectFactory = CType(app, esriFramework.IObjectFactory) # use IObjectFactory
    mxDoc = CType(app.Document, esriArcMapUI.IMxDocument)
    graphicsContainer = mxDoc.ActiveView.GraphicsContainer

    textElement = CType(objectFactory.Create("esriCarto.TextElement"), esriCarto.ITextElement)

    # initialize the symbols and elements, assign their geometries
    # etc...

    graphicsContainer.AddElement(element, 0)
    mxDoc.ActiveView.PartialRefresh(esriCarto.esriViewGraphics, None, None)

# At this point, we're out of the WITH block.
# The separate thread is stopped and no more WM_NULL messages are being sent.
print "DONE"

Try it out. I could not fully test it with my ArcMap 10 setup because I did not have any issues with the active view refresh (it executed immediately and refresh was successful), but the WM_NULL messages do get sent.

Petr Krebs
  • 10.3k
  • 1
  • 23
  • 33