Introduction
CXHtmlLog
provides a flexible, MFC-free way to
format selected fields from a text log file into HTML that can be displayed in
any browser. The requirements to use
CXHtmlLog
are simple: the log
file that serves as input to
CXHtmlLog
must be a text file, and
there must be delimiters between each of the fields in the log records. When
these two conditions are met, it is easy to set up the
CXHtmlLog
column properties with headers, color coding, and column order. It is also
possible to map input fields to columns in any order you wish - which means that
the output column order is independent of the order of the fields in the input
log file. Finally, by means of a callback function, it is possible to override
any display parameter - including what data is displayed - for each column
separately.
CXHtmlLog: What It Does
An example may be the best way to illustrate
what
CXHtmlLog
does. The following screenshot shows sample output
of the demo app:
This screenshot was generated from the following input lines:
0, 2389.3, C:\\apps\\Shuttle.exe, C:\\src\\Shuttle.cpp, 342, Captain!
A shuttle craft is approaching.
3, 2403.7, C:\\apps\\Battle.exe, C:\\src\\Battle.cpp, 474, Captain!
We have been hit. Shields are at 80%.
2, 2581.4, C:\\apps\\Crystalline.exe, C:\\src\\Crystalline.cpp, 1870,
Captain! The Crystalline entity is approaching the ship.
1, 2641.1, C:\\apps\\Dead.exe, C:\\src\\Dead.cpp, 922, Jim! For God's sake
man! He's dead!
4, 2890.1, C:\\apps\\WarpCore.exe, C:\\src\\WarpCore.cpp, 556, Captain!
The warp core containment field has failed. Warp breach imminent.
The
screenshot shows that the first field (the priority) in the input file is the
second column in the HTML output, and the second field (the stardate) is the
first column in the output. This happens because of the field mapping that is
possible with
CXHtmlLog
. Here is the code:
CXHtmlLog log;
XHTMLLOG_COLUMN_PROPERTIES props;
props.lpPropFunc = PropCallback;
props.nField = 1;
_tcscpy(props.szHeader, _T("Stardate"));
log.SetColumnProperties(0, &props);
props.nField = 0;
_tcscpy(props.szHeader, _T("Priority"));
log.SetColumnProperties(1, &props);
Also note that the fourth and
fifth input fields have been combined into the fourth output column (the
"Module" column). This happens because a callback function has been specified,
which provides an opportunity to customize the data that is displayed.
BOOL PropCallback(int nColumn,
void * props,
LPTSTR * lppszValueArray,
BOOL bHeader)
{
XHTMLLOG_COLUMN_PROPERTIES * pprops =
(XHTMLLOG_COLUMN_PROPERTIES *) props;
if (nColumn == 3 && !bHeader)
{
_stprintf(pprops->szData, _T("%s(%s)"),
lppszValueArray[pprops->nField],
lppszValueArray[4]);
}
The callback function allows the appearance of the columns (e.g.,
colors) to be customized. In the demo app, the color of the message column (the
bottom row of each displayed log entry) is set according to the value of the
priority field:
if (nColumn == 4)
{
COLORREF rgbBackground = RGB(0,0,0);
int nPriority = _ttoi(lppszValueArray[0]);
switch (nPriority)
{
case 0: rgbBackground = green; break;
case 1: rgbBackground = blue; break;
case 2: rgbBackground = yellow; break;
case 3: rgbBackground = orange; break;
case 4: rgbBackground = red; break;
}
pprops->rgbDataBackground = rgbBackground;
pprops->rgbDataText = RGB(255,255,255);
if (nPriority == 2 || nPriority == 3)
pprops->rgbDataText = RGB(0,0,0);
}
CXHtmlLog Functions
GenerateHtml()
- Generate HTML output from log file
CXHtmlLog
Callback Function (Implemented by caller)
SetBodyColors()
- Set colors for BODY tag.
SetColumnProperties()
- Set properties for column
nColumn.
SetInputFieldDelimiter()
- Set delimiter string for input
fields.
SetInputRecordDelimiter()
- Set delimiter string for
records.
SetTitle
- Set title string for HTML TITLE tag.
SetTopHeader
- Set top header string.
SetTopHeaderColor
- Set text color for top header.
SetTopHeaderFontFace
- Set top header font face.
SetTopHeaderFontSize
- Set top header font size.
How To Use
To integrate CXHtmlLog
class into your app, you first need to
add following files to your project:
- XHtmlLog.cpp
- XHtmlLog.h
- XFile.cpp
- XFile.h
- XTrace.h
The XTrace.h file is optional, and can be excluded. If you exclude
it, comment out #include "XTrace.h"
line from XFile.cpp and
XHtmlLog.cpp, and uncomment #define TRACE ((void)0)
and
#define TRACEERROR ((void)0)
lines.
If you include CXHtmlLog
in project that uses precompiled
headers, you must change C/C++ Precompiled Headers settings to Not
using precompiled headers for XHtmlLog.cpp and XFile.cpp.
Next, include the header file XHtmlLog.h in appropriate project
files. Now you are ready to start using CXHtmlLog
. There are many
notes concerning usage of various functions in XHtmlLog.cpp. Please
read all function header for each function you wish to use.
Then construct CXHtmlLog
object and define the columns:
CXHtmlLog log(10);
log.SetTitle(_T("Captain's Log"));
log.SetTopHeader(_T("Captain's Log"));
log.SetTopHeaderColor(RGB(0,0,255));
log.SetBodyColors(RGB(0,0,0), RGB(255,250,240));
XHTMLLOG_COLUMN_PROPERTIES props;
props.lpPropFunc = PropCallback;
props.rgbDataBackground = RGB(255,250,240);
props.nField = 1;
props.nWidth = 15;
_tcscpy(props.szHeader, _T("Stardate"));
log.SetColumnProperties(0, &props);
props.nField = 0;
props.nWidth = 15;
_tcscpy(props.szHeader, _T("Priority"));
log.SetColumnProperties(1, &props);
props.nField = 2;
props.nWidth = 30;
_tcscpy(props.szHeader, _T("Component"));
log.SetColumnProperties(2, &props);
props.nField = 3;
props.nWidth = 40;
_tcscpy(props.szHeader, _T("Module"));
log.SetColumnProperties(3, &props);
props.nField = 5;
props.bMessage = TRUE;
_tcscpy(props.szHeader, _T("message"));
log.SetColumnProperties(4, &props);
And finally generate the HTML:
log.GenerateHtml(_T("log.txt"), _T("log.html"));
Known Limitations
- By design,
CXHtmlLog
expects one of the output columns to be
designated as the "message" column, which contains the text of the log entry -
i.e., the primary information being conveyed by the log entry.
- The fields of the input file records must be delimited in a deterministic
manner - i.e., if fields are delimited by tabs, then a tab character must not
appear within a field.
- The records of the input file must have a fixed delimiter - the same
delimiter must be used for all records.
Frequently Asked Questions
- Can I use XHtmlLog in non-MFC apps?
Yes. It has been implemented
to compile with any Win32 program.
- When I try to include XHtmlLog.cpp in my MFC project, I get the compiler
error
XHtmlLog.cpp(754) : fatal error C1010: unexpected end
of file while looking for precompiled header directive
. How
can I fix this?
When using XHtmlLog in project that uses precompiled
headers, you must change C/C++ Precompiled Headers settings to Not
using precompiled headers for XHtmlLog.cpp and XFile.cpp. Be
sure to do this for All Configurations.
- When I try to build the demo app, I get the linker error
LINK : fatal error LNK1104: cannot open file "mfc42u.lib"
Error executing link.exe
. How can I fix this?
The default
installation options of Visual C++ v6.0 don't install the Unicode libraries of
MFC, so you might get an error that mfc42u.lib or mfc42ud.lib
cannot be found. You can fix this either by installing the Unicode libs from the
VC++ install CD, or by going to Build | Set Active Configuration and
selecting one of the non-Unicode configurations.
You can configure the Visual Studio toolbars to include the Select Active
Configuration combobox. This lets you see at a glance what configuration you
are working with.
- Can we use XHtmlLog in our (shareware/commercial) app?
Yes, you
can use XHtmlLog
without charge or license fee. It would be nice to
acknowledge my Copyright in your About box or splash screen, but this is up to
you.
Acknowledgments
Revision History
Version 1.0 - 2003 May 16
Usage
This software is released into the public domain. You are free to use it in
any way you like. If you modify it or extend it, please to consider posting new
code here for everyone to share. This software is provided "as is" with no
expressed or implied warranty. I accept no liability for any damage or loss of
business that this software may cause.