1

I am new to this and still trying to learn. I have a bunch of VBA code that I am trying to convert to C# and even the most basic things are hanging me up.

Currently I am trying to build a button that pans the display Left when pressed.

The original VBA code that I have looks as follows:

Sub pan_left()
On Error GoTo Errhandler


   Dim pMxDocument As IMxDocument
   Dim pactiveview As IActiveView
   Dim penv As IEnvelope
   Dim pxmax, pxmin, pymax, pymin As Double
   Dim nxmax, nxmin, nymax, nymin As Double
   Dim width, height As Double

   Set pMxDocument = ThisDocument
   Set pactiveview = pMxDocument.FocusMap
   Set penv = pactiveview.Extent

   pxmax = penv.XMax
   pxmin = penv.XMin
   pymax = penv.YMax
   pymin = penv.YMin

   width = pxmax - pxmin
   height = pymax - pymin
   nxmax = pxmax + (width / 1.08)
   nxmin = pxmin + (width / 1.08)
   nymax = pymax
   nymin = pymin

   penv.XMax = nxmax
   penv.XMin = nxmin
   penv.YMax = nymax
   penv.YMin = nymin

   pactiveview.Extent = penv
   pactiveview.Refresh

ThisDocument.fTimer
Exit Sub
Errhandler:
On Error Resume Next


End Sub

I have been trying to write it using the Desk top Addins. I have found some code on ESRI's website found here: Pan Left (Not sure if I am even on the right track.)

Currently my code looks as follows:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.ADF.CATIDs;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Framework;



namespace NAIP_QQv1

{



    [ClassInterface(ClassInterfaceType.None)]

    [Guid("593EDF4F-D1FE-4a8d-8076-C3B583C37F6B")]



    public class PanDown : ICommand

    {
    #region COM Registration Function(s)
    [ComRegisterFunction()]
    [ComVisible(false)]
    static void RegisterFunction(Type registerType)
    {
        // Required for ArcGIS Component Category Registrar support
        ArcGISCategoryRegistration(registerType);

        //
        // TODO: Add any COM registration code here
        //
    }

    [ComUnregisterFunction()]
    [ComVisible(false)]
    static void UnregisterFunction(Type registerType)
    {
        // Required for ArcGIS Component Category Registrar support
        ArcGISCategoryUnregistration(registerType);

        //
        // TODO: Add any COM unregistration code here
        //
    }

    #region ArcGIS Component Category Registrar generated code
    /// <summary>
    /// Required method for ArcGIS Component Category registration -
    /// Do not modify the contents of this method with the code editor.
    /// </summary>
    private static void ArcGISCategoryRegistration(Type registerType)
    {
        string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
        ControlsCommands.Register(regKey);

    }
    /// <summary>
    /// Required method for ArcGIS Component Category unregistration -
    /// Do not modify the contents of this method with the code editor.
    /// </summary>
    private static void ArcGISCategoryUnregistration(Type registerType)
    {
        string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
        ControlsCommands.Unregister(regKey);

    }

    #endregion
    #endregion


    [DllImport("user32.dll")]
    static extern IntPtr SetFocus(IntPtr hWnd);


    private System.Drawing.Bitmap m_bitmap;
    private IntPtr m_hBitmap;
    private IHookHelper m_pHookHelper;


    public class Pan_Left : ESRI.ArcGIS.Desktop.AddIns.Button
    {

        public Pan_Left()
        {
            //m_pHookHelper = new HookHelperClass ();

        }

        protected override void OnClick()
        {//Get the active view
            IActiveView pActiveView = m_pHookHelper.ActiveView;

            //Get the extent
            IEnvelope pEnvelope = (IEnvelope)pActiveView.Extent;


        }

        protected override void OnUpdate()
        {
        }
        }
    }
}
  • So, you've only got the extent, does that have a value? You could trim a lot of the code out and just leave the onClick() to make it more readable. – Michael Stimson Feb 26 '15 at 0:23
3

The fist problem is it's not an add-in.

public class PanDown : ICommand

should read

public class PanDown : ESRI.ArcGIS.Desktop.AddIns.Tool

or

public class PanDown : ESRI.ArcGIS.Desktop.AddIns.Button

Have a good read of this and start again from scratch, ensuring that you select an add-in type for your project when you start in Visual Studio. There are a lot of bits and pieces that are set/created in the project when you select Esri Add-in that would be very difficult to go back and change, so it's far easier to start with a blank slate.

enter image description here

Note the 'button' on the left is checked, that's instructing Visual Studio to make all the bits and pieces for a button. In the Category I use !MyStuff, when you go to add it to ArcMap in the customize dialog the tools with the exclamation mark come to the top.

After the basic template is created you need to add some more references, depending on what you want to do. The clues are in the ArcGis help:

enter image description here

This tells us that the IActiveView interface is in the Carto library. You can add this reference by right clicking on the references and select 'add ArcGis reference':

enter image description here

Will add Geometry (needed for IEnvelope).

As for your code:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ESRI.ArcGIS.Geometry;

namespace PanDown
{
    public class PanDownButton : ESRI.ArcGIS.Desktop.AddIns.Button
    {
        public PanDownButton()
        {
        }

