📄 itemview.cpp
字号:
// **************************************************************************
// itemview.cpp
//
// Description:
// Implements a CListView derived class. This the top right pane of our GUI
// which shows the OPC items.
//
// 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 "itemview.h"
#include "document.h"
#include "item.h"
#include "group.h"
#include "server.h"
#include "itempropertiesdlg.h"
#include "itemwritedlg.h"
#include "updateintervaldlg.h"
// Define some list control constants:
#define NUMCOLUMNS 6
#define DEFAULTCOLUMNWIDTH 120
#define ASCENDING 0
#define DESCENDING 1
// Define amount to grow item list by:
#define GROWLIST 1024
// Define column headers:
static LPCTSTR lpszRegSection = _T("Item View");
static LPCTSTR lpszSortColumn = _T("Sort Column");
static LPCTSTR lpszSortOrder = _T("Sort Order");
static LPCTSTR lpszUpdateInterval = _T("Update Interval");
// Item pane update timer evetn type:
#define UPDATE_ITEMPANE_EVENT 1
// Declare member statics:
WORD CKItemView::sm_wSortOrder = ASCENDING;
WORD CKItemView::sm_wSortColumn = 0;
DWORD* CKItemView::sm_pSortedItemList = NULL;
/////////////////////////////////////////////////////////////////////////////
// CKItemView
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE (CKItemView, CListView)
// **************************************************************************
BEGIN_MESSAGE_MAP (CKItemView, CListView)
//{{AFX_MSG_MAP(CKItemView)
ON_WM_DESTROY ()
ON_COMMAND (ID_EDIT_NEWITEM, OnNewItem)
ON_NOTIFY_REFLECT (LVN_GETDISPINFO, OnGetDispInfo)
ON_COMMAND (ID_EDIT_PROPERTIES, OnProperties)
ON_NOTIFY_REFLECT (LVN_COLUMNCLICK, OnColumnClick)
ON_WM_TIMER ()
ON_COMMAND (ID_EDIT_DELETE, OnDelete)
ON_WM_RBUTTONDOWN ()
ON_COMMAND (ID_VIEW_UPDATETIMER, OnUpdateTimer)
ON_COMMAND (ID_TOOLS_SYNC_WRITE, OnSyncWrite)
ON_COMMAND (ID_TOOLS_ASYNC10_WRITE, OnAsync10Write)
ON_COMMAND (ID_TOOLS_ASYNC20_WRITE, OnAsync20Write)
ON_COMMAND (ID_TOOLS_SET_ACTIVE, OnSetActive)
ON_COMMAND (ID_TOOLS_SET_INACTIVE, OnSetInactive)
ON_COMMAND (ID_TOOLS_SYNC_READ_CACHE, OnSyncReadCache)
ON_COMMAND (ID_TOOLS_SYNC_READ_DEVICE, OnSyncReadDevice)
ON_COMMAND (ID_TOOLS_ASYNC10_READ_CACHE, OnAsync10ReadCache)
ON_COMMAND (ID_TOOLS_ASYNC10_READ_DEVICE, OnAsync10ReadDevice)
ON_COMMAND (ID_TOOLS_ASYNC20_READ_DEVICE, OnAsync20ReadDevice)
ON_COMMAND (ID_TOOLS_ASYNC10_REFRESH_CACHE, OnAsync10RefreshCache)
ON_COMMAND (ID_TOOLS_ASYNC10_REFRESH_DEVICE, OnAsync10RefreshDevice)
ON_COMMAND (ID_TOOLS_ASYNC20_REFRESH_CACHE, OnAsync20RefreshCache)
ON_COMMAND (ID_TOOLS_ASYNC20_REFRESH_DEVICE, OnAsync20RefreshDevice)
ON_COMMAND (ID_EDIT_COPY, OnCopy)
ON_COMMAND (ID_EDIT_CUT, OnCut)
ON_COMMAND (ID_EDIT_PASTE, OnPaste)
ON_NOTIFY_REFLECT (NM_DBLCLK, OnDblclk)
ON_WM_CHAR ()
//}}AFX_MSG_MAP
ON_NOTIFY_EX_RANGE (TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE (TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP ()
// **************************************************************************
// CKItemView ()
//
// Description:
// Constructor.
//
// Parameters:
// none
//
// Returns:
// none
// **************************************************************************
CKItemView::CKItemView ()
{
// Initialize member variables:
sm_wSortOrder = ASCENDING;
sm_wSortColumn = 0;
m_wUpdateInterval = VIEW_DEFAULT_INTERVAL;
m_cnSortedItems = 0;
m_nSortedListSize = 0;
sm_pSortedItemList = NULL;
}
// **************************************************************************
// ~CKItemView ()
//
// Description:
// Destructor.
//
// Parameters:
// none
//
// Returns:
// none
// **************************************************************************
CKItemView::~CKItemView ()
{
// Free any memory used for sorted item list:
if (sm_pSortedItemList)
delete [] sm_pSortedItemList;
}
/////////////////////////////////////////////////////////////////////////////
// CKItemView creation/drawing
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// PreCreateWindow ()
//
// Description:
// Called by framework before the creation of this window. Use opportunity
// to modify style of window.
//
// Parameters:
// CREATESTRUCT &cs Defines the window initialization parameters.
//
// Returns:
// BOOL - TRUE if success.
// **************************************************************************
BOOL CKItemView::PreCreateWindow (CREATESTRUCT &cs)
{
// Perform default processing. Return FALSE if failure:
if (!CListView::PreCreateWindow (cs))
return (FALSE);
// Modify window sytle:
// First clear icon view, small icon view, and list view bits.
// Then set report view and owner data bits.
// (Owner data transfers the responsibility of managing data from the
// list control to the application programmer. This allows very large
// data sets to be handled efficiently. See MSDN discussion of Virtual
// List-View Style.)
cs.style &= ~(LVS_ICON | LVS_SMALLICON | LVS_LIST);
cs.style |= (LVS_REPORT | LVS_OWNERDATA);
// Return TRUE to indicate success:
return (TRUE);
}
// **************************************************************************
// PreSubclassWindow ()
//
// Description:
// This method is called by the framework to allow other necessary
// subclassing to occur before the window is subclassed.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemView::PreSubclassWindow ()
{
// Perform default processing:
CListView::PreSubclassWindow ();
// Enable tooltips:
EnableToolTips (TRUE);
}
// **************************************************************************
// Create
//
// Description:
// Creates the CKItemView window and attaches it to parent window. Use
// opportunity to set list control's column properties from data saved
// in registry and to start an update timer.
//
// 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 CKItemView::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. The bitmap must use a
// purple background color, RGB (255, 0, 255), so that the CImageList
// object can construct a mask. The images are 14x14 pixels. Set the
// image list background color to CLR_NONE so masked pixels will be
// transparent.
// Image number Use
// 0 Active tag
// 1 Inactive tag
// 2 Invalid tag
// 3 not used
m_cImageList.Create (IDB_ITEMIMAGES, 14, 2, RGB (255, 0, 255));
m_cImageList.SetBkColor (CLR_NONE);
GetListCtrl ().SetImageList (&m_cImageList, LVSIL_SMALL);
// Create a string to hold column tile:
CString strColumnTitle;
// Define list control columns:
for (int i = 0; i < NUMCOLUMNS; i++)
{
// Create a string to contain column width registry entry:
TCHAR szNum [8];
wsprintf (szNum, _T("%d"), i);
// Read the column width from the registry. This is the width of the column
// saved at the end of the last session.
int nWidth = AfxGetApp ()->GetProfileInt (lpszRegSection, szNum, DEFAULTCOLUMNWIDTH);
// Make sure it is valid:
if (nWidth < 0)
nWidth = DEFAULTCOLUMNWIDTH;
// Load the column title string resource:
switch (i)
{
case 0: // Item ID
strColumnTitle.LoadString (IDS_ITEMID);
break;
case 1: // Data Type
strColumnTitle.LoadString (IDS_DATATYPE);
break;
case 2: // Value
strColumnTitle.LoadString (IDS_VALUE);
break;
case 3: // Timestamp
strColumnTitle.LoadString (IDS_TIMESTAMP);
break;
case 4: // Quality
strColumnTitle.LoadString (IDS_QUALITY);
break;
case 5: // Update Count
strColumnTitle.LoadString (IDS_UPDATE_COUNT);
break;
default: // Unexpected column index
ASSERT (FALSE);
break;
}
// Insert the column:
GetListCtrl ().InsertColumn (i, strColumnTitle, LVCFMT_LEFT, nWidth);
}
// Load the sort settings from registry. (Settings saved at end of last session.)
sm_wSortColumn = AfxGetApp ()->GetProfileInt (lpszRegSection, lpszSortColumn, sm_wSortColumn);
sm_wSortOrder = AfxGetApp ()->GetProfileInt (lpszRegSection, lpszSortOrder, sm_wSortOrder);
// Load update interval setting from registry. (Setting saved at end of last session.)
m_wUpdateInterval = AfxGetApp ()->GetProfileInt (lpszRegSection, lpszUpdateInterval, m_wUpdateInterval);
// Start update view timer. This will give us a chance to do periodic
// maintenance of the view.
SetTimer (UPDATE_ITEMPANE_EVENT, m_wUpdateInterval, NULL);
// Add the extended full row selection style (This causes all subitems
// to be selected at once - i.e. full row is selected.)
SendMessage (LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
// Return TRUE to inicate success:
return (TRUE);
}
// **************************************************************************
// OnDestroy ()
//
// Description:
// Called by framework just before window is destroyed. Use opportunity to
// save list control's column settings to registry and kill update timer.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CKItemView::OnDestroy ()
{
// Perform default processing:
CListView::OnDestroy ();
// Save current column information to registry so we can use the same
// settings next time:
for (int i = 0; i < NUMCOLUMNS; i++)
{
// Create a string to identify column width registry entry:
TCHAR szNum [8];
wsprintf (szNum, _T("%d"), i);
// Save width:
AfxGetApp ()->WriteProfileInt (lpszRegSection, szNum, GetListCtrl ().GetColumnWidth (i));
}
// Save sorting preferences to registry:
AfxGetApp ()->WriteProfileInt (lpszRegSection, lpszSortColumn, sm_wSortColumn);
AfxGetApp ()->WriteProfileInt (lpszRegSection, lpszSortOrder, sm_wSortOrder);
// Save update interval to registry:
AfxGetApp ()->WriteProfileInt (lpszRegSection, lpszUpdateInterval, m_wUpdateInterval);
// Stop update view timer:
KillTimer (UPDATE_ITEMPANE_EVENT);
}
// **************************************************************************
// OnUpdate ()
//
// Description:
// Called when we the document has changed and we should update our view.
//
// Parameters:
// CView *pSender Points to the view that modified the document,
// or NULL if all views are to be updated.
// LPARAM lHint Contains information about the modifications.
// Hints used here are defined in globals.h.
// CObject *pHint Points to an object storing information about the
// modifications.
//
// Returns:
// void
// **************************************************************************
void CKItemView::OnUpdate (CView *pSender, LPARAM lHint, CObject *pHint)
{
// Create a wait cursor object. This will cause the wait cursor,
// usually an hourglass, to be displayed. When this object goes
// out of scope, its destructor will restore the previous cursor
// type.
CWaitCursor wc;
// Process according to hint type:
switch (lHint)
{
// Need to update view due to added items:
case HINT_ADD_ITEM:
{
// pHint points to a CObArray containing a list of CKItem
// objects to add.
// Check to see if pHint was set (debug only).
ASSERT (pHint != NULL);
// Get pointer to the item list:
CObArray *pList = (CObArray *)pHint;
// Initialize some variables:
CKItem *pItem = NULL;
DWORD dwIndex = 0;
// Postpone redrawing until we are done. This will make things
// go faster and look smoother.
SetRedraw (false);
// Insert all the items in array in. Get pointer to next item
// in object array, increment array index, and cast item pointer
// to CKItem pointer. A null pointer will have been placed in
// array after last item to mark end of data. This will cause
// the loop to terminate.
while (pItem = (CKItem *) pList->GetAt (dwIndex++))
Insert (pItem);
// Update the item count. (This is one of the responsibilities
// we took on by using a virtual list view. See comments in
// PreCreateWindow().) Set flags to prevent the scroll position
// from changing and to prevent the list control from repainting
// unless affected items are in view.
GetListCtrl ().SetItemCountEx (m_cnSortedItems, LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -