473,385 Members | 1,630 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

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.WriteLine("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.Collections;
using System.ComponentModel;
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(MessageType _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.RichTextBox 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.Threading.Thread m_UiThread;
static private LogViewer m_LogViewer = new LogViewer();

static LogViewer()
{
InitializeComponent();

m_IsDisplayed = false;
m_CurrentLine = 0;
}

/// <summary>
/// Private constructor, singleton
/// </summary>
private LogViewer()
{
//new thread ready to start
//m_UiThread = new System.Threading.Thread(new
System.Threading.ThreadStart(UIThread));
//m_UiThread.Start();
}

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

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

public static void UpdateLog(MessageType _Type, string _Text)
{
if ( Instance.InvokeRequired )
{
UpdateLogRtb delUpdate = new UpdateLogRtb(UpdateLog);
Instance.BeginInvoke(delUpdate, new object[]{_Type, _Text});
}
else
{
lock(richTextBox)
{
if(!m_IsDisplayed)
{
Instance.Show();
m_IsDisplayed = true;
}

Instance.SetColor(_Type);
richTextBox.AppendText(_Text);
}
}
}

void SetColor(MessageType _Type)
{
switch(_Type)
{
case MessageType.Error : richTextBox.SelectionColor =
System.Drawing.Color.Fuchsia;
break;
case MessageType.Exception : richTextBox.SelectionColor =
System.Drawing.Color.Red;
break;
case MessageType.Info : richTextBox.SelectionColor =
System.Drawing.Color.Blue;
break;
}
}

public static void WriteLine(MessageType _Type ,string _Text,
object[] _Parameters)
{
IEnumerator iter = _Parameters.GetEnumerator();
Write(_Type, "[" + DateTime.Now.ToShortDateString() + " " +
DateTime.Now.ToLongTimeString() + "] "+ _Text + " ");
while(iter.MoveNext())
{
Write(_Type, iter.Current.ToString());
Write(_Type, " ");
}
Write(_Type, "\n");
}

public static void WriteLine(MessageType _Type ,string _Text, object
_Parameter)
{
Write(_Type, "[" + DateTime.Now.ToShortDateString() + " " +
DateTime.Now.ToLongTimeString() + "] "+ _Text + " ");
Write(_Type, _Parameter.ToString());
Write(_Type,"\n");
}

public static void WriteLine(MessageType _Type, string _Text)
{
Write(_Type, "[" + DateTime.Now.ToShortDateString() + " " +
DateTime.Now.ToLongTimeString() + "] "+ _Text + " ");
Write(_Type,"\n");
m_CurrentLine++;
}

public static void Write(MessageType _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 InitializeComponent()
{
Instance.SuspendLayout();
//
// richTextBox
//
richTextBox.Cursor = System.Windows.Forms.Cursors.Arrow;
richTextBox.Location = new System.Drawing.Point(0, 0);
richTextBox.Name = "richTextBox";
richTextBox.ReadOnly = true;
richTextBox.Size = new System.Drawing.Size(640, 250 );
richTextBox.TabIndex = 0;
richTextBox.Text = "";
richTextBox.WordWrap = false;
//
// btnSaveAs
//
btnSaveAs.Location = new System.Drawing.Point(446, 254);
btnSaveAs.Name = "btnSaveAs";
btnSaveAs.Size = new System.Drawing.Size(89, 23);
btnSaveAs.TabIndex = 1;
btnSaveAs.Text = "Save as...";
btnSaveAs.Click += new System.EventHandler(btnSaveAs_Click);
//
// btnClearLog
//
btnClearLog.Location = new System.Drawing.Point(538, 254);
btnClearLog.Name = "btnClearLog";
btnClearLog.Size = new System.Drawing.Size(100, 23);
btnClearLog.TabIndex = 2;
btnClearLog.Text = "Clear Log";
btnClearLog.Click += new System.EventHandler(btnClearLog_Click);
//
// LogViewer
//
//m_LogViewer.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
Instance.ClientSize = new System.Drawing.Size(640, 280);
Instance.Controls.Add(btnClearLog);
Instance.Controls.Add(btnSaveAs);
Instance.Controls.Add(richTextBox);
Instance.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedToolWind ow;
Instance.Name = "LogViewer";
Instance.Text = "Events viewer";
Instance.Closing += new
System.ComponentModel.CancelEventHandler(LogViewer _Closing);
Instance.ResumeLayout(false);

}
#endregion
private static void LogViewer_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
Instance.Hide();
}

private static void btnSaveAs_Click(object sender, System.EventArgs
e)
{
SaveFileDialog saveFile = new SaveFileDialog();
saveFile.FileName = "QueueMeEvents.log";
if (saveFile.ShowDialog() != DialogResult.Cancel)
{
StreamWriter mySaveFile = File.CreateText(@saveFile.FileName);
mySaveFile.AutoFlush = true;
mySaveFile.Write(richTextBox.Text);
mySaveFile.Close();
}
}

private static void btnClearLog_Click(object sender, System.EventArgs
e)
{
richTextBox.Clear();
m_CurrentLine = 0;
}

// protected override void OnPaint(PaintEventArgs e)
// {
// base.OnPaint (e);
// Application.DoEvents();
// Invalidate();
// System.Threading.Thread.Sleep(100);
// }
}
}
Thanks !

Nov 17 '05 #1
2 2629
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.com

