473,545 Members | 2,092 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Creating a static Messages Viewer

Hi,

I'm pretty new to C#, and I'm quite stuck on the following problem.

I would like to add to my application a Windows.Form (singleton) on
which I could display a message of one of the following type :
Exception, Error, Warning, Infos (with differents colors, etc).

I would like to use it like the Console.WriteLi ne("My Message"); on
everywhere in my application.

Something like that :

Expand|Select|Wrap|Line Numbers
  1. using MyApp.Tools;
  2. //popup (if not already displayed) and display the error
  3. LogViewer.WriteLine(MessageType.Error, "Something bad happenend");
  4.  
My application is multithreaded.

I already tried many things but I always have problems ("Windows Handle
Already Exists", form not refreshing (aka no messages loop), form not
displaying, etc.)

Sorry but I'm out of ideas. So if any one is ready to give me a very
useful help it would be really appreciated !

Here is my test class, lot's of things are commented because I made a
lot's of test.

Main questions and remarks are :

- Is the delegate way of doing ok ?
- Since this code can be called before the main Application.Run (new
MainForm) should I call an Application.Run () for this form ?
- How to cleanly prevent the component of the form not to be released
when closing the form
Ok here we go :
using System;
using System.Collecti ons;
using System.Componen tModel;
using System.Windows. Forms;
using System.IO;

namespace Tools
{
/// <summary>
/// A singleton to display message in a windows form
/// </summary>
public class LogViewer : System.Windows. Forms.Form
{
//a delegate to update the rich text box from everywhere (another
thread)
private delegate void UpdateLogRtb(Me ssageType _Type, string _Text);

public enum MessageType
{
Info,
Error,
Exception
}

/// <summary>
/// Required designer variable.
/// </summary>
///

//common to all instances

private static bool m_IsDisplayed;
static private int m_CurrentLine;

private static System.Windows. Forms.RichTextB ox richTextBox = new
RichTextBox();
private static System.Windows. Forms.Button btnSaveAs = new
System.Windows. Forms.Button();
private static System.Windows. Forms.Button btnClearLog = new
System.Windows. Forms.Button();
private static System.Threadin g.Thread m_UiThread;
static private LogViewer m_LogViewer = new LogViewer();

static LogViewer()
{
InitializeCompo nent();

m_IsDisplayed = false;
m_CurrentLine = 0;
}

/// <summary>
/// Private constructor, singleton
/// </summary>
private LogViewer()
{
//new thread ready to start
//m_UiThread = new System.Threadin g.Thread(new
System.Threadin g.ThreadStart(U IThread));
//m_UiThread.Star t();
}

//private void UIThread()
//{
// Application.Run (Instance);
//}

public static LogViewer Instance
{
get
{
return m_LogViewer;
}
}

public static void UpdateLog(Messa geType _Type, string _Text)
{
if ( Instance.Invoke Required )
{
UpdateLogRtb delUpdate = new UpdateLogRtb(Up dateLog);
Instance.BeginI nvoke(delUpdate , new object[]{_Type, _Text});
}
else
{
lock(richTextBo x)
{
if(!m_IsDisplay ed)
{
Instance.Show() ;
m_IsDisplayed = true;
}

Instance.SetCol or(_Type);
richTextBox.App endText(_Text);
}
}
}

void SetColor(Messag eType _Type)
{
switch(_Type)
{
case MessageType.Err or : richTextBox.Sel ectionColor =
System.Drawing. Color.Fuchsia;
break;
case MessageType.Exc eption : richTextBox.Sel ectionColor =
System.Drawing. Color.Red;
break;
case MessageType.Inf o : richTextBox.Sel ectionColor =
System.Drawing. Color.Blue;
break;
}
}

public static void WriteLine(Messa geType _Type ,string _Text,
object[] _Parameters)
{
IEnumerator iter = _Parameters.Get Enumerator();
Write(_Type, "[" + DateTime.Now.To ShortDateString () + " " +
DateTime.Now.To LongTimeString( ) + "] "+ _Text + " ");
while(iter.Move Next())
{
Write(_Type, iter.Current.To String());
Write(_Type, " ");
}
Write(_Type, "\n");
}

