출처: https://mail-archives.apache.org/mod_mbox/logging-log4net-user/200804.mbox/%3C658979.41804.qm@web80002.mail.sp1.yahoo.com%3E
using System;
using System.Windows.Forms;
using System.Drawing;
using log4net;
using log4net.Core;
using log4net.Appender;
using log4net.Util;
namespace log4net.Appender
{
//.. <summary>
//.. Appends logging events to a RichTextBox
//.. </summary>
//.. <remarks>
//.. <para>
//.. RichTextBoxAppender appends log events to a specified RichTextBox control.
//.. It also allows the color, font and style of a specific type of message to be set.
//.. </para>
//.. <para>
//.. When configuring the rich text box appender, mapping should be
//.. specified to map a logging level to a text style. For example:
//.. </para>
//.. <code lang="XML" escaped="true">
//.. <mapping>
//.. <level value="DEBUG" />
//.. <textColorName value="DarkGreen" />
//.. </mapping>
//.. <mapping>
//.. <level value="INFO" />
//.. <textColorName value="ControlText" />
//.. </mapping>
//.. <mapping>
//.. <level value="WARN" />
//.. <textColorName value="Blue" />
//.. </mapping>
//.. <mapping>
//.. <level value="ERROR" />
//.. <textColorName value="Red" />
//.. <bold value="true" />
//.. <pointSize value="10" />
//.. </mapping>
//.. <mapping>
//.. <level value="FATAL" />
//.. <textColorName value="Black" />
//.. <backColorName value="Red" />
//.. <bold value="true" />
//.. <pointSize value="12" />
//.. <fontFamilyName value="Lucida Console" />
//.. </mapping>
//.. </code>
//.. <para>
//.. The Level is the standard log4net logging level. TextColorName and BackColorName should match
//.. a value of the System.Drawing.KnownColor enumeration. Bold and/or Italic may be specified, using
//.. <code>true</code> or <code>false</code>. FontFamilyName should match a font available on the client,
//.. but if it's not found, the control's font will be used.
//.. </para>
//.. <para>
//.. The RichTextBox property has to be set in code. The most straightforward way to accomplish
//.. this is in the Load event of the Form containing the control.
//.. <code lang="C#">
//.. private void MainForm_Load(object sender, EventArgs e)
//.. {
//.. log4net.Appender.RichTextBoxAppender.SetRichTextBox(logRichTextBox, "MainFormRichTextAppender");
//.. }
//.. </code>
//.. </para>
//.. </remarks>
//.. <author>Stephanie Giovannini</author>
public class RichTextBoxAppender : AppenderSkeleton
{
//.. <summary>
//.. Initializes a new instance of the <see cref="RichTextBoxAppender" /> class.
//.. </summary>
//.. <remarks>
//.. The instance of the <see cref="RichTextBoxAppender" /> class can be assigned
//.. a <see cref="System.Windows.Forms.RichTextBox" /> to write to.
//.. </remarks>
public RichTextBoxAppender() : base()
{
}
//.. <summary>
//.. Reference to RichTextBox that displays logging events
//.. </summary>
//.. <remarks>
//.. <para>
//.. This property is a reference to the RichTextBox control
//.. that will display logging events.
//.. </para>
//.. <para>If RichTextBox is null, no logging events will be displayed.</para>
//.. <para>RichTextBox will be set to null when the control's containing
//.. Form is closed.</para>
//.. </remarks>
public RichTextBox RichTextBox
{
set
{
if (!object.ReferenceEquals(value, _richtextBox))
{
if (_containerForm != null)
{
_containerForm.FormClosed -= new FormClosedEventHandler(containerForm_FormClosed);
_containerForm = null;
}
if (value != null)
{
value.ReadOnly = true;
value.HideSelection = false;
_containerForm = value.FindForm();
_containerForm.FormClosed += new FormClosedEventHandler(containerForm_FormClosed);
}
_richtextBox = value;
}
}
get
{
return _richtextBox;
}
}
//.. <summary>
//.. Add a mapping of level to text style - done by the config file
//.. </summary>
//.. <param name="mapping">The mapping to add</param>
//.. <remarks>
//.. <para>
//.. Add a <see cref="LevelTextStyle"/> mapping to this appender.
//.. Each mapping defines the text style for a level.
//.. </para>
//.. </remarks>
public void AddMapping(LevelTextStyle mapping)
{
_levelMapping.Add(mapping);
}
//.. <summary>
//.. Maximum number of characters in control before it is cleared
//.. </summary>
public int MaxBufferLength
{
get { return _maxTextLength; }
set
{
if (value > 0)
{
_maxTextLength = value;
}
}
}
//.. <summary>
//.. Initialize the options for this appender
//.. </summary>
//.. <remarks>
//.. <para>
//.. Initialize the level to text style mappings set on this appender.
//.. </para>
//.. </remarks>
public override void ActivateOptions()
{
base.ActivateOptions();
_levelMapping.ActivateOptions();
}
//.. <summary>
//.. This method is called by the <see cref="AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
//.. </summary>
//.. <param name="loggingEvent">The event to log.</param>
//.. <remarks>
//.. <para>
//.. Writes the event to the RichTextBox control, if set.
//.. </para>
//.. <para>
//.. The format of the output will depend on the appender's layout.
//.. </para>
//.. <para>
//.. This method can be called from any thread.
//.. </para>
//.. </remarks>
protected override void Append(LoggingEvent LoggingEvent)
{
if (_richtextBox != null)
{
if (_richtextBox.InvokeRequired)
{
_richtextBox.Invoke(
new UpdateControlDelegate(UpdateControl),
new object[] { LoggingEvent });
}
else
{
UpdateControl(LoggingEvent);
}
}
}
//.. <summary>
//.. Delegate used to invoke UpdateControl
//.. </summary>
//.. <param name="loggingEvent">The event to log</param>
//.. <remarks>This delegate is used when UpdateControl must be
//.. called from a thread other than the thread that created the
//.. RichTextBox control.</remarks>
private delegate void UpdateControlDelegate(LoggingEvent loggingEvent);
//.. <summary>
//.. Add logging event to configured control
//.. </summary>
//.. <param name="loggingEvent">The event to log</param>
private void UpdateControl(LoggingEvent loggingEvent)
{
// There may be performance issues if the buffer gets too long
// So periodically clear the buffer
if (_richtextBox.TextLength > _maxTextLength)
{
_richtextBox.Clear();
_richtextBox.AppendText(string.Format("(earlier messages cleared because log length exceeded maximum of {0})\n\n", _maxTextLength));
}
// look for a style mapping
LevelTextStyle selectedStyle = _levelMapping.Lookup(loggingEvent.Level) as LevelTextStyle;
if (selectedStyle != null)
{
// set the colors of the text about to be appended
_richtextBox.SelectionBackColor = selectedStyle.BackColor;
_richtextBox.SelectionColor = selectedStyle.TextColor;
// alter selection font as much as necessary
// missing settings are replaced by the font settings on the control
if (selectedStyle.Font != null)
{
// set Font Family, size and styles
_richtextBox.SelectionFont = selectedStyle.Font;
}
else if (selectedStyle.PointSize > 0 && _richtextBox.Font.SizeInPoints != selectedStyle.PointSize)
{
// use control's font family, set size and styles
float size = selectedStyle.PointSize > 0.0f ? selectedStyle.PointSize : _richtextBox.Font.SizeInPoints;
_richtextBox.SelectionFont = new Font(_richtextBox.Font.FontFamily.Name, size, selectedStyle.FontStyle);
}
else if (_richtextBox.Font.Style != selectedStyle.FontStyle)
{
// use control's font family and size, set styles
_richtextBox.SelectionFont = new Font(_richtextBox.Font, selectedStyle.FontStyle);
}
}
_richtextBox.AppendText(RenderLoggingEvent(loggingEvent));
}
//.. <summary>
//.. Remove reference to RichTextBox when container form is closed
//.. </summary>
//.. <param name="sender"></param>
//.. <param name="e"></param>
private void containerForm_FormClosed(object sender, FormClosedEventArgs e)
{
RichTextBox = null;
}
//.. <summary>
//.. Remove references to container form
//.. </summary>
protected override void OnClose()
{
base.OnClose();
if (_containerForm != null)
{
_containerForm.FormClosed -= new FormClosedEventHandler(containerForm_FormClosed);
_containerForm = null;
}
}
//.. <summary>
//.. This appender requires a <see cref="Layout"/> to be set.
//.. </summary>
//.. <value><c>true</c></value>
//.. <remarks>
//.. <para>
//.. This appender requires a <see cref="Layout"/> to be set.
//.. </para>
//.. </remarks>
protected override bool RequiresLayout
{
get
{
return true;
}
}
//.. <summary>
//.. Assign a RichTextBox to a RichTextBoxAppender
//.. </summary>
//.. <param name="richTextBox">Reference to RichTextBox control that will display logging events</param>
//.. <param name="appenderName">Name of RichTextBoxAppender (case-sensitive)</param>
//.. <returns>True if a RichTextBoxAppender named <code>appenderName</code> was found</returns>
//.. <remarks>
//.. <para>This method sets the RichTextBox property of the RichTextBoxAppender
//.. in the default repository with <code>Name == appenderName</code>.</para>
//.. </remarks>
//.. <example>
//.. <code lang="C#">
//.. private void MainForm_Load(object sender, EventArgs e)
//.. {
//.. log4net.Appender.RichTextBoxAppender.SetRichTextBox(logRichTextBox, "MainFormRichTextAppender");
//.. }
//.. </code>
//.. </example>
public static bool SetRichTextBox(RichTextBox richTextBox, string appenderName)
{
if (appenderName == null) return false;
IAppender[] appenders = LogManager.GetRepository().GetAppenders();
foreach (IAppender appender in appenders)
{
if (appender.Name == appenderName)
{
if (appender is RichTextBoxAppender)
{
((RichTextBoxAppender)appender).RichTextBox = richTextBox;
return true;
}
break;
}
}
return false;
}
//.. <summary>
//.. Reference to RichTextBox control that will display log events
//.. </summary>
private RichTextBox _richtextBox = null;
//.. <summary>
//.. Reference to Form that contains <code>_richtextBox</code>
//.. </summary>
private Form _containerForm = null;
//.. <summary>
//.. Mapping from level object to text style
//.. </summary>
private LevelMapping _levelMapping = new LevelMapping();
//.. <summary>
//.. Maximum length of RichTextBox buffer
//.. </summary>
private int _maxTextLength = 100000;
//.. <summary>
//.. A class to act as a mapping between the level that a logging call is made at and
//.. the text style in which it should be displayed.
//.. </summary>
//.. <remarks>
//.. <para>
//.. Defines the mapping between a level and the text style in which it should be displayed..
//.. </para>
//.. </remarks>
public class LevelTextStyle : LevelMappingEntry
{
private string _textColorName = "ControlText";
private string _backColorName = "ControlLight";
private Color _textColor;
private Color _backColor;
private FontStyle _fontStyle = FontStyle.Regular;
private float _pointSize = 0.0f;
private bool _bold = false;
private bool _italic = false;
private string _fontFamilyName = null;
private Font _font = null;
//.. <summary>
//.. Name of a KnownColor used for text
//.. </summary>
public string TextColorName
{
get { return _textColorName; }
set { _textColorName = value; }
}
//.. <summary>
//.. Name of a KnownColor used as text background
//.. </summary>
public string BackColorName
{
get { return _backColorName; }
set { _backColorName = value; }
}
//.. <summary>
//.. Name of a font family
//.. </summary>
public string FontFamilyName
{
get { return _fontFamilyName; }
set { _fontFamilyName = value; }
}
//.. <summary>
//.. Display level in bold style
//.. </summary>
public bool Bold
{
get { return _bold; }
set { _bold = value; }
}
//.. <summary>
//.. Display level in italic style
//.. </summary>
public bool Italic
{
get { return _italic; }
set { _italic = value; }
}
//.. <summary>
//.. Font size of level, 0 to use default
//.. </summary>
public float PointSize
{
get { return _pointSize; }
set { _pointSize = value; }
}
//.. <summary>
//.. Initialize the options for the object
//.. </summary>
//.. <remarks>Parse the properties</remarks>
public override void ActivateOptions()
{
base.ActivateOptions();
_textColor = Color.FromName(_textColorName);
_backColor = Color.FromName(_backColorName);
if (_bold) _fontStyle |= FontStyle.Bold;
if (_italic) _fontStyle |= FontStyle.Italic;
if (_fontFamilyName != null)
{
float size = _pointSize > 0.0f ? _pointSize : 8.25f;
try
{
_font = new Font(_fontFamilyName, size, _fontStyle);
}
catch (Exception)
{
_font = null;
}
}
}
internal Color TextColor
{
get { return _textColor; }
}
internal Color BackColor
{
get { return _backColor; }
}
internal FontStyle FontStyle
{
get { return _fontStyle; }
}
internal Font Font
{
get { return _font; }
}
}
}
}
'언어 > C#' 카테고리의 다른 글
Image to Byte Array C# (0) | 2018.03.26 |
---|---|
NLog.Windows.Forms (0) | 2018.03.22 |
log4net TextBox Appender (0) | 2018.03.20 |
Log4Net ScrollingTextBox (0) | 2018.03.20 |
DevApps - Podcast 03 - Comment tracer avec NLog ? (0) | 2018.03.20 |