I have a base tool class which handles 90% of my custom logic, but some tools need to set themselves as the current tool. The operations between ArcGIS Engine's IToolbarControl and ArcGIS Desktop's IApplication interface are different.

With ArcGIS Desktop, I need to have a reference to ESRI.ArcGIS.Framework, which is unavailable in a pure ArcEngine deployment.

Is there any way to set the Current Tool property without needing a reference to ESRI.ArcGIS.Framework?

As a side note: Any way of getting the ArcGIS Desktop's window handle without resorting to the Win32 API?

  • 1
    Why do you need to set yourself as the current tool? – Craig Williams Jul 7 '11 at 19:28
  • It's essentially to save a few clicks. We have some floating forms (network tracing, for example), which need to interact with the map, and the original developers wanted to have the form reactivate itself, say after a user zoomed in or out, or panned. They ended up using slews of preprocessor directives to change tools back and forth from ArcEngine to ArcDesktop, creating a maintenance nightmare. I was hoping to try to consolidate some of those operations without ending up with a wholesale rewrite. – StyxRiver Jul 8 '11 at 14:01
  • 1
    Sorry to say there is not a good solution for the particular problem. You'll need different hooks in different places. – Craig Williams Jul 29 '11 at 6:15

If you work in .NET, you could take advantage of its mechanism of assembly loading.

In a nutshell, an assembly is typically loaded into memory when one if its types is first accessed. A type is first accessed when a method which contains a reference to that type begins to execute.

This means that you can have your assembly reference the ESRI.ArcGIS.Framework interop assembly even in pure ArcGIS Engine environment - as long as any methods which work with this assembly never execute. If they don't ever begin to execute, the CLR will not attempt to load the dependency.

This is well-defined behavior, meaning you can rely on it without worrying it will change between CLR releases.

If this is still not suitable for your scenario, there are other things you could do, such as define a simple interface for setting the current tool and use some kind of dependency injection/inversion of control. You'd have another two assemblies, each of them would implement the interface in a different way and thus have its own set of assembly dependencies. The key is to inject the appropriate behavior, which is typically done through configuration, but some IoC containers can also do that at runtime.

  • I ended up creating a base assembly with two different abstract BaseTool implementations, one for Engine and the other for Desktop. I end up having two tool classes per assembly, but it has worked out quite well. – StyxRiver Aug 9 '11 at 13:58

Assuming you have a map control in your application, you can just use the .CurrentTool property to set it. Is that what you are looking for or did I misinterpret the question?

AxMapControl mapControl;
mapControl.CurrentTool = (ITool) SomeCommand;
  • Misinterpreted just a bit. ArcDesktop doesn't use an AxMapControl, or if it does, I've yet to find out how to reference it. It goes through a different mechanism to set the CurrentTool. – StyxRiver Aug 9 '11 at 13:45

If you want to write tools that work in both Desktop and Engine, then you can (try) to use the HookHelper class. I forget the details, but I did run into issues with this a few yrs ago. I ended up rolling my own inversion of control (as described by @Petr).


In Desktop apps, IApplication.hWnd off of AppRef gives you the window handle:

The handle of the application's window.

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.