<su*******@gmail.com> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.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.WriteLine("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.Collections;
using System.ComponentModel;
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(MessageType _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.RichTextBox 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.Threading.Thread m_UiThread;
static private LogViewer m_LogViewer = new LogViewer();

static LogViewer()
{
InitializeComponent();

m_IsDisplayed = false;
m_CurrentLine = 0;
}

/// <summary>
/// Private constructor, singleton
/// </summary>
private LogViewer()
{
//new thread ready to start
//m_UiThread = new System.Threading.Thread(new
System.Threading.ThreadStart(UIThread));
//m_UiThread.Start();
}

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

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

public static void UpdateLog(MessageType _Type, string _Text)
{
if ( Instance.InvokeRequired )
{
UpdateLogRtb delUpdate = new UpdateLogRtb(UpdateLog);
Instance.BeginInvoke(delUpdate, new object[]{_Type, _Text});
}
else
{
lock(richTextBox)
{
if(!m_IsDisplayed)
{
Instance.Show();
m_IsDisplayed = true;
}

Instance.SetColor(_Type);
richTextBox.AppendText(_Text);
}
}
}

void SetColor(MessageType _Type)
{
switch(_Type)
{
case MessageType.Error : richTextBox.SelectionColor =
System.Drawing.Color.Fuchsia;
break;
case MessageType.Exception : richTextBox.SelectionColor =
System.Drawing.Color.Red;
break;
case MessageType.Info : richTextBox.SelectionColor =
System.Drawing.Color.Blue;
break;
}
}

public static void WriteLine(MessageType _Type ,string _Text,
object[] _Parameters)
{
IEnumerator iter = _Parameters.GetEnumerator();
Write(_Type, "[" + DateTime.Now.ToShortDateString() + " " +
DateTime.Now.ToLongTimeString() + "] "+ _Text + " ");
while(iter.MoveNext())
{
Write(_Type, iter.Current.ToString());
Write(_Type, " ");
}
Write(_Type, "\n");
}

public static void WriteLine(MessageType _Type ,string _Text, object
_Parameter)
{
Write(_Type, "[" + DateTime.Now.ToShortDateString() + " " +
DateTime.Now.ToLongTimeString() + "] "+ _Text + " ");
Write(_Type, _Parameter.ToString());
Write(_Type,"\n");
}

public static void WriteLine(MessageType _Type, string _Text)
{
Write(_Type, "[" + DateTime.Now.ToShortDateString() + " " +
DateTime.Now.ToLongTimeString() + "] "+ _Text + " ");
Write(_Type,"\n");
m_CurrentLine++;
}

public static void Write(MessageType _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 InitializeComponent()
{
Instance.SuspendLayout();
//
// richTextBox
//
richTextBox.Cursor = System.Windows.Forms.Cursors.Arrow;
richTextBox.Location = new System.Drawing.Point(0, 0);
richTextBox.Name = "richTextBox";
richTextBox.ReadOnly = true;
richTextBox.Size = new System.Drawing.Size(640, 250 );
richTextBox.TabIndex = 0;
richTextBox.Text = "";
richTextBox.WordWrap = false;
//
// btnSaveAs
//
btnSaveAs.Location = new System.Drawing.Point(446, 254);
btnSaveAs.Name = "btnSaveAs";
btnSaveAs.Size = new System.Drawing.Size(89, 23);
btnSaveAs.TabIndex = 1;
btnSaveAs.Text = "Save as...";
btnSaveAs.Click += new System.EventHandler(btnSaveAs_Click);
//
// btnClearLog
//
btnClearLog.Location = new System.Drawing.Point(538, 254);
btnClearLog.Name = "btnClearLog";
btnClearLog.Size = new System.Drawing.Size(100, 23);
btnClearLog.TabIndex = 2;
btnClearLog.Text = "Clear Log";
btnClearLog.Click += new System.EventHandler(btnClearLog_Click);
//
// LogViewer
//
//m_LogViewer.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
Instance.ClientSize = new System.Drawing.Size(640, 280);
Instance.Controls.Add(btnClearLog);
Instance.Controls.Add(btnSaveAs);
Instance.Controls.Add(richTextBox);
Instance.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedToolWind ow;
Instance.Name = "LogViewer";
Instance.Text = "Events viewer";
Instance.Closing += new
System.ComponentModel.CancelEventHandler(LogViewer _Closing);
Instance.ResumeLayout(false);

}
#endregion
private static void LogViewer_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
Instance.Hide();
}

private static void btnSaveAs_Click(object sender, System.EventArgs
e)
{
SaveFileDialog saveFile = new SaveFileDialog();
saveFile.FileName = "QueueMeEvents.log";
if (saveFile.ShowDialog() != DialogResult.Cancel)
{
StreamWriter mySaveFile = File.CreateText(@saveFile.FileName);
mySaveFile.AutoFlush = true;
mySaveFile.Write(richTextBox.Text);
mySaveFile.Close();
}
}

private static void btnClearLog_Click(object sender, System.EventArgs
e)
{
richTextBox.Clear();
m_CurrentLine = 0;
}

// protected override void OnPaint(PaintEventArgs e)
// {
// base.OnPaint (e);
// Application.DoEvents();
// Invalidate();
// System.Threading.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
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...
5
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...
3
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#),...
1
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...
3
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...
0
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...
1
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...
31
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...
13
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()...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

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.