|

Introduction
NotifyWindow displays an MSN Messenger-like notification window. If
you want to display your own images in the notification window, you may prefer
to use John O'Byrne's
TaskbarNotifer. NotifyWindow may be easier to use if you
just intend to display text. Animations are used in opening and
closing the NotifyWindow, and the window is displayed TopMost while
not stealing focus. The window will be shown for a default of
11 seconds, although this can be changed. NotifyWindow does all of
its own drawing, so no extra image files are required.
Using
the code
It is pretty simple to display text using NotifyWindow.
NotifyWindow nw = new NotifyWindow ("This is a sample NotifyWindow");
nw.Notify();
NotifyWindow nw = new NotifyWindow ("NotifyWindow",
"This is a sample notification created with NotifyWindow");
nw.Notify();
If desired, a variety of other options can be changed - such as fonts and
colors. The included TestNotifyWindow
application will let you play around with a few of the settings, but
the code displayed here should serve as a more complete reference.
NotifyWindow nw = new NotifyWindow();
nw.Text = "This is the NotifyWindow text";
nw.Title = "Title Text";
nw.BackgroundStyle = NotifyWindow.BackgroundStyles.ForwardDiagonalGradient;
nw.BackColor = Color.SpringGreen;
nw.GradientColor = Color.White;
nw.TextColor = Color.Blue;
nw.TitleColor = Color.Black;
nw.PressedColor = Color.Red;
nw.Font = new Font ("Tahoma", 8.25F);
nw.TitleFont = new Font ("Tahoma", 8.25F, FontStyle.Bold);
nw.SetDimensions (nwWidth, nwHeight);
nw.WaitOnMouseOver = true;
nw.TextClicked += new System.EventHandler (nwTextClicked);
nw.TitleClicked += new System.EventHandler (nwTitleClicked);
nw.WaitTime = 20000;
nw.Notify();
This is how the NotifyWindow created with the above code will
look:
 Programmers can also use their own Blend
(for the background) or StringFormat
(which will be used when Text and Title are drawn) if desired by setting the
nw.Blend and nw.StringFormat variables.
Points of Interest
NotifyWindow is unique because it does all of its own drawing. The background is drawn using Graphics.FillRectangle with
either a LinearGradientBrush (default) or a SolidBrush. The borders are drawn using a series of calls to
Graphics.DrawRectangle and Graphics.DrawLine. On Windows XP or higher systems with Visual Styles enabled,
the close button is drawn using DrawThemeBackground() from UxTheme.dll - otherwise, ControlPaint.DrawCaptionButton
is used.
An obstacle faced in both this and similar applications has been
displaying the window on top without stealing focus. Both Form.Show() and
setting TopMost = true individually activate the form,
which steals focus. We get around
this by calling ShowWindow() and SetWindowPos()
with arguments instructing the operating system not to activate the
window. const Int32 HWND_TOPMOST = -1;
const Int32 SWP_NOACTIVATE = 0x0010;
const Int32 SW_SHOWNOACTIVATE = 4;
[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);
...
ShowWindow (this.Handle, SW_SHOWNOACTIVATE);
SetWindowPos (this.Handle, HWND_TOPMOST, Left, Top, Width, Height, SWP_NOACTIVATE);
A similar
NotifyWindow class was originally implemented for an
open-source project called
ChronosXP.
When it became apparant that others might like to use this code outside
of that project, it was modified, removing the ChronosXP-specific parts
and making it more generic. A class called NotifyWindow2000 is included with
the distribution that will display the NotifyWindow indefinitely until
there is mouse or keyboard activity, similar to balloon windows. It uses SetWindowsHookEx() with WH_KEYBOARD_LL/WH_MOUSE_LL
to detect user activity, so it will only work with Windows 2000 or
higher. If anyone knows how to do this on older versions of
Windows I would like to hear about it. History
- Initial coding: July 28, 2004
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 89 (Total in Forum: 89) (Refresh) | FirstPrevNext |
|
|
 |
