POST
|
I am working on an add-in program for ArcMap 10.5. When the user clicks the add-in button, an image displays in the winform picture box. (For this example, that image comes from solution's Resource folder, but that does not matter for now). When the user clicks "Run" on the winform, the program is meant to grab the image from the picture box, make it the same size as the mouse cursor, and then add that image NEXT TO the mouse cursor (preferably to the right of the existing mouse cursor). The image floats along next to the mouse cursor, until the user clicks the "Close" button. Right now, I cannot get this image addition to display next to my mouse cursor. Here is my code thus far: using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using LineByCursor.Properties;
namespace LineByCursor
{
// get X,Y from mouse event
// community.esri.com/t5/arcobjects-sdk-questions/add-in-button-mouse-down-capture/td-p/542368
public partial class Form1 : Form
{
private IGraphicTracker m_tracker;
// allows one to loop through the generated ids
private List<int> m_ids;
// private string m_xmlPath;
private MouseHook m_mh;
private IPoint m_lastLoc;
private int m_moveCount = 0;
private Image resourceImage = Resources.simpleDiagonalLine;
public Form1()
{
InitializeComponent();
pictureBox1.Image = resourceImage;
pictureBox1.Visible = true;
m_tracker = new GraphicTrackerClass();
//allows one to loop through the generated ids
m_ids = new List<int>();
}
private void Form1_Load(object sender, EventArgs e)
{
m_mh = new MouseHook();
m_mh.SetHook();
m_mh.MouseMoveEvent += mh_MouseMoveEvent;
this.Location = Settings.Default.MyLoc;
Rectangle rect = Screen.GetWorkingArea(this);
if (this.Size.Width + this.Location.X > rect.Right)
{
this.Location = new System.Drawing.Point(rect.Right - Size.Width, this.Location.Y);
}
if (this.Size.Height + this.Location.Y > rect.Bottom)
{
this.Location = new System.Drawing.Point(this.Location.X, rect.Bottom - Size.Height);
}
if (this.Location.Y < rect.Top)
{
this.Location = new System.Drawing.Point(this.Location.X, rect.Top);
}
if (this.Location.X < rect.Left)
{
this.Location = new System.Drawing.Point(rect.Left, this.Location.Y);
}
}
private void buttonRun_Click(object sender, EventArgs e)
{
try
{
IMouseCursor appCursor = new MouseCursorClass();
appCursor.SetCursor(2);
m_tracker.RemoveAll();
// from Distance Halo - needed?
m_ids.Clear();
// Load the image from your resources (assuming it's a PNG file?)
Image image = pictureBox1.Image;
int cursorSize = SystemInformation.CursorSize.Width; // Assuming the cursor size is a square
// Create a new Bitmap with the desired size
Bitmap resizedImageBMP = new Bitmap(cursorSize, cursorSize);
using (Graphics g = Graphics.FromImage(resizedImageBMP))
{
// Draw the original image onto the new Bitmap
g.DrawImage(image, new Rectangle(0, 0, cursorSize, cursorSize));
}
// Now, the "resizedImage" Bitmap will have the same size as the cursor
IPictureMarkerSymbol picMarkSymbol = new PictureMarkerSymbolClass();
picMarkSymbol.Picture = (stdole.IPictureDisp)ESRI.ArcGIS.ADF.COMSupport.OLE.GetIPictureDispFromBitmap(resizedImageBMP);
ISymbol symbol = (ISymbol)picMarkSymbol;
double radius = 10; // just off-setting from cursor, so not on top of it ... I think?
string units = string.Empty;
IGeometry geometry = BufferGeometry(radius, units);
m_tracker.Initialize(ArcMap.Document.FocusMap);
IGraphicTrackerSymbol trackerSymbol = m_tracker.CreateSymbol(symbol, null);
int id = m_tracker.Add(geometry, trackerSymbol);
m_ids.Add(id);
m_tracker.SetScaleMode(id, esriGTScale.esriGTScaleAuto);
m_tracker.SetVisible(id, false); // also try true?
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error - btnDraw_Click");
}
}
private IGeometry BufferGeometry(double radius, string units)
{
var map = ArcMap.Document.FocusMap;
var point = ArcMap.Document.CurrentLocation;
var projected = map.SpatialReference as IProjectedCoordinateSystem;
// double newRadius = 0.0;
var topoOperator = (ITopologicalOperator)point;
var polygon = topoOperator.Buffer(radius);
return polygon;
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void mh_MouseMoveEvent(object sender, MouseEventArgs e)
{
IPoint currentLoc = ArcMap.Document.CurrentLocation;
if (m_lastLoc != null && m_tracker.Count > 0)
{
if (currentLoc.X != m_lastLoc.X || currentLoc.Y != m_lastLoc.Y)
{
foreach (int id in m_ids)
{
m_tracker.SetVisible(id, true);
m_tracker.MoveTo(id, currentLoc.X, currentLoc.Y, currentLoc.Z);
m_moveCount = 0;
}
}
else
{
m_moveCount++;
if (m_moveCount >= 10)
{
foreach (int id in m_ids)
{
m_tracker.SetVisible(id, false);
m_moveCount = 0;
}
}
}
}
m_lastLoc = new PointClass();
m_lastLoc.X = currentLoc.X;
m_lastLoc.Y = currentLoc.Y;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
m_mh.UnHook();
m_tracker.RemoveAll();
m_ids.Clear();
if (this.WindowState == FormWindowState.Normal)
{
Settings.Default.MyLoc = this.Location;
}
else
{
Settings.Default.MyLoc = this.RestoreBounds.Location;
}
Settings.Default.Save();
}
private void buttonClose_Click(object sender, EventArgs e)
{
//this.Close();
// this.Close();
Close();
}
}
public class Win32Api
{
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
}
public class MouseHook
{
private System.Drawing.Point point;
private System.Drawing.Point Point
{
get { return point; }
set
{
if (point != value)
{
point = value;
if (MouseMoveEvent != null)
{
var e = new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0);
MouseMoveEvent(this, e);
}
}
}
}
private int hHook;
private const int WM_MOUSEMOVE = 0x200;
public const int WH_MOUSE_LL = 14;
public Win32Api.HookProc hProc;
public MouseHook()
{
this.Point = new System.Drawing.Point();
}
public int SetHook()
{
hProc = new Win32Api.HookProc(MouseHookProc);
hHook = Win32Api.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero, 0);
return hHook;
}
public void UnHook()
{
Win32Api.UnhookWindowsHookEx(hHook);
}
private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.MouseHookStruct));
if (nCode < 0)
{
return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
}
else
{
this.Point = new System.Drawing.Point(MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y);
return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
}
}
public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
public event MouseMoveHandler MouseMoveEvent;
}
}
... View more
11-09-2023
06:20 AM
|
0
|
0
|
233
|
POST
|
In ArcMap, I was able to determine if my users were in an edit session, or no. I know that an edit session isn't the same / not required in Pro. But many of my users are still new to Pro, so I suggest they follow the instructions in this link, to enable editing from the edit tab. https://www.youtube.com/watch?v=nQq3sgFbk8I I have a c# Add-In for ArcGIS pro. I would like my program to be able to determine if my user is in an edit session, or no. I have tried things like this: private async void CheckEditSession()
{
// Check if an edit session is in progress
bool editInProgress = false;
await QueuedTask.Run(() =>
{
editInProgress = EditingModule.Current.EditState == EditState.Editing;
});
// Display appropriate message
if (editInProgress)
{
MessageBox.Show("Edit session in progress.");
}
else
{
MessageBox.Show("Edit Session NOT in progress.");
}
} But, as you can see, this syntax isn't really available. I'm having trouble finding any equivalent in the vast work of Pro Snippets. How can I programmatically determine whether or not my user is in an edit session, or not?
... View more
08-15-2023
08:41 AM
|
1
|
1
|
391
|
POST
|
I am having trouble with minimums in my Pro Windows. For example: In an Add-In Button, written in C#, my button produces a Pro Window. Even when blank, I am unable to make my window width smaller. Here is the simple xaml for producing an empty Pro window, upon the click of an Add-In button: ``` <controls:ProWindow x:Class="My_AddIn_Pro.MySmallWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:controls="clr-namespace:ArcGIS.Desktop.Framework.Controls;assembly=ArcGIS.Desktop.Framework" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:extensions="clr-namespace:ArcGIS.Desktop.Extensions;assembly=ArcGIS.Desktop.Extensions" mc:Ignorable="d" Title="My Small Window" Height="300" Width="175"> <controls:ProWindow.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <extensions:DesignOnlyResourceDictionary Source="pack://application:,,,/ArcGIS.Desktop.Framework;component\Themes\Default.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </controls:ProWindow.Resources> <Grid> </Grid> </controls:ProWindow> ``` The resulting Pro Window isn't at Width 175 at all. It's nearly twice that width. In a simple Windows xaml window, I can set whatever size I wish, with a simple Width="". But, that simple window will not auto-adjust to dark mode & light mode in Pro. What needs to be done, to set Pro Window sizing to whatever is needed? I have a very similar issue with button size, seen here in this GIS Stack Exchange post: https://gis.stackexchange.com/questions/464688/how-to-make-a-dynamic-resource-esri-button-as-small-as-needed-in-an-arcgis-pro-w
... View more
08-11-2023
04:38 PM
|
0
|
0
|
307
|
POST
|
Thanks for the speedy reply! I have follow-up questions: But doesn't your example, var featLayers, only return 1 layer? The first in the flattened list? As it's just assigned as variable var, and not anything explicitly ESRI like IEnumLayer, I suppose I'm still a little unclear on that. When I try your example, I see that I can somehow select AsEnumerable, and maybe that will do ... something. Whereas, with IEnumLayer, I merely needed ".Next()" And I have absolutely no idea where to find syntax for creating a UIDClass. I'm searching & searching through the API Reference Guide and the Pro Snippets in GitHub, and I'm having a hard time not just flailing about! Some of the places I've been looking, to find any examples at all of people enumerating layers, or using UIDClass (or whatever the equivalent might be): https://pro.arcgis.com/en/pro-app/latest/sdk/api-reference/index.html#topic1.html https://github.com/esri/arcgis-pro-sdk/wiki/ProSnippets#mapexploration-snippets
... View more
12-13-2021
07:32 AM
|
0
|
1
|
618
|
POST
|
I'm combing through ArcPro snippets in GitHub, and I'm still having a very hard time transitioning to the Pro syntax. It was very simple, in ArcGIS for Desktop, to: -create a UID class -assign a value -enumerate layers, filtering by said UIDClass value UIDClass uIDClass = new UIDClass(); uIDClass.Value = "{setValueHere}"; IEnumLayer layers = Document.FocusMap.get_Layers(uIDClass, true); In Pro, I'm having the hardest time even finding how to enum layers! I see a LOT about GetLayersAsFlattenedList(), but I can't figure out HOW to use it for my purpose
... View more
12-13-2021
06:03 AM
|
0
|
3
|
650
|
POST
|
Long ago, on an older machine, with an older form of ArcGIS Desktop (10.4), I was able to make the console window appear upon startup for all local ArcGIS Desktop applications (ArcMap, Catalog, etc). It does not matter which language or IDE used, if debugging or not. I could see my logs immediately. Now on a newer machine, with 10.5, I cannot figure this out. I would like to set Desktop10.5 so that my console window appears upon startup for my desktop applications. (See the image as the example, in ArcMap, of what I'm trying to accomplish.) Debugging ArcMap, automatically have console window I've searched around in: C:\Program Files (x86)\ArcGIS\Desktop10.5\bin I'm just not finding what I'm looking for, or any documentation for this. Thank you!
... View more
05-26-2021
03:28 PM
|
0
|
0
|
395
|
POST
|
Hello, I'm familiar with assigning keyboard shortcuts for commands. But I'm trying to figure out if I can assign keyboard shortcuts for turning specific extensions on & off. Using ArcMap, not Pro. Any documentation / ideas? Many thanks.
... View more
05-01-2021
02:47 PM
|
1
|
2
|
660
|
POST
|
I follow these steps and an executable is created. I made sure that step 2 becomes the first few lines of MyProgram.py. After the executable is created, I copy & paste the Desktop10.4.pth file into the dist/site-packages folder, and here's what happens: -py2exe readout says: "The following modules appear to be missing ['_scproxy', '_sysconfigdata', 'sitecustomize', 'usercustomize']" -Black terminal window opens & closes quickly when I click the resulting MyProgram.exe. It's so fast, I can't capture a screenshot of it. I've no idea where those modules are, why they are missing, are they required? Is it ok for them to remain missing? No idea on that one. 2 other ideas: 1. I'm an ArcGIS10.4 user running python from: ...:\Python27\ArcGISx6410.4 But the .PTH file in the instructions, the one to copy & paste into the resulting dist/site-packages folder after the executable is created? That's in ...:\Python27\ArcGIS10.4\Lib\site-packages Perhaps that's the problem? If so, I don't know what to do about it. If not ... 2. I had to exclude a whole list of DLLs to get the py2exe to work without "missing dlls" list at the end. So here's my code for the setup.py: ``` from distutils.core import setup
import py2exe
options = {
"py2exe": {"excludes": ["arcpy"],
"dll_excludes": ["USER32.dll",
"IMM32.dll",
"SHELL32.dll",
"KERNEL32.dll",
"COMDLG32.dll",
"ADVAPI32.dll",
"WS2_32.dll",
"GDI32.dll",
"ole32.dll",
"OLEAUT32.dll",
"COMCTL32.dll"]}}
setup(console=['MyProgram.py'], options=options) I don't know what to do now. Help, please!
... View more
06-08-2020
07:10 AM
|
0
|
0
|
4982
|
POST
|
I have the exact same problem as liuyingjie above, not finding a clear solution.
... View more
05-28-2020
05:56 AM
|
0
|
0
|
1846
|
POST
|
I am struggling with ESRI's Picture / IPicture java arcobjects documentation for ArcGIS Desktop (not Runtime). I just need to grab the image file from my project's source (src) folder, and cast that as a Picture. Here's a little of what I've tried: ``` File pictureFile = new File("myImage.bmp"); Picture pictureDisp = (Picture) pictureFile; // FAIL: java.io.File cannot be cast to com.esri.arcgis.support.ms.stdole.Picture ``` or ``` Image image = ImageIO.read(getClass().getResource("myImage.bmp")); Picture pictureDisp = (Picture) image; // FAIL: java.awt.image.BufferedImage cannot be cast to com.esri.arcgis.support.ms.stdole.Picture ``` I've tried the above scenarios with IPicture as well. I have no idea by what process on can set the Picture (or IPicture) in Java for ArcDesktop. I can't use a file path, this project will be deployed as an add-in, and not all users will have access to the same file paths. I need the file embedded in my program. I just want my image file to be accessible via Picture or IPicture... or sure, BmpPictureElement. Why not! But I can't seem to access it, no matter what I try. I've also tried creating via BmpPictureElement, with zero success. http://help.arcgis.com/EN/sdk/10.0/Java_AO_ADF/api/arcobjects/com/esri/arcgis/support/ms/stdole/Picture.html http://resources.esri.com/help/9.3/arcgisengine/java/api/arcobjects/com/esri/arcgis/support/ms/stdole/IPicture.html#selectPicture(int,%20int[],%20int[]) http://resources.esri.com/help/9.3/ArcGISEngine/java/api/arcobjects/com/esri/arcgis/carto/BmpPictureElement.html
... View more
01-31-2020
11:44 AM
|
0
|
0
|
582
|
POST
|
I have tried: 1. placing the bitmap image in the package with the java classes 2. grabbing that image via InputStream 3. Casting the inputStream to an Object 4. using the IPIctureMarkerSymbol.equals(Object object) method. The program does not fail or produce an error, but the image does NOT display with this attempt. Again the image DOES display with the file path as String, but that is not a sustainable plan for deploying the add-in. Still stumped. ``` public class SymbologyChanger {
public SymbologyChanger(ArrayList<Point> pointsForTheLayer, IMap currentMap) throws AutomationException, IOException {
IGraphicsContainer graphContainer = (IGraphicsContainer) currentMap.getActiveGraphicsLayer();
for (int i = 0; i < pointsForTheLayer.size(); i++) {
Point point = (Point) pointsForTheLayer.get(i);
double symbolSize = 15;
IPictureMarkerSymbol picSym = new PictureMarkerSymbol();
picSym.setSize(symbolSize);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = getClass().getResourceAsStream("my_image.bmp");
Object inputObj = (Object) inputStream;
picSym.equals(inputObj);
IMarkerElement markerElement = new MarkerElement();
markerElement.setSymbol(picSym);
IElement element = (IElement) markerElement;
element.setGeometry(point);
graphContainer.addElement(element, 0);
}
}
}
```
... View more
01-29-2020
12:16 PM
|
0
|
0
|
594
|
POST
|
I've written a little java add-in button for ArcDesktop 10.4, in eclipse, which makes a new ArcMap layer with some points. (NOT Runtime) My goal is to assign a picture as the symbol for each of these points. I have success on my machine, but I can't figure out how to make my picture accessible to all future users. Here's my class, part of larger program, which does work, but image currently only comes through from path on my own computer: ``` public class SymbologyChanger { public SymbologyChanger(ArrayList<Point> pointsForTheLayer, IMap currentMap) throws AutomationException, IOException { IGraphicsContainer graphContainer = (IGraphicsContainer) currentMap.getActiveGraphicsLayer(); for (int i = 0; i < pointsForTheLayer.size(); i++) { Point point = (Point) pointsForTheLayer.get(i); double symbolSize = 15; IPictureMarkerSymbol picSym = new PictureMarkerSymbol(); picSym.setSize(symbolSize); // http://resources.esri.com/help/9.3/ArcGISDesktop/ArcObjects/esriDisplay/esriIPictureType.htm picSym.createMarkerSymbolFromFile(1, "C:\\Users\\userName\\eclipseWorkspace\\java_project\\images\\my_image.bmp"); IMarkerElement markerElement = new MarkerElement(); markerElement.setSymbol(picSym); IElement element = (IElement) markerElement; element.setGeometry(point); g raphContainer.addElement(element, 0); } } } ``` inspiration from: arcgissamples\cartography\DrawSymbolMain.java—ArcObjects 10.4 Help for Java | ArcGIS for Desktop So it's this particular line: ``` picSym.createMarkerSymbolFromFile(1, "C:\Users\userName\eclipseWorkspace\java_project\images\my_image.bmp"); ``` which is my problem. I've placed the image in the project images folder, along with the button icon. The button icon totally works, but for the points symbol, I've tried: ``` picSym.createMarkerSymbolFromFile(1, "images\my_image.bmp"); ``` And this does not work. Again, I get the image I want for the point symbol, but how to set the path correctly to share with others? I need the image to work as the point symbol with all machines, not just my own.
... View more
01-28-2020
01:31 PM
|
0
|
1
|
708
|
POST
|
Was this question ever fully answered, perhaps someplace else?
... View more
12-13-2019
09:24 AM
|
0
|
0
|
1388
|
POST
|
My solution was: -Separate out the Excel Workbook builder, with relies upon Apache jars, into a separate program, and send to the users as an executable. -Users run all the other code as an ArcCatalog add-in, which produces a .txt file, not an .xlsx file. -Users then run the .exe, which is now designed to read the .txt file. -Users get their Excel file. Not ideal. But I couldn't figure out what else to do, as the entire program would not function, intact, as either an .exe or an Add-in. It was either keep the arcobjects jar & the apache jars separate from one another, or rewrite the entire program in another language (which would take considerably more time for a junior-level developer). Not super happy with my solution, as I lost some of the elegance & user-friendliness I'd initially built. But it works. And that's how much I know, at this point in time.
... View more
12-02-2019
12:01 PM
|
0
|
0
|
794
|
Title | Kudos | Posted |
---|---|---|
1 | 08-15-2023 08:41 AM | |
1 | 05-01-2021 02:47 PM | |
1 | 05-02-2021 12:19 PM |
Online Status |
Offline
|
Date Last Visited |
02-23-2024
07:20 AM
|