        protected override void OnClick()
        {
            IEnvelope pEnv = ArcMap.Document.ActiveView.Extent;
            double pEnvHeight = pEnv.Height;
            pEnv.YMax -= pEnvHeight; // move top down by height of extent
            pEnv.YMin -= pEnvHeight; // move bottom down by same amount
            ArcMap.Document.ActiveView.Extent = pEnv;
            ArcMap.Document.ActiveView.Refresh(); // redraw the map

            //ArcMap.Application.CurrentTool = null; // turn this off so the current tool remains active
        }
        protected override void OnUpdate()
        {
            Enabled = ArcMap.Application != null;
        }
    }

}

Should do what you want.

There is another massive gotcha in visual studio if you are using 64bit windows. Esri is a 32bit program and can only talk to 32bit dlls', by default Visual Studio compiles to Any CPU - which means 64bit on 64bit windows. That needs to be changed to x86; if you have the Express version you need to follow another path to build for x86, because the configuration manager is disabled in Visual Studio express (this may be intentional) you must manually add <PlatformTarget>x86</PlatformTarget> to the build configurations.

In the vbproj or vcproj file copy:

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <DefineDebug>true</DefineDebug>
    <DefineTrace>true</DefineTrace>
    <OutputPath>bin\Debug\</OutputPath>
    <DocumentationFile>Class_and_Form.xml</DocumentationFile>
    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
    <RegisterForComInterop>true</RegisterForComInterop>
  </PropertyGroup>

to

 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <DefineDebug>true</DefineDebug>
    <DefineTrace>true</DefineTrace>
    <OutputPath>bin\Debug\</OutputPath>
    <DocumentationFile>Class_and_Form.xml</DocumentationFile>
    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
    <RegisterForComInterop>true</RegisterForComInterop>
    <PlatformTarget>x86</PlatformTarget> 
  </PropertyGroup>

and in the .vbproj.user ensure that the debug StartProgram is replicated:

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
    <StartProgram>C:\your\path\to\ArcMap.exe</StartProgram>
    <StartAction>Program</StartAction>
  </PropertyGroup>

to allow for step-debugging in Visual Studio.. when you run (F5) Studio will launch ArcMap, then when you click the tool execution will stop at your breakpoints and you can step through (F10 & F11)... invaluable!

and do the same for '$(Configuration)|$(Platform)' == 'Release|AnyCPU'. If you've done it right then the configuration manager will now be enabled. Again, these instructions are only for Visual Studio Express.

  • 1
    A recommended read along with what Micheal provided in his answer above is this book: ArcGIS for Desktop Development Using .NET – Jason Miller Feb 26 '15 at 15:28
  • The Esri help is a little counter-intuitive, you need to know what you're looking for to get any help on it so it's best to have a little bit of an understanding on how the common objects interact... snippets will only get you so far. – Michael Stimson Feb 26 '15 at 21:57
  • Thanks for the prompt and detailed response. I was out of the office last week and been trying the code this week. I have purchased the text you recommended (thanks Jason) and I am working though it. I have tried the code you gave me and have changed Visual Studio (I'm using regular not express) to x86. The code builds fine, however the screen does not pan when I press the button. I am attempting to troubleshoot, however any more help you can give will be very much appreciated. – Ryan Mar 10 '15 at 22:03
  • In addition when trying to troubleshoot I throw a breakpoint in after the OnClick(). I receive "The breakpoint will not currently be hit. No symbols have been used for this document." I have created a toolbar and put the Pan_Down button on the toolbar. I am assuming that I am missing something very simple. – Ryan Mar 10 '15 at 22:12
  • If the tool isn't created with the wizard in visual studio the event isn't wired. Was the OnClick event there or did you include it? I recommended in my answer to start from scratch - that is fairly important. – Michael Stimson Mar 10 '15 at 22:18
1

After spending some time working though Beginning ArcGIS for Desktop Development using .NET, I came back and was reviewing what was going wrong for me. For whatever reason in the code block Michael gave me when I added in a geographic layer the pEnv.YMax and the pEnv.YMin were coming out as the same number, hence the ActiveView.Extent was staying the same and was not panning. I modified the code as follows storing the pEnv.YMax - pEnv.YMin in a variable Height. I did the same for Width as I will use that for panning Left and Right. I am slowly figuring this stuff out and appreciate everyone's help.

protected override void OnClick()
    {
        IEnvelope pEnv = ArcMap.Document.ActiveView.Extent;

        //pEnv.YMax -= pEnv.Height; // move top down by height of extent
        //pEnv.YMin -= pEnv.Height; // move bottom down by same amount
        double Height = ((pEnv.YMax - pEnv.YMin) * 0.75); //Create Height of extent Variable because C# does not want to save it in above function, moves screen by 75%
        double Width = ((pEnv.XMax - pEnv.XMin) * 0.75); //Create Width of extent Variable because C# does not want to save it in above function, moves screen by 75%


        pEnv.YMax = (pEnv.YMax - Height); // move top down by height of extent
        pEnv.YMin = (pEnv.YMin - Height); // move bottom down by same amount

        //MessageBox.Show("Max: " + pEnv.YMax.ToString() + " Min: " + pEnv.YMin.ToString()); //Message Box Function used to trouble shoot.



        ArcMap.Document.ActiveView.Extent = pEnv;
        ArcMap.Document.ActiveView.Refresh(); // redraw the map

        //ArcMap.Application.CurrentTool = null; // turn this off so the current tool remains active
    }
  • it's a good effort. Yes you need to copy your height (and/or width) to a new variable because the height of the envelope changes as soon as you do the first pEnv.YMax = pEnv.YMax - Height; (height now == 0). This is why you can't do pEnv.YMax = pEnv.YMax - pEnv.Height; – Michael Stimson Jul 21 '15 at 3:32

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.