int CvId = SystemVariables.CVPORT;
Very curious about the above line. ^
Is there a reference to this?
Hi Bill,
That method did return a short but once value had been marshaled and under control of CLR going from short to int is a widening conversion so it implicitly casted.
Was just some code had laying around and the initial idea for SystemVariable class was to be able to set variables with some type safety and other checks like making sure it fell in range, or if a bitcode was a valid number.
Also have a indexer method for variables hardly used and the ability to add methods easily for new and/or variables that I find myself needing to set more than once and in different places.
Also wanted the ability to undo or roll back to a initial state mainly when scripting a command.
Tony has some nice implementations posted here you can search for(I think in
ExportLayout example and in
Library thread for Layout, Plot, etc....)
Tonight was the first time in a couple months I had time to sit down and play a little and here is what I ended up with.
Initially the properties for the variables were static, but was easier to change to instance methods to be able to reuse for temporarily setting the variables, so SystemVariables.CVPORT would now be SystemVariables.Current.CVPORT
First maybe a little example of using class
Basically in CTAB example can set it through indexer or through CTAB property which uses indexer.
The other 2 use the TemporarySystemVariable class which inherits from SystemVariable, and it just overrides the indexer to save the initial state before calling base implementation.
public class SystemVariTest : CommandClass
{
[CommandMethod("CTABSystemVariable")]
public void CTABSystemVariable()
{
Ed.WriteLine(SystemVariables.Current["CTAB"]);
SystemVariables.Current["CTAB"] = "Layout1";
Ed.WriteLine(SystemVariables.Current["CTAB"]);
SystemVariables.Current.CTAB = "Model";
}
[CommandMethod("UCSFOLLOWTempSystemVariable")]
public void UCSFOLLOWTempSystemVariable()
{
Ed.WriteLine(SystemVariables.Current.UCSFOLLOW);
using (TemporarySystemVariables temps
= new TemporarySystemVariables
()) {
Ed.WriteLine(temps.UCSFOLLOW);
temps.UCSFOLLOW = !temps.UCSFOLLOW;
Ed.WriteLine(temps.UCSFOLLOW);
}
Ed.WriteLine(SystemVariables.Current.UCSFOLLOW);
}
[CommandMethod("OSMODETempSystemVariable")]
public void OSMODETempSystemVariable()
{
Ed.WriteLine(SystemVariables.Current.OSMODE.ToString());
using (TemporarySystemVariables temps
= new TemporarySystemVariables
()) {
Ed.WriteLine(temps.OSMODE.ToString());
temps.OSMODE = OsnapMode.Endpoint | OsnapMode.Midpoint;
Ed.WriteLine(temps.OSMODE.ToString());
}
Ed.WriteLine(SystemVariables.Current.OSMODE.ToString());
}
}
Here is SystemVariable Class
using System;
using Autodesk.AutoCAD.DatabaseServices;
namespace Autodesk.AutoCAD.ApplicationServices.Core
{
public class SystemVariables
{
private static SystemVariables _current
= new SystemVariables
(); public static SystemVariables Current {get { return _current; } }
internal SystemVariables()
{
}
/// Would be nice to just let the name of the method be passed, and with .NET 4.5 a easy way
/// would be with [CallerMemberName] attribute
/// http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute.aspx
/// Requires .NET 4.5
////private T GetSystemVariable<T>([CallerMemberName] string name = null)
////{
//// return (T)this[name];
////}
private T GetSystemVariable<T>(string name)
{
return (T)this[name];
}
private void SetSystemVariable<T>(string name, T value)
{
this[name] = value;
}
private bool GetBoolSystemVariable(string name)
{
short val = GetSystemVariable<short>(name);
if (val == 1)
{
return true;
}
else
{
return false;
}
}
private void SetBoolSystemVariable(string name, bool value)
{
if (value)
{
SetSystemVariable<short>(name, 1);
}
else
{
SetSystemVariable<short>(name, 0);
}
}
public short CVPORT
{
get { return GetSystemVariable<short>("CVPORT"); }
set { SetSystemVariable<short>("CVPORT", value); }
}
public bool DWGTITLED
{
get { return GetBoolSystemVariable("DWGTITLED"); }
}
public bool UCSFOLLOW
{
get { return GetBoolSystemVariable("UCSFOLLOW"); }
set { SetBoolSystemVariable("UCSFOLLOW", value); }
}
public string CMDNAMES
{
get { return GetSystemVariable<string>("CMDNAMES"); }
}
/////// Think commands can have '(apostrophe) in them and would cause problem
// public ICollection<string> CMDNAMES
// {
// get { return GetSystemVariable<string>("CMDNAMES").Split('\''); }
// }
public string CTAB
{
get { return GetSystemVariable<string>("CTAB"); }
set { SetSystemVariable<string>("CTAB", value); }
}
public OsnapMode OSMODE
{
get { return GetSystemVariable<OsnapMode>("OSMODE"); }
set { SetSystemVariable<short>("OSMODE", (short)value); }
}
public virtual object this[string name]
{
get
{
if (name.IsNullOrWhiteSpace())
{
throw new ArgumentNullException
("{0} is Empty or Null", name
); }
try
{
return Application.GetSystemVariable(name);
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
if (ex.ErrorStatus == Runtime.ErrorStatus.InvalidInput)
{
throw new ArgumentException
("InvalidName", name
); }
else
{
throw;
}
}
}
set
{
try
{
Application.SetSystemVariable(name, value);
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
if (ex.ErrorStatus == Runtime.ErrorStatus.InvalidInput)
{
throw new ArgumentException
(String.Format("{0}:{1} is Invalid", name,
value)); }
throw;
}
}
}
}
}
and TemporarySystem variable class
using System;
using System.Collections.Generic;
namespace Autodesk.AutoCAD.ApplicationServices.Core
{
public class TemporarySystemVariables : SystemVariables, IDisposable
{
public TemporarySystemVariables()
{
}
private Dictionary
<string,
object> _variables
= new Dictionary
<string,
object>(); public override object this[string name]
{
get
{
return base[name];
}
set
{
if (!_variables.ContainsKey(name))
{
_variables.Add(name, base[name]);
}
base[name] = value;
}
}
public void Dispose()
{
foreach (var variable in _variables)
{
base[variable.Key] = variable.Value;
}
_variables.Clear();
}
}
}
Just threw it together and have not tested but very little, and until use it a little a bit not sure if I will be like it or not.
Sure the other guys here have better ideas they can add.
Will need to change WriteLine to WriteMessage, and get rid of CommandClass inheritance, etc....
I think the only thing left out was OsnapMode for OSMODE to work
[Flags]
public enum OsnapMode : short
{
None = 0,
Endpoint = 1,
Midpoint = 2,
Center = 4,
Node = 8,
Quadrant = 16,
Intersection = 32,
Insertion = 64,
Perpendicular = 128,
Tangent = 256,
Nearest = 512,
Quick = 1024,
ApparentIntersection = 2048,
Extension = 4096,
Parallel = 8192,
}