|
|
Great article, Can you help me out here, how can place a command bottom on the notifier. I do be glad if you or any one can help me out.
Keep up the good work !!!!!! Thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
' NotifyWindow.cs ' Copyright � 2004 by Robert Misiak <rmisiak@users.sourceforge.net> ' All Rights Reserved. ' ' Permission is granted to use, modify and distribute this code, as long as credit is given to the original author, and the copyright notice ' is retained. ' ' Based on a similar implementation used in ChronosXP, an open-source project: http://chronosxp.sourceforge.net
Imports System Imports System.Drawing Imports System.Drawing.Drawing2D Imports System.Reflection Imports System.Windows.Forms Imports System.Runtime.InteropServices
''' <summary> ''' Display An MSN-Messenger-Style NotifyWindow. ''' </summary> Public Class NotifyWindow Inherits System.Windows.Forms.Form
''' <summary> ''' Gets or sets the title text to be displayed in the NotifyWindow. ''' </summary> Public Title As String
''' <summary> ''' Gets or sets the Font used for the title text. ''' </summary> Public TitleFont As System.Drawing.Font
''' <summary> ''' Gets or sets the Font used when the mouse hovers over the main body of text. ''' </summary> Public HoverFont As System.Drawing.Font
''' <summary> ''' Gets or sets the Font used when the mouse hovers over the title text. ''' </summary> Public TitleHoverFont As System.Drawing.Font
''' <summary> ''' Gets or sets the style used when drawing the background of the NotifyWindow. ''' </summary> Public BackgroundStyle As BackgroundStyles
''' <summary> ''' Gets or sets the Blend used when drawing a gradient background for the NotifyWindow. ''' </summary> Public Blend As System.Drawing.Drawing2D.Blend
''' <summary> ''' Gets or sets the StringFormat used when drawing text in the NotifyWindow. ''' </summary> Public StringFormat As System.Drawing.StringFormat
''' <summary> ''' 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. ''' </summary> Public WaitOnMouseOver As Boolean
''' <summary> ''' Gets or sets the color of the title text. ''' </summary> Public TitleColor As System.Drawing.Color
''' <summary> ''' Gets or sets the color of the NotifyWindow main text. ''' </summary> Public TextColor As System.Drawing.Color
''' <summary> ''' Gets or sets the gradient color which will be blended in drawing the background. ''' </summary> Public GradientColor As System.Drawing.Color
''' <summary> ''' Gets or sets the color of text when the user clicks on it. ''' </summary> Public PressedColor As System.Drawing.Color
''' <summary> ''' Gets or sets the amount of milliseconds to display the NotifyWindow for. ''' </summary> Public WaitTime As Integer
''' <summary> ''' Gets or sets the full height of the NotifyWindow, used after the opening animation has been completed. ''' </summary> Public ActualHeight As Integer
''' <summary> ''' Gets or sets the full width of the NotifyWindow. ''' </summary> Public ActualWidth As Integer
Public ClockState As ClockStates
Protected closePressed As Boolean = False Protected textPressed As Boolean = False Protected titlePressed As Boolean = False Protected closeHot As Boolean = False Protected textHot As Boolean = False Protected titleHot As Boolean = False
Protected rClose As Rectangle Protected rText As Rectangle Protected rTitle As Rectangle Protected rDisplay As Rectangle Protected rScreen As Rectangle Protected rGlobClose As Rectangle Protected rGlobText As Rectangle Protected rGlobTitle As Rectangle Protected rGlobDisplay As Rectangle
Protected viewClock As System.Windows.Forms.Timer
''' <param name="_title">Title text displayed in the NotifyWindow</param> ''' <param name="_text">Main text displayedin the NotifyWindow</param> Public Sub New(ByVal _title As String, ByVal _text As String) MyBase.New() Title = _title Text = _text InitializeComponent()
End Sub
''' <param name="_text">Text displayed in the NotifyWindow</param> Public Sub New(ByVal _text As String) MyBase.New() Text = _text InitializeComponent() End Sub
Public Sub New() MyBase.New() 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 InitializeComponent() End Sub
''' <summary> ''' An EventHandler called when the NotifyWindow main text is clicked. ''' </summary> Public Event TextClicked As System.EventHandler
''' <summary> ''' An EventHandler called when the NotifyWindow title text is clicked. ''' </summary> Public Event TitleClicked As System.EventHandler
''' <summary> ''' Sets the width and height of the NotifyWindow. ''' </summary> Public Sub SetDimensions(ByVal width As Integer, ByVal height As Integer) ActualWidth = width ActualHeight = height End Sub
''' <summary> ''' Displays the NotifyWindow. ''' </summary> Public Sub Notify() If Text Is Nothing OrElse Text.Length < 1 Then Throw New System.Exception("You must set NotifyWindow.Text before calling Notify()") End If
Width = ActualWidth rScreen = Screen.GetWorkingArea(Screen.PrimaryScreen.Bounds) Height = 0 Top = rScreen.Bottom Left = rScreen.Width - Width - 11
If HoverFont Is Nothing Then HoverFont = New Font(Font, Font.Style Or FontStyle.Underline) End If If TitleFont Is Nothing Then TitleFont = Font End If If TitleHoverFont Is Nothing Then TitleHoverFont = New Font(TitleFont, TitleFont.Style Or FontStyle.Underline) End If If Me.StringFormat Is Nothing Then Me.StringFormat = New StringFormat() Me.StringFormat.Alignment = StringAlignment.Center Me.StringFormat.LineAlignment = StringAlignment.Center Me.StringFormat.Trimming = StringTrimming.EllipsisWord End If
rDisplay = New Rectangle(0, 0, Width, ActualHeight) rClose = New Rectangle(Width - 21, 10, 13, 13)
Dim offset As Integer If Title IsNot Nothing Then Using fx As Graphics = CreateGraphics() Dim sz As SizeF = fx.MeasureString(Title, TitleFont, ActualWidth - rClose.Width - 22, Me.StringFormat) rTitle = New Rectangle(11, 12, CInt(Math.Ceiling(sz.Width)), CInt(Math.Ceiling(sz.Height))) offset = CInt(Math.Max(Math.Ceiling(sz.Height + rTitle.Top + 2), rClose.Bottom + 5))
End Using Else offset = rClose.Bottom + 1 rTitle = New Rectangle(-1, -1, 1, 1) End If
rText = New Rectangle(11, offset, ActualWidth - 22, ActualHeight - CInt((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 IsNot Nothing Then rGlobTitle.Offset(Left, rScreen.Bottom - ActualHeight) End If 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() AddHandler viewClock.Tick, AddressOf viewTimer viewClock.Interval = 1 viewClock.Start()
ClockState = ClockStates.Opening
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) ' Draw the close button and text. drawCloseButton(e.Graphics) Dim useFont As Font Dim useColor As Color
If (Not (Title) Is Nothing) Then If titleHot Then useFont = TitleHoverFont Else useFont = TitleFont End If If titlePressed Then useColor = PressedColor Else useColor = TitleColor End If Dim br As SolidBrush = New SolidBrush(useColor) e.Graphics.DrawString(Title, useFont, br, rTitle, Me.StringFormat) End If
If textHot Then useFont = HoverFont Else useFont = Font End If If textPressed Then useColor = PressedColor Else useColor = TextColor End If Dim sb As SolidBrush = New SolidBrush(useColor) e.Graphics.DrawString(Text, useFont, sb, rText, Me.StringFormat)
End Sub
Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs) ' First paint the background If (BackgroundStyle = BackgroundStyles.Solid) Then Dim sb As SolidBrush = New SolidBrush(BackColor) e.Graphics.FillRectangle(sb, rDisplay) Else Dim lgm As LinearGradientMode Select Case (BackgroundStyle) Case BackgroundStyles.BackwardDiagonalGradient lgm = LinearGradientMode.BackwardDiagonal Case BackgroundStyles.ForwardDiagonalGradient lgm = LinearGradientMode.ForwardDiagonal Case BackgroundStyles.HorizontalGradient lgm = LinearGradientMode.Horizontal Case BackgroundStyles.VerticalGradient lgm = LinearGradientMode.Vertical End Select Dim lgb As LinearGradientBrush = New LinearGradientBrush(rDisplay, GradientColor, BackColor, lgm) If (Not (Me.Blend) Is Nothing) Then lgb.Blend = Me.Blend End If e.Graphics.FillRectangle(lgb, rDisplay) End If ' Next draw borders... drawBorder(e.Graphics) End Sub
Protected Overridable Sub drawBorder(ByVal fx As Graphics) 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)) End Sub
Protected Overridable Sub drawCloseButton(ByVal fx As Graphics) If visualStylesEnabled() Then drawThemeCloseButton(fx) Else drawLegacyCloseButton(fx) End If End Sub
''' <summary> ''' Draw a Windows XP style close button. ''' </summary> Protected Sub drawThemeCloseButton(ByVal fx As Graphics) Dim hTheme As IntPtr = OpenThemeData(Handle, "Window") If hTheme = IntPtr.Zero Then drawLegacyCloseButton(fx) Return End If Dim stateId As Integer If closePressed Then stateId = CBS_PUSHED ElseIf closeHot Then stateId = CBS_HOT Else stateId = CBS_NORMAL End If Dim reClose As New RECT(rClose) Dim reClip As RECT = reClose ' should fx.VisibleClipBounds be used here? Dim hDC As IntPtr = fx.GetHdc() DrawThemeBackground(hTheme, hDC, WP_CLOSEBUTTON, stateId, reClose, reClip) fx.ReleaseHdc(hDC) CloseThemeData(hTheme)
End Sub
''' <summary> ''' Draw a Windows 95 style close button. ''' </summary> Protected Sub drawLegacyCloseButton(ByVal fx As Graphics) Dim bState As ButtonState If closePressed Then bState = ButtonState.Pushed Else bState = ButtonState.Normal ' the Windows 95 theme doesn't have a "hot" button End If ControlPaint.DrawCaptionButton(fx, rClose, CaptionButton.Close, bState)
End Sub
''' <summary> ''' Determine whether or not XP Visual Styles are active. Compatible with pre-UxTheme.dll versions of Windows. ''' </summary> Protected Function visualStylesEnabled() As Boolean Try If IsThemeActive() = 1 Then Return True Else Return False End If Catch generatedExceptionName As System.DllNotFoundException ' pre-XP systems which don't have UxTheme.dll Return False End Try
End Function
Protected Sub viewTimer(ByVal sender As Object, ByVal e As System.EventArgs) Select Case (ClockState) Case ClockStates.Opening If ((Top - 2) _ <= (rScreen.Height - ActualHeight)) Then Top = (rScreen.Height - ActualHeight) Height = ActualHeight ClockState = ClockStates.Showing viewClock.Interval = WaitTime Else Top = (Top - 2) Height = (Height + 2) End If Case ClockStates.Showing If (Not WaitOnMouseOver _ OrElse Not rGlobDisplay.Contains(Windows.Forms.Cursor.Position)) Then viewClock.Interval = 1 ClockState = ClockStates.Closing End If Case ClockStates.Closing Top = (Top + 2) Height = (Height - 2) If (Top >= rScreen.Height) Then ClockState = ClockStates.None viewClock.Stop() viewClock.Dispose() Close() End If End Select End Sub
Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs) 'If Title IsNot Nothing AndAlso rGlobTitle.Contains(Windows.Forms.Cursor.Position) AndAlso Not textPressed AndAlso Not closePressed Then ' Cursor = Cursors.Hand ' titleHot = True ' textHot = False ' closeHot = False ' Invalidate() 'ElseIf rGlobText.Contains(Windows.Forms.Cursor.Position) AndAlso Not titlePressed AndAlso Not closePressed Then ' Cursor = Cursors.Hand ' textHot = True ' titleHot = False ' closeHot = False ' Invalidate() 'ElseIf rGlobClose.Contains(Windows.Forms.Cursor.Position) AndAlso Not titlePressed AndAlso Not textPressed Then If rGlobClose.Contains(Windows.Forms.Cursor.Position) AndAlso Not titlePressed AndAlso Not textPressed Then Cursor = Cursors.Hand closeHot = True titleHot = False textHot = False Invalidate() ElseIf (textHot OrElse titleHot OrElse closeHot) AndAlso (Not titlePressed AndAlso Not textPressed AndAlso Not closePressed) Then Cursor = Cursors.[Default] titleHot = False textHot = False closeHot = False Invalidate() End If MyBase.OnMouseMove(e) End Sub
Protected Overloads Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = Windows.Forms.MouseButtons.Left Then If rGlobClose.Contains(Windows.Forms.Cursor.Position) Then closePressed = True closeHot = False Invalidate() ElseIf rGlobText.Contains(Windows.Forms.Cursor.Position) Then textPressed = True Invalidate() ElseIf Title IsNot Nothing AndAlso rGlobTitle.Contains(Windows.Forms.Cursor.Position) Then titlePressed = True Invalidate() End If End If MyBase.OnMouseDown(e) End Sub
Protected Overloads Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = Windows.Forms.MouseButtons.Left Then If closePressed Then Cursor = Cursors.[Default] closePressed = False closeHot = False Invalidate() If rGlobClose.Contains(Windows.Forms.Cursor.Position) Then Close() End If ElseIf textPressed Then Cursor = Cursors.[Default] textPressed = False textHot = False Invalidate() If rGlobText.Contains(Windows.Forms.Cursor.Position) Then Close() RaiseEvent TextClicked(Me, New System.EventArgs()) End If ElseIf titlePressed Then Cursor = Cursors.[Default] titlePressed = False titleHot = False Invalidate() If rGlobTitle.Contains(Windows.Forms.Cursor.Position) Then Close() RaiseEvent TitleClicked(Me, New System.EventArgs()) End If End If End If MyBase.OnMouseUp(e) End Sub
'''''''''''''''''''''''''''''''''''''''''''''''''''
Protected Const WP_CLOSEBUTTON As Int32 = 18 Protected Const CBS_NORMAL As Int32 = 1 Protected Const CBS_HOT As Int32 = 2 Protected Const CBS_PUSHED As Int32 = 3 ' DrawThemeBackground() <StructLayout(LayoutKind.Explicit)> _ Protected Structure RECT <FieldOffset(0)> _ Public Left As Int32 <FieldOffset(4)> _ Public Top As Int32 <FieldOffset(8)> _ Public Right As Int32 <FieldOffset(12)> _ Public Bottom As Int32
Public Sub New(ByVal bounds As System.Drawing.Rectangle) Left = bounds.Left Top = bounds.Top Right = bounds.Right Bottom = bounds.Bottom End Sub End Structure Protected Const HWND_TOPMOST As Int32 = -1 Protected Const SWP_NOACTIVATE As Int32 = 16 Protected Const SW_SHOWNOACTIVATE As Int32 = 4
' SetWindowPos()
' ShowWindow()
' UxTheme.dll <DllImport("UxTheme.dll")> _ Protected Shared Function IsThemeActive() As Int32 End Function <DllImport("UxTheme.dll")> _ Protected Shared Function OpenThemeData(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPTStr)> _ ByVal classList As String) As IntPtr End Function <DllImport("UxTheme.dll")> _ Protected Shared Sub CloseThemeData(ByVal hTheme As IntPtr) End Sub <DllImport("UxTheme.dll")> _ Protected Shared Sub DrawThemeBackground(ByVal hTheme As IntPtr, ByVal hDC As IntPtr, ByVal partId As Int32, ByVal stateId As Int32, ByRef rect As RECT, ByRef clipRect As RECT) End Sub
' user32.dll <DllImport("user32.dll")> _ Protected Shared Function ShowWindow(ByVal hWnd As IntPtr, ByVal flags As Int32) As Boolean End Function <DllImport("user32.dll")> _ Protected Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As Int32, ByVal X As Int32, ByVal Y As Int32, ByVal cx As Int32, ByVal cy As Int32, _ ByVal uFlags As UInteger) As Boolean End Function
Public Enum BackgroundStyles
BackwardDiagonalGradient
ForwardDiagonalGradient
HorizontalGradient
VerticalGradient
Solid End Enum
Public Enum ClockStates
Opening
Closing
Showing
None End Enum
End Class
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
After login when I click the download link IE I return to login screeen.
What could be wrong ?
Thank you
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello.
I've adapted your sample to my application.
But when I moved to Windows Vista, the popups are show slow and they not on the top of window. It also behind gadget pine.
Have anyone a solution? 
Best regards
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
It's really cool ...
Please tell me how can i add a control like button to the notify window
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hello,
Is it possible to show to NotifyWindows above eachother? I'm building an RSS Reader for the taskbar and i want RSS header to be displayed in a NotifyWindow and two messages above eachother, is this possible?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, I have a C# system tray application which is scheduled for a every 1 minute to do some database updation process.This process is actually running on a separate thread.After every 1 minute, after database updation i want to give a notification to the user using your NotifyWindow.I am calling NotifyWindow.Notify inside the ThreadStart function.But i never get the Notifier Window.Can you tell me where i went wrong.Here is the code snippet i used.Notification works fine if i call it from any other window.Kindly help me in this.
public frmSystemTray() { this.Hide(); InitializeNotifyIcon(); Thread syncThread = new Thread(new ThreadStart(UpdateDatabase)); syncThread.Start(); }
private void UpdateDatabase() { NotifyWindow notifyWindow; while(true) { Monitor.Enter(this); rdbUpdate update = new rdbUpdate(); DataSet updateResults = update.UpdateData(); Monitor.Exit(this); notifyWindow = new NotifyWindow("Update Database", "Update"); notifyWindow.SetDimensions (130, 110); notifyWindow.Notify(); System.Threading.Thread.Sleep(60000); } }
Jisha
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi Jisha-
You probably want to display the NotifyWindow() indirectly using Invoke() or BeginInvoke(). You can probably find excellent examples of how to do this in various articles on this site.
Regards, Robert
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, Thanks a lot. I got that working using MethodInvoker and BeginInvoke for calling the notifywindow
Jisha
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Can you please please share your code with me? I tried making notifywindow work using threadstart...but no luck. and tried they way you mentioned. Can you please show you code?
thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
this.BeginInvoke(new MethodInvoker(delegate() { NotifyWindow alertWindow = new NotifyWindow("Test"); alertWindow.Notify(); }
Manjit Sooch wrote: Can you please please share your code with me? I tried making notifywindow work using threadstart...but no luck. and tried they way you mentioned. Can you please show you code?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi there,
Nice code! Thanks very much. I have just amended it to allow stacking of messages above each other (i.e. upwards towards the top of the screen) like Messenger does
Apologies for the cut n' paste (not sure how else to send it.)
John Wood
// NotifyWindow.cs // Copyright © 2004 by Robert Misiak // All Rights Reserved. // // Permission is granted to use, modify and distribute this code, as long as credit is given to the original author, and the copyright notice // is retained. // // Based on a similar implementation used in ChronosXP, an open-source project: http://chronosxp.sourceforge.net // // JW 29/03/2006: Added code to allow multiple windows to show in a stacked layout, each // higher up than the other so they don't overlay each other anymore. This is // how MSN Messenger shows them. // // Also there is a parameter to prevent ignore calls if there are already // lots of windows being shown.
using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Reflection; using System.Windows.Forms; using System.Runtime.InteropServices;
namespace NotifyWindow { /// /// Display An MSN-Messenger-Style NotifyWindow. /// public class NotifyWindow : System.Windows.Forms.Form { //Used to keep track of which windows are active //This stores NotifyWindow objects. static System.Collections.ArrayList activeWindows = new System.Collections.ArrayList();
//JW: The max number of windows to display at once public int MaxActiveWindows= 6; //6 is about right for my screen
#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() { 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; }
//JW: How much to adjust the height by (allows stacking of boxes) private int heightAdjustment = 0;
/// /// Displays the NotifyWindow. /// public void Notify() { //JW: Prevent multiple displays if (activeWindows.Count > MaxActiveWindows) { //Should we dispose now? this.Dispose(true); return; }
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;
//JW: Work out the stacking adjustment //{{{ heightAdjustment = activeWindows.Count * this.ActualHeight; Top -= heightAdjustment;
//Record that the window exists in the static member activeWindows.Add(this); //}}}
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); //JW Note heightAdjustment //was: // SetWindowPos (Handle, HWND_TOPMOST, rScreen.Width - ActualWidth - 11, rScreen.Bottom, ActualWidth, 0, SWP_NOACTIVATE); SetWindowPos (Handle, HWND_TOPMOST, rScreen.Width - ActualWidth - 11, rScreen.Bottom - heightAdjustment, 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);
//removed 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: //JW: Note heightAdjustment if (Top - 2 <= rScreen.Height - ActualHeight - heightAdjustment) { //JW: Note heightAdjustment Top = rScreen.Height - ActualHeight - heightAdjustment; 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; //JW: Note heightAdjustment if (Top >= rScreen.Height - heightAdjustment) { ClockState = ClockStates.None; viewClock.Stop(); viewClock.Dispose();
//JW: Remove the item from our map activeWindows.Remove(this);
Close();
//JW: Just in case... this.Dispose(true); } 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;< | | | | | |