POST
|
Mark, Just to note ... the information in the following thread provided insights that may be helpful: https://community.esri.com/thread/117206 Following that example, the fragment below shows a class derived from GraphicsLayer that overrides the OnInitializeGraphicsLayerRequestedAsync() method. --------------------- public class MyGraphicsLayer : GraphicsLayer { private SpatialReference _layerSpatialReference = null; public MyGraphicsLayer(SpatialReference layerSpatialReference) { // Capture the specified spatial reference so it is available // for use in the OnInitializeGraphicsLayerRequestedAsync() override. _layerSpatialReference = layerSpatialReference; } protected override Task<GraphicsLayerInitializationInfo> OnInitializeGraphicsLayerRequestedAsync() { return Task.FromResult( new GraphicsLayerInitializationInfo() { PreferredSpatialReference = _layerSpatialReference } ); } } ------------------- The fragment below demonstrates using the derived class (plus .InitializeAsynch) to assign the Spatial Reference: -------------------- // Source of the graphic data is a FeatureSet loaded from the content of a *.json file. // The returned FeatureSet has its SpatialReference property set. // The intent is to assign that SpatialReference to the graphics layer prior to populating the layer. string jsonFileContent = (... previously read from a *.json file ...) FeatureSet featureSet = FeatureSet.FromJson(jsonFileContent); MyGraphicsLayer graphicsLayer = new MyGraphicsLayer(featureSet.SpatialReference); // Execution of the .InitializeAsync() call does transfer control into // the OnInitializeGraphicsLayerRequestedAsync() override above. // The effect is to assign the spatial reference to the graphics layer. await graphicsLayer.InitializeAsync(); --------------------- While the above approach seems to achieve the objective, it does require more code than one might expect (at least, in my opinion, it seems there could be a more straightforward technique for assigning a Spatial Reference to a graphics layer). Scott
... View more
08-07-2015
04:49 AM
|
0
|
0
|
1332
|
POST
|
This entry is just to identify the resolution to the issue described in the previous entry (to the best we can identify via testing). Continued investigation led us to try our existing application code running with ArcGIS Engine Runtime 10.3.0 (instead of 10.2.2). ArcGIS 10.3.0 successfully performed the geographic transformation calculations between NAD27 and NAD83 during on-the-fly projection processing. These results indicate the following: The existing application code for assigning NAD_1927_To_NAD_1983_NADCON geographic transformation seems to be the correct approach (calling the geoTransformationOperationSet.Set() method, as shown in the previous posting). There appears to be an ArcGIS Engine Runtime bug regarding the NAD27-to-NAD83 geographic transformation calculations that: Did not exist in ArcGIS 10.1. Appeared in ArcGIS 10.2.2 (at least in the ArcEngine MapControl's on-the-fly projection processing). Has been fixed in ArcGIS 10.3.0. We are reluctant to just dismiss this as "an Esri bug" (especially because we have not been able to locate any documentation describing this type of bug), but the testing results seem reasonably convincing in this case. The same ArcObjects application code produces a different result based on whether it executes with ArcGIS Engine Runtime 10.2.2 vs. 10.3.0. For some reason, it appears ArcGIS 10.2.2 is unable to (or, does not detect the need to) perform the geographic transformation from NAD27 to NAD83 during on-the-fly projections for this particular pair of "From" and "To" Projected Coordinate Systems. The resolution is for our client to start using the version of the application based on ArcGIS Engine Runtime 10.3.0. Scott
... View more
05-14-2015
11:08 AM
|
1
|
0
|
921
|
POST
|
The information in this thread appears to help identify the underlying cause of a problem just reported to us today from one of our clients. Our application is implemented using ArcGIS Engine, so this follow-on question is trying to understand how to use ArcObjects to achieve the same effect of restoring the NAD_1927_To_NAD_1983_NADCON geographic transformation into the ArcGIS Engine MapControl environment (since it has now been removed). Our client just upgraded from the version of our application that used ArcGIS Engine Runtime 10.1 to the one that is built on ArcGIS Engine Runtime 10.2.2. The client's data is also in California and consists of multiple layers, some of which are vector data in UTM Zone 10N (NAD 1983) (customized to units of feet) and TIF file raster data that uses California State Plane Zone II (NAD 1927). The client is reporting that the NAD 27 raster layer is displayed offset approximately 300 feet east of where it displayed in the previous software release. We are already using the technique outlined in the ArcObjects Help for assigning the NAD_1927_To_NAD_1983_NADCON geographic transformation. We are using the approach from the following Help link, as shown in the sample code below. http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/d/000100000m6z000000.htm // This example demonstrates how to use the IGeoTransformationOperationSet methods. // Set the NAD27 to NAD83 - CONUS GeoTransformation. public void ChangeCoordinateSystem1() { ISpatialReferenceFactory2 spatialReferenceFactory = new SpatialReferenceEnvironmentClass(); IGeoTransformationOperationSet geoTransformationOperationSet = spatialReferenceFactory.GeoTransformationDefaults; // NAD27 to NAD83 - CONUS IGeoTransformation geoTransformation = spatialReferenceFactory.CreateGeoTransformation((int) esriSRGeoTransformation_NAD_1927_TO_NAD_1983_NADCON) as IGeoTransformation; geoTransformationOperationSet.Set(esriTransformDirection.esriTransformForward, geoTransformation); geoTransformationOperationSet.Set(esriTransformDirection.esriTransformReverse, geoTransformation); } Unfortunately, this approach does not seem to have any effect, in that the NAD 1927 data is still displayed in ArcGIS Engine 10.2.2 offset approximately 300 feet east of where the same raster files displayed with ArcGIS Engine 10.1. We would appreciate if anyone has any insights on how to achieve the effects with ArcObjects similar to the series of steps performed in ArcMap outlined in the earlier posting in this thread from Jan 22, 2014 1:31 PM. Thanks for your help. Scott
... View more
05-13-2015
02:42 PM
|
0
|
1
|
921
|
POST
|
We opened an incident with Esri Tech Support to investigate this question. It turns out it is possible to create a Query Layer from a SQLite database in ArcGIS 10.2 . The general approach from ArcObjects uses the SqlWorkspaceFactory::OpenFromFile method to gain access to the ISqlWorkspace interface pointer (where the file name is the name of the *.sqlite file itself). Essentially, the full file name of the *.sqlite file serves as the "connection data". There is no need to instantiate a class that supports the IPropertySet interface and build up a formal set of connection parameters/properties. An updated version of the Visual C++ code fragment is included below.
// Code fragment for creating a feature layer for a Query Layer from a SQLite database in ArcGIS Engine 10.2.
// Environment: Visual C++, MFC, Visual Studio 2010
IWorkspaceFactory2Ptr pWorkspaceFactory2 = NULL;
IWorkspacePtr pWorkspace = NULL;
ISqlWorkspacePtr pSqlWorkspace = NULL;
IQueryDescriptionPtr pQueryDescription = NULL;
ITablePtr pTableForSQL = NULL;
IFeatureClassPtr pFeatureClassForSQL = NULL;
IFeatureLayerPtr pFeatureLayer = NULL;
CString csSQLiteFileName = _T("C:\\Data\\TestDB.sqlite");
CComBSTR bstrNewQueryFeatureClassName;
OLE_HANDLE hWnd = 0;
HRESULT hr = S_OK;
// Note: All error handling removed from the sample code.
//
// For accessing a SQLite database file, it is necessary to
// use the SQL Workspace Factory.
pWorkspaceFactory2.CreateInstance(CLSID_SqlWorkspaceFactory);
// Use the *.sqlite file name as the basis for instantiating the
// necessary workspace interface pointer.
hr = pWorkspaceFactory2->OpenFromFile(CComBSTR(csSQLiteFileName),
hWnd, &pWorkspace);
// QI to get the ISqlWorkspace interface pointer
pSqlWorkspace = pWorkspace;
// Pass the SQL query text on to ArcGIS Engine Runtime so it can make its
// attempt to create the Query Description object.
// Note: This phase of the definition process may be iterative, repeated as often
// as needed to generate valid data held in the IQueryDescription interface pointer.
// For example, the methods similar to IQueryDescription::get_IsSpatialQuery,
// IQueryDescription::get_OIDFields, and IQueryDescription::get_Srid can be used
// to verify that the necessary information is available to ArcGIS Engine Runtime.
// If data is missing, it is necessary to obtain it and then re-invoke
// ->GetQueryDescription() (such as prompting the user for the name of the Unique ID
// attribute field if the underlying database table metadata does not allow ArcGIS
// Engine Runtime to identify the appropriate attribute by default).
hr = pSqlWorkspace->GetQueryDescription(CComBSTR(_T("SELECT * FROM BASEDB.DISTRIBUTIONMAIN")),
&pQueryDescription);
// Ensure that the specified name for the Query Layer feature class is not
// already being used.
// Please note that ISqlWorkspace::CheckDataSetName needs to be called before
// using the OpenQueryClass method. The name returned by ->CheckDatasetName()
// is the name to be used as the first parameter in the later
// call to ->OpenQueryClass().
bstrNewQueryFeatureClassName.Empty();
hr = pSqlWorkspace->CheckDatasetName(CComBSTR(_T("Distr_Mains"),
pQueryDescription,
&bstrNewQueryFeatureClassName);
// Attempt to open the Query Class for the Query Layer by passing in the
// (possibly modified) Query Description object.
hr = pSqlWorkspace->OpenQueryClass(bstrNewQueryFeatureClassName),
pQueryDescription,
&pTableForSQL);
// QI to verify the query class also supports the IFeatureClass interface.
// If so, this indicates it is able to form the basis for a Feature Layer.
pFeatureClassForSQL = pTableForSQL;
if (pFeatureClassForSQL != NULL)
{
// Create the new feature layer object
pFeatureLayer.CreateInstance(CLSID_FeatureLayer);
// Assign the just-created feature class to the layer
hr = pFeatureLayer->putref_FeatureClass(pFeatureClassForSQL);
// ... additional logic to assign layer properties ...
}
When using the "Add Data" button in ArcMap 10.2, browsing out to a *.sqlite file, and then selecting a feature class, ArcMap internally goes through the process of creating a Query Layer that then appears in the Table of Contents. If you open the Layer Properties dialog, go to the Source tab, and then click the [Change Query] button, the [Edit Query Layer] dialog is launched and you will see the text of the query built internally as part of creating the layer in the ArcMap environment. For those developers using .Net, the code example below is the one received from Esri Tech Support. After opening the SQLite dataset through ISqlWorkspaceFactory::OpenFromFile, you need to use ISqlWorkspace::GetQueryDescription(Query String). The code snippet below will help you better understand the workflow.
public class LoadSQLiteLayer : ESRI.ArcGIS.Desktop.AddIns.Button
{
private static readonly String Root = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
private static readonly String Data = System.IO.Path.Combine(Root, "Data");
private static readonly String Lite = System.IO.Path.Combine(Data, "test1.sqlite");
private static readonly String[] Fields = { "OBJECTID", "Shape", "HNR", "ZOT_ID", "AEN_DAT" };
private const String TableName = "main.locations";
private static readonly String Sql = string.Format("SELECT {0} FROM {1}", string.Join(", ", Fields), TableName);
protected override void OnClick()
{
try
{
Type factoryID = Type.GetTypeFromProgID("esriDataSourcesGDB.SqlWorkspaceFactory");
IWorkspaceFactory2 pWorkspaceFactory = (IWorkspaceFactory2)Activator.CreateInstance(factoryID);
ISqlWorkspace pSqlWorkspace = (ISqlWorkspace)pWorkspaceFactory.OpenFromFile(Lite, 0);
IStringArray pStringArray = pSqlWorkspace.GetTables();
List tableNames = new List();
for (int i = 0; i < pStringArray.Count; i++)
{
tableNames.Add(pStringArray.Element);
}
if (!tableNames.Contains(TableName)) throw new Exception("Table name not found");
//using (ComReleaser pComReleaser = new ComReleaser())
//{
// IFeatureCursor pFeatureCursor = (IFeatureCursor)pSqlWorkspace.OpenQueryCursor(Sql);
// pComReleaser.ManageLifetime(pComReleaser);
// IFeature pFeature = null;
// while ((pFeature = pFeatureCursor.NextFeature()) != null)
// {
// Debug.WriteLine("OID: " + pFeature.Value[0]);
// }
//}
IQueryDescription pQueryDesc = pSqlWorkspace.GetQueryDescription(Sql);
pQueryDesc.OIDFields = Fields[0];
string tableNameX;
pSqlWorkspace.CheckDatasetName(TableName, pQueryDesc, out tableNameX);
IFeatureClass pFeatureClass = (IFeatureClass)pSqlWorkspace.OpenQueryClass(tableNameX, pQueryDesc);
IFeatureLayer pFeatureLayer = new FeatureLayerClass { FeatureClass = pFeatureClass, Name = TableName, Visible = true };
ArcMap.Document.FocusMap.AddLayer(pFeatureLayer);
}
catch (Exception ex) { MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}
protected override void OnUpdate() { }
}
}
Please note that ISqlWorkspace::CheckDataSetName needs to be called before using OpenQueryClass method. If you need to know more details about ISQLWorkspace interface, you could visit the below link: ISqlWorkspace Interface http://resources.arcgis.com/en/help/arcobjects-net/componenthelp/index.html#/ISqlWorkspace_Interface/00250000085s000000/ I'm hoping this information will be useful for other developers. Scott
... View more
10-25-2013
12:05 PM
|
0
|
0
|
389
|
POST
|
iierace, The link below may also be of some use for binding from the Visual C++ environment: ArcObjects runtime binding for VC++ developers http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000nmm000000 Scott
... View more
10-17-2013
06:33 AM
|
0
|
0
|
270
|
POST
|
Is it possible to use a SQLite database as the basis for creating a Query Layer in an ArcGIS Engine application starting with ArcGIS 10.2? The ArcGIS 10.2 Help on Query Layers has been updated to specify the use of the Teradata databases (newly-supported in ArcGIS 10.2). Other portions of ArcGIS 10.2 Help mention SQLite, but the Query Layers documentation is notably silent on SQLite. The code fragment below shows an example of what would seem to be a potential approach (based on an existing method for creating a Query Layer against other database types). But I have not been able to locate any documentation on how to populate the PropertySet to establish a connection to a SQLite database.
// Code fragment for creating a feature layer for a Query Layer in ArcGIS Engine.
// Environment: Visual C++, MFC, Visual Studio 2010
IWorkspaceFactory2Ptr pWorkspaceFactory2 = NULL;
IWorkspacePtr pWorkspace = NULL;
ISqlWorkspacePtr pSqlWorkspace = NULL;
IQueryDescriptionPtr pQueryDescription = NULL;
ITablePtr pTableForSQL = NULL;
IFeatureClassPtr pFeatureClassForSQL = NULL;
IFeatureLayerPtr pFeatureLayer = NULL;
IPropertySetPtr pPropertySet = NULL;
OLE_HANDLE hWnd = 0;
HRESULT hr = S_OK;
// Note: All error handling removed from the sample code.
pWorkspaceFactory2.CreateInstance(CLSID_SdeWorkspaceFactory);
pPropertySet.CreateInstance(CLSID_PropertySet);
// ... Q: How to populate the PropertySet appropriately for a SQLite database(?)
//
// Once the Property Set is populated, open the workspace.
hr = pWorkspaceFactory2->Open(pPropertySet, hWnd, &pWorkspace);
// QI to get the ISqlWorkspace interface pointer
pSqlWorkspace = pWorkspace;
// Pass the incoming SQL query text on to ArcGIS Engine Runtime so it can make its
// attempt to create the Query Description object.
hr = pSqlWorkspace->GetQueryDescription(CComBSTR(_T("SELECT * FROM BASEDB.DISTRIBUTIONMAIN")),
&pQueryDescription);
// Attempt to open the Query Class for the Query Layer by passing in the
// (possibly modified) Query Description object.
hr = pSqlWorkspace->OpenQueryClass(CComBSTR(_T("Distr_Mains")),
pQueryDescription,
&pTableForSQL);
// QI to determine if the query class also supports the IFeatureClass interface.
// If so, this indicates it is able to form the basis for a Feature Layer.
pFeatureClassForSQL = pTableForSQL;
if (pFeatureClassForSQL != NULL)
{
// Create the new feature layer object
pFeatureLayer.CreateInstance(CLSID_FeatureLayer);
// Assign the just-created feature class to the layer
hr = pFeatureLayer->putref_FeatureClass(pFeatureClassForSQL);
// ... additional logic to assign layer properties ...
}
Any insights would be appreciated. Thanks for your help. Scott
... View more
10-12-2013
09:43 AM
|
0
|
1
|
4647
|
POST
|
Michael, Unfortunately, our application only uses ArcGIS Engine (just loading individual layers into the MapControl, not saving or interacting with any MXD files), so we don't have any experience with ArcMap or MXD files. As a result, I don't have any other thoughts to pass along. As noted in the forum entry I referenced in my earlier posting, it does seem that Esri has made some changes to the way database connections function in ArcGIS 10.1 (at least, for Query Layers). Perhaps there is also some difference for the work flow being used in your application. Sorry I could not provide any better information. Scott
... View more
09-04-2012
07:11 AM
|
0
|
0
|
285
|
POST
|
Michael, I'm not sure if this is directly related to the issue you are facing, but the following link describes a database connection issue we encountered in the transition from ArcGIS 10.0 to 10.1 with an ArcEngine-based application. In our case, the connection is made as part of defining a Query Layer. http://forums.arcgis.com/threads/61318-Load-Query-Layer-via-AddLayerFromFile()-difference-ArcGIS-10.1-Final-vs.-Prerelease At first we thought there might have been a change in AddLayerFromFile(), but it turned out to be an apparent change in Esri's philosophy on how connections are to be made to databases. One gets the impression that, starting with ArcGIS 10.1, Esri wants applications to always use the SdeWorkspaceFactory class when establishing a connection, whether the connection is for a geodatabase or not (such as when creating a connection for Query Layers). In our case, we were able to avoid the "prompt for credentials" in our ArcEngine-based application by making the following changes to our code that creates the connection and eventually obtains a ISqlWorkspace interface pointer that is used to create the Query Class that forms the basis for creating a Query Layer: - Replace use of the SqlWorkspaceFactory with the SdeWorkspaceFactory class. - In the PropertySet of connection properties, replace the SERVERINSTANCE property (from ArcGIS 10.0) with the DB_CONNECTION_PROPERTIES property (apparently, this is a new property at the ArcGIS 10.1 level). If your connection code is currently using the SERVERINSTANCE property, perhaps it will be necessary to change it to the DB_CONNECTION_PROPERTIES property. (We found it difficult to locate documentation on DB_CONNECTION_PROPERTIES, but it did show up in one of the Esri developer samples.) I hope this information is of some use. Scott
... View more
09-02-2012
10:40 AM
|
0
|
0
|
285
|
POST
|
David, I don't write in VB.Net, so I cannot provide exact syntax, but it does not appear that the point objects are ever "new"'ed in the sample code included in your post. In other words, before attempting to assign the X and Y coordinate values, it will be necessary to create an instance of the point object that is to be referenced through its IPoint interface. I'm confident there are samples in the ArcObjects developer help that will show VB.Net coding examples on how to "new" a new instance of a point object. I hope this information is of use. Scott
... View more
09-02-2012
10:18 AM
|
0
|
0
|
2133
|
POST
|
Continued investigation has shed some light on this problem and we wanted to post it here to hopefully save other ArcEngine developers from wasting a lot of time on Query Layer connection differences in ArcGIS 10.1. It appears that the difference is not in the layer (*.lyr) file processing itself, but a difference in the manner for making connections to support Query Layers starting in ArcGIS 10.1. While no specific �??What�??s new�?��?� documentation on the change has yet been located, it appears that Esri is no longer using the SqlWorkspaceFactory to make the connection for Query Layer processing in ArcGIS 10.1. Please see the attached file Sql_Workspace_Doc_Differences.png which shows that, while a very useful ArcObjects example was provided in the 10.0 Developer Help topic �??Working with SQL Workspaces�?�, that Help topic has been removed from Developer Help in ArcGIS 10.1. The attached file Query_Layer_Connection_info.png contrasts the type of dialog used by ArcMap for users to define Query Layer connection properties. It also appears that, while the ArcObjects samples for the SqlWorkspaceFactory class had the connection data being saved to *.qcf files in ArcGIS 10.0, the ArcGIS 10.1 approach indicates the connection data should be saved in *.sde files. One gets the impression that, starting with ArcGIS 10.1, Esri wants applications to always use the SdeWorkspaceFactory class when establishing a connection, whether the connection is for a geodatabase or not (such as when creating a connection for Query Layers). Back to our original posting, we have been able to avoid the �??prompt for credentials�?� in our ArcEngine-based application by making the following changes to our code that creates the connection and eventually obtains a ISqlWorkspace interface pointer that is used to create the Query Class that forms the basis for creating a Query Layer: - Replace use of the SqlWorkspaceFactory with the SdeWorkspaceFactory class. - In the PropertySet of connection properties, replace the SERVERINSTANCE property (from ArcGIS 10.0) with the DB_CONNECTION_PROPERTIES property (apparently, this is a new property at the ArcGIS 10.1 level). A Visual C++ sample code fragment (with all error checking removed) is shown below.
IPropertySetPtr pPropertySet = NULL;
IWorkspaceFactory2Ptr pWorkspaceFactory2 = NULL;
IWorkspacePtr pWorkspace = NULL;
ISqlWorkspacePtr pSqlWorkspace = NULL;
OLE_HANDLE hWnd = 0;
HRESULT hr = S_OK;
// Create the connection Property Set
pPropertySet.CreateInstance(CLSID_PropertySet);
// At ArcGIS 10.0, this parameter specified either "oracle10g" or "oracle11g"
// (when used with the SqlWorkspaceFactory class).
// At ArcGIS 10.1, this parameter is apparently to just be "oracle"
// (when used with the SdeWorkspaceFactory class).
hr = pPropertySet->SetProperty( CComBSTR(_T("DBCLIENT")),
CComVariant(CComBSTR(_T("oracle"))) );
// This appears to be a new property at the ArcGIS 10.1 level.
// It appears to replace the "SERVERINSTANCE" propety used in ArcGIS 10.0
// to call the ->Open() method on the SqlWorkspaceFactory.
hr = pPropertySet->SetProperty( CComBSTR(_T("DB_CONNECTION_PROPERTIES")),
CComVariant(CComBSTR(_T("sde:oracle11g:hydra04"))) );
hr = pPropertySet->SetProperty( CComBSTR(_T("AUTHENTICATION_MODE")),
CComVariant(CComBSTR(_T("DBMS"))) );
hr = pPropertySet->SetProperty( CComBSTR(_T("USER")),
CComVariant(CComBSTR(_T("scott"))) );
hr = pPropertySet->SetProperty( CComBSTR(_T("PASSWORD")),
CComVariant(CComBSTR(_T("zzzzzzz"))) );
// Create the SDE Workspace factory
pWorkspaceFactory2.CreateInstance(CLSID_SdeWorkspaceFactory);
// Open the SDE workspace with the PropertySet
hr = pWorkspaceFactory2->Open(pPropertySet, hWnd, &pWorkspace);
// QI to get the ISqlWorkspace interface pointer.
// Once gaining access to this ISqlWorkspace interface pointer,
// the rest of the processing for creating a Query Layer seems to be
// consistent with the ArcGIS 10.0 Query Layer processing.
pSqlWorkspace = pWorkspace;
We hope this information is helpful to other developers. Scott
... View more
07-29-2012
11:29 AM
|
0
|
0
|
256
|
POST
|
In general, my understanding is that it will not be possible to access an SDE geodatabase at the ArcGIS 10.0 level from an ArcGIS 9 client application. Please see the Help topic below. Client and geodatabase compatibility http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//003n00000008000000.htm One of the statements from that topic is: "Previous releases of ArcGIS clients cannot connect to and use geodatabases created with later versions of ArcGIS." I hope this helps. Scott
... View more
07-13-2012
09:26 AM
|
0
|
0
|
108
|
POST
|
Jakub, I believe the general approach in the Page Layout is to obtain a reference to the page element of interest (such as the MapFrame), get its geometry, and then retrieve the Envelope for that particular geometry. As an example, I have included a Visual C++ code fragment below extracted from one of the methods we use in our ArcGIS Engine application when interacting with the PageLayoutControl (with all error checking removed).
IMapFramePtr pMapFrame = NULL;
IElementPtr pElement = NULL;
IGeometryPtr pMapFrameGeometry = NULL;
IEnvelopePtr pMapFrameEnvelope = NULL;
HRESULT hr = S_OK;
double dXMin = 0.0;
double dYMin = 0.0;
double dXMax = 0.0;
double dYMax = 0.0;
// QI to get the IElement interface
pElement = pMapFrame;
// Obtain the extent of the MapFrame geometry
hr = pElement->get_Geometry(&pMapFrameGeometry);
hr = pMapFrameGeometry->get_Envelope(&pMapFrameEnvelope);
// Note that the min/max X,Y values are in page units (such as inches, cm, etc.)
hr = pMapFrameEnvelope->QueryCoords(&dXMin, &dYMin, &dXMax, &dYMax);
As another brief example, below is a Visual C++ code fragment that demonstrates one approach for obtaining a reference to the MapFrame element (within the overall Page Layout's graphics container).
IGraphicsContainerPtr pGraphicsContainer = NULL;
IElementPtr pElement = NULL;
IMapFramePtr pMapFrame = NULL;
// Iterate across all the elements in the PageLayoutControl graphics container
pGraphicsContainer = m_pPageLayoutControl->GetGraphicsContainer();
ASSERT(pGraphicsContainer != NULL);
if (pGraphicsContainer != NULL)
{
hr = pGraphicsContainer->Reset();
hr = pGraphicsContainer->Next(&pElement);
// Examine the next page element, only being interested in MapFrame elements for this method
while (pElement != NULL)
{
// QI to determine if this graphic element is the MapFrame
pMapFrame = pElement;
if (pMapFrame != NULL)
{
// ... processing for the MapFrame element
}
hr = pGraphicsContainer->Next(&pElement);
}
I hope this helps. Scott
... View more
07-08-2012
11:45 AM
|
0
|
0
|
251
|
POST
|
Environment: ArcGIS Engine Runtime 10.1, Visual Studio 2010, Visual C++ Testing of ArcGIS Engine Runtime 10.1 Final has uncovered a difference in the behavior of the IMapControl4::AddLayerFromFile() between the 10.1 Prerelease and 10.1 Final versions when loading a Query Layer whose definition was saved in a *.lyr file. It is during execution of IMapControl4::AddLayerFromFile() where the change is seen, but it seems the ISqlWorkspace or ILayerFile interfaces may be involved, since the processing is associated with creating and persisting the definition for a Query Layer. The difference in behavior is the following: - In ArcGIS 10.0 and ArcGIS 10.1 Prerelease, loading the saved *.lyr file for the Query Layer used the credentials (userid and password) saved in the *.lyr file to establish the connection to the underlying Oracle 11g database. The user was not prompted. - In ArcGIS 10.1 Final (after rebuilding our application), executing the same code to define the Query Layer and save its definition into a *.lyr file, ArcGIS now displays a prompt for credentials when executing the IMapControl4::AddLayerFromFile()file, as shown in the attached file ArcGIS_10_1_lyr_file_prompt.png. We have searched the ArcGIS 10.1 ???What???s new???-type online topics but, so far, have not located anything to help explain this change in behavior. We are trying to understand if: - This is expected behavior with ArcGIS 10.1 Final and we just have not yet located the documentation that explains the reason for this change(?) - Or, is this some type of bug (either in the ArcGIS code or something we might be doing wrong in our ArcObjects code)(?) We would appreciate any insights others might have. Thanks for your help. Scott
... View more
07-01-2012
11:12 AM
|
0
|
2
|
2525
|
POST
|
Richard, We know that working through the #import statement handling is never a pretty sight. It appears we have identified a workaround for the problem noted in this thread, but it does take dealing with the #import process to a whole new level of ugliness. The previous posting identified the fact that the #import "rename" processing on the esriGeometry library ended up repositioning the first use of the renamed esriLONG_PTR typedef to the statement prior to the typedef definition, as shown below: ------------------------------------------------------------------------------- typedef esriLONG_PTR esriSpatialReferenceImplHandle; <-- this out-of-sequence statement position causes the problem #if !defined(_WIN64) typedef __w64 long esriLONG_PTR; #else typedef __int64 esriLONG_PTR; #endif typedef esriLONG_PTR esriPrecisionImplHandle; ------------------------------------------------------------------------------- We really hate to have to do this, since it is a form of "making a bad situation worse", but we discovered that placing a duplicate of the esriGeometry typedef for the renamed esriLONG_PTR in our own header file *before* the #import "esriGeometry.olb" statement allows the esriLONG_PTR definition to be "recognized" when it encounters the out-of-sequence statement for "typedef esriLONG_PTR esriSpatialReferenceImplHandle;" (that is, it no longer results in the fatal compile error). As a result, the 2 changes we had to make in our own header file are listed below: 1. Physically include a typedef to duplicate the ArcGIS typedef, but using the rename name ("esriLONG_PTR"), as shown below. This typedef must be located *before* any of the #import statements. ----------------------------------- #if !defined(_WIN64) typedef __w64 long esriLONG_PTR; #else typedef __int64 esriLONG_PTR; #endif ----------------------------------- 2. Add the following rename attribute on the following two #import statements: rename("LONG_PTR", "esriLONG_PTR") ----------------------------------- #import "esriGeometry.olb" raw_interfaces_only raw_native_types named_guids rename("LONG_PTR", "esriLONG_PTR") #import "esriCarto.olb" raw_interfaces_only raw_native_types no_namespace named_guids exclude("OLE_COLOR", "OLE_HANDLE", "VARTYPE", "UINT_PTR"), rename ("ITableDefinition", "IEsriTableDefinition"), rename ("IRow", "IEsriRow") rename("LONG_PTR", "esriLONG_PTR") ----------------------------------- We are very uncomfortable with such a coding construct, but this at least lets us build and run in the environment of ArcGIS Engine Runtime 10.1 (Beta 2). We have submitted a Beta 2 Bug Report on this (ArcGIS10.1-000515) in an effort to make Esri aware of the problem. We are hopeful that Esri will be able to make some type of adjustment to eliminate this problem since it seems it will likely create problems for many development organizations and Business Partners. Thanks again. Scott
... View more
01-24-2012
05:41 AM
|
0
|
0
|
331
|
POST
|
Richard, Yes, it seems we also end up struggling with resolving a new set of #import problems with each new major ArcGIS release. The thing that is so frustrating on this particular item is why ArcGIS felt it needed to create its own typedef for LONG_PTR instead of just using the existing typedef provided by Microsoft in the basetsd.h header file. - It seems that this has to cause conflicts with any existing code that is already using the Microsoft LONG_PTR typedef - If ArcGIS really does need a custom version, then it would seem prudent for ArcGIS to choose a name different from the Microsoft name. - We are wasting a lot of time trying to find some way to workaround this problem, when it seems ArcGIS could have avoided the problem by just using a name that is not guaranteed to conflict with the existing Microsoft typedef. Historically, we have been able to resolve the #import issues by using combinations of "exclude" or "rename" attributes on the #import statement. Sometimes we had to modify our source code files that interact with ArcObjects to specify new names assigned via the "rename" attribute. The significant thing to resolving those earlier problems was that the code that had to be adjusted was in our product source files (so we could get to it and modify it). The problem we have encountered now with esriGeometry::LONG_PTR is that ArcGIS itself is specifying the typedef in its esriGeometry library and then explicitly referring to that typedef in the ArcGIS esriCarto library. So we cannot get to the code that is using this new typedef to modify it. We have been experimenting with various combinations of the "rename" attribute on our #import statement and have been able to get close, but still no success. When esriGeometry is imported with the following #import statement: #import "esriGeometry.olb" raw_interfaces_only raw_native_types named_guids the resulting series of statements in the resulting esrigeometry.tlh file are as shown below. This is what you would expect: the typedef is defined and then it is used in subsequent statements. -------------------------------------------------- #if !defined(_WIN64) typedef __w64 long LONG_PTR; #else typedef __int64 LONG_PTR; #endif typedef LONG_PTR esriSpatialReferenceImplHandle; typedef LONG_PTR esriPrecisionImplHandle; typedef LONG_PTR esriPrecisionExImplHandle; typedef LONG_PTR esriProjectionImplHandle; typedef LONG_PTR esriGeoTransformationImplHandle; typedef struct _esriSegmentInfo esriSegmentInfo; typedef LONG_PTR TopologyHandle; typedef struct _WKSPointVA WKSPointVA; -------------------------------------------------- But this appaorach then also generates the fatal "ambiguous symbol" error shown in the original posting in this thread. We tried adding the following "rename" attribute to the #import statements for esriGeometry and esriCarto: #import "esriGeometry.olb" raw_interfaces_only raw_native_types named_guids rename("LONG_PTR", "esriLONG_PTR") #import "esriCarto.olb" raw_interfaces_only raw_native_types no_namespace named_guids exclude("OLE_COLOR", "OLE_HANDLE", "VARTYPE", "UINT_PTR"), rename ("ITableDefinition", "IEsriTableDefinition"), rename ("IRow", "IEsriRow") rename("LONG_PTR", "esriLONG_PTR") The good news is that seemed to bypass the original problem we saw in the resulting esriCarto.tlh file by generating the following output for esriCarto: virtual HRESULT __stdcall OnMessage ( /*[in]*/ unsigned long msg, /*[in]*/ UINT_PTR wParam, /*[in]*/ esriGeometry::esriLONG_PTR lParam ) = 0; <-- good: The reference into esriGeometry was adjusted to esriLONG_PTR However, the fatal error moved back to esriGeometry.tlh because the content of the *.tlh file generated via #import with the "rename" attribute has the effect of moving the first use of the typedef to be *before* the typedef itself is actually specified, as shown below: -------------------------------------------------- typedef esriLONG_PTR esriSpatialReferenceImplHandle; <-- this out-of-sequence statement position causes the problem #if !defined(_WIN64) typedef __w64 long esriLONG_PTR; #else typedef __int64 esriLONG_PTR; #endif typedef esriLONG_PTR esriPrecisionImplHandle; typedef esriLONG_PTR esriPrecisionExImplHandle; typedef esriLONG_PTR esriProjectionImplHandle; typedef esriLONG_PTR esriGeoTransformationImplHandle; typedef struct _esriSegmentInfo esriSegmentInfo; typedef esriLONG_PTR TopologyHandle; typedef struct _WKSPointVA WKSPointVA; -------------------------------------------------- and this results in the following compile errors: 1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(718): error C2146: syntax error : missing ';' before identifier 'esriSpatialReferenceImplHandle' 1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(718): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(718): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(720): error C2371: 'esriGeometry::esriLONG_PTR' : redefinition; different basic types 1> c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(718) : see declaration of 'esriGeometry::esriLONG_PTR' 1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(1097): error C2061: syntax error : identifier 'esriSpatialReferenceImplHandle' 1>c:\productdev\synergee\gas\unicode\debug\stnetwork\esrigeometry.tlh(2053): error C2061: syntax error : identifier 'esriSpatialReferenceImplHandle' So we will have to continue the investigation. But until this problem can be resolved, we find outselves in the position where it is not possible to physically build our product in the ArcGIS 10.1 (Beta 2) environment. Thanks again for your insights. Scott
... View more
01-24-2012
02:52 AM
|
0
|
0
|
331
|
Title | Kudos | Posted |
---|---|---|
1 | 05-14-2015 11:08 AM | |
1 | 10-09-2011 09:09 AM |
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:23 AM
|