4

I'm trying to handle the closing event of ArcMap (10.0 SP5) within an ESRI Addin Extension using C# and Arcobjects. Furthermore I would like to handle 'a closing event', that is fired BEFORE ArcMap tries to stop a started edit session. As background: I want to create an extension that does the database handling automatically without asking the user if he wants to save the changes in the database when closing ArcMap (this should happen programmatically).

At first I tried to handle the ESRI.ArcGIS.ArcMapUI.IDocumentEvents.BeforeCloseDocument, but this event will be fired AFTER ArcMap tries to stop an active edit session. The situation is not different with the ESRI.ArcGIS.Editor.IEditEvents2_Event.BeforeStopEditingevent. In both cases the user is asked if he wants to save the changes before one can handle the event. And at last I tried the ESRI.ArcGIS.Desktop.AddIns.Extension.OnShutdown event, but this is fired much more later after the user is asked for saving the changes in the Geodatabase and saving the MXD. Now I am at my wit’s end.

Does anyone else has an idea or a workaround? Have I missed another event? Is it possible to ‘cast’ the ArcMap application window to System.Windows.Forms.Form to wire the FormClosing event?

  • Have you tried IEditEvents.OnStopEditing? – Hornbydd Sep 30 '15 at 10:32
  • Yes, it is fired after the the user decided to save or discard his changes, too. – Propper Sep 30 '15 at 12:07
  • What about calling the ArcMap Command Save Edits for each change/edit event during the edit session? See here. Its a bit redundant but will commit changes as they happen, without ending the current edit session. – Barbarossa Sep 30 '15 at 14:20
  • I have already checked this option before. I handled the events OnCreateFeature, OnChangeFeature and OnDeleteFeature and for all these events I tried to execute the command ‘esriEditor.SaveEditsCommand’ as you suggested. However this brings me several other problems. Calling the ArcMap command Save Edits raises the OnChangeFeature again, so I ended in an endless loop. Furthermore this command internally stops and restarts the edit session what results in losing the last active tool and especially losing the edit template (IEditTemplate) the user selected for creating a feature. – Propper Oct 1 '15 at 8:22
  • There is another event IWorkspaceEditEvents2.OnBeginStopEditing. It is called before changes are saved to the database, but it is fired AFTER the user selected to save or discard changes, too. Unfortunately still no solution. – Propper Oct 1 '15 at 10:12
2
+50

Try hooking IApplication.hWnd in OnStartup() and catching WM_CLOSE. This will fire before you are prompted to save edits. It will also fire regardless of whether the user selected "File - Exit" or the "X" in the top-right corner of the window.

Calling StopEditing(true) in WM_CLOSE does save the edits; however, the user may (will) still be prompted to save edits. You should also call StartEditing(ws) in case the user Cancels the ArcMap Close.

Note: Other extensions/addins may not be happy w/ this e.g. I tested (Save Design) w/ ArcFM Designer and it resulted in all design toolbar buttons being disabled; which is unacceptable if the user Cancels the Close. More fiddling w/ the code may be able to work around this.

e.g.

public class ArcAppWnd : global::System.Windows.Forms.NativeWindow
{
    public const int WM_CLOSE = 0x10;
    protected IntPtr hWnd;

    public ArcAppWnd( int HWND ) : base() 
    {
        hWnd = new IntPtr(HWND);
        AssignHandle(hWnd);
    }

    protected override void WndProc( ref Message MSG )
    {
        switch( MSG.Msg ) {
            case WM_CLOSE:
                if( App.Editor.HasEdits() ) {
                    var ws = App.Editor.EditWorkspace as IWorkspaceEdit;
                    ws.StopEditing(true);
                    ws.StartEditing(true);
                }
                break;
        }
        base.WndProc(ref MSG);
    }
}

and in the extension ...

ArcAppWnd appWnd;

public void Startup( ref object INITIALIZATIONDATA ) {
    ...
    var app = INITIALIZATIONDATA as IAppication;
    appWnd = new ArcAppWnd(app.hWnd);
    ...
}

(Replace App.Editor w/ whatever you use to get/track IEditor)

  • Great! That was exactly the thing I thought about (as last hope) but couldn’t implement before on my own AND it works! One question concerning the programming philosophy. This is obviously not the intension of the ArcObjects developer? I’ve a little doubtful feeling to implement this. ‘Steeling’ the handle and misuse a pseudo window for this purposes. It looks a little bit like hacking or is this legitimately programming? Thanks for the other good hints. My extension will run in an encapsulated environment and for the MXD I set the dirty flag, to prevent the user to abort the close of ArcMap. – Propper Sep 7 '16 at 11:23
  • It's not common, but I don't know if I'd call it a 'hack'. NativeWindow was created to allow code like this. It is a .NET technique and has nothing to do with ArcObjects. You aren't 'stealing' the handle, you are wrapping a Win32 handle with a .NET object. AssignHandle is subclassing the Win32 window, which is a well established Win32 programming pattern. The main possible issue is perf overhead in having to Marshal each message to the main ArcMap window between Win32 and .NET. – Chris Kushnir Sep 7 '16 at 17:29
  • Thanks for the additional information which convinces me to implement this. – Propper Sep 8 '16 at 7:31
2

If you wait to hook your editor until the BeforeCloseDocument event fires, BeforeCloseDocument will fire BEFORE ArcMap tries to stop the edit session. This will give you the opportunity to stop the edit operation and save edits and will suppress the "save edits" dialog. When I hooked the editor on extension creation, the BeforeCloseDocument event fired - AFTER - ArcMap tried to save edits. Code below works for me everytime. EDIT: Moving the hook to OnStartUp will give you access to the editor and will also allow for the saving of edits during BeforeCloseDocument, before ArcMap tries to stop the edit session. My version is 10.4.

public class OnCloseSave : ESRI.ArcGIS.Desktop.AddIns.Extension
{
    private IEditor m_editor;
    private IApplication m_application;
    private IDocument m_doc;

    public OnCloseSave()
    {
        m_application = this.Hook as IApplication;
        m_doc = m_application.Document;
        //hook editor here causes arcmap to stop edit session before calling BeforeCloseDocument

        IDocumentEvents_Event docEvents = (IDocumentEvents_Event)m_doc;
        docEvents.BeforeCloseDocument += new IDocumentEvents_BeforeCloseDocumentEventHandler(BeforeCloseDocument);
    }

    protected override void OnStartup()
    {
        m_editor = this.Hook as IEditor;

        UID editorUid = new UID();
        editorUid.Value = "esriEditor.Editor";

        m_editor = m_application.FindExtensionByCLSID(editorUid) as IEditor;
    }
    protected override void OnShutdown()
    {

    }

    void ActiveViewChanged()
    {
        throw new NotImplementedException();
    }

    bool BeforeCloseDocument()
    {


        if (m_editor.HasEdits())
        {
            m_editor.StopOperation("");
            m_editor.StopEditing(true);
                        }  
        return false;
    }

    void CloseDocument()
    {
        throw new NotImplementedException();
    }

    void MapsChanged()
    {
        throw new NotImplementedException();
    }

    void NewDocument()
    {
        throw new NotImplementedException();
    }

    bool OnContextMenu(int x, int y)
    {
        throw new NotImplementedException();
    }

    void OpenDocument()
    {
        throw new NotImplementedException();
    }
}
  • I’ve set up a new test extension and used exactly your posted code but the BeforeCloseDocument event is fired AFTER the "save edits" dialog again. Which ArcGIS version are you using. I have ArcGIS 10.0 SP5 installed. Furthermore I need the editor during the whole life time of the extension because I’m handling OnCreateFeature, OnChangeFeature and OnDeleteFeature to show some custom dialogs to provide the user with more clearer interfaces and I’m rearranging the edit template (IEditTemplate) automatically. – Propper Sep 6 '16 at 14:39
  • Made an edit to the answer that will allow access to the editor and still allow for saving before ArcMap tries to close the edit session. However, my version is 10.4 and this could account for the difference in order of events. – Brad Sep 6 '16 at 15:40
  • I have been in contact with an ESRI support employee years ago and he told me there is a different behavior in event handling between 10.1 and 10.2. The events are handled much faster and in a different order between 10.1 and the following versions. At that time I didn’t suspect that this will affect me that fast. At the moment I will implement one of the other solutions, but when we change the ArcGIS version your solution seams to be the cleanest. – Propper Sep 7 '16 at 11:01
1

Handle OnStopOperation event, that is called when an edit operation is finished. So you don't need to handle OnCreate or OnChange events seperatelly. However ensure that all of your custom edits are bracketed with an edit operation. In ArcGIS almost every tool underpins an edit operation.

In the handler, call IWorkspaceEdit.StopEditing(true) to save edits and then IWorkspaceEdit.StartEditing(true) to restart the editing; this is what 'Save Edits' command does internally.

  • 1
    This is a very good workaround which generally solves my problem. Thank you very much. The only disadvantage is, that saving, stop editing and start editing is done each time a feature is created which is to the disadvantage of the performance. And in my special case the most frequent case is to discard all changes on shutdown of ArcMap. That’s why I will keep the bounty alive for the moment. If there is no better solution which handles the closing of ArcMap directly, you’ll of course get the award. – Propper Sep 6 '16 at 10:29
  • Remember, the undo stack is cleared on Save. Some users may prefer the risk of not hitting "Yes" to save edits vs losing the ability to undo. – Chris Kushnir Sep 6 '16 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.