using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using DevExpress.XtraEditors; using ProjectBase.Data.Logs; using ProjectBase.Data.BaseDAL; using System.Runtime.InteropServices; using SIMDP.BLL; using System.Drawing.Drawing2D; using ProjectBase.Util; using SIMDP.Model; namespace SIMDP.View { public partial class NotifyWindow : DevExpress.XtraEditors.XtraForm { #region Public Variables /// /// Gets or sets the title text to be displayed in the NotifyWindow. /// public string Title; /// /// Gets or sets the Font used for the title text. /// public System.Drawing.Font TitleFont; /// /// Gets or sets the Font used when the mouse hovers over the main body of text. /// public System.Drawing.Font HoverFont; /// /// Gets or sets the Font used when the mouse hovers over the title text. /// public System.Drawing.Font TitleHoverFont; /// /// Gets or sets the style used when drawing the background of the NotifyWindow. /// public BackgroundStyles BackgroundStyle; /// /// Gets or sets the Blend used when drawing a gradient background for the NotifyWindow. /// public System.Drawing.Drawing2D.Blend Blend; /// /// Gets or sets the StringFormat used when drawing text in the NotifyWindow. /// public System.Drawing.StringFormat StringFormat; /// /// Gets or sets a value specifiying whether or not the window should continue to be displayed if the mouse cursor is inside the bounds /// of the NotifyWindow. /// public bool WaitOnMouseOver; /// /// An EventHandler called when the NotifyWindow main text is clicked. /// public event System.EventHandler TextClicked; /// /// An EventHandler called when the NotifyWindow title text is clicked. /// public event System.EventHandler TitleClicked; /// /// Gets or sets the color of the title text. /// public System.Drawing.Color TitleColor; /// /// Gets or sets the color of the NotifyWindow main text. /// public System.Drawing.Color TextColor; /// /// Gets or sets the gradient color which will be blended in drawing the background. /// public System.Drawing.Color GradientColor; /// /// Gets or sets the color of text when the user clicks on it. /// public System.Drawing.Color PressedColor; /// /// Gets or sets the amount of milliseconds to display the NotifyWindow for. /// public int WaitTime; /// /// Gets or sets the full height of the NotifyWindow, used after the opening animation has been completed. /// public int ActualHeight; /// /// Gets or sets the full width of the NotifyWindow. /// public int ActualWidth; public enum BackgroundStyles { BackwardDiagonalGradient, ForwardDiagonalGradient, HorizontalGradient, VerticalGradient, Solid }; public enum ClockStates { Opening, Closing, Showing, None }; public ClockStates ClockState; #endregion #region Protected Variables protected bool closePressed = false, textPressed = false, titlePressed = false, closeHot = false, textHot = false, titleHot = false; protected Rectangle rClose, rText, rTitle, rDisplay, rScreen, rGlobClose, rGlobText, rGlobTitle, rGlobDisplay; protected System.Windows.Forms.Timer viewClock; #endregion #region Constructor /// Title text displayed in the NotifyWindow /// Main text displayedin the NotifyWindow public NotifyWindow(string title, string text) : this() { Title = title; Text = text; } /// Text displayed in the NotifyWindow public NotifyWindow(string text) : this() { Text = text; } public NotifyWindow() { InitializeComponent(); this.gridControl1.DataSource = BLLFactory.Instance.Find(string.Format(" notice_sign = {0}", 0)); SetStyle(ControlStyles.UserMouse, true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); // WmPaint calls OnPaint and OnPaintBackground SetStyle(ControlStyles.DoubleBuffer, true); ShowInTaskbar = false; FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; StartPosition = System.Windows.Forms.FormStartPosition.Manual; // Default values BackgroundStyle = BackgroundStyles.VerticalGradient; ClockState = ClockStates.None; BackColor = Color.SteelBlue; GradientColor = Color.WhiteSmoke; PressedColor = Color.Gray; TitleColor = SystemColors.ControlText; TextColor = SystemColors.ControlText; WaitOnMouseOver = true; ActualWidth = 130; ActualHeight = 110; WaitTime = 11000; } #endregion #region Public Methods /// /// Sets the width and height of the NotifyWindow. /// public void SetDimensions(int width, int height) { ActualWidth = width; ActualHeight = height; } /// /// Displays the NotifyWindow. /// public void Notify() { //if (Text == null || Text.Length < 1) // throw new System.Exception("You must set NotifyWindow.Text before calling Notify()"); Width = ActualWidth; rScreen = Screen.GetWorkingArea(Screen.PrimaryScreen.Bounds); Height = 0; Top = rScreen.Bottom; Left = rScreen.Width - Width - 11; if (HoverFont == null) HoverFont = new Font(Font, Font.Style | FontStyle.Underline); if (TitleFont == null) TitleFont = Font; if (TitleHoverFont == null) TitleHoverFont = new Font(TitleFont, TitleFont.Style | FontStyle.Underline); if (this.StringFormat == null) { this.StringFormat = new StringFormat(); this.StringFormat.Alignment = StringAlignment.Center; this.StringFormat.LineAlignment = StringAlignment.Center; this.StringFormat.Trimming = StringTrimming.EllipsisWord; } rDisplay = new Rectangle(0, 0, Width, ActualHeight); rClose = new Rectangle(Width - 21, 10, 13, 13); int offset; if (Title != null) { using (Graphics fx = CreateGraphics()) { SizeF sz = fx.MeasureString(Title, TitleFont, ActualWidth - rClose.Width - 22, this.StringFormat); rTitle = new Rectangle(11, 12, (int)Math.Ceiling(sz.Width), (int)Math.Ceiling(sz.Height)); offset = (int)Math.Max(Math.Ceiling(sz.Height + rTitle.Top + 2), rClose.Bottom + 5); } } else { offset = rClose.Bottom + 1; rTitle = new Rectangle(-1, -1, 1, 1); } rText = new Rectangle(11, offset, ActualWidth - 22, ActualHeight - (int)(offset * 1.5)); // rGlob* are Rectangle's Offset'ed to their actual position on the screen, for use with Cursor.Position. rGlobClose = rClose; rGlobClose.Offset(Left, rScreen.Bottom - ActualHeight); rGlobText = rText; rGlobText.Offset(Left, rScreen.Bottom - ActualHeight); rGlobTitle = rTitle; if (Title != null) rGlobTitle.Offset(Left, rScreen.Bottom - ActualHeight); rGlobDisplay = rDisplay; rGlobDisplay.Offset(Left, rScreen.Bottom - ActualHeight); rGlobClose = rClose; rGlobClose.Offset(Left, rScreen.Bottom - ActualHeight); rGlobDisplay = rDisplay; rGlobDisplay.Offset(Left, rScreen.Bottom - ActualHeight); // Use unmanaged ShowWindow() and SetWindowPos() instead of the managed Show() to display the window - this method will display // the window TopMost, but without stealing focus (namely the SW_SHOWNOACTIVATE and SWP_NOACTIVATE flags) ShowWindow(Handle, SW_SHOWNOACTIVATE); SetWindowPos(Handle, HWND_TOPMOST, rScreen.Width - ActualWidth - 11, rScreen.Bottom, ActualWidth, 0, SWP_NOACTIVATE); viewClock = new System.Windows.Forms.Timer(); viewClock.Tick += new System.EventHandler(viewTimer); viewClock.Interval = 1; viewClock.Start(); ClockState = ClockStates.Opening; } #endregion #region Drawing protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { // Draw the close button and text. drawCloseButton(e.Graphics); Font useFont; Color useColor; if (Title != null) { if (titleHot) useFont = TitleHoverFont; else useFont = TitleFont; if (titlePressed) useColor = PressedColor; else useColor = TitleColor; using (SolidBrush sb = new SolidBrush(useColor)) e.Graphics.DrawString(Title, useFont, sb, rTitle, this.StringFormat); } if (textHot) useFont = HoverFont; else useFont = Font; if (textPressed) useColor = PressedColor; else useColor = TextColor; using (SolidBrush sb = new SolidBrush(useColor)) e.Graphics.DrawString(Text, useFont, sb, rText, this.StringFormat); } protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e) { // First paint the background if (BackgroundStyle == BackgroundStyles.Solid) { using (SolidBrush sb = new SolidBrush(BackColor)) e.Graphics.FillRectangle(sb, rDisplay); } else { LinearGradientMode lgm; switch (BackgroundStyle) { case BackgroundStyles.BackwardDiagonalGradient: lgm = LinearGradientMode.BackwardDiagonal; break; case BackgroundStyles.ForwardDiagonalGradient: lgm = LinearGradientMode.ForwardDiagonal; break; case BackgroundStyles.HorizontalGradient: lgm = LinearGradientMode.Horizontal; break; default: case BackgroundStyles.VerticalGradient: lgm = LinearGradientMode.Vertical; break; } using (LinearGradientBrush lgb = new LinearGradientBrush(rDisplay, GradientColor, BackColor, lgm)) { if (this.Blend != null) lgb.Blend = this.Blend; e.Graphics.FillRectangle(lgb, rDisplay); } } // Next draw borders... drawBorder(e.Graphics); } protected virtual void drawBorder(Graphics fx) { fx.DrawRectangle(Pens.Silver, 2, 2, Width - 4, ActualHeight - 4); // Top border fx.DrawLine(Pens.Silver, 0, 0, Width, 0); fx.DrawLine(Pens.White, 0, 1, Width, 1); fx.DrawLine(Pens.DarkGray, 3, 3, Width - 4, 3); fx.DrawLine(Pens.DimGray, 4, 4, Width - 5, 4); // Left border fx.DrawLine(Pens.Silver, 0, 0, 0, ActualHeight); fx.DrawLine(Pens.White, 1, 1, 1, ActualHeight); fx.DrawLine(Pens.DarkGray, 3, 3, 3, ActualHeight - 4); fx.DrawLine(Pens.DimGray, 4, 4, 4, ActualHeight - 5); // Bottom border fx.DrawLine(Pens.DarkGray, 1, ActualHeight - 1, Width - 1, ActualHeight - 1); fx.DrawLine(Pens.White, 3, ActualHeight - 3, Width - 3, ActualHeight - 3); fx.DrawLine(Pens.Silver, 4, ActualHeight - 4, Width - 4, ActualHeight - 4); // Right border fx.DrawLine(Pens.DarkGray, Width - 1, 1, Width - 1, ActualHeight - 1); fx.DrawLine(Pens.White, Width - 3, 3, Width - 3, ActualHeight - 3); fx.DrawLine(Pens.Silver, Width - 4, 4, Width - 4, ActualHeight - 4); } protected virtual void drawCloseButton(Graphics fx) { if (visualStylesEnabled()) drawThemeCloseButton(fx); else drawLegacyCloseButton(fx); } /// /// Draw a Windows XP style close button. /// protected void drawThemeCloseButton(Graphics fx) { IntPtr hTheme = OpenThemeData(Handle, "Window"); if (hTheme == IntPtr.Zero) { drawLegacyCloseButton(fx); return; } int stateId; if (closePressed) stateId = CBS_PUSHED; else if (closeHot) stateId = CBS_HOT; else stateId = CBS_NORMAL; RECT reClose = new RECT(rClose); RECT reClip = reClose; // should fx.VisibleClipBounds be used here? IntPtr hDC = fx.GetHdc(); DrawThemeBackground(hTheme, hDC, WP_CLOSEBUTTON, stateId, ref reClose, ref reClip); fx.ReleaseHdc(hDC); CloseThemeData(hTheme); } /// /// Draw a Windows 95 style close button. /// protected void drawLegacyCloseButton(Graphics fx) { ButtonState bState; if (closePressed) bState = ButtonState.Pushed; else // the Windows 95 theme doesn't have a "hot" button bState = ButtonState.Normal; ControlPaint.DrawCaptionButton(fx, rClose, CaptionButton.Close, bState); } /// /// Determine whether or not XP Visual Styles are active. Compatible with pre-UxTheme.dll versions of Windows. /// protected bool visualStylesEnabled() { try { if (IsThemeActive() == 1) return true; else return false; } catch (System.DllNotFoundException) // pre-XP systems which don't have UxTheme.dll { return false; } } #endregion #region Timers and EventHandlers protected void viewTimer(object sender, System.EventArgs e) { switch (ClockState) { case ClockStates.Opening: if (Top - 2 <= rScreen.Height - ActualHeight) { Top = rScreen.Height - ActualHeight; Height = ActualHeight; ClockState = ClockStates.Showing; viewClock.Interval = WaitTime; } else { Top -= 2; Height += 2; } break; case ClockStates.Showing: if (!WaitOnMouseOver || !rGlobDisplay.Contains(Cursor.Position)) { viewClock.Interval = 1; //ClockState = ClockStates.Closing; } break; case ClockStates.Closing: Top += 2; Height -= 2; if (Top >= rScreen.Height) { ClockState = ClockStates.None; viewClock.Stop(); viewClock.Dispose(); Close(); } break; } } protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e) { if (Title != null && rGlobTitle.Contains(Cursor.Position) && !textPressed && !closePressed) { Cursor = Cursors.Hand; titleHot = true; textHot = false; closeHot = false; Invalidate(); } else if (rGlobText.Contains(Cursor.Position) && !titlePressed && !closePressed) { Cursor = Cursors.Hand; textHot = true; titleHot = false; closeHot = false; Invalidate(); } else if (rGlobClose.Contains(Cursor.Position) && !titlePressed && !textPressed) { Cursor = Cursors.Hand; closeHot = true; titleHot = false; textHot = false; Invalidate(); } else if ((textHot || titleHot || closeHot) && (!titlePressed && !textPressed && !closePressed)) { Cursor = Cursors.Default; titleHot = false; textHot = false; closeHot = false; Invalidate(); } base.OnMouseMove(e); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (rGlobClose.Contains(Cursor.Position)) { closePressed = true; closeHot = false; Invalidate(); } else if (rGlobText.Contains(Cursor.Position)) { textPressed = true; Invalidate(); } else if (Title != null && rGlobTitle.Contains(Cursor.Position)) { titlePressed = true; Invalidate(); } } base.OnMouseDown(e); } protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (closePressed) { Cursor = Cursors.Default; closePressed = false; closeHot = false; Invalidate(); if (rGlobClose.Contains(Cursor.Position)) Close(); } else if (textPressed) { Cursor = Cursors.Default; textPressed = false; textHot = false; Invalidate(); if (rGlobText.Contains(Cursor.Position)) { Close(); if (TextClicked != null) TextClicked(this, new System.EventArgs()); } } else if (titlePressed) { Cursor = Cursors.Default; titlePressed = false; titleHot = false; Invalidate(); if (rGlobTitle.Contains(Cursor.Position)) { Close(); if (TitleClicked != null) TitleClicked(this, new System.EventArgs()); } } } base.OnMouseUp(e); } #endregion #region P/Invoke // DrawThemeBackground() protected const Int32 WP_CLOSEBUTTON = 18; protected const Int32 CBS_NORMAL = 1; protected const Int32 CBS_HOT = 2; protected const Int32 CBS_PUSHED = 3; [StructLayout(LayoutKind.Explicit)] protected struct RECT { [FieldOffset(0)] public Int32 Left; [FieldOffset(4)] public Int32 Top; [FieldOffset(8)] public Int32 Right; [FieldOffset(12)] public Int32 Bottom; public RECT(System.Drawing.Rectangle bounds) { Left = bounds.Left; Top = bounds.Top; Right = bounds.Right; Bottom = bounds.Bottom; } } // SetWindowPos() protected const Int32 HWND_TOPMOST = -1; protected const Int32 SWP_NOACTIVATE = 0x0010; // ShowWindow() protected const Int32 SW_SHOWNOACTIVATE = 4; // UxTheme.dll [DllImport("UxTheme.dll")] protected static extern Int32 IsThemeActive(); [DllImport("UxTheme.dll")] protected static extern IntPtr OpenThemeData(IntPtr hWnd, [MarshalAs(UnmanagedType.LPTStr)] string classList); [DllImport("UxTheme.dll")] protected static extern void CloseThemeData(IntPtr hTheme); [DllImport("UxTheme.dll")] protected static extern void DrawThemeBackground(IntPtr hTheme, IntPtr hDC, Int32 partId, Int32 stateId, ref RECT rect, ref RECT clipRect); // user32.dll [DllImport("user32.dll")] protected static extern bool ShowWindow(IntPtr hWnd, Int32 flags); [DllImport("user32.dll")] protected static extern bool SetWindowPos(IntPtr hWnd, Int32 hWndInsertAfter, Int32 X, Int32 Y, Int32 cx, Int32 cy, uint uFlags); #endregion /// /// 表格显示 /// /// /// private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) { if (e.Column.ColumnType == typeof(DateTime)) { string columnName = e.Column.FieldName; if (e.Value != null) { if (Convert.ToDateTime(e.Value) <= Convert.ToDateTime("1900-1-1")) { e.DisplayText = ""; } else { e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm:ss");//yyyy-MM-dd } } } if (e.Column.FieldName == "NoticeType") { e.DisplayText = SysEnvironment.dirSystemNoticType.FirstOrDefault(p => p.Key == Convert.ToInt32(e.Value)).Value; } } /// /// 表格超链接点击事件 /// /// /// private void repositoryItemHyperLinkEdit1_Click(object sender, EventArgs e) { MoSystemNotice selectRow = this.gridView1.GetFocusedRow() as MoSystemNotice; try { selectRow.NoticeOperator = SysEnvironment.CurrentLoginID; selectRow.NoticeSign = true; bool flag = BLLFactory.Instance.Update(selectRow, selectRow.ID); if (flag) { RefreshWindow(); } } catch (Exception ex) { DevExpress.XtraEditors.XtraMessageBox.Show("确认失败。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); LogHelper.log.Error(string.Format("修改数据库system_notice出现错误:{0}", ex)); } } /// /// 刷新窗口 /// public void RefreshWindow() { this.gridControl1.DataSource = BLLFactory.Instance.Find(string.Format(" notice_sign = {0}", 0)); this.gridControl1.RefreshDataSource(); } } }