AE(ArcEngine)定制工具Tool工具箱
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Runtime.InteropServices; 5 using ESRI.ArcGIS.Geodatabase; 6 using ESRI.ArcGIS.Geometry; 7 using ESRI.ArcGIS.Geoprocessing; 8 using ESRI.ArcGIS.esriSystem; 9 using ESRI.ArcGIS.DataSourcesFile; 10 using ESRI.ArcGIS.DataSourcesGDB; 11 using ESRI.ArcGIS.ADF.CATIDs; 12 13 namespace GPCalculateArea 14 { 15 16 public class CalculateAreaFunction : IGPFunction2 17 { 18 private string m_ToolName = "CalculateArea"; //Function Name 19 //Local members 20 21 private string m_metadatafile = "CalculateArea_area.xml"; 22 private IArray m_Parameters; // Array of Parameters 23 private IGPUtilities m_GPUtilities; // GPUtilities object 24 25 public CalculateAreaFunction() 26 { 27 m_GPUtilities = new GPUtilitiesClass(); 28 } 29 30 #region IGPFunction Members 31 32 // Set the name of the function tool. 33 // This name appears when executing the tool at the command line or in scripting. 34 // This name should be unique to each toolbox and must not contain spaces. 35 public string Name 36 { 37 get { return m_ToolName; } 38 } 39 40 // Set the function tool Display Name as seen in ArcToolbox. 41 public string DisplayName 42 { 43 get { return "Calculate Area"; } 44 } 45 46 // This is the location where the parameters to the Function Tool are defined. 47 // This property returns an IArray of parameter objects (IGPParameter). 48 // These objects define the characteristics of the input and output parameters. 49 public IArray ParameterInfo 50 { 51 get 52 { 53 //Array to the hold the parameters 54 IArray parameters = new ArrayClass(); 55 56 //Input DataType is GPFeatureLayerType 57 IGPParameterEdit3 inputParameter = new GPParameterClass(); 58 inputParameter.DataType = new GPFeatureLayerTypeClass(); 59 60 // Default Value object is GPFeatureLayer 61 inputParameter.Value = new GPFeatureLayerClass(); 62 63 // Set Input Parameter properties 64 inputParameter.Direction = esriGPParameterDirection.esriGPParameterDirectionInput; 65 inputParameter.DisplayName = "Input Features"; 66 inputParameter.Name = "input_features"; 67 inputParameter.ParameterType = esriGPParameterType.esriGPParameterTypeRequired; 68 parameters.Add(inputParameter); 69 70 // Area field parameter 71 inputParameter = new GPParameterClass(); 72 inputParameter.DataType = new GPStringTypeClass(); 73 74 // Value object is GPString 75 IGPString gpStringValue = new GPStringClass(); 76 gpStringValue.Value = "Area"; 77 inputParameter.Value = (IGPValue)gpStringValue; 78 79 // Set field name parameter properties 80 inputParameter.Direction = esriGPParameterDirection.esriGPParameterDirectionInput; 81 inputParameter.DisplayName = "Area Field Name"; 82 inputParameter.Name = "field_name"; 83 inputParameter.ParameterType = esriGPParameterType.esriGPParameterTypeRequired; 84 parameters.Add(inputParameter); 85 86 // Output parameter (Derived) and data type is DEFeatureClass 87 IGPParameterEdit3 outputParameter = new GPParameterClass(); 88 outputParameter.DataType = new GPFeatureLayerTypeClass(); 89 90 // Value object is DEFeatureClass 91 outputParameter.Value = new DEFeatureClassClass(); 92 93 // Set output parameter properties 94 outputParameter.Direction = esriGPParameterDirection.esriGPParameterDirectionOutput; 95 outputParameter.DisplayName = "Output FeatureClass"; 96 outputParameter.Name = "out_featureclass"; 97 outputParameter.ParameterType = esriGPParameterType.esriGPParameterTypeDerived; 98 99 // Create a new schema object - schema means the structure or design of the feature class (field information, geometry information, extent) 100 IGPFeatureSchema outputSchema = new GPFeatureSchemaClass(); 101 IGPSchema schema = (IGPSchema)outputSchema; 102 103 // Clone the schema from the dependency. 104 //This means update the output with the same schema as the input feature class (the dependency). 105 schema.CloneDependency = true; 106 107 // Set the schema on the output because this tool will add an additional field. 108 outputParameter.Schema = outputSchema as IGPSchema; 109 outputParameter.AddDependency("input_features"); 110 parameters.Add(outputParameter); 111 112 return parameters; 113 } 114 } 115 116 // Validate: 117 // - Validate is an IGPFunction method, and we need to implement it in case there 118 // is legacy code that queries for the IGPFunction interface instead of the IGPFunction2 119 // interface. 120 // - This Validate code is boilerplate - copy and insert into any IGPFunction2 code.. 121 // - This is the calling sequence that the gp framework now uses when it QI's for IGPFunction2.. 122 public IGPMessages Validate(IArray paramvalues, bool updateValues, IGPEnvironmentManager envMgr) 123 { 124 if (m_Parameters == null) 125 m_Parameters = ParameterInfo; 126 127 // Call UpdateParameters(). 128 // Only Call if updatevalues is true. 129 if (updateValues == true) 130 { 131 UpdateParameters(paramvalues, envMgr); 132 } 133 134 // Call InternalValidate (Basic Validation). Are all the required parameters supplied? 135 // Are the Values to the parameters the correct data type? 136 IGPMessages validateMsgs = m_GPUtilities.InternalValidate(m_Parameters, paramvalues, updateValues, true, envMgr); 137 138 // Call UpdateMessages(); 139 UpdateMessages(paramvalues, envMgr, validateMsgs); 140 141 // Return the messages 142 return validateMsgs; 143 } 144 145 // This method will update the output parameter value with the additional area field. 146 public void UpdateParameters(IArray paramvalues, IGPEnvironmentManager pEnvMgr) 147 { 148 m_Parameters = paramvalues; 149 150 // Retrieve the input parameter value 151 IGPValue parameterValue = m_GPUtilities.UnpackGPValue(m_Parameters.get_Element(0)); 152 153 // Get the derived output feature class schema and empty the additional fields. This will ensure you don't get duplicate entries. 154 IGPParameter3 derivedFeatures = (IGPParameter3)paramvalues.get_Element(2); 155 IGPFeatureSchema schema = (IGPFeatureSchema)derivedFeatures.Schema; 156 schema.AdditionalFields = null; 157 158 // If we have an input value, create a new field based on the field name the user entered. 159 if (parameterValue.IsEmpty() == false) 160 { 161 IGPParameter3 fieldNameParameter = (IGPParameter3)paramvalues.get_Element(1); 162 string fieldName = fieldNameParameter.Value.GetAsText(); 163 164 // Check if the user's input field already exists 165 IField areaField = m_GPUtilities.FindField(parameterValue, fieldName); 166 if (areaField == null) 167 { 168 IFieldsEdit fieldsEdit = new FieldsClass(); 169 IFieldEdit fieldEdit = new FieldClass(); 170 fieldEdit.Name_2 = fieldName; 171 fieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble; 172 fieldsEdit.AddField(fieldEdit); 173 174 // Add an additional field for the area values to the derived output. 175 IFields fields = fieldsEdit as IFields; 176 schema.AdditionalFields = fields; 177 } 178 179 } 180 } 181 182 // Called after returning from the update parameters routine. 183 // You can examine the messages created from internal validation and change them if desired. 184 public void UpdateMessages(IArray paramvalues, IGPEnvironmentManager pEnvMgr, IGPMessages Messages) 185 { 186 // Check for error messages 187 IGPMessage msg = (IGPMessage)Messages; 188 if (msg.IsError()) 189 return; 190 191 // Get the first Input Parameter 192 IGPParameter parameter = (IGPParameter)paramvalues.get_Element(0); 193 194 // UnPackGPValue. This ensures you get the value either form the dataelement or GpVariable (ModelBuilder) 195 IGPValue parameterValue = m_GPUtilities.UnpackGPValue(parameter); 196 197 // Open the Input Dataset - Use DecodeFeatureLayer as the input might be a layer file or a feature layer from ArcMap. 198 IFeatureClass inputFeatureClass; 199 IQueryFilter qf; 200 m_GPUtilities.DecodeFeatureLayer(parameterValue, out inputFeatureClass, out qf); 201 202 IGPParameter3 fieldParameter = (IGPParameter3)paramvalues.get_Element(1); 203 string fieldName = fieldParameter.Value.GetAsText(); 204 205 // Check if the field already exists and provide a warning. 206 int indexA = inputFeatureClass.FindField(fieldName); 207 if (indexA > 0) 208 { 209 Messages.ReplaceWarning(1, "Field already exists. It will be overwritten."); 210 } 211 212 return; 213 } 214 215 // Execute: Execute the function given the array of the parameters 216 public void Execute(IArray paramvalues, ITrackCancel trackcancel, IGPEnvironmentManager envMgr, IGPMessages message) 217 { 218 219 // Get the first Input Parameter 220 IGPParameter parameter = (IGPParameter)paramvalues.get_Element(0); 221 222 // UnPackGPValue. This ensures you get the value either form the dataelement or GpVariable (ModelBuilder) 223 IGPValue parameterValue = m_GPUtilities.UnpackGPValue(parameter); 224 225 // Open Input Dataset 226 IFeatureClass inputFeatureClass; 227 IQueryFilter qf; 228 m_GPUtilities.DecodeFeatureLayer(parameterValue, out inputFeatureClass, out qf); 229 230 if (inputFeatureClass == null) 231 { 232 message.AddError(2, "Could not open input dataset."); 233 return; 234 } 235 236 // Add the field if it does not exist. 237 int indexA; 238 239 parameter = (IGPParameter)paramvalues.get_Element(1); 240 string field = parameter.Value.GetAsText(); 241 242 243 indexA = inputFeatureClass.FindField(field); 244 if (indexA < 0) 245 { 246 IFieldEdit fieldEdit = new FieldClass(); 247 fieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble; 248 fieldEdit.Name_2 = field; 249 inputFeatureClass.AddField(fieldEdit); 250 } 251 252 int featcount = inputFeatureClass.FeatureCount(null); 253 254 //Set the properties of the Step Progressor 255 IStepProgressor pStepPro = (IStepProgressor)trackcancel; 256 pStepPro.MinRange = 0; 257 pStepPro.MaxRange = featcount; 258 pStepPro.StepValue = (1); 259 pStepPro.Message = "Calculating Area"; 260 pStepPro.Position = 0; 261 pStepPro.Show(); 262 263 // Create an Update Cursor 264 indexA = inputFeatureClass.FindField(field); 265 IFeatureCursor updateCursor = inputFeatureClass.Update(qf, false); 266 IFeature updateFeature = updateCursor.NextFeature(); 267 IGeometry geometry; 268 IArea area; 269 double dArea; 270 271 while (updateFeature != null) 272 { 273 geometry = updateFeature.Shape; 274 area = (IArea)geometry; 275 dArea = area.Area; 276 updateFeature.set_Value(indexA, dArea); 277 updateCursor.UpdateFeature(updateFeature); 278 updateFeature.Store(); 279 updateFeature = updateCursor.NextFeature(); 280 pStepPro.Step(); 281 } 282 283 pStepPro.Hide(); 284 285 // Release the update cursor to remove the lock on the input data. 286 System.Runtime.InteropServices.Marshal.ReleaseComObject(updateCursor); 287 } 288 289 // This is the function name object for the Geoprocessing Function Tool. 290 // This name object is created and returned by the Function Factory. 291 // The Function Factory must first be created before implementing this property. 292 public IName FullName 293 { 294 get 295 { 296 // Add CalculateArea.FullName getter implementation 297 IGPFunctionFactory functionFactory = new CalculateAreaFunctionFactory(); 298 return (IName)functionFactory.GetFunctionName(m_ToolName); 299 } 300 } 301 302 // This is used to set a custom renderer for the output of the Function Tool. 303 public object GetRenderer(IGPParameter pParam) 304 { 305 return null; 306 } 307 308 // This is the unique context identifier in a [MAP] file (.h). 309 // ESRI Knowledge Base article #27680 provides more information about creating a [MAP] file. 310 public int HelpContext 311 { 312 get { return 0; } 313 } 314 315 // This is the path to a .chm file which is used to describe and explain the function and its operation. 316 public string HelpFile 317 { 318 get { return ""; } 319 } 320 321 // This is used to return whether the function tool is licensed to execute. 322 public bool IsLicensed() 323 { 324 IAoInitialize aoi = new AoInitializeClass(); 325 ILicenseInformation licInfo = (ILicenseInformation)aoi; 326 327 string licName = licInfo.GetLicenseProductName(aoi.InitializedProduct()); 328 329 if (licName == "ArcInfo") 330 { 331 return true; 332 } 333 else 334 return false; 335 } 336 337 // This is the name of the (.xml) file containing the default metadata for this function tool. 338 // The metadata file is used to supply the parameter descriptions in the help panel in the dialog. 339 // If no (.chm) file is provided, the help is based on the metadata file. 340 // ESRI Knowledge Base article #27000 provides more information about creating a metadata file. 341 public string MetadataFile 342 { 343 get { return m_metadatafile; } 344 } 345 346 // By default, the Toolbox will create a dialog based upon the parameters returned 347 // by the ParameterInfo property. 348 public UID DialogCLSID 349 { 350 // DO NOT USE. INTERNAL USE ONLY. 351 get { return null; } 352 } 353 354 #endregion 355 } 356 357 ////////////////////////////// 358 // Function Factory Class 359 //////////////////////////// 360 [ 361 Guid("2554BFC7-94F9-4d28-B3FE-14D17599B35A"), 362 ComVisible(true) 363 ] 364 public class CalculateAreaFunctionFactory : IGPFunctionFactory 365 { 366 private const string m_ToolName = "ylArea"; //Function Name 367 // Register the Function Factory with the ESRI Geoprocessor Function Factory Component Category. 368 #region "Component Category Registration" 369 [ComRegisterFunction()] 370 static void Reg(string regKey) 371 { 372 373 GPFunctionFactories.Register(regKey); 374 } 375 376 [ComUnregisterFunction()] 377 static void Unreg(string regKey) 378 { 379 GPFunctionFactories.Unregister(regKey); 380 } 381 #endregion 382 383 // Utility Function added to create the function names. 384 private IGPFunctionName CreateGPFunctionNames(long index) 385 { 386 IGPFunctionName functionName = new GPFunctionNameClass(); 387 functionName.MinimumProduct = esriProductCode.esriProductCodeProfessional; 388 IGPName name; 389 390 switch (index) 391 { 392 case (0): 393 name = (IGPName)functionName; 394 name.Category = "AreaCalculation"; 395 name.Description = "Calculate Area for FeatureClass"; 396 name.DisplayName = "Calculate Area"; 397 name.Name = m_ToolName; 398 name.Factory = (IGPFunctionFactory)this; 399 break; 400 } 401 402 return functionName; 403 } 404 405 // Implementation of the Function Factory 406 #region IGPFunctionFactory Members 407 408 // This is the name of the function factory. 409 // This is used when generating the Toolbox containing the function tools of the factory. 410 public string Name 411 { 412 get { return m_ToolName; } 413 } 414 415 // This is the alias name of the factory. 416 public string Alias 417 { 418 get { return "area"; } 419 } 420 421 // This is the class id of the factory. 422 public UID CLSID 423 { 424 get 425 { 426 UID id = new UIDClass(); 427 id.Value = this.GetType().GUID.ToString("B"); 428 return id; 429 } 430 } 431 432 // This method will create and return a function object based upon the input name. 433 public IGPFunction GetFunction(string Name) 434 { 435 switch (Name) 436 { 437 case (m_ToolName): 438 IGPFunction gpFunction = new CalculateAreaFunction(); 439 return gpFunction; 440 } 441 442 return null; 443 } 444 445 // This method will create and return a function name object based upon the input name. 446 public IGPName GetFunctionName(string Name) 447 { 448 IGPName gpName = new GPFunctionNameClass(); 449 450 switch (Name) 451 { 452 case (m_ToolName): 453 return (IGPName)CreateGPFunctionNames(0); 454 455 } 456 return null; 457 } 458 459 // This method will create and return an enumeration of function names that the factory supports. 460 public IEnumGPName GetFunctionNames() 461 { 462 IArray nameArray = new EnumGPNameClass(); 463 nameArray.Add(CreateGPFunctionNames(0)); 464 return (IEnumGPName)nameArray; 465 } 466 467 // This method will create and return an enumeration of GPEnvironment objects. 468 // If tools published by this function factory required new environment settings, 469 //then you would define the additional environment settings here. 470 // This would be similar to how parameters are defined. 471 public IEnumGPEnvironment GetFunctionEnvironments() 472 { 473 return null; 474 } 475 476 477 #endregion 478 } 479 480 }