public static void WriteLine(Messa geType _Type ,string _Text, object
_Parameter)
{
Write(_Type, "[" + DateTime.Now.To ShortDateString () + " " +
DateTime.Now.To LongTimeString( ) + "] "+ _Text + " ");
Write(_Type, _Parameter.ToSt ring());
Write(_Type,"\n ");
}

public static void WriteLine(Messa geType _Type, string _Text)
{
Write(_Type, "[" + DateTime.Now.To ShortDateString () + " " +
DateTime.Now.To LongTimeString( ) + "] "+ _Text + " ");
Write(_Type,"\n ");
m_CurrentLine++ ;
}

public static void Write(MessageTy pe _Type, string _Text)
{
UpdateLog(_Type , _Text);
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
m_IsDisplayed = false;
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private static void InitializeCompo nent()
{
Instance.Suspen dLayout();
//
// richTextBox
//
richTextBox.Cur sor = System.Windows. Forms.Cursors.A rrow;
richTextBox.Loc ation = new System.Drawing. Point(0, 0);
richTextBox.Nam e = "richTextBo x";
richTextBox.Rea dOnly = true;
richTextBox.Siz e = new System.Drawing. Size(640, 250 );
richTextBox.Tab Index = 0;
richTextBox.Tex t = "";
richTextBox.Wor dWrap = false;
//
// btnSaveAs
//
btnSaveAs.Locat ion = new System.Drawing. Point(446, 254);
btnSaveAs.Name = "btnSaveAs" ;
btnSaveAs.Size = new System.Drawing. Size(89, 23);
btnSaveAs.TabIn dex = 1;
btnSaveAs.Text = "Save as...";
btnSaveAs.Click += new System.EventHan dler(btnSaveAs_ Click);
//
// btnClearLog
//
btnClearLog.Loc ation = new System.Drawing. Point(538, 254);
btnClearLog.Nam e = "btnClearLo g";
btnClearLog.Siz e = new System.Drawing. Size(100, 23);
btnClearLog.Tab Index = 2;
btnClearLog.Tex t = "Clear Log";
btnClearLog.Cli ck += new System.EventHan dler(btnClearLo g_Click);
//
// LogViewer
//
//m_LogViewer.Aut oScaleBaseSize = new System.Drawing. Size(5, 13);
Instance.Client Size = new System.Drawing. Size(640, 280);
Instance.Contro ls.Add(btnClear Log);
Instance.Contro ls.Add(btnSaveA s);
Instance.Contro ls.Add(richText Box);
Instance.FormBo rderStyle =
System.Windows. Forms.FormBorde rStyle.FixedToo lWindow;
Instance.Name = "LogViewer" ;
Instance.Text = "Events viewer";
Instance.Closin g += new
System.Componen tModel.CancelEv entHandler(LogV iewer_Closing);
Instance.Resume Layout(false);

}
#endregion
private static void LogViewer_Closi ng(object sender,
System.Componen tModel.CancelEv entArgs e)
{
Instance.Hide() ;
}

private static void btnSaveAs_Click (object sender, System.EventArg s
e)
{
SaveFileDialog saveFile = new SaveFileDialog( );
saveFile.FileNa me = "QueueMeEvents. log";
if (saveFile.ShowD ialog() != DialogResult.Ca ncel)
{
StreamWriter mySaveFile = File.CreateText (@saveFile.File Name);
mySaveFile.Auto Flush = true;
mySaveFile.Writ e(richTextBox.T ext);
mySaveFile.Clos e();
}
}

private static void btnClearLog_Cli ck(object sender, System.EventArg s
e)
{
richTextBox.Cle ar();
m_CurrentLine = 0;
}

// protected override void OnPaint(PaintEv entArgs e)
// {
// base.OnPaint (e);
// Application.DoE vents();
// Invalidate();
// System.Threadin g.Thread.Sleep( 100);
// }
}
}
Thanks !

