跳到主要内容

使用SOLIDWORKS API处理自定义属性修改事件(添加、删除、更改)

SOLIDWORKS API提供了通知来处理自定义属性的修改(如添加、删除或更改)。这些事件(AddCustomPropertyNotify、DeleteCustomPropertyNotify、ChangeCustomPropertyNotify)适用于零件、装配体和图纸,并支持通用和配置特定的自定义属性。然而,自SOLIDWORKS 2018以来,这些事件不再适用于用户界面中由用户修改的自定义属性,只支持通过SOLIDWORKS API修改的自定义属性。

下面的代码示例提供了解决此问题的方法,并且可以处理无论以何种方式修改自定义属性。

  • 创建控制台应用程序并添加下面的代码
  • 运行控制台
  • 修改自定义属性。修改结果将输出到控制台窗口:

将属性修改信息输出到控制台

Program.cs

程序的入口点

using SolidWorks.Interop.sldworks;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace HandlePrpsEvents
{
class Program
{
static void Main(string[] args)
{
var app = Activator.CreateInstance(Type.GetTypeFromProgID("SldWorks.Application")) as ISldWorks;
app.Visible = true;

IModelDoc2 model = null;

do
{
model = app.IActiveDoc2;
if (model == null)
{
Console.WriteLine("打开模型并按任意键继续");
Console.ReadLine();
}
} while (model == null);


var handler = new CustomPropertiesEventsHandler(app, model);
handler.PropertyChanged += OnPropertyChanged;


Console.ReadLine();

handler.Dispose();
}

private static void OnPropertyChanged(PropertyChangeAction_e type, string name, string conf, string value)
{
Console.WriteLine($"属性 {name};操作:{type};配置:{conf};值:{value}");
}
}
}

CustomPropertiesEventsHandler.cs

using SolidWorks.Interop.sldworks;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace HandlePrpsEvents
{
public enum PropertyChangeAction_e
{
添加,
删除,
修改
}

public class CustomPropertiesEventsHandler : IDisposable
{
private class PropertiesList : Dictionary<string, string>
{
internal PropertiesList(ICustomPropertyManager prpsMgr) : base(StringComparer.CurrentCultureIgnoreCase)
{
var prpNames = prpsMgr.GetNames() as string[];

if (prpNames != null)
{
foreach (var prpName in prpNames)
{
string val;
string resVal;
bool wasRes;
prpsMgr.Get5(prpName, true, out val, out resVal, out wasRes);
Add(prpName, val);
}
}
}
}

private class PropertiesSet : Dictionary<string, PropertiesList>
{
internal PropertiesSet(IModelDoc2 model) : base(StringComparer.CurrentCultureIgnoreCase)
{
Add("", new PropertiesList(model.Extension.CustomPropertyManager[""]));

var confNames = model.GetConfigurationNames() as string[];

if (confNames != null)
{
foreach (var confName in confNames)
{
Add(confName, new PropertiesList(model.Extension.CustomPropertyManager[confName]));
}
}
}
}

public delegate void PropertyChangedDelegate(PropertyChangeAction_e type, string name, string conf, string value);

public event PropertyChangedDelegate PropertyChanged;

#region WinAPI

private delegate bool EnumWindowProc(IntPtr handle, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowTextLength(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true)]
private static extern bool EnumThreadWindows(uint threadId, EnumWindowProc enumProc, IntPtr lParam);

[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindow(IntPtr hWnd);

#endregion

private readonly ISldWorks m_App;
private readonly IModelDoc2 m_Model;

private IntPtr m_CurrentSummaryHandle;

private PropertiesSet m_CurPrpsSet;

public CustomPropertiesEventsHandler(ISldWorks app, IModelDoc2 model)
{
m_App = app;
m_Model = model;

(m_App as SldWorks).CommandCloseNotify += OnCommandCloseNotify;
(m_App as SldWorks).OnIdleNotify += OnIdleNotify;

if (model is PartDoc)
{
(model as PartDoc).AddCustomPropertyNotify += OnAddCustomPropertyNotify;
(model as PartDoc).DeleteCustomPropertyNotify += OnDeleteCustomPropertyNotify;
(model as PartDoc).ChangeCustomPropertyNotify += OnChangeCustomPropertyNotify;
}
else if (model is AssemblyDoc)
{
(model as AssemblyDoc).AddCustomPropertyNotify += OnAddCustomPropertyNotify;
(model as AssemblyDoc).DeleteCustomPropertyNotify += OnDeleteCustomPropertyNotify;
(model as AssemblyDoc).ChangeCustomPropertyNotify += OnChangeCustomPropertyNotify;
}
else if (model is DrawingDoc)
{
(model as DrawingDoc).AddCustomPropertyNotify += OnAddCustomPropertyNotify;
(model as DrawingDoc).DeleteCustomPropertyNotify += OnDeleteCustomPropertyNotify;
(model as DrawingDoc).ChangeCustomPropertyNotify += OnChangeCustomPropertyNotify;
}
else
{
throw new NotSupportedException();
}

CaptureCurrentProperties();
}

private int OnIdleNotify()
{
if (m_CurrentSummaryHandle != IntPtr.Zero)
{
if (!IsWindow(m_CurrentSummaryHandle))
{
FindDifferences(m_CurPrpsSet, new PropertiesSet(m_Model));
m_CurrentSummaryHandle = IntPtr.Zero;
m_CurPrpsSet = null;
}
}

return 0;
}

private void FindDifferences(PropertiesSet oldSet, PropertiesSet newSet)
{
foreach (var conf in oldSet.Keys)
{
var oldPrsList = oldSet[conf];
var newPrsList = newSet[conf];

var addedPrpNames = newPrsList.Keys.Except(oldPrsList.Keys);

foreach (var newPrpName in addedPrpNames)
{
PropertyChanged?.Invoke(PropertyChangeAction_e.添加, newPrpName, conf, newPrsList[newPrpName]);
}

var removedPrpNames = oldPrsList.Keys.Except(newPrsList.Keys);

foreach (var deletedPrpName in removedPrpNames)
{
PropertyChanged?.Invoke(PropertyChangeAction_e.删除, deletedPrpName, conf, oldPrsList[deletedPrpName]);
}

var commonPrpNames = oldPrsList.Keys.Intersect(newPrsList.Keys);

foreach (var prpName in commonPrpNames)
{
if (newPrsList[prpName] != oldPrsList[prpName])
{
PropertyChanged?.Invoke(PropertyChangeAction_e.修改, prpName, conf, newPrsList[prpName]);
}
}
}
}

private int OnAddCustomPropertyNotify(string propName, string Configuration, string Value, int valueType)
{
PropertyChanged?.Invoke(PropertyChangeAction_e.添加, propName, Configuration, Value);
return 0;
}

private int OnDeleteCustomPropertyNotify(string propName, string Configuration, string Value, int valueType)
{
PropertyChanged?.Invoke(PropertyChangeAction_e.删除, propName, Configuration, Value);
return 0;
}

private int OnChangeCustomPropertyNotify(string propName, string Configuration, string oldValue, string NewValue, int valueType)
{
PropertyChanged?.Invoke(PropertyChangeAction_e.修改, propName, Configuration, NewValue);
return 0;
}

private int OnCommandCloseNotify(int Command, int reason)
{
const int swCommands_File_Summaryinfo = 963;

if (Command == swCommands_File_Summaryinfo)
{
if (!CaptureCurrentProperties())
{
throw new Exception("无法找到摘要信息对话框");
}
}

return 0;
}

private bool CaptureCurrentProperties()
{
var handle = GetSummaryInfoDialogHandle();

if (handle != IntPtr.Zero)
{
m_CurPrpsSet = new PropertiesSet(m_Model);
return true;
}
else
{
return false;
}
}

private bool FindSymmaryInfoDialog(IntPtr handle, IntPtr lParam)
{
var captionLength = GetWindowTextLength(handle) + 1;
var caption = new StringBuilder(captionLength);

if (GetWindowText(handle, caption, captionLength) > 0)
{
if (caption.ToString() == "Summary Information")
{
var clsName = new StringBuilder(260);

GetClassName(handle, clsName, clsName.Capacity);

if (clsName.ToString() == "#32770")
{
m_CurrentSummaryHandle = handle;
}
}
}

return true;
}

private IntPtr GetSummaryInfoDialogHandle()
{
m_CurrentSummaryHandle = IntPtr.Zero;

var prc = Process.GetProcessById(m_App.GetProcessID());

for (int i = 0; i < prc.Threads.Count; i++)
{
var threadId = (uint)prc.Threads[i].Id;
EnumThreadWindows(threadId, FindSymmaryInfoDialog, IntPtr.Zero);
}

return m_CurrentSummaryHandle;
}

public void Dispose()
{
}
}
}