/********************************************************************************************* * Copyright 2004 - Volian Enterprises, Inc. All rights reserved. * Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE * ------------------------------------------------------------------------------ * $Workfile: VEObject.cs $ $Revision: 9 $ * $Author: Jsj $ $Date: 8/30/06 10:04a $ * * $History: VEObject.cs $ * * ***************** Version 9 ***************** * User: Jsj Date: 8/30/06 Time: 10:04a * Updated in $/LibSource/VEObject * Added Multi Procedure Data Checker * * ***************** Version 8 ***************** * User: Kathy Date: 6/21/05 Time: 7:27a * Updated in $/LibSource/VEObject * edit for approve if from procset/procedures node * * ***************** Version 7 ***************** * User: Kathy Date: 5/11/05 Time: 9:29a * Updated in $/LibSource/VEObject * approve menu from procedures tree node * * ***************** Version 6 ***************** * User: Kathy Date: 4/21/05 Time: 10:24a * Updated in $/LibSource/VEObject * remove upgrade2005 define * * ***************** Version 5 ***************** * User: Kathy Date: 3/22/05 Time: 10:14a * Updated in $/LibSource/VEObject * approve: remove revise menu enable * * ***************** Version 4 ***************** * User: Kathy Date: 2/03/05 Time: 11:20a * Updated in $/LibSource/VEObject * Change 'DUMMY' node to 'TEMP' node (just in case user sees it) * * ***************** Version 3 ***************** * User: Kathy Date: 1/31/05 Time: 11:06a * Updated in $/LibSource/VEObject * Fix B2005-005 (connection & delete directory errors). also, fix icon * * ***************** Version 2 ***************** * User: Kathy Date: 10/25/04 Time: 10:24a * Updated in $/LibSource/VEObject * Fix B2004-049 * * ***************** Version 1 ***************** * User: Kathy Date: 7/27/04 Time: 8:53a * Created in $/LibSource/VEObject *********************************************************************************************/ using System; using System.Text; using System.Collections; using System.Windows.Forms; using System.Runtime.InteropServices; using Utils; using VENetwork; using VEMessageNS; namespace VEObject { /// /// VEObject namespace provides classes for the Volian Enterprises Objects DataRoot, DataPath, /// Plant, Procedure Set, Procedures, Library Documents and Archives. /// /// This file has the base class, VEO_Base, which all other objects inherits from. /// public enum VEObjectTypesDefs { Generic = 0, ProcedureSet = 1, Procedure = 2, Archive = 3, LibraryDoc =4, System = 5, Plant = 6, DummySet = 7 }; public enum VEO_IconStates { Normal=0, LckByMe=1, LckByOther=2, LckPending=3, Empty=4 }; public enum ProcTypeOptions { // Standard=0, Background=1, Deviation=2, Slave=3 Standard=0, Slave=1, Background=2, Deviation=3 }; public class VEO_Base { public int [] iconStates; public int icon; public string _Title; public string _Location; public ArrayList Children; public Object parentObj; public UserRunTime usrRunTime; public bool isOpen; private bool Expanded; public bool IsEmpty; public int VEObjectType; public bool isNew; public bool AllowListViewSort; public VELock Lock; public VEConnection Connection; public TreeNode treeNode; public enum ProcColumnOptions { OneColumn=0, TwoColumn=1, ThreeColumn=2 }; public enum ArchiveTypeOptions { Full=0, Partial=1 }; // constructor public VEO_Base() { Expanded = false; isOpen = false; AllowListViewSort = false; Children = new ArrayList(); VEObjectType = (int)VEObjectTypesDefs.Generic; } ~ VEO_Base() { if (Connection!=null) Connection.Exit(); } public virtual void LoadLockInfo() { Lock = new VELock(_Location, usrRunTime==null?null:usrRunTime.myUserData, VENetwork.LockTypes.None); } public virtual bool mnuAllowDelete() { return true; } public virtual bool mnuAllowApprove() { return false; } public virtual bool mnuAllowApproveSel() { return false; } public virtual bool mnuAllowApproveAll() { return false; } public virtual bool mnuAllowProperties() { return true; } public virtual bool mnuAllowNew() { return true; } public virtual bool mnuAllowUpdRO() { return false; } public virtual bool mnuAllowClean() { return false; } public virtual bool mnuAllowDataCheck() { return false; } public virtual bool mnuAllowChgDef() { return false; } public virtual bool mnuAllowUpdateArch() { return false; } public virtual bool mnuAllowTestArchive() { return false; } public virtual bool mnuAllowExtractArch() { return false; } public virtual bool mnuAllowLckDB() { return false; } public virtual bool mnuAllowUnlckDB() { return false; } public virtual bool mnuAllowMonUsr() { if (usrRunTime.InMultiUserMode && !(Lock.LockType==VENetwork.LockTypes.None) && !(Lock.LockStatus==VENetwork.Status.LockedByOther)) return true; return false; } public virtual bool canEdit() { return true; } // used to flag whether all siblings of a node should be collapsed before expanding the // node. This is needed for multi-user support for the plant & procedure set levels so // that a user does not have open connections all over the tree. public virtual bool CollapseSibling() { return false; } public virtual bool amILockedByMe() { // if not a newtork serial number, treat it as anything is locked. if (!usrRunTime.InMultiUserMode)return true; VEO_Base obj = this; while (obj!=null) { if (obj.Lock.LockStatus == VENetwork.Status.Locked) return true; obj = (VEO_Base) obj.parentObj; } return false; } public virtual bool isProcSet() { return false; } public virtual bool isArchiveSet() { return false; } public virtual bool updateROValues() { return false; } public virtual void CleanTransitionsAndROsUsages(int clntype,string ProcName) { return; } public virtual void ApproveProcedures(int ApproveType, ArrayList prcs) { return; } public virtual void DataIntegrityCheck(string ProcName) { return; } // Add TreeNodes to the input TreeNode parent. public virtual void AddToTree(TreeNode parentnd) { for(int i=0; i0) veo.Children.Clear(); if (nd.Nodes.Count>0) nd.Nodes.Clear(); veo.Read(false); veo.AddToTree(nd); } // if the object can have a lock at this level, but it currently doesnot // have a lock, if it has children add a temp node to the treeview. This // is done so that if this becomes expanded, the lock is checked again. else if (veo.Lock.LockStatus!=VENetwork.Status.LockedByOther) { veo.Read(true); if (veo.Children.Count>0) { veo.Children.Clear(); TreeNode dmy = new TreeNode("TEMP"); nd.Nodes.Add(dmy); } } // if multi-user serial number, may have to reset lock status icon. if (usrRunTime.InMultiUserMode) { // if no lock & emtpy, show empty. Otherwise, show lock icon if (IsEmpty && veo.Lock.LockStatus==VENetwork.Status.NoLock) veo.icon = veo.iconStates[(int)VEO_IconStates.Empty]; else veo.icon = veo.iconStates[(int)veo.Lock.LockStatus]; nd.ImageIndex = veo.icon; nd.SelectedImageIndex = veo.icon; } } // When the user collapses the treenode, also, do some object cleanup. // This removes children, exits connections for all sub-tree children // and also refreshes locks, updates icons based on lock changes and // load in children at the current node level. public void Collapse(TreeNode nd, TreeViewAction act, bool dorefresh,bool closeconn) { Expanded=false; Children.Clear(); if (Connection != null && closeconn) Connection.Exit(); // if this is the actual node that was collapsed, then refresh at this level, // i.e. refresh the lock, update the icon (in case of lock status change) // and load children (may make into temp child if necessary) if (act == TreeViewAction.Collapse||dorefresh) { RefreshTreeNode(nd); // need to exit again because refresh tree node opens the connection // to determine locking status. if (Connection != null && closeconn) Connection.Exit(); } } // Expand the TreeNode. This makes a new/reenters connection at the level, sets up // icons for the level, enters it by loading its children (if it successfully // entered it, i.e. it's not locked. public virtual bool Expand(TreeNode mytreend) { if (Connection==null) Connection = new VEConnection(Lock, usrRunTime); // Enter the connection, i.e. refresh the lock & then see if can get into the // data level. bool canenter = Connection.Enter(false); // update icons (in case of lock status change) if (usrRunTime.InMultiUserMode) { // if no lock & emtpy, show empty. Otherwise, show lock icon if (IsEmpty && Lock.LockStatus==VENetwork.Status.NoLock) icon = iconStates[(int)VEO_IconStates.Empty]; else icon = iconStates[(int)Lock.LockStatus]; mytreend.ImageIndex = icon; mytreend.SelectedImageIndex = icon; } // if user cannot enter, it must be locked. Return a false. if (canenter==false) { Collapse(mytreend,TreeViewAction.Unknown,true,false); mytreend.Nodes.Clear(); mytreend.TreeView.Refresh(); return false; } if (Expanded) return true; Expanded = true; // load the children. First check for either no children (in case this was locked on // load, and then subsequently unlocked before the selection or check for a 'TEMP' // node. If it exists, remove it. Then if this has a lock type of none, load it's // children. Otherwise, load a temp child under each child. The temp child is // used because when the user actually expands this node, a recheck of the lock // status is needed and a change may have occurred (another user may have added, // deleted or modified children by the time this is entered). TreeNode frstchld = mytreend.FirstNode; if (frstchld==null || frstchld.Text == "TEMP") { mytreend.Nodes.Clear(); Read(false); AddToTree(mytreend); } VEO_Base veo; for (int i=0; i0) { veo.Children.Clear(); TreeNode dmy = new TreeNode("TEMP"); mytreend.Nodes[i].Nodes.Add(dmy); } } } return true; } public virtual void LockedDlg() { } // virtual read public virtual bool Read(bool dummy) { return true; } // virtual write public virtual bool Write() { return false; } public virtual bool Open() { return false; } public virtual bool Close() { return false; } // virtual cancel write (save) public virtual void CancelWrite() { } public virtual bool Delete() { return true; } // make a new plain vanilla object (this is really a virtual. public virtual Object MakeNewChild() { return (new Object()); } public virtual Object Copy() { return this; //default to returning self } public virtual Object AddNewChild() { VEO_Base newobj = (VEO_Base) this.MakeNewChild(); if (newobj==null) return null; // something happened, just return newobj.parentObj = (VEO_Base) this; newobj.isNew=true; bool prpchg = newobj.PropertiesDlg(this); if (prpchg == true) { // Copy is used so that a VEO-object is created that has editable // (versus new) properties. When the object is 'new' many fields // are editable that should not be editable when not new (this is // mainly an issue with the property grid, since the ReadOnly // setting can only be done at compile/build time - it CANNOT be // done at run-time. So when a new object is created, if it's // successful, it's copied to an object which is edit (not new) // for the treeview & any further operations. VEO_Base cpyobj = (VEO_Base) newobj.Copy(); Children.Add(cpyobj); // add the new one to the children if(newobj!=cpyobj)Children.Remove(newobj); cpyobj.Read(false); // read any child data return cpyobj; } else return null; } public virtual string GetTreeNodeText() { return _Title; } public virtual bool SaveChild(Object obj) { return false; } // virtual SaveNew public virtual bool SaveNew(string pth) { return false; } public virtual void DoListView(ListView veoListView) { return; } public virtual void DoWizzard() { return; } // Comunication between this object & vfw struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; public IntPtr lpData; } const int WM_COPYDATA = 0x004A; // sending side [DllImport("user32.dll")] static extern bool SendMessage( IntPtr hWnd, UInt32 Msg, UInt32 wParam, ref COPYDATASTRUCT lParam); public struct RqstAttachMsg { public Int16 level; public Int16 flag; public Int32 longval; } public struct AnswerMsg { public Int16 done; public Int16 intAnswer; public Int32 longAnswer; } public struct PRecordMsg { public Int16 done; public Int16 cnt; [MarshalAs(UnmanagedType.ByValTStr,SizeConst=140)] public String buff; } [StructLayout(LayoutKind.Sequential)] public struct PosUpdateStr { [MarshalAs(UnmanagedType.ByValTStr,SizeConst=16)] public String sender; [MarshalAs(UnmanagedType.ByValTStr,SizeConst=80)] public String directory; public Int32 docnumindx; public Int32 recID; } private VEO_Base GetObjectAtLevel(int level) { try { VEO_Base veo = this; while (veo != null) { if (level == 2 && veo.VEObjectType == (int)VEObjectTypesDefs.ProcedureSet) return veo; else if (level == 1 && veo.VEObjectType == (int)VEObjectTypesDefs.Plant) return veo; else if (level == 0 && veo.VEObjectType == (int)VEObjectTypesDefs.System) return veo; veo = (VEO_Base)veo.parentObj; } } catch (Exception e) { MessageBox.Show(e.Message.ToString()); } return null; } private bool ReturnProcRecord(VEO_Base veo,Int16 size, IntPtr vfwhndl) { bool success=true; COPYDATASTRUCT cds = new COPYDATASTRUCT(); PRecordMsg prmsg; prmsg.done = 1; byte [] bt = new byte[size+4]; prmsg.cnt = veo.Connection.GetProcRecBuff(size, ref bt); if (prmsg.cnt != size) { MessageBox.Show("Could not read multi-user connection information"); return false; } prmsg.buff = Encoding.ASCII.GetString(bt,0,size); IntPtr p = Marshal.AllocHGlobal(size+4); Marshal.StructureToPtr(prmsg,p,true); cds.dwData = (IntPtr)VEMessageNS.MessageOps.GETPROCESSREC; // the following would be 'size+4', however marshalling requires space to be // a multiple of 8 cds.cbData = 160; cds.lpData = p; try { SendMessage(vfwhndl,WM_COPYDATA,(UInt32)8, ref cds); } catch (Exception e) { MessageBox.Show(e.Message.ToString()); success=false; } Marshal.FreeHGlobal(p); return success; } private bool Reply(Int16 done, Int16 intAnswer, Int32 longAnswer, IntPtr vfwhndl) { bool success=true; COPYDATASTRUCT cds = new COPYDATASTRUCT(); AnswerMsg ans; ans.done = done; ans.intAnswer = intAnswer; ans.longAnswer = longAnswer; IntPtr p=Marshal.AllocHGlobal(8); Marshal.StructureToPtr(ans,p,true); cds.dwData = (IntPtr)VEMessageNS.MessageOps.GETANSWER; cds.cbData = 8; cds.lpData = p; try { SendMessage(vfwhndl,WM_COPYDATA,(UInt32)8, ref cds); } catch (Exception e) { MessageBox.Show(e.Message.ToString()); success=false; } Marshal.FreeHGlobal(p); return success; } public virtual void ProcessMessage(Message m, IntPtr vfwhndl) { VEO_Base veo = null; bool success=false; if (m.Msg==(int)VEMessageNS.MessageOps.POSQUERY) { // POSQUERY is only called to get initial procedure - make the main // form invisible when this request is made. Wait until now so that // the main form is visible until vfw window is just about to be // made visible. IntPtr handle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; Form mainForm = (Form)Form.FromHandle(handle); mainForm.Visible = false; COPYDATASTRUCT cds = new COPYDATASTRUCT(); PosUpdateStr pu; pu.sender = "NEWBROWSER"; VEO_Proc prc = null; if (!(this is VEO_Proc)) { // get to a proc, this is either a set or 'procedures' node // from an approve selected. VEO_ProcSet ps = null; if (this is VEO_ProcSet) ps = (VEO_ProcSet) this; else if (this is VEO_DummySet) ps = (VEO_ProcSet) this.parentObj; else { MessageBox.Show("Error finding procedure for edit","VE-PROMS"); return; } prc=ps.AppSelForEdit; } else prc = (VEO_Proc) this; VEO_DummySet ds = (VEO_DummySet) prc.parentObj; pu.directory = ds._Location; pu.docnumindx = ds.Children.IndexOf(prc); pu.recID = System.Convert.ToInt32(prc.recid,10); IntPtr p=Marshal.AllocHGlobal(130); Marshal.StructureToPtr(pu,p,true); cds.dwData = (IntPtr)VEMessageNS.MessageOps.POSUPDATE; cds.cbData = 130; cds.lpData = p; try { SendMessage(vfwhndl,WM_COPYDATA,(UInt32)8, ref cds); } catch (Exception e) { MessageBox.Show(e.Message.ToString()); } Marshal.FreeHGlobal(p); } else if (m.Msg==WM_COPYDATA) { bool reply = true; Int16 int1=0, int2=0; int int3=0; int lvl = 0; COPYDATASTRUCT cds = (COPYDATASTRUCT) m.GetLParam(typeof(COPYDATASTRUCT)); int tmpmsg = (int)cds.dwData; VEMessageNS.MessageOps msg = (VEMessageNS.MessageOps) tmpmsg; RqstAttachMsg ramsg = (RqstAttachMsg)Marshal.PtrToStructure(cds.lpData,typeof(RqstAttachMsg)); // get level veobject associated with this request, i.e. system, plant, or procset // and then connect at level lvl = ramsg.level; try { veo = GetObjectAtLevel(lvl); switch (msg) { case VEMessageNS.MessageOps.RQSTATTACH: success = veo.Connection.Enter(false); int2 = (short)(success?1:0); break; case VEMessageNS.MessageOps.RQSTFILEOFFSET: if (ramsg.flag==0) int3 = (int)veo.Connection.FileOffset; //else // MessageBox.Show("Set file offset" + ramsg.longval.ToString()); break; case VEMessageNS.MessageOps.RQSTFILEMODE: int2 = (short) veo.Connection.GetVfwMode(); break; case VEMessageNS.MessageOps.RQSTFILEOWNER: int2 = 1; break; case VEMessageNS.MessageOps.RQSTFILESEEK: int3 = (int)veo.Connection.Seek(ramsg.longval, ramsg.flag); break; case VEMessageNS.MessageOps.RQSTFILECLOSE: //used in lock/unlock veo.Connection.Close(); break; case VEMessageNS.MessageOps.RQSTFILEOPEN: //used in lock/unlock int2 = (short) veo.Connection.Open(ramsg.flag); break; // RQSTFILEREAD - not used in vfw <-> browser communication case VEMessageNS.MessageOps.RQSTFILEREAD: MessageBox.Show("RqstFileRead"); break; case VEMessageNS.MessageOps.RQSTFILEWRITE: //used in lock/unlock MessageBox.Show("RqstFileWrite"); break; case VEMessageNS.MessageOps.RQSTPROCESSRECORD: reply=false; success=ReturnProcRecord(veo,ramsg.flag,vfwhndl); break; case VEMessageNS.MessageOps.SETLOCKBYUSER: //do set lock yet. if (ramsg.flag >= 0) { if (ramsg.flag==0) veo.Lock.LockStatus=VENetwork.Status.NoLock; else veo.Lock.LockStatus=VENetwork.Status.Locked; } int2 = (Int16)((veo.Lock.LockStatus==VENetwork.Status.Locked)?1:0); break; } if (reply) success = Reply(int1,int2,int3,vfwhndl); } catch (Exception e) { MessageBox.Show(e.Message); } } } } }