12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070 |
- using System;
- using System.Runtime.InteropServices;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Controls.Primitives;
- using System.Windows.Media;
- namespace ComPDFKit.Controls.Common.BaseControl
- {
- #region EnumPlacement
- public enum EnumPlacement
- {
- /// <summary>
- /// 左上
- /// </summary>
- LeftTop,
- /// <summary>
- /// 左中
- /// </summary>
- LeftCenter,
- /// <summary>
- /// 左下
- /// </summary>
- LeftBottom,
- /// <summary>
- /// 右上
- /// </summary>
- RightTop,
- /// <summary>
- /// 右中
- /// </summary>
- RightCenter,
- /// <summary>
- /// 右下
- /// </summary>
- RightBottom,
- /// <summary>
- /// 上左
- /// </summary>
- TopLeft,
- /// <summary>
- /// 上中
- /// </summary>
- TopCenter,
- /// <summary>
- /// 上右
- /// </summary>
- TopRight,
- /// <summary>
- /// 下左
- /// </summary>
- BottomLeft,
- /// <summary>
- /// 下中
- /// </summary>
- BottomCenter,
- /// <summary>
- /// 下右
- /// </summary>
- BottomRight,
- }
- #endregion EnumPlacement
- public class DoubleUtil
- {
- public static double DpiScaleX
- {
- get
- {
- int dx = 0;
- int dy = 0;
- GetDPI(out dx, out dy);
- if (dx != 96)
- {
- return (double)dx / 96.0;
- }
- return 1.0;
- }
- }
- public static double DpiScaleY
- {
- get
- {
- int dx = 0;
- int dy = 0;
- GetDPI(out dx, out dy);
- if (dy != 96)
- {
- return (double)dy / 96.0;
- }
- return 1.0;
- }
- }
- public static void GetDPI(out int dpix, out int dpiy)
- {
- dpix = 0;
- dpiy = 0;
- using (System.Management.ManagementClass mc = new System.Management.ManagementClass("Win32_DesktopMonitor"))
- {
- using (System.Management.ManagementObjectCollection moc = mc.GetInstances())
- {
- foreach (System.Management.ManagementObject each in moc)
- {
- dpix = int.Parse((each.Properties["PixelsPerXLogicalInch"].Value.ToString()));
- dpiy = int.Parse((each.Properties["PixelsPerYLogicalInch"].Value.ToString()));
- }
- }
- }
- }
- public static bool AreClose(double value1, double value2)
- {
- if (value1 == value2)
- {
- return true;
- }
- double num = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * 2.2204460492503131E-16;
- double num2 = value1 - value2;
- return -num < num2 && num > num2;
- }
- [StructLayout(LayoutKind.Explicit)]
- private struct NanUnion
- {
- [FieldOffset(0)]
- internal double DoubleValue;
- [FieldOffset(0)]
- internal ulong UintValue;
- }
- public static bool IsNaN(double value)
- {
- DoubleUtil.NanUnion nanUnion = default(DoubleUtil.NanUnion);
- nanUnion.DoubleValue = value;
- ulong num = nanUnion.UintValue & 18442240474082181120uL;
- ulong num2 = nanUnion.UintValue & 4503599627370495uL;
- return (num == 9218868437227405312uL || num == 18442240474082181120uL) && num2 != 0uL;
- }
- }
- public class UIElementEx
- {
- public static double RoundLayoutValue(double value, double dpiScale)
- {
- double num;
- if (!DoubleUtil.AreClose(dpiScale, 1.0))
- {
- num = Math.Round(value * dpiScale) / dpiScale;
- if (DoubleUtil.IsNaN(num) || double.IsInfinity(num) || DoubleUtil.AreClose(num, 1.7976931348623157E+308))
- {
- num = value;
- }
- }
- else
- {
- num = Math.Round(value);
- }
- return num;
- }
- }
- /// <summary>
- /// 带三角形的气泡边框
- /// </summary>
- public class AngleBorder : Decorator
- {
- #region 依赖属性
- public static readonly DependencyProperty PlacementProperty =
- DependencyProperty.Register("Placement", typeof(EnumPlacement), typeof(AngleBorder),
- new FrameworkPropertyMetadata(EnumPlacement.RightCenter, FrameworkPropertyMetadataOptions.AffectsRender, OnDirectionPropertyChangedCallback));
- public EnumPlacement Placement
- {
- get { return (EnumPlacement)GetValue(PlacementProperty); }
- set { SetValue(PlacementProperty, value); }
- }
- public static readonly DependencyProperty TailWidthProperty =
- DependencyProperty.Register("TailWidth", typeof(double), typeof(AngleBorder), new PropertyMetadata(10d));
- /// <summary>
- /// 尾巴的宽度,默认值为7
- /// </summary>
- public double TailWidth
- {
- get { return (double)GetValue(TailWidthProperty); }
- set { SetValue(TailWidthProperty, value); }
- }
- public static readonly DependencyProperty TailHeightProperty =
- DependencyProperty.Register("TailHeight", typeof(double), typeof(AngleBorder), new PropertyMetadata(10d));
- /// <summary>
- /// 尾巴的高度,默认值为10
- /// </summary>
- public double TailHeight
- {
- get { return (double)GetValue(TailHeightProperty); }
- set { SetValue(TailHeightProperty, value); }
- }
- public static readonly DependencyProperty TailVerticalOffsetProperty =
- DependencyProperty.Register("TailVerticalOffset", typeof(double), typeof(AngleBorder), new PropertyMetadata(13d));
- /// <summary>
- /// 尾巴距离顶部的距离,默认值为10
- /// </summary>
- public double TailVerticalOffset
- {
- get { return (double)GetValue(TailVerticalOffsetProperty); }
- set { SetValue(TailVerticalOffsetProperty, value); }
- }
- public static readonly DependencyProperty TailHorizontalOffsetProperty =
- DependencyProperty.Register("TailHorizontalOffset", typeof(double), typeof(AngleBorder),
- new PropertyMetadata(12d));
- /// <summary>
- /// 尾巴距离顶部的距离,默认值为10
- /// </summary>
- public double TailHorizontalOffset
- {
- get { return (double)GetValue(TailHorizontalOffsetProperty); }
- set { SetValue(TailHorizontalOffsetProperty, value); }
- }
- public static readonly DependencyProperty BackgroundProperty =
- DependencyProperty.Register("Background", typeof(Brush), typeof(AngleBorder)
- , new PropertyMetadata(new SolidColorBrush(Color.FromRgb(255, 255, 255))));
- /// <summary>
- /// 背景色,默认值为#FFFFFF,白色
- /// </summary>
- public Brush Background
- {
- get { return (Brush)GetValue(BackgroundProperty); }
- set { SetValue(BackgroundProperty, value); }
- }
- public static readonly DependencyProperty PaddingProperty =
- DependencyProperty.Register("Padding", typeof(Thickness), typeof(AngleBorder)
- , new PropertyMetadata(new Thickness(10, 5, 10, 5)));
- /// <summary>
- /// 内边距
- /// </summary>
- public Thickness Padding
- {
- get { return (Thickness)GetValue(PaddingProperty); }
- set { SetValue(PaddingProperty, value); }
- }
- public static readonly DependencyProperty BorderBrushProperty =
- DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(AngleBorder)
- , new PropertyMetadata(default(Brush)));
- /// <summary>
- /// 边框颜色
- /// </summary>
- public Brush BorderBrush
- {
- get { return (Brush)GetValue(BorderBrushProperty); }
- set { SetValue(BorderBrushProperty, value); }
- }
- public static readonly DependencyProperty BorderThicknessProperty =
- DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(AngleBorder), new PropertyMetadata(new Thickness(1d)));
- /// <summary>
- /// 边框大小
- /// </summary>
- public Thickness BorderThickness
- {
- get { return (Thickness)GetValue(BorderThicknessProperty); }
- set { SetValue(BorderThicknessProperty, value); }
- }
- public static readonly DependencyProperty CornerRadiusProperty =
- DependencyProperty.Register("CornerRadius", typeof(System.Windows.CornerRadius)
- , typeof(AngleBorder), new PropertyMetadata(new CornerRadius(0)));
- /// <summary>
- /// 边框大小
- /// </summary>
- public System.Windows.CornerRadius CornerRadius
- {
- get { return (System.Windows.CornerRadius)GetValue(CornerRadiusProperty); }
- set { SetValue(CornerRadiusProperty, value); }
- }
- #endregion 依赖属性
- #region 方法重写
- /// <summary>
- /// 该方法用于测量整个控件的大小
- /// </summary>
- /// <param name="constraint"></param>
- /// <returns>控件的大小</returns>
- protected override Size MeasureOverride(Size constraint)
- {
- Thickness padding = this.Padding;
- Size result = new Size();
- if (Child != null)
- {
- //测量子控件的大小
- Child.Measure(constraint);
- //三角形在左边与右边的,整个容器的宽度则为:里面子控件的宽度 + 设置的padding + 三角形的宽度
- //三角形在上面与下面的,整个容器的高度则为:里面子控件的高度 + 设置的padding + 三角形的高度
- switch (Placement)
- {
- case EnumPlacement.LeftTop:
- case EnumPlacement.LeftBottom:
- case EnumPlacement.LeftCenter:
- case EnumPlacement.RightTop:
- case EnumPlacement.RightBottom:
- case EnumPlacement.RightCenter:
- result.Width = Child.DesiredSize.Width + padding.Left + padding.Right + this.TailWidth;
- result.Height = Child.DesiredSize.Height + padding.Top + padding.Bottom;
- break;
- case EnumPlacement.TopLeft:
- case EnumPlacement.TopCenter:
- case EnumPlacement.TopRight:
- case EnumPlacement.BottomLeft:
- case EnumPlacement.BottomCenter:
- case EnumPlacement.BottomRight:
- result.Width = Child.DesiredSize.Width + padding.Left + padding.Right;
- result.Height = Child.DesiredSize.Height + padding.Top + padding.Bottom + this.TailHeight;
- break;
- default:
- break;
- }
- }
- return result;
- }
- /// <summary>
- /// 设置子控件的大小与位置
- /// </summary>
- /// <param name="arrangeSize"></param>
- /// <returns></returns>
- protected override Size ArrangeOverride(Size arrangeSize)
- {
- Thickness padding = this.Padding;
- if (Child != null)
- {
- switch (Placement)
- {
- case EnumPlacement.LeftTop:
- case EnumPlacement.LeftBottom:
- case EnumPlacement.LeftCenter:
- this.TailWidth = 6;
- Child.Arrange(new Rect(new Point(padding.Left + this.TailWidth, padding.Top), Child.DesiredSize));
- //ArrangeChildLeft();
- break;
- case EnumPlacement.RightTop:
- case EnumPlacement.RightBottom:
- case EnumPlacement.RightCenter:
- ArrangeChildRight(padding);
- break;
- case EnumPlacement.TopLeft:
- case EnumPlacement.TopRight:
- case EnumPlacement.TopCenter:
- Child.Arrange(new Rect(new Point(padding.Left, this.TailHeight + padding.Top), Child.DesiredSize));
- break;
- case EnumPlacement.BottomLeft:
- case EnumPlacement.BottomRight:
- case EnumPlacement.BottomCenter:
- Child.Arrange(new Rect(new Point(padding.Left, padding.Top), Child.DesiredSize));
- break;
- default:
- break;
- }
- }
- return arrangeSize;
- }
- private void ArrangeChildRight(Thickness padding)
- {
- double x = padding.Left;
- double y = padding.Top;
- if (!Double.IsNaN(this.Height) && this.Height != 0)
- {
- y = (this.Height - (Child.DesiredSize.Height)) / 2;
- }
- Child.Arrange(new Rect(new Point(x, y), Child.DesiredSize));
- }
- /// <summary>
- /// 绘制控件
- /// </summary>
- /// <param name="drawingContext"></param>
- protected override void OnRender(DrawingContext drawingContext)
- {
- if (Child != null)
- {
- Geometry cg = null;
- Brush brush = null;
- Pen pen = new Pen();
- pen.Brush = this.BorderBrush;
- pen.Thickness = UIElementEx.RoundLayoutValue(BorderThickness.Left, DoubleUtil.DpiScaleX);
- switch (Placement)
- {
- case EnumPlacement.LeftTop:
- case EnumPlacement.LeftBottom:
- case EnumPlacement.LeftCenter:
- //生成小尾巴在左侧的图形和底色
- cg = CreateGeometryTailAtLeft();
- brush = CreateFillBrush();
- break;
- case EnumPlacement.RightTop:
- case EnumPlacement.RightCenter:
- case EnumPlacement.RightBottom:
- //生成小尾巴在右侧的图形和底色
- cg = CreateGeometryTailAtRight();
- brush = CreateFillBrush();
- break;
- case EnumPlacement.TopLeft:
- case EnumPlacement.TopCenter:
- case EnumPlacement.TopRight:
- //生成小尾巴在右侧的图形和底色
- cg = CreateGeometryTailAtTop();
- brush = CreateFillBrush();
- break;
- case EnumPlacement.BottomLeft:
- case EnumPlacement.BottomCenter:
- case EnumPlacement.BottomRight:
- //生成小尾巴在右侧的图形和底色
- cg = CreateGeometryTailAtBottom();
- brush = CreateFillBrush();
- break;
- default:
- break;
- }
- GuidelineSet guideLines = new GuidelineSet();
- drawingContext.PushGuidelineSet(guideLines);
- drawingContext.DrawGeometry(brush, pen, cg);
- }
- }
- #endregion 方法重写
- #region 私有方法
- private Geometry CreateGeometryTailAtRight()
- {
- CombinedGeometry result = new CombinedGeometry();
- this.TailHeight = 12;
- this.TailWidth = 6;
- switch (this.Placement)
- {
- case EnumPlacement.RightTop:
- //不做任何处理
- break;
- case EnumPlacement.RightBottom:
- this.TailVerticalOffset = this.ActualHeight - this.TailHeight - this.TailVerticalOffset;
- break;
- case EnumPlacement.RightCenter:
- this.TailVerticalOffset = (this.ActualHeight - this.TailHeight) / 2;
- break;
- }
- #region 绘制三角形
- Point arcPoint1 = new Point(this.ActualWidth - TailWidth, TailVerticalOffset);
- Point arcPoint2 = new Point(this.ActualWidth, TailVerticalOffset + TailHeight / 2);
- Point arcPoint3 = new Point(this.ActualWidth - TailWidth, TailVerticalOffset + TailHeight);
- LineSegment as1_2 = new LineSegment(arcPoint2, false);
- LineSegment as2_3 = new LineSegment(arcPoint3, false);
- PathFigure pf1 = new PathFigure();
- pf1.IsClosed = false;
- pf1.StartPoint = arcPoint1;
- pf1.Segments.Add(as1_2);
- pf1.Segments.Add(as2_3);
- PathGeometry pg1 = new PathGeometry();
- pg1.Figures.Add(pf1);
- #endregion 绘制三角形
- #region 绘制矩形边框
- RectangleGeometry rg2 = new RectangleGeometry(new Rect(0, 0, this.ActualWidth - TailWidth, this.ActualHeight)
- , CornerRadius.TopLeft, CornerRadius.BottomRight, new TranslateTransform(0.5, 0.5));
- #endregion 绘制矩形边框
- #region 合并两个图形
- result.Geometry1 = pg1;
- result.Geometry2 = rg2;
- result.GeometryCombineMode = GeometryCombineMode.Union;
- #endregion 合并两个图形
- return result;
- }
- private Geometry CreateGeometryTailAtLeft()
- {
- CombinedGeometry result = new CombinedGeometry();
- this.TailHeight = 12;
- this.TailWidth = 6;
- switch (this.Placement)
- {
- case EnumPlacement.LeftTop:
- //不做任何处理
- break;
- case EnumPlacement.LeftBottom:
- this.TailVerticalOffset = this.ActualHeight - this.TailHeight - this.TailVerticalOffset;
- break;
- case EnumPlacement.LeftCenter:
- this.TailVerticalOffset = (this.ActualHeight - this.TailHeight) / 2;
- break;
- }
- #region 绘制三角形
- Point arcPoint1 = new Point(TailWidth, TailVerticalOffset);
- Point arcPoint2 = new Point(0, TailVerticalOffset + TailHeight / 2);
- Point arcPoint3 = new Point(TailWidth, TailVerticalOffset + TailHeight);
- LineSegment as1_2 = new LineSegment(arcPoint2, false);
- LineSegment as2_3 = new LineSegment(arcPoint3, false);
- PathFigure pf = new PathFigure();
- pf.IsClosed = false;
- pf.StartPoint = arcPoint1;
- pf.Segments.Add(as1_2);
- pf.Segments.Add(as2_3);
- PathGeometry g1 = new PathGeometry();
- g1.Figures.Add(pf);
- #endregion 绘制三角形
- #region 绘制矩形边框
- RectangleGeometry g2 = new RectangleGeometry(new Rect(TailWidth, 0, this.ActualWidth - this.TailWidth, this.ActualHeight)
- , CornerRadius.TopLeft, CornerRadius.BottomRight);
- #endregion 绘制矩形边框
- #region 合并两个图形
- result.Geometry1 = g1;
- result.Geometry2 = g2;
- result.GeometryCombineMode = GeometryCombineMode.Union;
- #endregion 合并两个图形
- return result;
- }
- private Geometry CreateGeometryTailAtTop()
- {
- CombinedGeometry result = new CombinedGeometry();
- switch (this.Placement)
- {
- case EnumPlacement.TopLeft:
- break;
- case EnumPlacement.TopCenter:
- this.TailHorizontalOffset = (this.ActualWidth - this.TailWidth) / 2;
- break;
- case EnumPlacement.TopRight:
- this.TailHorizontalOffset = this.ActualWidth - this.TailWidth - this.TailHorizontalOffset;
- break;
- }
- #region 绘制三角形
- Point anglePoint1 = new Point(this.TailHorizontalOffset, this.TailHeight);
- Point anglePoint2 = new Point(this.TailHorizontalOffset + (this.TailWidth / 2), 0);
- Point anglePoint3 = new Point(this.TailHorizontalOffset + this.TailWidth, this.TailHeight);
- LineSegment as1_2 = new LineSegment(anglePoint2, true);
- LineSegment as2_3 = new LineSegment(anglePoint3, true);
- PathFigure pf = new PathFigure();
- pf.IsClosed = false;
- pf.StartPoint = anglePoint1;
- pf.Segments.Add(as1_2);
- pf.Segments.Add(as2_3);
- PathGeometry g1 = new PathGeometry();
- g1.Figures.Add(pf);
- #endregion 绘制三角形
- #region 绘制矩形边框
- RectangleGeometry g2 = new RectangleGeometry(new Rect(0, this.TailHeight, this.ActualWidth, this.ActualHeight - this.TailHeight)
- , CornerRadius.TopLeft, CornerRadius.BottomRight);
- #endregion 绘制矩形边框
- #region 合并
- result.Geometry1 = g1;
- result.Geometry2 = g2;
- result.GeometryCombineMode = GeometryCombineMode.Union;
- #endregion 合并
- return result;
- }
- private Geometry CreateGeometryTailAtBottom()
- {
- CombinedGeometry result = new CombinedGeometry();
- switch (this.Placement)
- {
- case EnumPlacement.BottomLeft:
- break;
- case EnumPlacement.BottomCenter:
- this.TailHorizontalOffset = (this.ActualWidth - this.TailWidth) / 2;
- break;
- case EnumPlacement.BottomRight:
- this.TailHorizontalOffset = this.ActualWidth - this.TailWidth - this.TailHorizontalOffset;
- break;
- }
- #region 绘制三角形
- Point anglePoint1 = new Point(this.TailHorizontalOffset, this.ActualHeight - this.TailHeight);
- Point anglePoint2 = new Point(this.TailHorizontalOffset + this.TailWidth / 2, this.ActualHeight);
- Point anglePoint3 = new Point(this.TailHorizontalOffset + this.TailWidth, this.ActualHeight - this.TailHeight);
- LineSegment as1_2 = new LineSegment(anglePoint2, true);
- LineSegment as2_3 = new LineSegment(anglePoint3, true);
- PathFigure pf = new PathFigure();
- pf.IsClosed = false;
- pf.StartPoint = anglePoint1;
- pf.Segments.Add(as1_2);
- pf.Segments.Add(as2_3);
- PathGeometry g1 = new PathGeometry();
- g1.Figures.Add(pf);
- #endregion 绘制三角形
- #region 绘制矩形边框
- RectangleGeometry g2 = new RectangleGeometry(new Rect(0, 0, this.ActualWidth, this.ActualHeight - this.TailHeight)
- , CornerRadius.TopLeft, CornerRadius.BottomRight);
- #endregion 绘制矩形边框
- #region 合并
- result.Geometry1 = g1;
- result.Geometry2 = g2;
- result.GeometryCombineMode = GeometryCombineMode.Union;
- #endregion 合并
- return result;
- }
- private Brush CreateFillBrush()
- {
- Brush result = null;
- GradientStopCollection gsc = new GradientStopCollection();
- gsc.Add(new GradientStop(((SolidColorBrush)this.Background).Color, 0));
- LinearGradientBrush backGroundBrush = new LinearGradientBrush(gsc, new Point(0, 0), new Point(0, 1));
- result = backGroundBrush;
- return result;
- }
- /// <summary>
- /// 根据三角形方向设置消息框的水平位置,偏左还是偏右
- /// </summary>
- /// <param name="d"></param>
- /// <param name="e"></param>
- public static void OnDirectionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- AngleBorder angleBorder = d as AngleBorder;
- if (angleBorder != null)
- {
- switch ((EnumPlacement)e.NewValue)
- {
- case EnumPlacement.LeftTop:
- case EnumPlacement.LeftBottom:
- case EnumPlacement.LeftCenter:
- case EnumPlacement.RightTop:
- case EnumPlacement.RightBottom:
- case EnumPlacement.RightCenter:
- angleBorder.TailWidth = 6;
- angleBorder.TailHeight = 12;
- break;
- case EnumPlacement.TopLeft:
- case EnumPlacement.TopCenter:
- case EnumPlacement.TopRight:
- case EnumPlacement.BottomLeft:
- case EnumPlacement.BottomCenter:
- case EnumPlacement.BottomRight:
- angleBorder.TailWidth = 12;
- angleBorder.TailHeight = 6;
- break;
- default:
- break;
- }
- }
- }
- #endregion 私有方法
- }
- public class PopTip : Popup
- {
- #region private fields
- private bool mIsLoaded = false;
- private AngleBorder angleBorder;
- #endregion private fields
- #region DependencyProperty
- #region PlacementEx
- public EnumPlacement PlacementEx
- {
- get { return (EnumPlacement)GetValue(PlacementExProperty); }
- set { SetValue(PlacementExProperty, value); }
- }
- public static readonly DependencyProperty PlacementExProperty =
- DependencyProperty.Register("PlacementEx", typeof(EnumPlacement), typeof(PopTip)
- , new PropertyMetadata(EnumPlacement.TopLeft, PlacementExChangedCallback));
- private static void PlacementExChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- PopTip poptip = d as PopTip;
- if (poptip != null)
- {
- EnumPlacement placement = (EnumPlacement)e.NewValue;
- switch (placement)
- {
- case EnumPlacement.LeftTop:
- break;
- case EnumPlacement.LeftBottom:
- break;
- case EnumPlacement.LeftCenter:
- break;
- case EnumPlacement.RightTop:
- break;
- case EnumPlacement.RightBottom:
- break;
- case EnumPlacement.RightCenter:
- break;
- case EnumPlacement.TopLeft:
- break;
- case EnumPlacement.TopCenter:
- poptip.Placement = PlacementMode.Top;
- break;
- case EnumPlacement.TopRight:
- break;
- case EnumPlacement.BottomLeft:
- break;
- case EnumPlacement.BottomCenter:
- break;
- case EnumPlacement.BottomRight:
- break;
- default:
- break;
- }
- }
- }
- #endregion PlacementEx
- #region Background
- public Brush Background
- {
- get { return (Brush)GetValue(BackgroundProperty); }
- set { SetValue(BackgroundProperty, value); }
- }
- public static readonly DependencyProperty BackgroundProperty =
- DependencyProperty.Register("Background", typeof(Brush), typeof(PopTip), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(109, 129, 154))));
- #endregion Background
- #region BorderThickness
- public Thickness BorderThickness
- {
- get { return (Thickness)GetValue(BorderThicknessProperty); }
- set { SetValue(BorderThicknessProperty, value); }
- }
- public static readonly DependencyProperty BorderThicknessProperty =
- DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(PopTip), new PropertyMetadata(new Thickness(1)));
- #endregion BorderThickness
- #region BorderBrush
- public Brush BorderBrush
- {
- get { return (Brush)GetValue(BorderBrushProperty); }
- set { SetValue(BorderBrushProperty, value); }
- }
- public static readonly DependencyProperty BorderBrushProperty =
- DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(PopTip), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(204, 206, 219))));
- #endregion BorderBrush
- #region CornerRadius
- public CornerRadius CornerRadius
- {
- get { return (CornerRadius)GetValue(CornerRadiusProperty); }
- set { SetValue(CornerRadiusProperty, value); }
- }
- public static readonly DependencyProperty CornerRadiusProperty =
- DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(PopTip), new PropertyMetadata(new CornerRadius(5)));
- #endregion CornerRadius
- #endregion DependencyProperty
- #region Override
- protected override void OnInitialized(EventArgs e)
- {
- base.OnInitialized(e);
- this.AllowsTransparency = true;
- //this.StaysOpen = false;
- UIElement element = this.Child;
- this.Child = null;
- Grid root = new Grid()
- {
- Margin = new Thickness(10),
- };
- angleBorder = new AngleBorder()
- {
- Background = this.Background,
- CornerRadius = this.CornerRadius,
- BorderThickness = this.BorderThickness,
- BorderBrush = this.BorderBrush,
- };
- switch (this.PlacementEx)
- {
- case EnumPlacement.LeftTop:
- angleBorder.Placement = EnumPlacement.RightTop;
- break;
- case EnumPlacement.LeftBottom:
- angleBorder.Placement = EnumPlacement.RightBottom;
- break;
- case EnumPlacement.LeftCenter:
- angleBorder.Placement = EnumPlacement.RightCenter;
- break;
- case EnumPlacement.RightTop:
- angleBorder.Placement = EnumPlacement.LeftTop;
- break;
- case EnumPlacement.RightBottom:
- angleBorder.Placement = EnumPlacement.LeftBottom;
- break;
- case EnumPlacement.RightCenter:
- angleBorder.Placement = EnumPlacement.LeftCenter;
- break;
- case EnumPlacement.TopLeft:
- angleBorder.Placement = EnumPlacement.BottomLeft;
- break;
- case EnumPlacement.TopCenter:
- angleBorder.Placement = EnumPlacement.BottomCenter;
- break;
- case EnumPlacement.TopRight:
- angleBorder.Placement = EnumPlacement.BottomRight;
- break;
- case EnumPlacement.BottomLeft:
- angleBorder.Placement = EnumPlacement.TopLeft;
- break;
- case EnumPlacement.BottomCenter:
- angleBorder.Placement = EnumPlacement.TopCenter;
- break;
- case EnumPlacement.BottomRight:
- angleBorder.Placement = EnumPlacement.TopRight;
- break;
- default:
- break;
- }
- //在原有控件基础上,最外层套一个AngleBorder
- angleBorder.Child = element;
- root.Children.Add(angleBorder);
- this.Child = root;
- }
- protected override void OnOpened(EventArgs e)
- {
- base.OnOpened(e);
- if (this.mIsLoaded)
- {
- return;
- }
- FrameworkElement targetElement = this.PlacementTarget as FrameworkElement;
- FrameworkElement child = this.Child as FrameworkElement;
- if (targetElement == null || child == null) return;
- switch (this.PlacementEx)
- {
- case EnumPlacement.LeftTop:
- this.Placement = PlacementMode.Left;
- break;
- case EnumPlacement.LeftBottom:
- this.Placement = PlacementMode.Left;
- this.VerticalOffset = targetElement.ActualHeight - child.ActualHeight;
- break;
- case EnumPlacement.LeftCenter:
- this.Placement = PlacementMode.Left;
- this.VerticalOffset = this.GetOffset(targetElement.ActualHeight, child.ActualHeight);
- break;
- case EnumPlacement.RightTop:
- this.Placement = PlacementMode.Right;
- break;
- case EnumPlacement.RightBottom:
- this.Placement = PlacementMode.Right;
- this.VerticalOffset = targetElement.ActualHeight - child.ActualHeight;
- break;
- case EnumPlacement.RightCenter:
- this.Placement = PlacementMode.Right;
- this.VerticalOffset = this.GetOffset(targetElement.ActualHeight, child.ActualHeight);
- break;
- case EnumPlacement.TopLeft:
- this.Placement = PlacementMode.Top;
- break;
- case EnumPlacement.TopCenter:
- this.Placement = PlacementMode.Top;
- this.HorizontalOffset = this.GetOffset(targetElement.ActualWidth, child.ActualWidth);
- break;
- case EnumPlacement.TopRight:
- this.Placement = PlacementMode.Top;
- this.HorizontalOffset = targetElement.ActualWidth - child.ActualWidth;
- break;
- case EnumPlacement.BottomLeft:
- this.Placement = PlacementMode.Bottom;
- break;
- case EnumPlacement.BottomCenter:
- this.Placement = PlacementMode.Bottom;
- this.HorizontalOffset = this.GetOffset(targetElement.ActualWidth, child.ActualWidth);
- break;
- case EnumPlacement.BottomRight:
- this.Placement = PlacementMode.Bottom;
- this.HorizontalOffset = targetElement.ActualWidth - child.ActualWidth;
- break;
- }
- this.mIsLoaded = true;
- }
- #endregion Override
- #region private function
- private double GetOffset(double targetSize, double poptipSize)
- {
- if (double.IsNaN(targetSize) || double.IsNaN(poptipSize))
- {
- return 0;
- }
- return (targetSize / 2.0) - (poptipSize / 2.0);
- }
- #endregion private function
- }
- }
|