📄 eventview.cpp
字号:
// **************************************************************************
// eventview.cpp
//
// Description:
// Implements a CListView derived class. This the bottom pane of our GUI
// which shows event messages.
//
// DISCLAIMER:
// This programming example is provided "AS IS". As such Kepware, Inc.
// makes no claims to the worthiness of the code and does not warranty
// the code to be error free. It is provided freely and can be used in
// your own projects. If you do find this code useful, place a little
// marketing plug for Kepware in your code. While we would love to help
// every one who is trying to write a great OPC client application, the
// uniqueness of every project and the limited number of hours in a day
// simply prevents us from doing so. If you really find yourself in a
// bind, please contact Kepware's technical support. We will not be able
// to assist you with server related problems unless you are using KepServer
// or KepServerEx.
// **************************************************************************
#include "stdafx.h"
#include "opctestclient.h"
#include "eventview.h"
#define NUMCOLUMNS 3
#define DEFAULTCOLUMNWIDTH 120
#define GROWEVENTS 1024
#define MAXEVENTS GROWEVENTS
static LPCTSTR lpszRegSection = _T("Event View");
static LPCTSTR lpszLogErrorsOnly = _T("Log Errors Only");
// event pane update timer
#define UPDATE_EVENTPANE_EVENT 1
/////////////////////////////////////////////////////////////////////////////
// CKEventView
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE (CKEventView, CListView)
// **************************************************************************
BEGIN_MESSAGE_MAP (CKEventView, CListView)
//{{AFX_MSG_MAP(CKEventView)
ON_WM_DESTROY ()
ON_NOTIFY_REFLECT (LVN_GETDISPINFO, OnGetDispInfo)
ON_COMMAND (ID_VIEW_CLEAR, OnClear)
ON_WM_RBUTTONDOWN ()
ON_WM_TIMER ()
ON_WM_CHAR ()
ON_COMMAND (ID_VIEW_ERRORONLY, OnLogErrorsOnly)
//}}AFX_MSG_MAP
END_MESSAGE_MAP ()
// **************************************************************************
// CKEventView ()
//
// Description:
// Constructor.
//
// Parameters:
// none
//
// Returns:
// none
// **************************************************************************
CKEventView::CKEventView ()
{
// Initialize member variables:
m_cnEvents = 0;
m_cnAllocEvents = 0;
m_pEventList = NULL;
m_bAutoScroll = true;
m_bLogErrorsOnly = false;
m_cnPendingEvents = 0;
m_cnPendingAllocEvents = 0;
m_pPendingEventList = NULL;
}
// **************************************************************************
// ~CKEventView ()
//
// Description:
// Destructor.
//
// Parameters:
// none
//
// Returns:
// none
// **************************************************************************
CKEventView::~CKEventView ()
{
int i;
// Free events:
for (i = 0; i < m_cnEvents; i++)
{
delete m_pEventList [i];
m_pEventList [i] = NULL;
}
// Free event list:
if (m_pEventList)
delete [] m_pEventList;
// Free pending events:
for (i = 0; i < m_cnPendingEvents; i++)
{
delete m_pPendingEventList [i];
m_pPendingEventList [i] = NULL;
}
// Free pending event list:
if (m_pPendingEventList)
delete [] m_pPendingEventList;
}
/////////////////////////////////////////////////////////////////////////////
// CKEventView drawing
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// OnDraw ()
//
// Description:
// OnDraw event handler. This function needs to be implemented since it is
// declared as a pure virtual function in base class. We don't need to do
// anything with it in this case.
//
// Parameters:
// CDC *pDC Pointer to view's device context.
//
// Returns:
// void
// **************************************************************************
void CKEventView::OnDraw (CDC *pDC)
{
// This is how we get our document object in case we need to do something
// with this function at some point:
CDocument* pDoc = GetDocument ();
}
/////////////////////////////////////////////////////////////////////////////
// CKEventView diagnostics
/////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
void CKEventView::AssertValid () const
{
CListView::AssertValid ();
}
void CKEventView::Dump (CDumpContext &dc) const
{
CListView::Dump (dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CKEventView message handlers
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// PreCreateWindow ()
//
// Description:
// PreCreateWindow event handler.
//
// Parameters:
// CREATESTRUCT &cs Defines the initialization parameters for window.
//
// Returns:
// BOOL - TRUE if success.
// **************************************************************************
BOOL CKEventView::PreCreateWindow (CREATESTRUCT &cs)
{
// Perform default processing. Return FALSE if failure:
if (!CListView::PreCreateWindow (cs))
return (FALSE);
// Modify the window style so that list view has report format and
// column headers that do not sort rows:
cs.style |= LVS_REPORT | LVS_NOSORTHEADER;
// Return TRUE to indicate success:
return (TRUE);
}
// **************************************************************************
// Create ()
//
// Description:
// Creates the CKEventView window and attaches it to parent window.
//
// Parameters:
// LPCTSTR lpszClassName Names the Windows class.
// LPCTSTR lpszWindowName Window name.
// DWORD dwStyle Window stype.
// const RECT &rect The size and position of the window.
// CWnd *pParentWnd Parent window.
// UINT nID The ID of the child window.
// CCreateContext *pContext The create context of window.
//
// Returns:
// BOOL - TRUE if success.
// **************************************************************************
BOOL CKEventView::Create (LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID, CCreateContext *pContext)
{
// Perform default processing. Return FALSE if failure:
if (!CWnd::Create (lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext))
return (FALSE);
// Initialize the image list for the items. These are the images that
// show up to the left of each item in list. The bitmap must use a
// purple background color, RGB (255, 0, 255), so that the CImageList
// object can construct a mask. The images are 16x16 pixels. Set the
// image list background color to CLR_NONE so masked pixels will be
// transparent.
//
// Image number Use
// 0 Information event
// 1 Error event
m_cImageList.Create (IDB_EVENTIMAGES, 16, 4, RGB (255, 0, 255));
m_cImageList.SetBkColor (CLR_NONE);
GetListCtrl ().SetImageList (&m_cImageList, LVSIL_SMALL);
// Create columns. Column width used in last session were saved in
// registry. Use these widths for the present session.
CString strColumnTitle;
for (int i = 0; i < NUMCOLUMNS; i++)
{
// Create a string that will identify the registry entry for each column:
TCHAR szNum [8];
wsprintf (szNum, _T("%d"), i);
// Read the column width from the registry:
int nWidth = AfxGetApp ()->GetProfileInt (lpszRegSection, szNum, DEFAULTCOLUMNWIDTH);
// Make sure it is valid:
if (nWidth < 0)
nWidth = DEFAULTCOLUMNWIDTH;
// Load the column title string resources:
switch (i)
{
case 0: // Date
strColumnTitle.LoadString (IDS_DATE);
break;
case 1: // Time
strColumnTitle.LoadString (IDS_TIME);
break;
case 2: // Event
strColumnTitle.LoadString (IDS_EVENT);
break;
default:
ASSERT (FALSE);
break;
}
// Insert the column:
GetListCtrl ().InsertColumn (i, strColumnTitle, LVCFMT_LEFT, nWidth);
}
// Get the "log errors only" flag saved in registry last time:
m_bLogErrorsOnly = AfxGetApp ()->GetProfileInt (lpszRegSection, lpszLogErrorsOnly, FALSE) ? true : false;
// Start update view timer:
SetTimer (UPDATE_EVENTPANE_EVENT, 100, NULL);
// Return TRUE to indicate success:
return (TRUE);
}
// **************************************************************************
// OnDestroy ()
//
// Description:
// Called when window is destroyed. Take opportunity to kill timer and save
// view settings to registry.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKEventView::OnDestroy ()
{
CListView::OnDestroy ();
// Stop update view timer:
KillTimer (UPDATE_EVENTPANE_EVENT);
// Save column widths in registry so we can use them next time:
for (int i = 0; i < NUMCOLUMNS; i++)
{
// Create a string that will identify the registry entry for each
// column:
TCHAR szNum [8];
wsprintf (szNum, _T("%d"), i);
// Save the width:
AfxGetApp ()->WriteProfileInt (lpszRegSection, szNum, GetListCtrl ().GetColumnWidth (i));
}
// Save "log errors only" flag in registry too:
AfxGetApp ()->WriteProfileInt (lpszRegSection, lpszLogErrorsOnly, m_bLogErrorsOnly);
}
// **************************************************************************
// OnGetDispInfo ()
//
// Description:
// Handle notification to fill item information for display.
//
// Parameters:
// NMHDR *pNMHDR Contains information about a notification message.
// LRESULT *pResult A 32-bit value returned from a window procedure
// or callback function.
//
// Returns:
// void
// **************************************************************************
void CKEventView::OnGetDispInfo (NMHDR *pNMHDR, LRESULT *pResult)
{
// Extract pointer to list view item and associated CKEvent object
// from pNMHDER. The CKEvent object describes the event and is
// associated when a list view item is created through the item's lParam.
LV_DISPINFO *plvdi = (LV_DISPINFO *)pNMHDR;
LV_ITEM *pItem = &plvdi->item;
CKEvent *pEvent = (CKEvent *)pItem->lParam;
ASSERT (pEvent);
// The item's mask text bit will be set if we are being asked to supply
// the item's text. The subitem will indicate what column the text is
// needed for.
if (pItem->mask & LVIF_TEXT)
{
switch (pItem->iSubItem)
{
case 0: // Date
pEvent->FormatDate (pItem->pszText, pItem->cchTextMax);
break;
case 1: // Time
pEvent->FormatTime (pItem->pszText, pItem->cchTextMax);
break;
case 2: // Event
lstrcpyn (pItem->pszText, pEvent->GetMessage (), pItem->cchTextMax);
break;
default:
ASSERT (FALSE);
break;
}
}
// The item's mask image bit will be set if we are being asked to supply
// the items image (index into image list. It the event type is
// tEventInformation we will supply the first image in the image list,
// else we will supply the second (error event).
if (pItem->mask & LVIF_IMAGE)
pItem->iImage = (pEvent->GetType () == tEventInformation) ? 0 : 1;
}
// **************************************************************************
// OnClear ()
//
// Description:
// ID_VIEW_CLEAR event handler. Delete all items from list view and redraw.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKEventView::OnClear ()
{
// Create a CSafeLock to make this object thread safe. Our critical
// section gets locked here, and will automatically be unlocked when the
// CSafeLock goes out of scope.
CSafeLock sf (&m_csLog);
// Postpone any redrawing until we are done. This will make things
// go faster and look smoother.
SetRedraw (false);
// Delete all items in list control:
GetListCtrl ().DeleteAllItems ();
// Delete any CKEvent objects associated with deleted list control items:
for (int i = 0; i < m_cnEvents; i++)
{
delete m_pEventList [i];
m_pEventList [i] = NULL;
}
// Reset event count to zero:
m_cnEvents = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -