You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1684 lines
50 KiB
1684 lines
50 KiB
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1996-2000 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// ListView.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of the CListView class.
|
|
//
|
|
// Author:
|
|
// David Potter (davidp) May 6, 1996
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Notes:
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "CluAdmin.h"
|
|
#include "ConstDef.h"
|
|
#include "ClusDoc.h"
|
|
#include "ClusItem.h"
|
|
#include "ListView.h"
|
|
#include "ListItem.h"
|
|
#include "ListItem.inl"
|
|
#include "SplitFrm.h"
|
|
#include "TreeItem.h"
|
|
#include "TreeView.h"
|
|
#include "ClusDoc.h"
|
|
#include "TraceTag.h"
|
|
#include "ExcOper.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Global Variables
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef _DEBUG
|
|
CTraceTag g_tagListView(_T("UI"), _T("LIST VIEW"), 0);
|
|
CTraceTag g_tagListDrag(_T("Drag&Drop"), _T("LIST VIEW DRAG"), 0);
|
|
CTraceTag g_tagListDragMouse(_T("Drag&Drop"), _T("LIST VIEW DRAG MOUSE"), 0);
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CClusterListView
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_DYNCREATE(CClusterListView, CListView)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Message Maps
|
|
|
|
BEGIN_MESSAGE_MAP(CClusterListView, CListView)
|
|
//{{AFX_MSG_MAP(CClusterListView)
|
|
ON_WM_DESTROY()
|
|
ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged)
|
|
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
|
|
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblClk)
|
|
ON_COMMAND(ID_OPEN_ITEM, OpenItem)
|
|
ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnBeginLabelEdit)
|
|
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndLabelEdit)
|
|
ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateProperties)
|
|
ON_COMMAND(ID_FILE_PROPERTIES, OnCmdProperties)
|
|
ON_COMMAND(ID_FILE_RENAME, OnCmdRename)
|
|
ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBeginDrag)
|
|
ON_NOTIFY_REFLECT(LVN_BEGINRDRAG, OnBeginDrag)
|
|
ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeyDown)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::CClusterListView
|
|
//
|
|
// Routine Description:
|
|
// Default constructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CClusterListView::CClusterListView(void)
|
|
{
|
|
m_ptiParent = NULL;
|
|
m_nColumns = 0;
|
|
m_nSortDirection = -1;
|
|
m_pcoliSort = NULL;
|
|
|
|
m_pframe = NULL;
|
|
|
|
// Initialize label editing.
|
|
m_pliBeingEdited = NULL;
|
|
m_bShiftPressed = FALSE;
|
|
m_bControlPressed = FALSE;
|
|
m_bAltPressed = FALSE;
|
|
|
|
// Initialize drag & drop.
|
|
m_iliDrag = -1;
|
|
m_pliDrag = NULL;
|
|
m_iliDrop = -1;
|
|
|
|
} //*** CClusterListView::CClusterListView()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::~CClusterListView
|
|
//
|
|
// Routine Description:
|
|
// Destructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CClusterListView::~CClusterListView(void)
|
|
{
|
|
if (m_ptiParent != NULL)
|
|
m_ptiParent->Release();
|
|
|
|
} //*** CClusterListView::~CClusterListView()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::Create
|
|
//
|
|
// Routine Description:
|
|
// Create the window.
|
|
//
|
|
// Arguments:
|
|
// lpszClassName [IN] Name of the window class to create.
|
|
// lpszWindowName [IN] Name of the window (used as the caption).
|
|
// dwStyle [IN] Window styles.
|
|
// rect [IN] Size and position of the window
|
|
// pParentWnd [IN OUT ] Parent window.
|
|
// nID [IN] ID of the window.
|
|
// pContext [IN OUT] Create context of the window.
|
|
//
|
|
// Return Value:
|
|
// 0 Successful.
|
|
// !0 Unsuccessful.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterListView::Create(
|
|
LPCTSTR lpszClassName,
|
|
LPCTSTR lpszWindowName,
|
|
DWORD dwStyle,
|
|
const RECT & rect,
|
|
CWnd * pParentWnd,
|
|
UINT nID,
|
|
CCreateContext * pContext
|
|
)
|
|
{
|
|
BOOL bSuccess;
|
|
|
|
// Set default style bits.
|
|
dwStyle |=
|
|
LVS_SHAREIMAGELISTS
|
|
| LVS_EDITLABELS
|
|
| LVS_SINGLESEL
|
|
| LVS_SHOWSELALWAYS
|
|
| LVS_ICON
|
|
| LVS_REPORT
|
|
;
|
|
|
|
bSuccess = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
|
|
if (bSuccess)
|
|
{
|
|
GetListCtrl().SetImageList(GetClusterAdminApp()->PilLargeImages(), LVSIL_NORMAL);
|
|
GetListCtrl().SetImageList(GetClusterAdminApp()->PilSmallImages(), LVSIL_SMALL);
|
|
// GetListCtrl().SetImageList(GetClusterAdminApp()->PilSmallImages(), LVSIL_STATE);
|
|
|
|
// Change list view control extended styles.
|
|
{
|
|
DWORD dwExtendedStyle;
|
|
|
|
dwExtendedStyle = (DWORD)GetListCtrl().SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE);
|
|
GetListCtrl().SendMessage(
|
|
LVM_SETEXTENDEDLISTVIEWSTYLE,
|
|
0,
|
|
dwExtendedStyle
|
|
| LVS_EX_FULLROWSELECT
|
|
| LVS_EX_HEADERDRAGDROP
|
|
);
|
|
} // Change list view control extended styles
|
|
|
|
} // if: window created successfully
|
|
|
|
return bSuccess;
|
|
|
|
} //*** CClusterListView::Create()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnInitialUpdate
|
|
//
|
|
// Routine Description:
|
|
// Do one-time initialization.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnInitialUpdate()
|
|
{
|
|
CListView::OnInitialUpdate();
|
|
|
|
// Save the frame pointer.
|
|
// ASSERT(m_pframe == NULL);
|
|
m_pframe = (CSplitterFrame *) GetParentFrame();
|
|
ASSERT_VALID(m_pframe);
|
|
ASSERT_KINDOF(CSplitterFrame, m_pframe);
|
|
|
|
} //*** CClusterListView::OnInitialUpdate()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::Refresh
|
|
//
|
|
// Routine Description:
|
|
// Refresh the view by reloading all the data.
|
|
//
|
|
// Arguments:
|
|
// ptiSelected [IN OUT] Pointer to currently selected item in the tree control.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::Refresh(IN OUT CTreeItem * ptiSelected)
|
|
{
|
|
// Save columns.
|
|
if (PtiParent() != NULL)
|
|
SaveColumns();
|
|
|
|
// Clean up the control to start with.
|
|
DeleteAllItems();
|
|
|
|
// Cleanup the previous parent tree item.
|
|
if (m_ptiParent != NULL)
|
|
m_ptiParent->Release();
|
|
m_ptiParent = ptiSelected;
|
|
|
|
// Setup the new selection.
|
|
if (m_ptiParent != NULL)
|
|
{
|
|
ASSERT_VALID(ptiSelected);
|
|
|
|
CListCtrl & rListCtrl = GetListCtrl();
|
|
const CListItemList & rlpli = ptiSelected->LpliChildren();
|
|
|
|
m_ptiParent->AddRef();
|
|
|
|
// Add columns to the list control.
|
|
AddColumns();
|
|
|
|
// Add items from the tree item's list to the list view.
|
|
{
|
|
POSITION pos;
|
|
CListItem * pli;
|
|
|
|
// Tell the list control how many items we will be adding.
|
|
// This improves performance.
|
|
rListCtrl.SetItemCount((int)rlpli.GetCount());
|
|
|
|
// Add the items to the list control.
|
|
pos = rlpli.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
pli = rlpli.GetNext(pos);
|
|
ASSERT_VALID(pli);
|
|
pli->IliInsertInList(this);
|
|
} // while: more items in the list
|
|
} // Add items from the tree item's list to the list view
|
|
|
|
// Give the focus to the first item in the list.
|
|
if (rListCtrl.GetItemCount() != 0)
|
|
rListCtrl.SetItem(0, 0, LVIF_STATE, NULL, 0, LVIS_FOCUSED, LVIS_FOCUSED, NULL);
|
|
} // if: non-null selection
|
|
|
|
// Set the sort column and direction.
|
|
m_nSortDirection = -1;
|
|
m_pcoliSort = NULL;
|
|
|
|
} //*** CClusterListView::Refresh()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::DeleteAllItems
|
|
//
|
|
// Routine Description:
|
|
// Delete all the list and column items.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE All items deleted successfully.
|
|
// FALSE Not all items were deleted successfully.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterListView::DeleteAllItems(void)
|
|
{
|
|
BOOL bDeletedAllItems;
|
|
BOOL bDeletedAllColumns = TRUE;
|
|
int icol;
|
|
|
|
// Remove all the items from our list.
|
|
{
|
|
CListItem * pli;
|
|
int ili;
|
|
int cli = GetListCtrl().GetItemCount();
|
|
|
|
// Get the index of the first item.
|
|
for (ili = 0 ; ili < cli; ili++)
|
|
{
|
|
pli = (CListItem *) GetListCtrl().GetItemData(ili);
|
|
ASSERT_VALID(pli);
|
|
pli->PreRemoveFromList(this);
|
|
} // for: each item in the list
|
|
|
|
} // Remove all the items from the cluster item back pointer list
|
|
|
|
// Delete the columns.
|
|
{
|
|
for (icol = m_nColumns - 1 ; icol >= 0 ; icol--)
|
|
{
|
|
// Delete the column from the view.
|
|
if (!GetListCtrl().DeleteColumn(icol))
|
|
bDeletedAllColumns = FALSE;
|
|
} // for: each column
|
|
m_nColumns = 0;
|
|
} // Delete the columns
|
|
|
|
// Remove all the items from the list.
|
|
bDeletedAllItems = GetListCtrl().DeleteAllItems();
|
|
|
|
return (bDeletedAllItems && bDeletedAllColumns);
|
|
|
|
} //*** CClusterListView::DeleteAllItems()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::SaveColumns
|
|
//
|
|
// Routine Description:
|
|
// Save the columns being displayed in the list view.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::SaveColumns(void)
|
|
{
|
|
int icol;
|
|
DWORD * prgnColumnInfo;
|
|
CListCtrl & rplc = GetListCtrl();
|
|
|
|
ASSERT_VALID(PtiParent());
|
|
|
|
// We can only save column information if we are in report view.
|
|
if (GetView() & LVS_REPORT)
|
|
{
|
|
try
|
|
{
|
|
// Get the column info array for this view.
|
|
prgnColumnInfo = PtiParent()->PrgnColumnInfo(this);
|
|
|
|
// Save the widths of the columns.
|
|
for (icol = m_nColumns - 1 ; icol >= 0 ; icol--)
|
|
prgnColumnInfo[icol + 1] = rplc.GetColumnWidth(icol);
|
|
|
|
// Save the position information in the array.
|
|
rplc.SendMessage(LVM_GETCOLUMNORDERARRAY, m_nColumns, (LPARAM) &prgnColumnInfo[m_nColumns + 1]);
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->Delete();
|
|
} // catch: CException
|
|
} // if: we are in detail view
|
|
|
|
} //*** CClusterListView::SaveColumns()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::AddColumns
|
|
//
|
|
// Routine Description:
|
|
// Add columns to the list view.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::AddColumns(void)
|
|
{
|
|
POSITION pos;
|
|
int cColumns;
|
|
int icoli = 0;
|
|
CColumnItem * pcoli;
|
|
DWORD * prgnColumnInfo;
|
|
CListCtrl & rplc = GetListCtrl();
|
|
|
|
ASSERT_VALID(PtiParent());
|
|
|
|
try
|
|
{
|
|
// Get the column info.
|
|
cColumns = (int)PtiParent()->Lpcoli().GetCount();
|
|
prgnColumnInfo = PtiParent()->PrgnColumnInfo(this);
|
|
|
|
pos = PtiParent()->Lpcoli().GetHeadPosition();
|
|
for (icoli = 0 ; pos != NULL ; icoli++)
|
|
{
|
|
// Get the next column item.
|
|
pcoli = PtiParent()->Lpcoli().GetNext(pos);
|
|
ASSERT(pcoli != NULL);
|
|
|
|
// Insert the column item in the list.
|
|
rplc.InsertColumn(
|
|
icoli, // nCol
|
|
pcoli->StrText(), // lpszColumnHeading
|
|
LVCFMT_LEFT, // nFormat
|
|
prgnColumnInfo[icoli + 1], // nWidth
|
|
icoli // nSubItem
|
|
);
|
|
} // while: more items in the list
|
|
|
|
// Set column positions.
|
|
rplc.SendMessage(LVM_SETCOLUMNORDERARRAY, cColumns, (LPARAM) &prgnColumnInfo[cColumns + 1]);
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
} // catch: CException
|
|
|
|
m_nColumns = icoli;
|
|
|
|
} //*** CClusterListView::AddColumns()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CClusterListView diagnostics
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef _DEBUG
|
|
void CClusterListView::AssertValid(void) const
|
|
{
|
|
CListView::AssertValid();
|
|
|
|
} //*** CClusterListView::AssertValid()
|
|
|
|
void CClusterListView::Dump(CDumpContext& dc) const
|
|
{
|
|
CListView::Dump(dc);
|
|
|
|
} //*** CClusterListView::Dump()
|
|
|
|
CClusterDoc * CClusterListView::GetDocument(void) // non-debug version is inline
|
|
{
|
|
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CClusterDoc)));
|
|
return (CClusterDoc *) m_pDocument;
|
|
|
|
} //*** CClusterListView::GetDocument()
|
|
#endif //_DEBUG
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::PliFocused
|
|
//
|
|
// Routine Description:
|
|
// Get the list item that has the focus.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// pliSelected The item with the focus or NULL if no item has focus.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CListItem * CClusterListView::PliFocused(void) const
|
|
{
|
|
int iliFocused;
|
|
CListItem * pliFocused;
|
|
|
|
iliFocused = IliFocused();
|
|
if (iliFocused != -1)
|
|
{
|
|
pliFocused = (CListItem *) GetListCtrl().GetItemData(iliFocused);
|
|
ASSERT_VALID(pliFocused);
|
|
} // if: found an item with the focus
|
|
else
|
|
pliFocused = NULL;
|
|
|
|
return pliFocused;
|
|
|
|
} //*** CClusterListView::PliFocused()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnCmdMsg
|
|
//
|
|
// Routine Description:
|
|
// Processes command messages. Attempts to pass them on to a selected
|
|
// item first.
|
|
//
|
|
// Arguments:
|
|
// nID [IN] Command ID.
|
|
// nCode [IN] Notification code.
|
|
// pExtra [IN OUT] Used according to the value of nCode.
|
|
// pHandlerInfo [OUT] ???
|
|
//
|
|
// Return Value:
|
|
// TRUE Message has been handled.
|
|
// FALSE Message has NOT been handled.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterListView::OnCmdMsg(
|
|
UINT nID,
|
|
int nCode,
|
|
void * pExtra,
|
|
AFX_CMDHANDLERINFO * pHandlerInfo
|
|
)
|
|
{
|
|
int ili;
|
|
CListItem * pli;
|
|
BOOL bHandled = FALSE;
|
|
|
|
// If there is a current item selected, give it a chance
|
|
// to handle the message.
|
|
ili = GetListCtrl().GetNextItem(-1, LVNI_FOCUSED);
|
|
if (ili != -1)
|
|
{
|
|
pli = (CListItem *) GetListCtrl().GetItemData(ili);
|
|
ASSERT_VALID(pli);
|
|
bHandled = pli->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
|
|
} // if: an item is selected
|
|
|
|
if (!bHandled)
|
|
bHandled = CListView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
|
|
|
|
return bHandled;
|
|
|
|
} //*** CClusterListView::OnCmdMsg()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::PmenuPopup
|
|
//
|
|
// Routine Description:
|
|
// Returns a popup menu.
|
|
//
|
|
// Arguments:
|
|
// rpointScreen [IN OUT] Position of the cursor, in screen coordinates.
|
|
// rpci [OUT] Pointer in which to return associated cluster item.
|
|
//
|
|
// Return Value:
|
|
// pmenu A popup menu for the item.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CMenu * CClusterListView::PmenuPopup(
|
|
IN OUT CPoint & rpointScreen,
|
|
OUT CClusterItem *& rpci
|
|
)
|
|
{
|
|
CListItem * pli = NULL;
|
|
CMenu * pmenu = NULL;
|
|
|
|
rpci = NULL;
|
|
|
|
// If there are no coordinates (-1,-1), display a menu for the selected item.
|
|
if ((rpointScreen.x == -1) && (rpointScreen.y == -1))
|
|
{
|
|
CListItem * pliFocused = PliFocused();
|
|
CRect rect;
|
|
|
|
if ((pliFocused != NULL)
|
|
&& GetListCtrl().GetItemRect(IliFocused(), &rect, LVIR_BOUNDS))
|
|
{
|
|
pli = pliFocused;
|
|
} // if: item with focus and it is visible
|
|
else
|
|
GetWindowRect(&rect);
|
|
rpointScreen.x = (rect.right - rect.left) / 2;
|
|
rpointScreen.y = (rect.bottom - rect.top) / 2;
|
|
ClientToScreen(&rpointScreen);
|
|
} // if: no coordinates
|
|
else
|
|
{
|
|
CPoint pointClient;
|
|
int ili;
|
|
UINT uiFlags;
|
|
|
|
// Get the coordinates of the point where the user clicked the right mouse
|
|
// button. We need in both screen and client coordinates.
|
|
pointClient = rpointScreen;
|
|
ScreenToClient(&pointClient);
|
|
|
|
// Get the item under the cursor and get its popup menu.
|
|
ili = GetListCtrl().HitTest(pointClient, &uiFlags);
|
|
if ((ili != -1) && ((uiFlags | LVHT_ONITEM) != 0))
|
|
{
|
|
// Get the list item for the item under the cursor.
|
|
pli = (CListItem *) GetListCtrl().GetItemData(ili);
|
|
ASSERT_VALID(pli);
|
|
} // if: on an item
|
|
} // else: coordinates specified
|
|
|
|
if (pli != NULL)
|
|
{
|
|
// Get a menu from the item.
|
|
pmenu = pli->PmenuPopup();
|
|
rpci = pli->Pci();
|
|
} // if: item found
|
|
|
|
return pmenu;
|
|
|
|
} //*** CClusterListView::PmenuPopup()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnUpdateProperties
|
|
//
|
|
// Routine Description:
|
|
// Determines whether menu items corresponding to ID_FILE_PROPERTIES
|
|
// should be enabled or not.
|
|
//
|
|
// Arguments:
|
|
// pCmdUI [IN OUT] Command routing object.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnUpdateProperties(CCmdUI * pCmdUI)
|
|
{
|
|
CListItem * pliFocused = PliFocused();
|
|
|
|
// If there is an item with the focus, pass this message on to it.
|
|
if (pliFocused != NULL)
|
|
{
|
|
ASSERT_VALID(pliFocused->Pci());
|
|
pliFocused->Pci()->OnUpdateProperties(pCmdUI);
|
|
} // if: there is an item with the focus
|
|
|
|
} //*** CClusterListView::OnUpdateProperties()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnCmdProperties
|
|
//
|
|
// Routine Description:
|
|
// Processes the ID_FILE_PROPERTIES menu command.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnCmdProperties(void)
|
|
{
|
|
CListItem * pliFocused = PliFocused();
|
|
|
|
// If there is an item with the focus, pass this message on to it.
|
|
if (pliFocused != NULL)
|
|
{
|
|
ASSERT_VALID(pliFocused->Pci());
|
|
pliFocused->Pci()->OnCmdProperties();
|
|
} // if: there is an item with the focus
|
|
|
|
} //*** CClusterListView::OnCmdProperties()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnItemChanged
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the LVN_ITEMCHANGED message.
|
|
//
|
|
// Arguments:
|
|
// pNMHDR [IN OUT] WM_NOTIFY structure.
|
|
// pResult [OUT] LRESULT in which to return the result of this operation.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnItemChanged(NMHDR * pNMHDR, LRESULT * pResult)
|
|
{
|
|
NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;
|
|
CWnd * pwndFocus = GetFocus();
|
|
CListItem * pli;
|
|
|
|
if (m_pDocument != NULL) // this happens on system shutdown
|
|
{
|
|
// If the item has just lost or received the focus, save it and set the menu.
|
|
if ((pNMListView->uChanged & LVIF_STATE)
|
|
&& (pwndFocus == &GetListCtrl()))
|
|
{
|
|
ASSERT(pNMListView->iItem != -1);
|
|
|
|
// Get the item whose state is changing.
|
|
pli = (CListItem *) pNMListView->lParam;
|
|
ASSERT_VALID(pli);
|
|
|
|
if ((pNMListView->uOldState & LVIS_FOCUSED)
|
|
&& !(pNMListView->uNewState & LVIS_FOCUSED))
|
|
{
|
|
Trace(g_tagListView, _T("OnItemChanged() - '%s' lost focus"), pli->Pci()->StrName());
|
|
|
|
// Tell the document of the new selection.
|
|
GetDocument()->OnSelChanged(NULL);
|
|
} // if: old item losing focus
|
|
else if (!(pNMListView->uOldState & LVIS_FOCUSED)
|
|
&& (pNMListView->uNewState & LVIS_FOCUSED))
|
|
{
|
|
Trace(g_tagListView, _T("OnItemChanged() - '%s' received focus"), pli->Pci()->StrName());
|
|
|
|
// Tell the document of the new selection.
|
|
GetDocument()->OnSelChanged(pli->Pci());
|
|
} // else: new item receiving focus
|
|
} // if: item received the focus
|
|
} // if: document is available
|
|
|
|
*pResult = 0;
|
|
|
|
} //*** CClusterListView::OnItemChanged()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnActivateView
|
|
//
|
|
// Routine Description:
|
|
// Called when the view is activated.
|
|
//
|
|
// Arguments:
|
|
// bActivate [IN] Indicates whether the view being activated or deactivated.
|
|
// pActivateView [IN OUT] Points to the view object that is being activated.
|
|
// peactiveView [IN OUT] Points to the view object that is being deactivated.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnActivateView(
|
|
BOOL bActivate,
|
|
CView * pActivateView,
|
|
CView * pDeactiveView
|
|
)
|
|
{
|
|
CListItem * pliFocused = PliFocused();
|
|
|
|
if (m_pDocument != NULL) // this happens on system shutdown
|
|
{
|
|
if (bActivate && (pliFocused != NULL))
|
|
{
|
|
ASSERT_VALID(pliFocused->Pci());
|
|
Trace(g_tagListView, _T("OnActivateView() - '%s' received focus"), pliFocused->Pci()->StrName());
|
|
|
|
// Tell the document of the new selection.
|
|
GetDocument()->OnSelChanged(pliFocused->Pci());
|
|
} // if: we are being activated
|
|
} // if: document is available
|
|
|
|
CListView::OnActivateView(bActivate, pActivateView, pDeactiveView);
|
|
|
|
} //*** CClusterListView::OnActivateView()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnDestroy
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the WM_DESTROY message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnDestroy(void)
|
|
{
|
|
// Save the columns.
|
|
if (PtiParent() != NULL)
|
|
SaveColumns();
|
|
|
|
// Clean up the control.
|
|
DeleteAllItems();
|
|
|
|
CListView::OnDestroy();
|
|
|
|
} //*** CClusterListView::OnDestroy()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnColumnClick
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the LVN_COLUMNCLICK message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnColumnClick(NMHDR * pNMHDR, LRESULT * pResult)
|
|
{
|
|
NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;
|
|
int ili;
|
|
CListItem * pli;
|
|
POSITION pos;
|
|
CColumnItem * pcoli;
|
|
|
|
if (GetListCtrl().GetItemCount() != 0)
|
|
{
|
|
// Get the first item in the list.
|
|
ili = GetListCtrl().GetNextItem(-1, LVNI_ALL);
|
|
ASSERT(ili != -1);
|
|
pli = (CListItem *) GetListCtrl().GetItemData(ili);
|
|
ASSERT_VALID(pli);
|
|
ASSERT_VALID(pli->PtiParent());
|
|
|
|
// Get the column item to sort by.
|
|
pos = pli->PtiParent()->Lpcoli().FindIndex(pNMListView->iSubItem);
|
|
ASSERT(pos != NULL);
|
|
pcoli = pli->PtiParent()->Lpcoli().GetAt(pos);
|
|
ASSERT_VALID(pcoli);
|
|
|
|
// Save the current sort column and direction.
|
|
if (pcoli == PcoliSort())
|
|
m_nSortDirection ^= -1;
|
|
else
|
|
{
|
|
m_pcoliSort = pcoli;
|
|
m_nSortDirection = 0;
|
|
} // else: different column
|
|
|
|
// Sort the list.
|
|
GetListCtrl().SortItems(CompareItems, (LPARAM) this);
|
|
} // if: there are items in the list
|
|
|
|
*pResult = 0;
|
|
|
|
} //*** CClusterListView::OnColumnClick()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::CompareItems [static]
|
|
//
|
|
// Routine Description:
|
|
// Callback function for the CListCtrl::SortItems method.
|
|
//
|
|
// Arguments:
|
|
// lparam1 First item to compare.
|
|
// lparam2 Second item to compare.
|
|
// lparamSort Sort parameter.
|
|
//
|
|
// Return Value:
|
|
// -1 First parameter comes before second.
|
|
// 0 First and second parameters are the same.
|
|
// 1 First parameter comes after second.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int CALLBACK CClusterListView::CompareItems(
|
|
LPARAM lparam1,
|
|
LPARAM lparam2,
|
|
LPARAM lparamSort
|
|
)
|
|
{
|
|
CListItem * pli1 = (CListItem *) lparam1;
|
|
CListItem * pli2 = (CListItem *) lparam2;
|
|
CClusterListView * pclv = (CClusterListView *) lparamSort;
|
|
CString str1;
|
|
CString str2;
|
|
int nResult;
|
|
|
|
ASSERT_VALID(pli1);
|
|
ASSERT_VALID(pli2);
|
|
ASSERT_VALID(pli1->Pci());
|
|
ASSERT_VALID(pli2->Pci());
|
|
ASSERT_VALID(pclv);
|
|
ASSERT_VALID(pclv->PcoliSort());
|
|
|
|
// Get the strings from the list items.
|
|
pli1->Pci()->BGetColumnData(pclv->PcoliSort()->Colid(), str1);
|
|
pli2->Pci()->BGetColumnData(pclv->PcoliSort()->Colid(), str2);
|
|
|
|
// Compare the two strings.
|
|
// Use CompareString() so that it will sort properly on localized builds.
|
|
nResult = CompareString(
|
|
LOCALE_USER_DEFAULT,
|
|
0,
|
|
str1,
|
|
str1.GetLength(),
|
|
str2,
|
|
str2.GetLength()
|
|
);
|
|
if ( nResult == CSTR_LESS_THAN )
|
|
{
|
|
nResult = -1;
|
|
}
|
|
else if ( nResult == CSTR_EQUAL )
|
|
{
|
|
nResult = 0;
|
|
}
|
|
else if ( nResult == CSTR_GREATER_THAN )
|
|
{
|
|
nResult = 1;
|
|
}
|
|
else
|
|
{
|
|
// An error occurred. Ignore it.
|
|
nResult = 0;
|
|
}
|
|
|
|
// Return the result based on the direction we are sorting.
|
|
if (pclv->NSortDirection() != 0)
|
|
nResult = -nResult;
|
|
|
|
return nResult;
|
|
|
|
} //*** CClusterListView::CompareItems()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnDblClk
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the NM_DBLCLK message.
|
|
//
|
|
// Arguments:
|
|
// pNMHDR Notification message structure.
|
|
// pResult Place in which to return the result.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnDblClk(NMHDR * pNMHDR, LRESULT * pResult)
|
|
{
|
|
OpenItem();
|
|
*pResult = 0;
|
|
|
|
} //*** CClusterListView::OnDblClk()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OpenItem
|
|
//
|
|
// Routine Description:
|
|
// Open the item with the focus.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OpenItem(void)
|
|
{
|
|
CListItem * pliFocused = PliFocused();
|
|
|
|
if (m_pliBeingEdited == NULL)
|
|
{
|
|
// If an item has focus, open it or show its properties.
|
|
if (pliFocused != NULL)
|
|
{
|
|
CTreeItem * pti;
|
|
|
|
ASSERT_VALID(pliFocused->PtiParent());
|
|
|
|
Trace(g_tagListView, _T("Opening item '%s'"), pliFocused->Pci()->StrName());
|
|
|
|
// Find the item tree item for the list item.
|
|
pti = pliFocused->PtiParent()->PtiChildFromPci(pliFocused->Pci());
|
|
|
|
// If this item has a tree item, open it up. Otherwise show its
|
|
// properties.
|
|
if (pti != NULL)
|
|
{
|
|
CSplitterFrame * pframe;
|
|
|
|
// Get the frame pointer so we can talk to the tree view.
|
|
pframe = (CSplitterFrame *) GetParentFrame();
|
|
ASSERT_KINDOF(CSplitterFrame, pframe);
|
|
|
|
pliFocused->PtiParent()->OpenChild(pti, pframe);
|
|
} // if: item is openable
|
|
else
|
|
OnCmdProperties();
|
|
} // if: an item has focus
|
|
} // if: label not being edited
|
|
else
|
|
{
|
|
ASSERT_VALID(m_pliBeingEdited);
|
|
Trace(g_tagListView, _T("Not opening item '%s'"), m_pliBeingEdited->Pci()->StrName());
|
|
} // else if: label being edited
|
|
|
|
} //*** CClusterListView::OpenItem()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnBeginLabelEdit
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the LVN_BEGINLABELEDIT message.
|
|
//
|
|
// Arguments:
|
|
// pNMHDR Notification message structure.
|
|
// pResult Place in which to return the result.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnBeginLabelEdit(NMHDR * pNMHDR, LRESULT * pResult)
|
|
{
|
|
ASSERT(pNMHDR != NULL);
|
|
|
|
LV_DISPINFO * pDispInfo = (LV_DISPINFO *) pNMHDR;
|
|
CListItem * pli = (CListItem *) pDispInfo->item.lParam;
|
|
|
|
ASSERT(m_pliBeingEdited == NULL);
|
|
ASSERT_VALID(pli->Pci());
|
|
|
|
if (pli->Pci()->BCanBeEdited())
|
|
{
|
|
pli->Pci()->OnBeginLabelEdit(GetListCtrl().GetEditControl());
|
|
m_pliBeingEdited = pli;
|
|
*pResult = FALSE;
|
|
} // if: object can be renamed
|
|
else
|
|
*pResult = TRUE;
|
|
|
|
m_bShiftPressed = FALSE;
|
|
m_bControlPressed = FALSE;
|
|
m_bAltPressed = FALSE;
|
|
|
|
} //*** CClusterListView::OnBeginLabelEdit()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnEndLabelEdit
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the LVN_ENDLABELEDIT message.
|
|
//
|
|
// Arguments:
|
|
// pNMHDR Notification message structure.
|
|
// pResult Place in which to return the result.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnEndLabelEdit(NMHDR * pNMHDR, LRESULT * pResult)
|
|
{
|
|
ASSERT(pNMHDR != NULL);
|
|
|
|
LV_DISPINFO * pDispInfo = (LV_DISPINFO *) pNMHDR;
|
|
CListItem * pli = (CListItem *) pDispInfo->item.lParam;
|
|
|
|
ASSERT_VALID(pli);
|
|
ASSERT(pli == m_pliBeingEdited);
|
|
ASSERT_VALID(pli->Pci());
|
|
|
|
// If the edit wasn't cancelled, rename it.
|
|
if (pDispInfo->item.mask & LVIF_TEXT)
|
|
{
|
|
ASSERT(pli->Pci()->BCanBeEdited());
|
|
ASSERT(pDispInfo->item.pszText != NULL);
|
|
|
|
Trace(g_tagListView, _T("Ending edit of item '%s' (Saving as '%s')"), pli->Pci()->StrName(), pDispInfo->item.pszText);
|
|
|
|
if ( pli->Pci()->BIsLabelEditValueValid( pDispInfo->item.pszText ) )
|
|
{
|
|
try
|
|
{
|
|
pli->Pci()->Rename(pDispInfo->item.pszText);
|
|
*pResult = TRUE;
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
*pResult = FALSE;
|
|
} // catch: CException
|
|
} // if: name is valid
|
|
else
|
|
{
|
|
*pResult = FALSE;
|
|
}
|
|
} // if: the edit wasn't cancelled
|
|
else
|
|
{
|
|
Trace(g_tagListView, _T("Ending edit of item '%s' (Not Saving)"), pli->Pci()->StrName());
|
|
*pResult = TRUE;
|
|
} // else: edit was cancelled
|
|
|
|
m_pliBeingEdited = NULL;
|
|
m_bShiftPressed = FALSE;
|
|
m_bControlPressed = FALSE;
|
|
m_bAltPressed = FALSE;
|
|
|
|
} //*** CClusterListView::OnEndLabelEdit()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnBeginDrag
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the LVN_BEGINDRAG and LVN_BEGINRDRAG messages.
|
|
//
|
|
// Arguments:
|
|
// pNMHDR Notification message structure.
|
|
// pResult Place in which to return the result.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnBeginDrag(NMHDR * pNMHDR, LRESULT * pResult)
|
|
{
|
|
NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;
|
|
CListCtrl & rlc = GetListCtrl();
|
|
CPoint ptAction;
|
|
CClusterItem * pci = NULL;
|
|
CImageList * pimagelist;
|
|
|
|
ASSERT_VALID(Pframe());
|
|
|
|
// Get the item being dragged.
|
|
{
|
|
int ili;
|
|
CListItem * pli;
|
|
|
|
// Get the item being dragged.
|
|
ili = pNMListView->iItem;
|
|
pli = (CListItem *) rlc.GetItemData(ili);
|
|
ASSERT_VALID(pli);
|
|
ASSERT_KINDOF(CListItem, pli);
|
|
ASSERT_VALID(pli->Pci());
|
|
|
|
// If the item can not be dragged, abort the operation.
|
|
if (!pli->Pci()->BCanBeDragged())
|
|
return;
|
|
|
|
// Deselect the item being dragged.
|
|
rlc.SetItemState(ili, 0, LVIS_SELECTED);
|
|
|
|
// Save info for later.
|
|
m_iliDrag = ili;
|
|
m_pliDrag = pli;
|
|
m_iliDrop = -1;
|
|
pci = pli->Pci();
|
|
} // Get the item being dragged
|
|
|
|
// Create the image list and let the frame window initialize the drag operation.
|
|
{
|
|
CPoint ptImage;
|
|
CPoint ptFrameItem;
|
|
CPoint ptHotSpot;
|
|
|
|
pimagelist = rlc.CreateDragImage(m_iliDrag, &ptImage);
|
|
ASSERT(pimagelist != NULL);
|
|
ptFrameItem = pNMListView->ptAction;
|
|
Pframe()->ScreenToClient(&ptFrameItem);
|
|
|
|
// Calculate the hot spot point.
|
|
{
|
|
long lStyle = rlc.GetStyle() & LVS_TYPEMASK;
|
|
switch (lStyle)
|
|
{
|
|
case LVS_REPORT:
|
|
case LVS_LIST:
|
|
case LVS_SMALLICON:
|
|
ptHotSpot.x = 0;
|
|
ptHotSpot.y = -16;
|
|
break;
|
|
case LVS_ICON:
|
|
ptHotSpot.x = 8;
|
|
ptHotSpot.y = 8;
|
|
break;
|
|
} // switch: lStyle
|
|
} // Calculate the hot spot point
|
|
|
|
Trace(g_tagListDrag, _T("OnBeginDrag() - Dragging '%s' at (%d,%d)"), m_pliDrag->StrName(), ptFrameItem.x, ptFrameItem.y);
|
|
Pframe()->BeginDrag(pimagelist, pci, ptFrameItem, ptHotSpot);
|
|
pimagelist->SetDragCursorImage(0, CPoint(0, 0)); // define the hot spot for the new cursor image
|
|
} // Create the image list and let the frame window initialize the drag operation
|
|
|
|
*pResult = 0;
|
|
|
|
} //*** CClusterListView::OnBeginDrag(pNMHDR, pResult)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnMouseMoveForDrag
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the WM_MOUSEMOVE message during a drag operation.
|
|
// This function is only responsible for providing view-specific
|
|
// functionality, such as selecting the drop target if it is valid.
|
|
//
|
|
// Arguments:
|
|
// nFlags Indicates whether various virtual keys are down.
|
|
// point Specifies the x- and y-coordinate of the cursor in frame
|
|
// coordinates.
|
|
// pwndDrop Specifies the window under the cursor.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnMouseMoveForDrag(
|
|
IN UINT nFlags,
|
|
IN OUT CPoint point,
|
|
IN const CWnd * pwndDrop
|
|
)
|
|
{
|
|
ASSERT(BDragging());
|
|
ASSERT_VALID(Pframe());
|
|
|
|
// If we are dragging, select the drop target.
|
|
if (BDragging())
|
|
{
|
|
int ili;
|
|
UINT uFlags;
|
|
CPoint ptView;
|
|
CListCtrl & rlc = GetListCtrl();
|
|
|
|
// Convert the point to view coordinates.
|
|
ptView = point;
|
|
Pframe()->ClientToScreen(&ptView);
|
|
rlc.ScreenToClient(&ptView);
|
|
|
|
// If this window is the drop target, find the item under the cursor.
|
|
if (pwndDrop == &rlc)
|
|
{
|
|
// If we are over a list item, highlight it.
|
|
ili = rlc.HitTest(ptView, &uFlags);
|
|
if (ili != -1)
|
|
{
|
|
CListItem * pli;
|
|
|
|
// Get the item to be highlight.
|
|
pli = (CListItem *) rlc.GetItemData(ili);
|
|
ASSERT_VALID(pli);
|
|
ASSERT_KINDOF(CListItem, pli);
|
|
ASSERT_VALID(pli->Pci());
|
|
|
|
// If this is not a drop target, change the cursor.
|
|
if (pli->Pci()->BCanBeDropTarget(Pframe()->PciDrag()))
|
|
Pframe()->ChangeDragCursor(IDC_ARROW);
|
|
else
|
|
Pframe()->ChangeDragCursor(IDC_NO);
|
|
} // if: over a list item
|
|
} // if: this window is the drop target
|
|
else
|
|
ili = -1;
|
|
|
|
// If the drop target is or was in this view, update the view.
|
|
if ((ili != -1) || (m_iliDrop != -1))
|
|
{
|
|
// Unlock window updates.
|
|
VERIFY(Pimagelist()->DragShowNolock(FALSE /*bShow*/));
|
|
|
|
// Turn off highlight for the previous drop target.
|
|
if (m_iliDrop != -1)
|
|
{
|
|
VERIFY(rlc.SetItemState(m_iliDrop, 0, LVIS_DROPHILITED));
|
|
VERIFY(rlc.RedrawItems(m_iliDrop, m_iliDrop));
|
|
} // if: there was a previous drop target
|
|
|
|
// Highlight the new drop target.
|
|
if (ili != -1)
|
|
{
|
|
VERIFY(rlc.SetItemState(ili, LVIS_DROPHILITED, LVIS_DROPHILITED));
|
|
VERIFY(rlc.RedrawItems(ili, ili));
|
|
} // if: over an item
|
|
m_iliDrop = ili;
|
|
|
|
rlc.UpdateWindow();
|
|
VERIFY(Pimagelist()->DragShowNolock(TRUE /*bShow*/));
|
|
} // if: new or old drop target
|
|
|
|
} // if: list item is being dragged
|
|
|
|
} //*** CClusterListView::OnMouseMoveForDrag()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnButtonUpForDrag
|
|
//
|
|
// Routine Description:
|
|
// Called to handle a button up event during drag and drop.
|
|
//
|
|
// Arguments:
|
|
// nFlags Indicates whether various virtual keys are down.
|
|
// point Specifies the x- and y-coordinate of the cursor.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnButtonUpForDrag(IN UINT nFlags, IN CPoint point)
|
|
{
|
|
ASSERT(BDragging());
|
|
ASSERT_VALID(Pframe());
|
|
ASSERT_VALID(Pframe()->PciDrag());
|
|
|
|
// If we are dragging, process the drop.
|
|
if (BDragging())
|
|
{
|
|
int ili;
|
|
UINT flags;
|
|
CPoint ptView;
|
|
CListCtrl & rlc = GetListCtrl();
|
|
|
|
Trace(g_tagListDrag, _T("OnButtonUpForDrag()"));
|
|
|
|
// Convert the point to view coordinates.
|
|
ptView = point;
|
|
Pframe()->ClientToScreen(&ptView);
|
|
rlc.ScreenToClient(&ptView);
|
|
|
|
// If we are over a tree item, drop the item being dragged.
|
|
ili = rlc.HitTest(ptView, &flags);
|
|
if (ili != -1)
|
|
{
|
|
CListItem * pliDropTarget;
|
|
|
|
// Get the item to drop on.
|
|
pliDropTarget = (CListItem *) rlc.GetItemData(ili);
|
|
ASSERT_VALID(pliDropTarget);
|
|
ASSERT_KINDOF(CListItem, pliDropTarget);
|
|
ASSERT_VALID(pliDropTarget->Pci());
|
|
|
|
if (pliDropTarget->Pci() != Pframe()->PciDrag())
|
|
pliDropTarget->Pci()->DropItem(Pframe()->PciDrag());
|
|
} // if: over a tree item
|
|
} // if: tree item is being dragged
|
|
|
|
} //*** CClusterListView::OnButtonUpForDrag()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::BeginDrag
|
|
//
|
|
// Routine Description:
|
|
// Called by the frame to begin a drag operation.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::BeginDrag(void)
|
|
{
|
|
Trace(g_tagListDrag, _T("BeginDrag()"));
|
|
|
|
} //*** CClusterListView::BeginDrag()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::EndDrag
|
|
//
|
|
// Routine Description:
|
|
// Called by the frame to end a drag operation.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::EndDrag(void)
|
|
{
|
|
// Clear and reset highlights. The second one can fail, since the item
|
|
// could be removed from the list by this time.
|
|
if (m_iliDrop != -1)
|
|
VERIFY(GetListCtrl().SetItemState(m_iliDrop, 0, LVIS_DROPHILITED));
|
|
if (m_iliDrag != -1)
|
|
GetListCtrl().SetItemState(m_iliDrag, LVIS_SELECTED, LVIS_SELECTED);
|
|
|
|
m_iliDrag = -1;
|
|
m_pliDrag = NULL;
|
|
m_iliDrop = -1;
|
|
|
|
Trace(g_tagListDrag, _T("EndDrag()"));
|
|
|
|
} //*** CClusterListView::EndDrag()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::PreTranslateMessage
|
|
//
|
|
// Routine Description:
|
|
// Translate window messages before they are dispatched.
|
|
// This is necessary for handling keystrokes properly while editing
|
|
// the label on an item.
|
|
//
|
|
// Arguments:
|
|
// pMsg Points to a MSG structure that contains the message to process.
|
|
//
|
|
// Return Value:
|
|
// TRUE Message was handled.
|
|
// FALSE Message was not handled.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterListView::PreTranslateMessage(MSG * pMsg)
|
|
{
|
|
BOOL bForward = FALSE;
|
|
|
|
if (m_pliBeingEdited != NULL)
|
|
{
|
|
CEdit * pedit = GetListCtrl().GetEditControl();
|
|
ASSERT(pedit != NULL);
|
|
|
|
if (pMsg->message == WM_KEYDOWN)
|
|
{
|
|
if (pMsg->wParam == VK_SHIFT)
|
|
m_bShiftPressed = TRUE;
|
|
else if (pMsg->wParam == VK_CONTROL)
|
|
{
|
|
::CopyMemory(&m_msgControl, pMsg, sizeof(m_msgControl));
|
|
m_bControlPressed = TRUE;
|
|
} // else if: control key pressed
|
|
else if ((pMsg->wParam == VK_RETURN)
|
|
|| (pMsg->wParam == VK_ESCAPE)
|
|
|| (pMsg->wParam == VK_INSERT)
|
|
|| (pMsg->wParam == VK_DELETE)
|
|
|| (pMsg->wParam == VK_F1)
|
|
|| (pMsg->wParam == VK_F5)
|
|
|| (pMsg->wParam == VK_F6)
|
|
)
|
|
{
|
|
Trace(g_tagListView, _T("PreTranslateMessage() - Forwarding WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
|
|
bForward = TRUE;
|
|
if (m_bControlPressed)
|
|
{
|
|
if (pMsg->wParam == VK_RETURN)
|
|
pedit->SendMessage(WM_KEYUP, m_msgControl.wParam, m_msgControl.lParam);
|
|
} // if: control key pressed
|
|
} // else if: editing key pressed
|
|
else if ((pMsg->wParam == VK_TAB)
|
|
|| (m_bControlPressed
|
|
&& (_T('A') <= pMsg->wParam) && (pMsg->wParam <= _T('Y'))
|
|
&& (pMsg->wParam != _T('C'))
|
|
&& (pMsg->wParam != _T('H'))
|
|
&& (pMsg->wParam != _T('M'))
|
|
&& (pMsg->wParam != _T('V'))
|
|
&& (pMsg->wParam != _T('X'))
|
|
)
|
|
)
|
|
{
|
|
Trace(g_tagListView, _T("PreTranslateMessage() - Ignoring WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
return TRUE;
|
|
} // else if: key pressed that should be ignored
|
|
#ifdef NEVER
|
|
else
|
|
{
|
|
Trace(g_tagListView, _T("PreTranslateMessage() - Not forwarding WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
|
|
} // else: not processing key
|
|
#endif
|
|
} // if: key pressed while editing label
|
|
else if (pMsg->message == WM_SYSKEYDOWN)
|
|
{
|
|
if (pMsg->wParam == VK_MENU)
|
|
m_bAltPressed = TRUE;
|
|
else if ((pMsg->wParam == VK_RETURN)
|
|
)
|
|
{
|
|
Trace(g_tagListView, _T("PreTranslateMessage() - Forwarding WM_SYSKEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
|
|
bForward = TRUE;
|
|
} // else if: editing key pressed
|
|
#ifdef NEVER
|
|
else
|
|
{
|
|
Trace(g_tagListView, _T("PreTranslateMessage() - Not forwarding WM_SYSKEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
|
|
} // else: not processing key
|
|
#endif
|
|
} // else if: system key pressed while editing label
|
|
if (bForward)
|
|
{
|
|
pedit->SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
|
|
return TRUE;
|
|
} // if: forwarding the message
|
|
else if (pMsg->message == WM_KEYUP)
|
|
{
|
|
if (pMsg->wParam == VK_SHIFT)
|
|
m_bShiftPressed = FALSE;
|
|
else if (pMsg->wParam == VK_CONTROL)
|
|
m_bControlPressed = FALSE;
|
|
} // else if: key up
|
|
else if (pMsg->message == WM_SYSKEYUP)
|
|
{
|
|
if (pMsg->wParam == VK_MENU)
|
|
m_bAltPressed = FALSE;
|
|
} // else if: system key up
|
|
} // if: editing a label
|
|
|
|
return CListView::PreTranslateMessage(pMsg);
|
|
|
|
} //*** CClusterListView::PreTranslateMessage()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnCmdRename
|
|
//
|
|
// Routine Description:
|
|
// Processes the ID_FILE_RENAME menu command.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnCmdRename(void)
|
|
{
|
|
CListItem * pliFocused = PliFocused();
|
|
|
|
// If an item has focus, begin label editing
|
|
if (pliFocused != NULL)
|
|
{
|
|
ASSERT_VALID(pliFocused);
|
|
pliFocused->EditLabel(this);
|
|
} // if: an item has the focus
|
|
|
|
} //*** CClusterListView::OnCmdRename()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::SetView
|
|
//
|
|
// Routine Description:
|
|
// Set the current view of the list view control.
|
|
//
|
|
// Arguments:
|
|
// dwView [IN] List view to set.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::SetView(IN DWORD dwView)
|
|
{
|
|
// Get the current window style.
|
|
DWORD dwStyle = GetWindowLong(GetListCtrl().m_hWnd, GWL_STYLE);
|
|
|
|
// Only set the window style if the view bits have changed.
|
|
if ((dwStyle & LVS_TYPEMASK) != dwView)
|
|
{
|
|
// Save the column information before switching out of report view.
|
|
if ((dwStyle & LVS_REPORT) && (PtiParent() != NULL))
|
|
SaveColumns();
|
|
|
|
// Set the new view.
|
|
SetWindowLong(GetListCtrl().m_hWnd, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | dwView);
|
|
} // if: view has changed
|
|
|
|
} //*** CClusterListView::SetView()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterListView::OnKeyDown
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the LVN_KEYDOWN message.
|
|
//
|
|
// Arguments:
|
|
// pNMHDR Notification message structure.
|
|
// pResult Place in which to return the result.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterListView::OnKeyDown(NMHDR * pNMHDR, LRESULT * pResult)
|
|
{
|
|
LV_KEYDOWN * pLVKeyDown = (LV_KEYDOWN *) pNMHDR;
|
|
|
|
if (BDragging() && (pLVKeyDown->wVKey == VK_ESCAPE))
|
|
Pframe()->AbortDrag();
|
|
|
|
*pResult = 0;
|
|
|
|
} //*** CClusterListView::OnKeyDown()
|