using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SIMDP
{
public partial class FormNoticeDetail : DevExpress.XtraEditors.XtraForm
{
private string Title;
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;
/// Title text displayed in the NotifyWindow
/// Main text displayedin the NotifyWindow
public enum BackgroundStyles { BackwardDiagonalGradient, ForwardDiagonalGradient, HorizontalGradient, VerticalGradient, Solid };
public enum ClockStates { Opening, Closing, Showing, None };
public ClockStates ClockState;
#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
public FormNoticeDetail(string title, string text) : this() { Title = title; Text = text; }
/// Text displayed in the NotifyWindow
public FormNoticeDetail(string text) : this() { Text = text; }
public FormNoticeDetail()
{
InitializeComponent();
this.TopMost = true;
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;
}
private void FormNoticeDetail_Load(object sender, EventArgs e)
{
//this.TopMost = true;
//this.ShowInTaskbar = false;
//this.WindowStartupLocation = WindowStartuplocation.Manual;
}
#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(Rectangle workArea)
{
//if (Text == null || Text.Length < 1)
// throw new System.Exception("You must set NotifyWindow.Text before calling Notify()");
Width = ActualWidth;
rScreen = workArea;//Screen.GetWorkingArea(Screen.PrimaryScreen.Bounds);
Height = 0;
Top = rScreen.Bottom;
Left = rScreen.Right - Width - 5;
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.Right - 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;
}
#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
#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
}
}