Select to view content in your preferred language

problem using IDisplay.DrawPolygon & screen refresh

2515
5
07-07-2011 07:23 AM
by Anonymous User
Not applicable
Original User: Scole

I ported over a "zoom to parcel" tool from VBA to VB.NET and, in the process I wanted to change part of its functionality. Originally, my script added a graphic polygon element to the display to let the user know which parcel was the one they were interested in.

I wanted to modify this so that the parcel highlight was only drawn to the screen temporarily instead of added as a graphic element. I re-wrote this section of my code to use IDisplay.DrawPolygon but when the code is actually run, the events seem out of sequence. Here's the relevent code:

pEnvelope = pGeometry.Envelope
pEnvelope.Expand(1.5, 1.5, True)

pActiveView.Extent = pEnvelope
pActiveView.refresh

pScreenDisplay = pActiveView.ScreenDisplay
pScreenDisplay.StartDrawing(pScreenDisplay.hDC, CShort(ESRI.ArcGIS.Display.esriScreenCache.esriNoScreenCache))
pScreenDisplay.SetSymbol(pFillSymbol)
pScreenDisplay.DrawPolygon(pGeometry)
pScreenDisplay.FinishDrawing()


So, from the user experience side, here's the order of events as I witness them:

  1. display zooms to the extent of the parcel

  2. the parcel outline draws (the DrawPolygon step)

  3. the actual parcel features draw

It all happens very fast but the drawing of the data features wipes out my DrawPolygon highlight. How do I get the order of events to behave the way I have coded them??

I tried throwing a System.Threading.Thread.Sleep() statement into the mix but it doesn't correct the issue; it literally just delays it.

Thanks!
Steve
0 Kudos
5 Replies
by Anonymous User
Not applicable
Original User: Scole

Wanted to bump this since I still haven't figured this out. I also forgot to ask someone from ESRI about this while I had my chance at the UC. Doh!..

Thanks!
0 Kudos
NeilClemmons
Honored Contributor
Where are you calling this code from?  If you're not calling it inside the IActiveviewEvents.AfterDraw event then whatever you draw will disappear the next time anything causes the screen to refresh.
0 Kudos
by Anonymous User
Not applicable
Original User: Scole

Hi Neil,

Sorry for not making that clear- this code snippet is at the very end of a Ok button click() event from a dialog (to obtain the parcel number from the user). I understand that my drawing will disappear upon the next redraw and that's ok. I just wanted to give the user a brief visual on which parcel was the one they specified and did not want to clutter the document with graphic elements if I didn't need to.

I'm just at a loss to explain how the actual display redraw after zooming into the extent of the parcel happens AFTER the drawPolyon code despite being before the drawPolygon line of code.
0 Kudos
NeilClemmons
Honored Contributor
It's probably getting overwritten because the pActiveView.Refresh call hasn't finished.  The call to Refresh will return before the actual refreshing of the map is complete.  You will probably have to add the drawing code to the AfterDraw event or listen for the DisplayFinished event and execute the drawing code after it has fired.
0 Kudos
by Anonymous User
Not applicable
Original User: Scole

Thanks, Neil. What you describe makes sense. I decided to pursue your suggestion and implemented an event listener on the AfterDraw event. I wasn't quite sure how to do it since I've never done one before but, after some reading up on the issue, it seems to work like I want it to. For the benefit of others, here's what I did:

I used the event listener code for the .NET snippet named "Add Event Wiring for All IActiveViewEvents Snippet." To backtrack, my code to zoom to a parcel's extent is contained in the click event of a dialog form. In the declaractions part of the VB code for the form, I inserted:

    Private m_ActiveViewEventsAfterDraw As ESRI.ArcGIS.Carto.IActiveViewEvents_AfterDrawEventHandler
    Dim pGeometry As ESRI.ArcGIS.Geometry.IGeometry = Nothing


The event handler requires a small subroutine to initiate it so I added the following into the main body of VB code for my form:

    Private Sub SetupActiveViewEvents(ByVal map As ESRI.ArcGIS.Carto.IMap)

        If map Is Nothing Then
            Return
        End If

        Dim activeViewEvents As ESRI.ArcGIS.Carto.IActiveViewEvents_Event = TryCast(map, ESRI.ArcGIS.Carto.IActiveViewEvents_Event)

        'Create an instance of the delegate, add it to AfterDraw event
        m_ActiveViewEventsAfterDraw = New ESRI.ArcGIS.Carto.IActiveViewEvents_AfterDrawEventHandler(AddressOf OnActiveViewEventsAfterDraw)
        AddHandler activeViewEvents.AfterDraw, m_ActiveViewEventsAfterDraw
    End Sub


That could is straight off of the snippet. Nothing custom yet. The next thing I inserted was the subroutine that gets triggered by the AfterDraw event and it is also inserted into the main body of VB code:

    Private Sub OnActiveViewEventsAfterDraw(ByVal display As ESRI.ArcGIS.Display.IDisplay, ByVal phase As ESRI.ArcGIS.Carto.esriViewDrawPhase)
        'Highlight the parcel's shape on screen
        Dim pFillSymbol As ESRI.ArcGIS.Display.ISimpleFillSymbol
        Dim pLineSymbol As ESRI.ArcGIS.Display.ILineSymbol
        Dim pRgbColor As ESRI.ArcGIS.Display.IRgbColor
        Dim pScreenDisplay As ESRI.ArcGIS.Display.ScreenDisplay = Nothing
        Dim pActiveView As ESRI.ArcGIS.Carto.IActiveView

        If Not pGeometry Is Nothing And phase = ESRI.ArcGIS.Carto.esriViewDrawPhase.esriViewForeground Then
            pActiveView = My.ArcMap.Document.FocusMap

            pFillSymbol = New ESRI.ArcGIS.Display.SimpleFillSymbol
            pRgbColor = New ESRI.ArcGIS.Display.RgbColor
            pLineSymbol = pFillSymbol.Outline

            pRgbColor.Red = 255

            pLineSymbol.Width = 2.25
            pLineSymbol.Color = pRgbColor
            pFillSymbol.Color = pRgbColor

            pFillSymbol.Outline = pLineSymbol
            pFillSymbol.Style = ESRI.ArcGIS.Display.esriSimpleFillStyle.esriSFSHollow

            pScreenDisplay = pActiveView.ScreenDisplay
            pScreenDisplay.StartDrawing(pScreenDisplay.hDC, CShort(ESRI.ArcGIS.Display.esriScreenCache.esriNoScreenCache))
            pScreenDisplay.SetSymbol(pFillSymbol)
            pScreenDisplay.DrawPolygon(pGeometry)
            pScreenDisplay.FinishDrawing()
            pGeometry = Nothing
        End If
    End Sub


Everything in the sub is what I wrote. I had to give this subroutine a way to access the parcel's geometry so that is why I declared it globally at the top of the class. I also discovered that the AfterDraw event is triggered multiple times during one redraw (due to the various "phases"). The esriViewForeground is the last phase in the sequence so that's why I specifcally mention it in my IF..THEN block.

It's also important to set the geometry to Nothing at the end of this routine. If you do not, it will keep drawing the shape on the screen (even though the form is dismissed).

The last step is very simple. In the subroutine for my form's OK button click event, I added this line to actually fire off the event listener:

SetupActiveViewEvents(pMap)


That's it. The display zooms to the parcel and it gets a red outline. The next display refresh wipes it clean. Thanks again for the pointing me in the right direction, Neil!

Cheers,
Steve
0 Kudos