Drawing order
To better understand the events that are fired when a map draws, the following describes the order in which objects are drawn for each view (Map and PageLayout):
-
Map (data view)—The following table shows top-to-bottom order (each item is drawn above the items beneath it):
Object
|
Phase
|
Cache
|
Graphic selection | esriViewForeground | none |
Clip border | esriViewForeground | none |
Feature selection | esriViewGeoSelection | selection |
Auto labels | esriViewGraphics | annotation |
Graphics | esriViewGraphics | annotation |
Layer annotation | esriViewGraphics | annotation |
Layers | esriViewGeography | layer or layers |
Background | esriViewBackground | bottom layer |
-
PageLayout—The following table shows top-to-bottom order (each item is drawn above the items beneath it):
Object
|
Phase
|
Cache
|
Snap guides | esriViewForeground | none |
Selection | esriViewGraphicSelection | selection |
Elements | esriViewGraphics | element |
Snap grid | esriViewBackground | element |
Print margins | esriViewBackground | element |
Paper | esriViewBackground | element |
Drawing events
The following IActiveViewEvents can be used to add custom drawing to your application:
- AfterDraw(display, esriViewBackground)
- AfterDraw(display, esriViewGeography)
- AfterDraw(display, esriViewGeoSelection)
- AfterDraw(display, esriViewGraphics)
- AfterDraw(display, esriViewGraphicSelection)
- AfterDraw(display, esriViewForeground)
- AfterItemDraw(display, idx, esriDPGeography)
- AfterItemDraw(display, idx, esriDPAnnotation)
- AfterItemDraw(display, idx, esriDPSelection)
The AfterDraw event is fired after every phase of drawing. Do the following to draw a graphic into a cache:
- Create an object that connects to the active view (map); for example, Events.
- Choose the draw phase that you want to draw after. The phase you choose determines what is drawn above and below you.
- Draw in response to IActiveViewEvents.AfterDraw.
Not all the views fire all the events. Additionally, if a view is partially refreshed, the phases that draw from cache do not fire their AfterDraw event. For example, if the selection is refreshed, all the layers draw from cache. As a result, the AfterDraw(esriViewGeography) event does not fire; however, there is an exception. In the case of esriViewForeground, the event is fired every time the view draws. Even if everything in the map draws from the recording cache, the foreground event still fires.
Enabling item events with VerboseEvents
The AfterItemDraw event is fired after each feature or graphic is displayed and can seriously impact drawing performance if a connected handler is not efficient. Normally, clients connect to the AfterDraw event.
It is important to check the second argument and respond to the appropriate phase of drawing since the AfterDraw routine will be called several times when the map is drawn.
For efficiency, IActiveView has a VerboseEvents property. It can be used to limit the number of events that are fired. If VerboseEvents = false, AfterItemDraw is not fired (this is the default setting).
Events and display caching
The following tables show the handle device context (HDC) that is active when each of the AfterDraw events is fired:
Event
|
Active HDC
|
esriViewForeground | window |
esriViewGraphics | annotation cache |
esriViewGeoSelection | selection cache |
esriViewGeography | top layer cache |
esriViewBackground | bottom layer cache |
Event
|
Active HDC
|
esriViewForeground | window |
esriViewGraphicSelection | selection cache |
esriViewGraphics | element cache |
esriViewBackground | element cache |
Creating a private cache
For drawing graphics (events), you may want to use esriViewGraphics. AfterDraw has two arguments: pDisplay and drawPhase. It is called for each of the phases, so make sure you only draw when your phase is specified. Draw directly to the display and do not worry about caches. The StartDrawing and FinishDrawing methods are called by map. If the phase you are drawing after is cached, your drawing is automatically cached. See the following:
- Create the cache in response to IDocumentEvents.ActiveViewChanged. Map creates its cache in response to Activate and throws away all caches in response to Deactivate. The ActiveViewChanged event is fired after map creates its cache, so if there is not enough memory, the map gets its cache but the private cache doesn't. See the following code example:
IActiveView pActiveView = pMap as IActiveView;
IScreenDisplay pScreen = pActiveView.ScreenDisplay;
pScreen.AddCache(m_myCacheID);
[VB.NET]
Dim pActiveView As IActiveView = CType(pMap, ActiveView)
Dim pScreen As IScreenDisplay = pActiveView.ScreenDisplay
pScreen.AddCache(m_myCacheID)
- AfterDraw looks like the following code example:
if (phase != esriViewXXX)
{
return ;
}
IScreenDisplay pScreen = pDisplay;
if ((!(pScreen == null)))
{
// Draw directly to output device.
DrawMyStuff(pDisplay);
return ;
}
// Draw to screen using cache if possible.
long hWindowDC;
WindowDC = pScreen.WindowDC;
bool bDirty;
pScreen.IsCacheDirty(m_myCacheID, bDirty);
if ((bDirty))
{
// Draw from scratch.
pScreen.FinishDrawing();
pScreen.StartDrawing(hWindowDC, m_myCacheID);
DrawMyStuff(pDisplay);
}
else
{
// Draw from cache.
pScreen.DrawCache(hWindowDC, m_myCacheID, null, null);
}
[VB.NET]
If Not (phase = esriViewXXX) Then
Return
End If
Dim pScreen As IScreenDisplay = pDisplay
If (Not (pScreen Is Nothing)) Then
' Draw directly to output device.
DrawMyStuff(pDisplay)
Return
End If
' Draw to screen using cache if possible.
Dim hWindowDC As Long
WindowDC = pScreen.WindowDC
Dim bDirty As Boolean
pScreen.IsCacheDirty(m_myCacheID, bDirty)
If (bDirty) Then
' Draw from scratch.
pScreen.FinishDrawing()
pScreen.StartDrawing(hWindowDC, m_myCacheID)
DrawMyStuff(pDisplay)
Else
' Draw from cache.
pScreen.DrawCache(hWindowDC, m_myCacheID, Nothing, Nothing)
End If
Transform events
The ITransformEvents interface provides access to display transformation events. ITransformEvents have their counterparts in the properties of the IDisplayTransformation.
For instance, ITransformEvents.BoundsUpdated is fired when IDisplayTransformation.Bounds is set. For information on these properties and the related ITransformEvents, refer to the documentation for IDisplayTransformation. See the following illustration:
One scenario in which ITransformEvents is useful is when implementing a custom graphic element. By sinking the outbound ITransformEvents interface of the DisplayTransformation, you can update the custom element to reflect changes, such as the data frame being rotated. You can also use ITransformEvents to update the element's selection tracker geometry correctly when the map scale changes.
Development licensing | Deployment licensing |
---|---|
ArcGIS for Desktop Basic | ArcGIS for Desktop Basic |
ArcGIS for Desktop Standard | ArcGIS for Desktop Standard |
ArcGIS for Desktop Advanced | ArcGIS for Desktop Advanced |
Engine Developer Kit | Engine |