Nov 17 '05 #1
2 2644
I wouldn't expose the form as a singleton. Rather, I would expose
static methods which would access a private static member which stores the
form in a field.

This form can not and should not be called before the call to
Application.Run . The message loop for the application hasn't been set up
yet, and it can cause unexpected side effects.

Basically, you would expose your method that will take your message
parameters. The first thing you would do is check the field to see if the
form is created (the check would be thread-safe, using a lock statement).
If it is, then you continue. Otherwise, you ignore the message (or cache it
for when the form is actually created).

Then, you would make a call to the InvokeRequired property on the form.
If it returns true, you would create a delegate with the signature of your
method, passing the delegate and the parameters to your method to the Invoke
method on the form (so that the calls are made on the correct thread). If
InvokeRequired is set to false, then you append or set the text elements to
the message.

You would also require a method which would be called when your main
form is run (through Application.Run ). This method would check the field to
see if it is null (again, in a thread-safe way). If it is null, then you
create the new instance of your form, and store it in the field, otherwise,
you just exit your method.

If you created your form, and you cached messages, you would also
display them when your form is created (of course, you would make calls to
your method which would handle calling the method on the correct thread).

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

<su*******@gmai l.com> wrote in message
news:11******** **************@ g44g2000cwa.goo glegroups.com.. .
Hi,

I'm pretty new to C#, and I'm quite stuck on the following problem.

I would like to add to my application a Windows.Form (singleton) on
which I could display a message of one of the following type :
Exception, Error, Warning, Infos (with differents colors, etc).

I would like to use it like the Console.WriteLi ne("My Message"); on
everywhere in my application.

Something like that :

Expand|Select|Wrap|Line Numbers
  1.  using MyApp.Tools;
  2.  //popup (if not already displayed) and display the error
  3.  LogViewer.WriteLine(MessageType.Error, "Something bad happenend");
  4.  

My application is multithreaded.

I already tried many things but I always have problems ("Windows Handle
Already Exists", form not refreshing (aka no messages loop), form not
displaying, etc.)

Sorry but I'm out of ideas. So if any one is ready to give me a very
useful help it would be really appreciated !

Here is my test class, lot's of things are commented because I made a
lot's of test.

Main questions and remarks are :

- Is the delegate way of doing ok ?
- Since this code can be called before the main Application.Run (new
MainForm) should I call an Application.Run () for this form ?
- How to cleanly prevent the component of the form not to be released
when closing the form
Ok here we go :
using System;
using System.Collecti ons;
using System.Componen tModel;
using System.Windows. Forms;
using System.IO;

namespace Tools
{
/// <summary>
/// A singleton to display message in a windows form
/// </summary>
public class LogViewer : System.Windows. Forms.Form
{
//a delegate to update the rich text box from everywhere (another
thread)
private delegate void UpdateLogRtb(Me ssageType _Type, string _Text);

public enum MessageType
{
Info,
Error,
Exception
}

/// <summary>
/// Required designer variable.
/// </summary>
///

//common to all instances

private static bool m_IsDisplayed;
static private int m_CurrentLine;

private static System.Windows. Forms.RichTextB ox richTextBox = new
RichTextBox();
private static System.Windows. Forms.Button btnSaveAs = new
System.Windows. Forms.Button();
private static System.Windows. Forms.Button btnClearLog = new
System.Windows. Forms.Button();
private static System.Threadin g.Thread m_UiThread;
static private LogViewer m_LogViewer = new LogViewer();

static LogViewer()
{
InitializeCompo nent();

m_IsDisplayed = false;
m_CurrentLine = 0;
}

/// <summary>
/// Private constructor, singleton
/// </summary>
private LogViewer()
{
//new thread ready to start
//m_UiThread = new System.Threadin g.Thread(new
System.Threadin g.ThreadStart(U IThread));
//m_UiThread.Star t();
}

//private void UIThread()
//{
// Application.Run (Instance);
//}

public static LogViewer Instance
{
get
{
return m_LogViewer;
}
}

