📄 groupview.cpp
字号:
// **************************************************************************
// groupview.cpp
//
// Description:
// Implements a CTreeView derived class. This the top left pane of our GUI
// which shows the OPC servers and groups.
//
// 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 "groupview.h"
#include "document.h"
#include "server.h"
#include "group.h"
#include "item.h"
#include "servergeterrorstringdlg.h"
#include "servergroupbynamedlg.h"
#include "serverenumgroupsdlg.h"
// Define string constsants for CSV file import/export common dialog:
static LPCTSTR lpszPaths = _T("Paths");
static LPCTSTR lpszOpenFile = _T("Open File");
static LPCTSTR lpszCSV = _T("csv");
/////////////////////////////////////////////////////////////////////////////
// CKGroupView
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE (CKGroupView, CTreeView)
// **************************************************************************
BEGIN_MESSAGE_MAP (CKGroupView, CTreeView)
//{{AFX_MSG_MAP(CKGroupView)
ON_COMMAND (ID_EDIT_NEWSERVER, OnNewServer)
ON_COMMAND (ID_EDIT_NEWGROUP, OnNewGroup)
ON_NOTIFY_REFLECT (TVN_GETDISPINFO, OnGetDispInfo)
ON_COMMAND (ID_EDIT_PROPERTIES, OnProperties)
ON_NOTIFY_REFLECT (TVN_SELCHANGED, OnSelectionChanged)
ON_COMMAND (ID_EDIT_DELETE, OnDelete)
ON_WM_RBUTTONDOWN ()
ON_WM_LBUTTONDBLCLK ()
ON_COMMAND (ID_TOOLS_GET_ERROR_STRING, OnGetErrorString)
ON_COMMAND (ID_TOOLS_CLONE_GROUP, OnCloneGroup)
ON_COMMAND (ID_TOOLS_GET_GROUP_BY_NAME, OnGetGroupByName)
ON_COMMAND (ID_TOOLS_ENUMERATE_GROUPS, OnEnumerateGroups)
ON_COMMAND (ID_TOOLS_CONNECT, OnConnect)
ON_COMMAND (ID_TOOLS_DISCONNECT, OnDisconnect)
ON_COMMAND (ID_TOOLS_RECONNECT, OnReconnect)
ON_COMMAND (ID_EDIT_COPY, OnCopy)
ON_COMMAND (ID_EDIT_CUT, OnCut)
ON_COMMAND (ID_EDIT_PASTE, OnPaste)
ON_WM_CHAR ()
ON_COMMAND (ID_TOOLS_EXPORT_CSV, OnExportCsv)
ON_COMMAND (ID_TOOLS_IMPORT_CSV, OnImportCsv)
//}}AFX_MSG_MAP
END_MESSAGE_MAP ()
// **************************************************************************
// CKGroupView ()
//
// Description:
// Constructor
//
// Parameters:
// none
//
// Returns:
// none
// **************************************************************************
CKGroupView::CKGroupView ()
{
}
// **************************************************************************
// ~CKGroupView ()
//
// Description:
// Destructor
//
// Parameters:
// none
//
// Returns:
// none
// **************************************************************************
CKGroupView::~CKGroupView ()
{
}
/////////////////////////////////////////////////////////////////////////////
// CKGroupView creation/drawing
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// Create ()
//
// Description:
// Creates the view 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 CKGroupView::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 16x16 pixels. Set the
// image list background color to CLR_NONE so masked pixels will be
// transparent.
// Image number Use
// 0 Connected Server
// 1 not used
// 2 Active Group (not selected)
// 3 Inactive Group (not selected)
// 4 Active Group (selected)
// 5 Inactive Group (selected)
// 6 Disconnected Server
// 7 Invalid Group
// 8 not used
// 9 not used
m_cImageList.Create (IDB_GROUPIMAGES, 16, 4, RGB (255, 0, 255));
m_cImageList.SetBkColor (CLR_NONE);
GetTreeCtrl ().SetImageList (&m_cImageList, LVSIL_NORMAL);
// Set the style we want for the tree: Draw lines connecting child and
// parent, has buttons to expand or collapse tree, draw line to root and
// let root have button.
GetTreeCtrl ().ModifyStyle (0, // Don't remove any styles
TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT); // Add these styles
// Return TRUE to inidcate success:
return (TRUE);
}
// **************************************************************************
// 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 Device context
//
// Returns:
// void
// **************************************************************************
void CKGroupView::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 ();
}
// **************************************************************************
// 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 CKGroupView::OnUpdate (CView *pSender, LPARAM lHint, CObject *pHint)
{
switch (lHint)
{
case HINT_ADD_SERVER:
ASSERT (pHint != NULL); // pHint contains CKServer *
Insert (TVI_ROOT, pHint);
break;
case HINT_REMOVE_SERVER:
ASSERT (pHint != NULL); // pHint contains CKServer *
Delete (((CKServer *)pHint)->GetGUIHandle ());
break;
case HINT_ADD_GROUP:
{
ASSERT (pHint != NULL); // pHint contains CKGroup *
CKGroup *pGroup = (CKGroup *)pHint;
CKServer *pParent = pGroup->GetParentServer ();
ASSERT (pParent != NULL);
Insert (pParent->GetGUIHandle (), pGroup);
}
break;
case HINT_REMOVE_GROUP:
ASSERT (pHint != NULL); // pHint contains CKGroup *
Delete (((CKGroup *)pHint)->GetGUIHandle ());
break;
case HINT_SELECT_GROUP:
{
// pHint contains CKGroup *
// Get reference to link control:
CTreeCtrl &cTree = GetTreeCtrl ();
// Get handle of group:
HTREEITEM hItem;
if (pHint == NULL)
{
// No group passed in, get the first one in the tree
hItem = cTree.GetChildItem (TVI_ROOT); // Get first child of root (i.e., server)
hItem = cTree.GetChildItem (hItem); // Get first child of parent (i.e., group)
}
else
hItem = ((CKGroup*)pHint)->GetGUIHandle ();
// Select the group:
if (hItem != NULL)
{
// Select the group:
cTree.SelectItem (hItem);
// Force a repaint:
cTree.Invalidate (false);
cTree.UpdateWindow ();
}
}
break;
case HINT_ADD_SERVER_AND_GROUPS:
{
// pHint contains CKServer *
ASSERT (pHint != NULL);
CKServer *pServer = (CKServer *) pHint;
// Insert the server:
Insert (TVI_ROOT, pServer);
// Now insert its groups:
// We'll need the handle of parent server,
HTREEITEM hParent = pServer->GetGUIHandle ();
// and the head of its linked list of groups:
CKGroup *pGroup = pServer->GetGroupHead ();
// Loop over groups in linked list. End of list will be indicated
// by a NULL pointer.
while (pGroup)
{
// Insert group item into the server branch of the tree:
Insert (hParent, pGroup, false);
// Move onto next group in linked list:
pGroup = pGroup->GetNext ();
}
// Force a repaint:
GetTreeCtrl ().Invalidate (false);
GetTreeCtrl ().UpdateWindow ();
}
break;
case HINT_LOAD_PROJECT:
{
// pHint contains CKServer * (head of linked list of servers)
ASSERT (pHint != NULL);
CKServer *pServer = (CKServer *)pHint;
// Loop over all servers in linked list. End of list will be
// indicated by a NULL pointer:
while (pServer)
{
// Insert server item into the root of the tree:
Insert (TVI_ROOT, pServer, false);
// Insert server's groups:
// We'll need the handle of the parent server,
HTREEITEM hParent = pServer->GetGUIHandle ();
// and the head of its linked list of groups:
CKGroup *pGroup = pServer->GetGroupHead ();
// Loop over all groups in linked list. End of list will be
// indicated by a NULL pointer:
while (pGroup)
{
// Insert group item into the server branch of the tree:
Insert (hParent, pGroup, false);
// Move onto next group in linked list:
pGroup = pGroup->GetNext ();
}
// Move onto next server connection in linked list:
pServer = pServer->GetNext ();
}
// Select first item in the tree:
CTreeCtrl &cTree = GetTreeCtrl ();
HTREEITEM hFirstItem = cTree.GetFirstVisibleItem ();
if (hFirstItem != NULL)
cTree.SelectItem (hFirstItem);
}
break;
case HINT_REFRESH_GROUPVIEW:
// Force a repaint:
GetTreeCtrl ().Invalidate (true);
GetTreeCtrl ().UpdateWindow ();
break;
default:
// Default processing:
CView::OnUpdate (pSender, lHint, pHint);
break;
}
}
/////////////////////////////////////////////////////////////////////////////
// CKGroupView mouse handlers
/////////////////////////////////////////////////////////////////////////////
// **************************************************************************
// OnRButtonDown ()
//
// Description:
// Process right button click messages for this view. Build and display an
// appropriate popup menu.
//
// Parameters:
// UINT uFlags Indicates whether various virtual keys are down.
// CPoint point Specifies the x and y coordinates of the cursor.
// These coordinates are always relative to the
// upper-left corner of the window.
//
// Returns:
// void
// **************************************************************************
void CKGroupView::OnRButtonDown (UINT uFlags, CPoint point)
{
// Get reference to tree control:
CTreeCtrl &cTree = GetTreeCtrl ();
// Get pointer to our main menu. We will use it to get text for
// the popup menu:
CMenu *pMainMenu = AfxGetMainWnd ()->GetMenu ();
// Define flags to so that popup menu items will get text from pointer
// to null terminated string.
int nFlags = MF_ENABLED | MF_STRING;
CMenu cMenu;
UINT uHitFlags;
HTREEITEM hItem;
CString strMenuText;
// Get a handle to the item that was clicked on (handle
// will be NULL if click was not on a item):
hItem = cTree.HitTest (point, &uHitFlags);
// Select item if clicked on:
if (hItem && (uHitFlags & TVHT_ONITEM))
cTree.Select (hItem, TVGN_CARET);
// Convert point to screen coordinates:
ClientToScreen (&point);
// Build and display our context menu:
if (cMenu.CreatePopupMenu ())
{
// If click was on an item:
if (hItem)
{
// If click was on a server connection:
if (cTree.GetParentItem (hItem) == NULL)
{
// Add Add Group menu item:
pMainMenu->GetMenuString (ID_EDIT_NEWGROUP, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_EDIT_NEWGROUP, strMenuText);
// Add separator menu item:
cMenu.AppendMenu (MF_SEPARATOR);
// Add Connect menu item:
pMainMenu->GetMenuString (ID_TOOLS_CONNECT, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_TOOLS_CONNECT, strMenuText);
// Add Disconnect menu item:
pMainMenu->GetMenuString (ID_TOOLS_DISCONNECT, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_TOOLS_DISCONNECT, strMenuText);
// Add Reconnect menu item:
pMainMenu->GetMenuString (ID_TOOLS_RECONNECT, strMenuText, MF_BYCOMMAND);
cMenu.AppendMenu (nFlags, ID_TOOLS_RECONNECT, strMenuText);
// Add separator:
cMenu.AppendMenu (MF_SEPARATOR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -