using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Windows; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using DataService; using HMIControl; using Microsoft.Research.DynamicDataDisplay.DataSources; using FORMS = System.Windows.Forms; namespace CoreTest { public static class WindowHelper { //绑定到DAServer,采用递归 public static List BindingToServer(this DependencyObject panel, IDataServer _srv) { if (_srv == null) return null; ExpressionEval eval = _srv.Eval; List valueChangedList = new List(); var items = panel.FindTagControls(); if (items != null) { foreach (var element in items) { BindingControl(element, valueChangedList, eval); } } eval.Clear(); valueChangedList.Sort(); return valueChangedList; } private static void BindingControl(ITagLink taglink, List valueChangedList, ExpressionEval eval) { var ctrl = taglink as UIElement; if (ctrl == null) return; var complex = taglink as ITagReader; if (complex != null) { string txt = complex.TagReadText; if (!string.IsNullOrEmpty(txt)) { foreach (var v in txt.GetListFromText()) { ITagLink tagConn = complex; string[] strs = v.Key.Split('.'); if (strs.Length > 1) { for (int i = 0; i < strs.Length - 1; i++) { var c = tagConn as ITagReader; if (c == null || c.Children == null) break; foreach (var item in c.Children) { if (item.Node == strs[i]) { tagConn = item; break; } } } } var r = tagConn as ITagReader; var key = strs[strs.Length - 1]; try { var action = r.SetTagReader(key, eval.Eval(v.Value)); if (action != null) { action(); ValueChangedEventHandler handle = (s1, e1) => { ctrl.InvokeAsynchronously(action); }; foreach (ITag tag in eval.TagList) { valueChangedList.Add(new TagNodeHandle(tag.ID, key, tagConn, handle)); tag.ValueChanged += handle; } } } catch (Exception e) { App.AddErrorLog(e); MessageBox.Show(string.Format("设备'{0}'属性'{1}'的值'{2}'转化出错!", string.IsNullOrEmpty(r.Node) ? r.GetType().ToString() : r.Node, key, v.Value)); } if (Attribute.IsDefined(tagConn.GetType(), typeof(StartableAttribute), false)) { FrameworkElement element = tagConn as FrameworkElement; element.Cursor = Cursors.UpArrow; element.AddHandler(UIElement.MouseEnterEvent, new MouseEventHandler(element_MouseEnter)); element.AddHandler(UIElement.MouseLeaveEvent, new MouseEventHandler(element_MouseLeave)); element.AddHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(element_MouseLeftButtonDown)); } var hmi = tagConn as HMIControlBase; if (hmi != null && hmi.ShowCaption && !string.IsNullOrEmpty(hmi.Caption)) { AdornerLayer lay = AdornerLayer.GetAdornerLayer(hmi); if (lay != null) { TextAdorner frame = new TextAdorner(hmi); frame.Text = hmi.Caption; lay.Add(frame); } } } } } var writer = taglink as ITagWriter; if (writer != null && !string.IsNullOrEmpty(writer.TagWriteText)) { var delgts = new List(); foreach (var item in writer.TagWriteText.GetListFromText()) { try { if (!string.IsNullOrEmpty(item.Value)) delgts.Add(eval.WriteEval(item.Key, item.Value)); else delgts.Add(eval.WriteEval(item.Key)); } catch (Exception e) { App.AddErrorLog(e); MessageBox.Show(string.Format("设备{0}变量{1}写入PLC公式转换失败", taglink.Node, item.Key) + "\n" + e.Message); } writer.SetTagWriter(delgts); } } } static AnimationTimeline animaEnter = new DoubleAnimationUsingKeyFrames { KeyFrames = new DoubleKeyFrameCollection { new DiscreteDoubleKeyFrame(1.05, KeyTime.FromPercent(0)) } }; static AnimationTimeline animaLeave = new DoubleAnimationUsingKeyFrames { KeyFrames = new DoubleKeyFrameCollection { new DiscreteDoubleKeyFrame(1, KeyTime.FromPercent(0)) } }; static ScaleTransform GetScaleTransform(UIElement element) { var group = element.RenderTransform as TransformGroup; ScaleTransform scale = null; if (group == null) { scale = new ScaleTransform(); element.RenderTransform = new TransformGroup { Children = new TransformCollection { element.RenderTransform, scale } }; } else { if (group.IsFrozen) group = group.Clone(); foreach (var transform in group.Children) { scale = transform as ScaleTransform; if (scale != null) break; } if (scale == null) { scale = new ScaleTransform(); group.Children.Add(scale); } element.RenderTransform = group; } return scale; } static void element_MouseEnter(object sender, MouseEventArgs e) { UIElement element = sender as UIElement; //ScaleTransform scale = GetScaleTransform(element); //scale.BeginAnimation(ScaleTransform.ScaleXProperty, animaEnter); //scale.BeginAnimation(ScaleTransform.ScaleYProperty, animaEnter); AdornerLayer lay = AdornerLayer.GetAdornerLayer(element); if (lay != null) { FrameAdorner frame = new FrameAdorner(element); lay.Add(frame); } } static void element_MouseLeave(object sender, MouseEventArgs e) { UIElement element = sender as UIElement; //var scale = GetScaleTransform(element); //scale.BeginAnimation(ScaleTransform.ScaleXProperty, animaLeave); //scale.BeginAnimation(ScaleTransform.ScaleYProperty, animaLeave); AdornerLayer lay = AdornerLayer.GetAdornerLayer(element); if (lay != null) { var adorners = lay.GetAdorners(element); if (adorners != null) { FrameAdorner frame = null; for (int i = 0; i < adorners.Length; i++) { frame = adorners[i] as FrameAdorner; if (frame != null) { lay.Remove(frame); return; } } } } } static StartDevice frm1 = null; static void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { HMIControlBase ui = sender as HMIControlBase; if (ui != null && !string.IsNullOrEmpty(ui.DeviceName)) { if (frm1 != null) frm1.Close(); frm1 = new StartDevice(ui.DeviceName, ui.PointToScreen(new Point(ui.ActualWidth / 2, ui.ActualHeight / 2))); frm1.Show(); } e.Handled = true; } static ITagLink FindElement(ITagLink tag, string key) { ITagLink tagConn = tag; string[] strs = key.Split('.'); for (int i = 0; i < strs.Length; i++) { var c = tagConn as ITagReader; if (c == null || c.Children == null) break; foreach (var item in c.Children) { if (item.Node == strs[i]) { tagConn = item; break; } } } return tagConn; } public static IEnumerable FindVisualChildren(this DependencyObject parent) { var count = VisualTreeHelper.GetChildrenCount(parent); if (count > 0) { for (var i = 0; i < count; i++) { var child = VisualTreeHelper.GetChild(parent, i); yield return child; var children = FindVisualChildren(child); foreach (var item in children) yield return item; } } } public static IEnumerable FindChildren(this DependencyObject parent) where T : class { var count = VisualTreeHelper.GetChildrenCount(parent); if (count > 0) { for (var i = 0; i < count; i++) { var child = VisualTreeHelper.GetChild(parent, i); var t = child as T; if (t != null) yield return t; var children = FindChildren(child); foreach (var item in children) yield return item; } } } public static IEnumerable FindTagControls(this DependencyObject parent) { var count = VisualTreeHelper.GetChildrenCount(parent); if (count > 0) { for (var i = 0; i < count; i++) { var child = VisualTreeHelper.GetChild(parent, i); var t = child as ITagLink; if (t != null) yield return t; else { var children = FindTagControls(child); foreach (var item in children) yield return item; } } } } public static LinkLine FindLine(this DependencyObject parent, string source, string target) { if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(target)) return null; var controls = parent.FindTagControls(); if (controls == null) return null; var lines = new List(); Rect sourcerect = Rect.Empty; Rect targetrect = Rect.Empty; foreach (var ctrl in controls) { var element = ctrl as HMIControlBase; if (element != null) { if (sourcerect == Rect.Empty && element.Caption == source) { sourcerect = new Rect(element.TranslatePoint(new Point(), element.Parent as UIElement), new Size(element.ActualWidth, element.ActualHeight)); } else if (targetrect == Rect.Empty && element.Caption == target) { targetrect = new Rect(element.TranslatePoint(new Point(), element.Parent as UIElement), new Size(element.ActualWidth, element.ActualHeight)); } } else { var line = ctrl as LinkLine; if (line != null) { if (sourcerect != Rect.Empty && targetrect != Rect.Empty) { if (line.OriginInfo.DesignerRect == sourcerect && line.TargetInfo.DesignerRect == targetrect) return line; } else lines.Add(line); } } } if (sourcerect == Rect.Empty || targetrect == Rect.Empty) return null; foreach (LinkLine line in lines) { if (line.OriginInfo.DesignerRect == sourcerect && line.TargetInfo.DesignerRect == targetrect) return line; } return null; } public static T HitTest(this Visual hitobj, Point p) { var target = VisualTreeHelper.HitTest(hitobj, p).VisualHit; while (target != null && !(target is T)) { target = VisualTreeHelper.GetParent(target); } return target == null ? default(T) : (T)((object)target); } public static Window GetParentWindow(this DependencyObject child) { DependencyObject parentObject = VisualTreeHelper.GetParent(child); if (parentObject == null) { return null; } Window parent = parentObject as Window; if (parent != null) { return parent; } else { return GetParentWindow(parentObject); } } public static void RemoveHandles(this IDataServer srv, params List[] handleLists) { foreach (var handleList in handleLists) { if (handleList != null) { foreach (var item in handleList) { srv[item.TagID].ValueChanged -= item.Handle; var element = item.Element as FrameworkElement; if (element != null) { element.RemoveHandler(UIElement.MouseEnterEvent, new MouseEventHandler(element_MouseEnter)); element.RemoveHandler(UIElement.MouseLeaveEvent, new MouseEventHandler(element_MouseLeave)); element.RemoveHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(element_MouseLeftButtonDown)); } } handleList.Clear(); } } } public static void SetWindowState(this Window window) { Dictionary dict = ConfigCache.Windows; string name = window.DependencyObjectType.Name; if (dict.ContainsKey(name)) { Rect rec = dict[name]; if (rec.Width == 0 || rec.Height == 0 || double.IsInfinity(rec.Left) || double.IsInfinity(rec.Top)) { window.WindowState = WindowState.Maximized; window.WindowStartupLocation = WindowStartupLocation.CenterScreen; } else { window.Left = rec.Left; window.Top = rec.Top; window.Width = rec.Width; window.Height = rec.Height; } } else { ConfigCache.Windows.Add(name, new Rect()); window.WindowState = WindowState.Maximized; window.WindowStartupLocation = WindowStartupLocation.CenterScreen; } } public static void SaveWindowState(this Window window) { Dictionary dict = ConfigCache.Windows; dict[window.DependencyObjectType.Name] = window.WindowState == WindowState.Maximized ? new Rect() : new Rect(window.Left, window.Top, window.Width, window.Height); } public static Window FindWindow(string name) { foreach (Window window in App.Current.Windows) { if (window.DependencyObjectType.Name == name) { return window; } } return null; } public static void SetWindowPos(this Window window, int screenIndex) { var screens = FORMS.Screen.AllScreens;//只是测试状态,待完善 if (screenIndex < screens.Length) { var area = screens[screenIndex].WorkingArea; if (window.WindowState == WindowState.Maximized) { window.Top = area.Top; window.Left = area.Left; } else { window.Top += area.Top; window.Left += area.Left; } } } public static void InvokeAsynchronously(this UIElement element, Action action) { if (element.Dispatcher.CheckAccess()) { action(); } else element.Dispatcher.BeginInvoke(action, System.Windows.Threading.DispatcherPriority.Normal); } public static void GetWorkInfo(DateTime current, out DateTime start, out DateTime end, out string team) { float[] startarray = new float[3] { App.Server["START_1"].Value.Single, App.Server["START_2"].Value.Single, App.Server["START_3"].Value.Single }; float[] endarray = new float[3] { App.Server["END_1"].Value.Single, App.Server["END_2"].Value.Single, App.Server["END_3"].Value.Single }; double hour = current.Hour + current.Minute / 60.0; //Array.Sort(startarray); DateTime today = current.Date; for (int i = 0; i < startarray.Length; i++) { if (startarray[i] == endarray[i]) continue; if (hour >= startarray[i] && hour <= endarray[i]) { start = today.AddHours(startarray[i]); end = today.AddHours(endarray[i]); team = i.ToString(); return; } else if (startarray[i] >= endarray[i] && hour >= startarray[i]) { start = today.AddHours(startarray[i]); end = today.AddDays(1).AddHours(endarray[i]); team = i.ToString(); return; } else if (startarray[i] >= endarray[i] && hour <= endarray[i]) { start = today.AddDays(-1).AddHours(startarray[i]); end = today.AddHours(endarray[i]); team = i.ToString(); return; } } start = current.AddHours(-8); end = current; team = null; } //startTime/endTime:班次上/下班时间 starthour/endhour:阶段起始/结束时间 start/end:本班次阶段区间 public static void GetTimeRange(DateTime startTime, DateTime endTime, float starthour, float endhour, out DateTime start, out DateTime end) { if (starthour == endhour) { start = end = DateTime.MinValue; return; } DateTime startdate = startTime.Date; DateTime enddate = endTime.Date; double hstart = startTime.Hour + startTime.Minute / 60.0 + startTime.Second / 60.0; double hend = endTime.Hour + endTime.Minute / 60.0 + endTime.Second / 60.0; if (startdate == enddate) { if (endhour > starthour) { start = starthour > hstart ? startdate.AddHours(starthour) : startTime; end = endhour < hend ? startdate.AddHours(endhour) : endTime; } else { if (endhour > hstart) { start = startTime; end = endhour > hend ? endTime : startdate.AddHours(endhour); } else if (starthour < hend) { end = endTime; start = starthour > hstart ? startdate.AddHours(starthour) : startTime; } else { start = end = DateTime.MinValue; } } } else { if (endhour > starthour) { if (endhour > hstart) { start = starthour > hstart ? startdate.AddHours(starthour) : startTime; end = startdate.AddHours(endhour); } else if (starthour < hend) { end = endhour < hend ? enddate.AddHours(endhour) : endTime; start = enddate.AddHours(starthour); } else { start = end = DateTime.MinValue; } } else { start = starthour > hstart ? startdate.AddHours(starthour) : startTime; end = endhour < hend ? enddate.AddHours(endhour) : endTime; } } } public static void SetSourceMapping(this QueueListSource source, ITag currentTag) { if (currentTag != null) { switch (currentTag.Address.VarType) { case DataType.BOOL: source.SetYMapping(Y => Y.Value.Boolean ? 1 : 0); break; case DataType.BYTE: source.SetYMapping(Y => Y.Value.Byte); break; case DataType.WORD: case DataType.SHORT: source.SetYMapping(Y => Y.Value.Int16); break; case DataType.TIME: case DataType.INT: source.SetYMapping(Y => Y.Value.Int32); break; case DataType.FLOAT: source.SetYMapping(Y => Y.Value.Single); break; } } } public static void SetSourceMapping(this ObservableDataSource source, ITag currentTag) { if (currentTag != null) { switch (currentTag.Address.VarType) { case DataType.BOOL: source.SetYMapping(Y => Y.Value.Boolean ? 1 : 0); break; case DataType.BYTE: source.SetYMapping(Y => Y.Value.Byte); break; case DataType.WORD: case DataType.SHORT: source.SetYMapping(Y => Y.Value.Int16); break; case DataType.TIME: case DataType.INT: source.SetYMapping(Y => Y.Value.Int32); break; case DataType.FLOAT: source.SetYMapping(Y => Y.Value.Single); break; } } } } public class TagNodeHandle : IComparable { short _tagID; public short TagID { get { return _tagID; } } string _key; public string Key { get { return _key; } } ITagLink _element; public ITagLink Element { get { return _element; } } ValueChangedEventHandler _handle; public ValueChangedEventHandler Handle { get { return _handle; } } public TagNodeHandle(short tag, string key, ITagLink element, ValueChangedEventHandler handle) { _tagID = tag; _key = key; _element = element; _handle = handle; } public int CompareTo(TagNodeHandle other) { int comp = _tagID.CompareTo(other._tagID); return comp == 0 ? _key.CompareTo(other._key) : comp; } } public static class Extension { public static string GetNullableString(this SqlDataReader dataReader, int index) { var svr = dataReader.GetSqlString(index); return svr.IsNull ? null : svr.Value; } public static string GetNullableString(this DateTime? time) { return time.HasValue ? "'" + time.ToString() + "'" : "NULL"; } /// /// 返回指定变量最接近指定时间的值 /// /// /// 时间 /// /// public static int GetInt(this IEnumerable list, DateTime time, short id) { var data = (from raw in list where raw.ID == id && raw.TimeStamp <= time && raw.Value.Int32 > 0 select raw.Value.Int32).LastOrDefault(); if (data == 0) data = (from raw in list where raw.ID == id && raw.TimeStamp >= time && raw.Value.Int32 > 0 select raw.Value.Int32).FirstOrDefault(); return data; } /// /// 返回变量最接近指定时间的值 /// /// /// 时间 /// public static int GetInt(this IEnumerable list, DateTime time) { var data = (from raw in list where raw.TimeStamp <= time && raw.Value.Int32 > 0 select raw.Value.Int32).LastOrDefault(); if (data == 0) data = (from raw in list where raw.TimeStamp >= time && raw.Value.Int32 > 0 select raw.Value.Int32).FirstOrDefault(); return data; } /// /// 返回在开始时间和结束时间范围内变量的变化值 /// /// /// 开始时间 /// 结束时间 /// /// public static int GetInt(this IEnumerable list, DateTime start, DateTime end, short id) { return GetInt(list, end, id) - GetInt(list, start, id); } /// /// 返回指定变量最接近指定时间的值 /// /// /// 时间 /// /// public static float GetFloat(this IEnumerable list, DateTime time, short id) { var data = (from raw in list where raw.ID == id && raw.TimeStamp <= time && raw.Value.Single > 0 select raw.Value.Single).LastOrDefault(); if (data == 0) data = (from raw in list where raw.ID == id && raw.TimeStamp >= time && raw.Value.Single > 0 select raw.Value.Single).FirstOrDefault(); return data; } /// /// 返回变量最接近指定时间的值 /// /// /// 时间 /// public static float GetFloat(this IEnumerable list, DateTime time) { var data = (from raw in list where raw.TimeStamp <= time && raw.Value.Single > 0 select raw.Value.Single).LastOrDefault(); if (data == 0) data = (from raw in list where raw.TimeStamp >= time && raw.Value.Single > 0 select raw.Value.Single).FirstOrDefault(); return data; } /// /// 返回在开始时间和结束时间范围内变量的变化值 /// /// /// 开始时间 /// 结束时间 /// /// public static float GetFloat(this IEnumerable list, DateTime start, DateTime end, short id) { return GetFloat(list, end, id) - GetFloat(list, start, id); } public static float GetFloat2(this List list, DateTime start, DateTime end, short id) { float result = 0; var data = (from raw in list where raw.TimeStamp >= start && raw.TimeStamp <= end && raw.ID == id && raw.Value.Single >= 0 select raw.Value.Single).ToList(); if (data.Count > 0) { List li = new List(); li.Add(0); for (int i = 0; i < data.Count - 1; i++) { if (data[i] > data[i + 1] && i > 0) { li.Add(i); } } li.Add(data.Count - 1); for (int i = 1; i < li.Count; i++) { result += data[li[i]] - data[li[i - 1] + 1]; } } return result; } } }