public static void UpdateLog(Messa geType _Type, string _Text)
{
if ( Instance.Invoke Required )
{
UpdateLogRtb delUpdate = new UpdateLogRtb(Up dateLog);
Instance.BeginI nvoke(delUpdate , new object[]{_Type, _Text});
}
else
{
lock(richTextBo x)
{
if(!m_IsDisplay ed)
{
Instance.Show() ;
m_IsDisplayed = true;
}

Instance.SetCol or(_Type);
richTextBox.App endText(_Text);
}
}
}

void SetColor(Messag eType _Type)
{
switch(_Type)
{
case MessageType.Err or : richTextBox.Sel ectionColor =
System.Drawing. Color.Fuchsia;
break;
case MessageType.Exc eption : richTextBox.Sel ectionColor =
System.Drawing. Color.Red;
break;
case MessageType.Inf o : richTextBox.Sel ectionColor =
System.Drawing. Color.Blue;
break;
}
}

public static void WriteLine(Messa geType _Type ,string _Text,
object[] _Parameters)
{
IEnumerator iter = _Parameters.Get Enumerator();
Write(_Type, "[" + DateTime.Now.To ShortDateString () + " " +
DateTime.Now.To LongTimeString( ) + "] "+ _Text + " ");
while(iter.Move Next())
{
Write(_Type, iter.Current.To String());
Write(_Type, " ");
}
Write(_Type, "\n");
}

public static void WriteLine(Messa geType _Type ,string _Text, object
_Parameter)
{
Write(_Type, "[" + DateTime.Now.To ShortDateString () + " " +
DateTime.Now.To LongTimeString( ) + "] "+ _Text + " ");
Write(_Type, _Parameter.ToSt ring());
Write(_Type,"\n ");
}

public static void WriteLine(Messa geType _Type, string _Text)
{
Write(_Type, "[" + DateTime.Now.To ShortDateString () + " " +
DateTime.Now.To LongTimeString( ) + "] "+ _Text + " ");
Write(_Type,"\n ");
m_CurrentLine++ ;
}

public static void Write(MessageTy pe _Type, string _Text)
{
UpdateLog(_Type , _Text);
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
m_IsDisplayed = false;
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private static void InitializeCompo nent()
{
Instance.Suspen dLayout();
//
// richTextBox
//
richTextBox.Cur sor = System.Windows. Forms.Cursors.A rrow;
richTextBox.Loc ation = new System.Drawing. Point(0, 0);
richTextBox.Nam e = "richTextBo x";
richTextBox.Rea dOnly = true;
richTextBox.Siz e = new System.Drawing. Size(640, 250 );
richTextBox.Tab Index = 0;
richTextBox.Tex t = "";
richTextBox.Wor dWrap = false;
//
// btnSaveAs
//
btnSaveAs.Locat ion = new System.Drawing. Point(446, 254);
btnSaveAs.Name = "btnSaveAs" ;
btnSaveAs.Size = new System.Drawing. Size(89, 23);
btnSaveAs.TabIn dex = 1;
btnSaveAs.Text = "Save as...";
btnSaveAs.Click += new System.EventHan dler(btnSaveAs_ Click);
//
// btnClearLog
//
btnClearLog.Loc ation = new System.Drawing. Point(538, 254);
btnClearLog.Nam e = "btnClearLo g";
btnClearLog.Siz e = new System.Drawing. Size(100, 23);
btnClearLog.Tab Index = 2;
btnClearLog.Tex t = "Clear Log";
btnClearLog.Cli ck += new System.EventHan dler(btnClearLo g_Click);
//
// LogViewer
//
//m_LogViewer.Aut oScaleBaseSize = new System.Drawing. Size(5, 13);
Instance.Client Size = new System.Drawing. Size(640, 280);
Instance.Contro ls.Add(btnClear Log);
Instance.Contro ls.Add(btnSaveA s);
Instance.Contro ls.Add(richText Box);
Instance.FormBo rderStyle =
System.Windows. Forms.FormBorde rStyle.FixedToo lWindow;
Instance.Name = "LogViewer" ;
Instance.Text = "Events viewer";
Instance.Closin g += new
System.Componen tModel.CancelEv entHandler(LogV iewer_Closing);
Instance.Resume Layout(false);

}
#endregion
private static void LogViewer_Closi ng(object sender,
System.Componen tModel.CancelEv entArgs e)
{
Instance.Hide() ;
}

private static void btnSaveAs_Click (object sender, System.EventArg s
e)
{
SaveFileDialog saveFile = new SaveFileDialog( );
saveFile.FileNa me = "QueueMeEvents. log";
if (saveFile.ShowD ialog() != DialogResult.Ca ncel)
{
StreamWriter mySaveFile = File.CreateText (@saveFile.File Name);
mySaveFile.Auto Flush = true;
mySaveFile.Writ e(richTextBox.T ext);
mySaveFile.Clos e();
}
}

private static void btnClearLog_Cli ck(object sender, System.EventArg s
e)
{
richTextBox.Cle ar();
m_CurrentLine = 0;
}

// protected override void OnPaint(PaintEv entArgs e)
// {
// base.OnPaint (e);
// Application.DoE vents();
// Invalidate();
// System.Threadin g.Thread.Sleep( 100);
// }
}
}
Thanks !

Nov 17 '05 #2
Thanks, I will try this.

Nov 17 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
2216
by: Wavemaker | last post by:
I'm writing a class whose methods can throw exceptions under certain circumstances. These exceptions will need string messages. I was thinking about placing these messages in a resource instead of hard coding them into the class itself. The question I'm pondering is where would be the best place to load these string resources? The string...
5
1997
by: Adam | last post by:
Hi, How do i listen for windows messages in c# on compact.net? I have a window containing an instantiation of the HTML viewer control, which is a child of the main form. As the compact implementation of the form class does not have a wndproc function to override, i cannot get the messages. I cannot use a message window, as the window i am...
3
1846
by: Adam | last post by:
I've posted about this previously, but failed to receive a satisfactory response, so have included a code sample: I am trying to receive messages from an HTML viewer control in compact.net (c#), but cannot use message window as the control's parent window, as this is invisible and so the html is not viewable! I have a code sample showing...
1
3210
by: paulakeijzers | last post by:
I've got a problem with asp.net i am trying to make a menu control. and have searched the web for serveral controls but they don't work correctly. I am pretty new to asp.net building. What am i looking for. i am looking for code to make a dynamical menu with submenus The menu items are stored in a MS SQL Table and when by loading the page the...
3
1604
by: pauldepstein | last post by:
Sorry in advance if this message sounds imprecise but it's difficult to be precise when you don't really understand what's going on. I have a class called Parameters. The default constructor Parameter:Parameter() contains various values such as interest = 0.05; My intent is for the user to be able to override these defaults so I have a...
0
1199
by: emferrari | last post by:
Hi all I was going to start a new ASP.NET application yesterday. When I tryed to create it using the Microsoft Visual Studio.NET I got some messages that the application was unable to access the local server to create the ASP.NET application. After that I restarted the IIS and tryed to open the page http://localhost, without success.
1
1566
by: BK | last post by:
A little rant first... I have 15+ years experience with developing software. Why is it that everything related to creating reports in .NET seems so convoluted to me? I don't want to use Crystal. I've worked with SQL Reporting Services and I'm not impressed. I've spent time looking at the new ReportViewer control and I'm not impressed. ...
31
3152
by: JoeC | last post by:
I have read books and have ideas on how to create objects. I often create my own projects and programs. They end up getting pretty complex and long. I often use objects in my programs they are some of the most powerful programming tools I have found. Often times as my program grows so do my objects. Often times I look back and see that...
13
3692
by: mliptak | last post by:
I'm trying to implement logging in my application, so that each log message has its unique identifier, e.g. log(identifier, text) What I want to achieve is that the compiler screams if the log() with 'identifier' is also used in some other place in the code which would make the 'identifier' not unique. Is that something that can be achieved...
0
7815
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7433
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7763
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
5976
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5340
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
4949
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3458
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1891
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1020
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.