明察秋毫,很多情況下是非常需要的,例如,如果我們完善了一套系統,能夠將四川赈災的款項的籌集、采購、分發等步驟都能明察秋毫,相信整個世界會安靜很多。
同樣,對於一個使用Visio進行二次開發的程序來說,背後你需要知道用戶增加了那些設備,刪除了那些設備,修改了那些設備,這樣你才能對整個系統的數據進行有效的控制,否則“赈災”款項就可能丟失了,呵呵。
那我們應該如何做才能有效的處理這些事件,達到對設備的變更明察秋毫呢?
我前面介紹了一篇文章《C#進行Visio開發的事件處理 》,其中也介紹了各種事件偵聽,我們要對設備進行跟蹤的話,基本上只需要偵聽這幾個事件,並對之進行處理即可。
const string sink = "";
Event newEvent = null;
EventList applicationEvents = eventApplication.EventList;
EventList documentEvents = eventDocument.EventList;
newEvent = documentEvents.AddAdvise(
(unchecked((short)VisEventCodes.visEvtAdd) + (short)VisEventCodes.visEvtShape),
(IVisEventProc)this, sink, "ShapeAdd");
newEvent = documentEvents.AddAdvise(
(short)VisEventCodes.visEvtDel + (short)VisEventCodes.visEvtShape,
(IVisEventProc)this, sink, "ShapeDelete");
newEvent = documentEvents.AddAdvise(
(short)VisEventCodes.visEvtMod + (short)VisEventCodes.visEvtCell,
(IVisEventProc)this, sink, "CellChanged");
object IVisEventProc.VisEventProc(short eventCode, object source, int eventId,
int eventSequenceNumber, object subject, object moreInfo)
{
......
switch (eventCode)
{
case (short)VisEventCodes.visEvtShape + unchecked((short)VisEventCodes.visEvtAdd):
eventShape = (Shape)subject;
handleShapeAdd(eventShape);
break;
case (short)VisEventCodes.visEvtDel + (short)VisEventCodes.visEvtShape:
eventShape = (Shape)subject;
handleShapeDelete(eventShape);
break;
case (short)VisEventCodes.visEvtCell + (short)VisEventCodes.visEvtMod:
Visio.Cell cell = (Cell)subject;
if (cell.Name.IndexOf("Prop") >= 0)//限制只執行自定義事件一次
{
eventShape = cell.Shape;
handleCellModify(eventShape);
}
break;
default:
break;
}
return result;
}
以上是對幾個特別事件的偵聽,我們要實現設備的跟蹤,需要在這幾個事件中處理相關的設備信息。為了跟蹤好設備的相關信息,我們需要定義一個實體類ShapeLogInfo類放置相關的設備信息,如Shape的GUID,Shape的ID,設備狀態(添加、修改、刪除),Shape的Name,還有就是我們自定義的一個屬性“設備類型”。
/// <summary>
/// 形狀的類型,即設備類型
/// </summary>
public string ShapeType
/**//// <summary>
/// 形狀ID
/// </summary>
public string ShapeID
/**//// <summary>
/// 形狀的GUID
/// </summary>
public string ShapeGuid
/**//// <summary>
/// 形狀的狀態:新增、編輯、刪除
/// </summary>
public ShapeStatus ShapeStatus
/**//// <summary>
/// 形狀名稱
/// </summary>
public string ShapeName
為了更好的管理ShapeLogInfo的相關信息,我們把相同設備類型(ShapeType)的放到一起管理,於是,我們再創建一個ShapeTypeLogInfo類來裝載相關的日志信息,具體如下:
/// <summary>
/// 形狀類型
/// </summary>
public string ShapeType
/**//// <summary>
/// 形狀類型對應的數據庫表名稱
/// </summary>
public string ShapeTableName
/**//// <summary>
/// 該形狀類型對應的形狀日志對象集合
/// </summary>
public Dictionary<string, ShapeLogInfo> ShapeColloction
為了判斷是否有相應的ShapeTypeLogInfo和ShapeLogInfo,需要定義幾個函數用來維護相關的集合信息,如下所示:
/**//// <summary>
/// 獲取形狀對應的類型,如果沒有則創建
/// </summary>
private ShapeTypeLogInfo GetShapeType(ShapeLogInfo shape)
/**//// <summary>
/// 如果集合中有,修改狀態;否則添加一個新的
/// </summary>
public void AddLog(ShapeLogInfo shapeLogInfo)
/**//// <summary>
/// 判斷指定的形狀是否是在集合中存在
/// </summary>
public bool IsNewShape(ShapeLogInfo shape)
/**//// <summary>
/// 取當前設備在集合中存儲的ShapeLog對象
/// </summary>
public ShapeLogInfo GetShape(string shapeType, string shapeId)
完成這些函數後,最後需要做的就是在添加、刪除、修改Shape的偵聽事件中加入相關的日志就可以了,如在刪除設備的時候,我們是這樣記錄相關信息的
private void visioEventSink_OnShapeDelete(object sender, EventArgs e)
{
Shape shape = (Shape)sender;
string strDeviceType = string.Empty;
string strDeviceName = string.Empty;
string strDeviceID = string.Empty;
strDeviceType = VisioUtility.GetShapeCellValue(shape, "設備類型");
strDeviceID = VisioUtility.GetShapeCellValue(shape, "GUID");
ShapeLogInfo logInfo = new ShapeLogInfo();
logInfo.ShapeType = strDeviceType;
logInfo.ShapeID = shape.NameID;
logInfo.ShapeName = VisioUtility.GetShapeCellValue(shape, "名稱");
if (shape.Application.IsUndoingOrRedoing)
{
ShapeLogInfo info = Portal.gc.gOperationLog.GetShape(strDeviceType, shape.NameID);
if (info != null)
{
strDeviceID = info.ShapeGuid;
}
}
logInfo.ShapeGuid = strDeviceID;
logInfo.ShapeStatus = ShapeStatus.DeleteShape;
Portal.gc.gOperationLog.AddLog(logInfo);
}
其中if (shape.Application.IsUndoingOrRedoing)是為了判斷該操作是否為Undo或者Redo導致的操作,如果是,我們獲取它之前Shape的GUID即可。
記錄了設備的這些修改信息,我們就可以在保存數據的時候,根據這些信息移除相關的關系,添加或者刪除相關的設備信息了,而且這些信息,對於我們記錄用戶的圖紙修訂記錄也是必須要做的事情。