📄 eventview.cpp
字号:
// Now allow view to redraw:
SetRedraw (true);
}
// **************************************************************************
// OnLogErrorsOnly ()
//
// Description:
// ID_VIEW_ERRORONLY event handler. Toggles the log errors only flag.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKEventView::OnLogErrorsOnly ()
{
// 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);
// Toggle the log errors only flag:
m_bLogErrorsOnly = m_bLogErrorsOnly ? false : true;
}
// **************************************************************************
// OnRButtonDown ()
//
// Description:
// Right mouse button down event handler. Used to display context menu.
//
// Parameters:
// UINT nFlags Flags
// CPoint point Mouse cursor location.
//
// Returns:
// void
// **************************************************************************
void CKEventView::OnRButtonDown (UINT nFlags, CPoint point)
{
CMenu cMenu;
// Convert point to screen coordinates:
ClientToScreen (&point);
// Create a popup menu:
if (cMenu.CreatePopupMenu ())
{
// Get pointer to our main menu. We will use it to get text for
// the popup menu:
CMenu *pMainMenu = AfxGetMainWnd ()->GetMenu ();
// Declare a container for menu text:
CString strMenuText;
// Define flags to so that popup menu items will get text from pointer
// to null terminated string.
int nFlags = MF_ENABLED | MF_STRING;
// If we have event, then add a "clear view" menu item:
if (m_cnEvents)
{
pMainMenu->GetMenuString (ID_VIEW_CLEAR, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_VIEW_CLEAR, strMenuText);
}
// Add a "log errors only" menu item:
pMainMenu->GetMenuString (ID_VIEW_ERRORONLY, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_VIEW_ERRORONLY, strMenuText);
// Place the popup menu at the point of right mouse click, and route
// all WM_COMMAND messages though the frame:
cMenu.TrackPopupMenu (TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd ());
}
}
/////////////////////////////////////////////////////////////////////////////
// CKEventView log message handlers
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// LogMsg ()
//
// Description:
// Log a message to the event log. Creates an CKEvent object and adds it to
// the pending event list. Event will be taken from pending event list
// and placed in list control in OnTimer().
//
// Parameters:
// EVENTTYPE eType Event type (tEventError, tEventWarning, etc)
// LPCTSTR lpszMessage Pointer to message string.
//
// Returns:
// void
// **************************************************************************
void CKEventView::LogMsg (EVENTTYPE eType, LPCTSTR lpszMessage)
{
// 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);
// No need to add the event if it is not an error and we are
// logging errors only:
if (m_bLogErrorsOnly && eType != tEventError)
return;
// Create an event and add to pending event list. Wrap with exception
// handler in case of memory allocation propbles (not too likely).
try
{
// Instantiate a new CKEvent object to contain information about
// this event:
CKEvent *pEvent = new CKEvent (lpszMessage, eType);
// Check for room in the pending events list. If we are out of
// room, allocate larger block of memory and transfer existing
// events to it.
if (m_cnPendingEvents == m_cnPendingAllocEvents)
{
// Create a pointer to a new pending events array:
CKEvent **p;
// Allocate memory for the new array/list large enough for
// existing events plus room for new ones. (This is an array
// of pointers to CKEvent objects.)
p = new CKEvent * [m_cnPendingAllocEvents + GROWEVENTS];
// Transfer existing events to the new memory and free memory
// used by old list:
if (m_cnPendingEvents)
{
memcpy (p, m_pPendingEventList, m_cnPendingEvents * sizeof (m_pPendingEventList[0]));
delete [] m_pPendingEventList;
}
// Reset pointer to pending event list to give new memory area:
m_pPendingEventList = p;
// Increment size of memory allocated for new pending event list:
m_cnPendingAllocEvents += GROWEVENTS;
}
// Add the item to the event list and increment the pending events
// counter:
m_pPendingEventList [m_cnPendingEvents++] = pEvent;
}
catch (...)
{
TRACE (_T("OTC: Exception handler invoked adding an event to the log\n"));
}
}
// **************************************************************************
// AddEvent ()
//
// Description:
// Places an event in list control
//
// Parameters:
// CKEvent *pEvent Pointer to event object
//
// Returns:
// bool - true if success.
// **************************************************************************
bool CKEventView::AddEvent (CKEvent *pEvent)
{
// Create a list view item structure:
LV_ITEM lvi;
// Get reference to list view's list control:
CListCtrl &cList = GetListCtrl ();
// Fill the list view item structure:
// Item props we will fill (text, parameter, image):
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
// No sub items:
lvi.iSubItem = 0;
// Defer to OnGetDispInfo () to get image:
lvi.iImage = I_IMAGECALLBACK;
// Defer to OnGetDispInfo () to get text:
lvi.pszText = LPSTR_TEXTCALLBACK;
// Set item number:
lvi.iItem = cList.GetItemCount ();
// We will use the list view item parameter to contain a pointer to
// the associated CKEvent object. The CKEvent object contains
// contains information about the event.
lvi.lParam = (LPARAM)pEvent;
ASSERT (pEvent != NULL);
// Insert the new item into list control:
int nIndex = cList.InsertItem (&lvi);
// If auto scroll flag is set, and new item's index is good, then force
// list control to scroll if necessary to show new item:
if (m_bAutoScroll && nIndex != -1)
cList.EnsureVisible (nIndex, false);
// If new item's index is -1 there was a problem, so return false
// to indicate this. Else return true to indicate success:
return (nIndex != -1);
}
// **************************************************************************
// OnTimer ()
//
// Description:
// Timer event handler. Do periodic maintenance of view.
//
// Parameters:
// UINT nIDEvent Timer event type.
//
// Returns:
// void
// **************************************************************************
void CKEventView::OnTimer (UINT nIDEvent)
{
// Process according to timer event type:
switch (nIDEvent)
{
// This is the view maitenance timer event type we defined:
case UPDATE_EVENTPANE_EVENT:
{
// 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);
// Get reference to list view's list control:
CListCtrl &cList = GetListCtrl ();
// Create a scratch pointer to event object:
CKEvent *pEvent = NULL;
int nIndex = 0;
// If we have pending event we will be adding to view, postpone
// redrawing until we are done. This will make things go faster
// and look smoother.
if (m_cnPendingEvents)
cList.SetRedraw (false);
// Process all event in pending events list:
while (nIndex < m_cnPendingEvents)
{
// Get next event in pending events list:
pEvent = m_pPendingEventList [nIndex];
ASSERT (pEvent != NULL);
// Invalidate pending event:
m_pPendingEventList [nIndex++] = NULL;
// If we have reached the self-imposed limit of displayable
// events then remove the first one in list control to make
// room:
if (m_cnEvents == MAXEVENTS)
{
// Delete first item in list (FIFO):
cList.DeleteItem (0);
// Delete the associated event object:
delete m_pEventList [0];
// Scroll events up one notch:
memcpy (m_pEventList, &m_pEventList[1], (m_cnEvents - 1) * sizeof (m_pEventList[0]));
// Decrement the number of events:
--m_cnEvents;
}
// Check for room in the events list. If we are out of
// room, allocate larger block of memory and transfer
// existing events to it.
else if (m_cnEvents == m_cnAllocEvents)
{
// Create a pointer to new events array:
CKEvent **p;
// Allocate memory for the new array/list large enough
// for existing events plus room for new ones. (This is
// an array of pointers to CKEvent objects.)
p = new CKEvent * [m_cnAllocEvents + GROWEVENTS];
// Transfer existing events to the new memory and free
// memory used by old list:
if (m_cnEvents)
{
memcpy (p, m_pEventList, m_cnEvents * sizeof (m_pEventList[0]));
delete [] m_pEventList;
}
// Reset pointer to event list to give new memory area:
m_pEventList = p;
// Increment size of memory allocated for new event list:
m_cnAllocEvents += GROWEVENTS;
}
// Add the item to the event list and increment index for next
// item in pending events list:
m_pEventList[m_cnEvents++] = pEvent;
// Add the item to the list control:
AddEvent (pEvent);
}
// We should have processed all items in pending event list.
// If there were pending items, we need to reset pending
// event counter to zero, restore the list control redraw flag,
// and invalidate the list control to force a redraw.
if (m_cnPendingEvents)
{
m_cnPendingEvents = 0;
cList.SetRedraw (true);
cList.Invalidate ();
}
}
break;
// Perform default processing for all other timer event types:
default:
CListView::OnTimer (nIDEvent);
break;
}
}
// **************************************************************************
// OnChar ()
//
// Description:
// Handle keyboard input. Switch view on tab, etc.
//
// Parameters:
// UINT nChar Character code
// UINT nRepCnt repeat count
// UINT nFlags Flags
//
// Returns:
// void
// **************************************************************************
void CKEventView::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
{
// Switch views on TAB:
if (nChar == VK_TAB)
{
// Post a change view message to main window:
AfxGetMainWnd ()->PostMessage (UM_CHANGEVIEW, 0, (LPARAM)this);
// Return now so default processing does not occur:
return;
}
// Show context menu on SPACEBAR:
else if (nChar == VK_SPACE)
{
// Initialize item index to -1, to indicate no item selected:
int nItem = -1;
// Get reference to list control:
CListCtrl &cList = GetListCtrl ();
// Get the first selected item:
nItem = cList.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
// Get a sensible rectangular region to place the context menu in:
CRect rc;
// If there is a selected item, use its rectangle:
if (nItem >= 0)
{
// Force the list control to scroll if necessary to show
// selected item:
cList.EnsureVisible (nItem, false);
// Get the item's rectangle:
cList.GetItemRect (nItem, &rc, LVIR_LABEL);
}
// Otherwise use the window's rectangle:
else
{
// Get the window's rectangle:
GetWindowRect (&rc);
// Must convert dimensions returned by GetWindowRect():
ScreenToClient (&rc);
}
// Compute coordinates of the rectangle's center:
rc.left = (rc.left + rc.right) / 2;
rc.top = (rc.top + rc.bottom) / 2;
// Display our context menu at rectangle's center. No point in
// reinventing the wheel, use the code already developed for right
// mouse down events to do this:
OnRButtonDown (0, CPoint (rc.left, rc.top));
// Return now so default processing does not occur:
return;
}
// Perform default processing for all other characters:
CListView::OnChar (nChar, nRepCnt, nFlags);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -