windows-nt/Source/XPSP1/NT/net/mmc/common/listctrl.cpp
2020-09-26 16:20:57 +08:00

463 lines
10 KiB
C++

//============================================================================
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: lcx.cpp
//
// History:
// 07/13/96 Abolade Gbadegesin Created, based on C code by Steve Cobb
//
// Implements an enhanced list-control.
//============================================================================
#include "stdafx.h"
#include "resource.h"
#include "util.h"
#include "listctrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CListCtrlEx, CListCtrl)
BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
//{{AFX_MSG_MAP(CListCtrlEx)
ON_WM_LBUTTONDOWN()
ON_WM_CHAR()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//----------------------------------------------------------------------------
// Function: CListCtrlEx::~CListCtrlEx
//
// Destructor. Deletes the image list, if any, and unloads row-information.
//----------------------------------------------------------------------------
CListCtrlEx::~CListCtrlEx(
) {
delete m_pimlChecks;
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::GetColumnCount
//
// Called to retrieve the number of columns in any list-control.
//----------------------------------------------------------------------------
INT
CListCtrlEx::GetColumnCount(
) {
return Header_GetItemCount(ListView_GetHeader(m_hWnd));
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::SetColumnText
//
// Sets the text in the header of the column in position 'iCol'.
//----------------------------------------------------------------------------
BOOL
CListCtrlEx::SetColumnText(
INT iCol,
LPCTSTR pszText,
INT fmt
) {
LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_TEXT;
lvc.pszText = (LPTSTR)pszText;
lvc.fmt = fmt;
return SetColumn(iCol, &lvc);
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::InstallChecks
//
// Installs check-box handling for the list-control.
//----------------------------------------------------------------------------
BOOL
CListCtrlEx::InstallChecks(
) {
HICON hIcon;
//
// Make sure the list-control is in report-mode
//
if (!(GetStyle() & LVS_REPORT)) { return FALSE; }
//
// Allocate a new image-list.
//
m_pimlChecks = new CImageList;
if (!m_pimlChecks) { return FALSE; }
do {
//
// Initialize the image-list
//
if (!m_pimlChecks->Create(
::GetSystemMetrics(SM_CXSMICON),
::GetSystemMetrics(SM_CYSMICON),
ILC_MASK, 2, 2
)) {
break;
}
//
// Add the icons for the checked and unchecked images
//
hIcon = ::LoadIcon(
AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_COMMON_UNCHECK)
);
if (!hIcon) { break; }
m_pimlChecks->Add(hIcon); ::DeleteObject(hIcon);
hIcon = ::LoadIcon(
AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_COMMON_CHECK)
);
if (!hIcon) { break; }
m_pimlChecks->Add(hIcon); ::DeleteObject(hIcon);
//
// Replace the list-control's current image-list with the new one
//
m_pimlOldState = SetImageList(m_pimlChecks, LVSIL_STATE);
return TRUE;
} while(FALSE);
//
// If we arrive here, an error occurred, so clean up and fail
//
delete m_pimlChecks; m_pimlChecks = NULL;
return FALSE;
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::UninstallChecks
//
// Uninstalls checkbox-handling for the list-control.
//----------------------------------------------------------------------------
VOID
CListCtrlEx::UninstallChecks(
) {
if (!m_pimlChecks) { return; }
if (m_pimlOldState) { SetImageList(m_pimlOldState, LVSIL_STATE); }
delete m_pimlChecks; m_pimlChecks = NULL;
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::GetCheck
//
// Returns TRUE if the specified item is checked, FALSE otherwise.
//----------------------------------------------------------------------------
BOOL
CListCtrlEx::GetCheck(
INT iItem
) {
return !!(GetItemState(iItem, LVIS_STATEIMAGEMASK) &
INDEXTOSTATEIMAGEMASK(LCXI_CHECKED));
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::SetCheck
//
// If 'fCheck' is non-zero, checks 'iItem', otherwise clears 'iItem'.
//----------------------------------------------------------------------------
VOID
CListCtrlEx::SetCheck(
INT iItem,
BOOL fCheck
) {
SetItemState(
iItem,
INDEXTOSTATEIMAGEMASK(fCheck ? LCXI_CHECKED : LCXI_UNCHECKED),
LVIS_STATEIMAGEMASK
);
if (GetParent()) {
NMHDR nmh;
nmh.code = LVXN_SETCHECK;
nmh.hwndFrom = m_hWnd;
::SendMessage(
GetParent()->m_hWnd, WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmh
);
}
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::OnChar
//
// Handles the 'WM_CHAR' message for the list-control.
// This allows users to change items' checked-states using the keyboard.
//----------------------------------------------------------------------------
VOID
CListCtrlEx::OnChar(
UINT nChar,
UINT nRepCnt,
UINT nFlags
) {
BOOL fSet = FALSE;
BOOL fClear = FALSE;
BOOL fToggle = FALSE;
INT iItem;
//
// Handle characters with special meaning for us
//
switch (nChar) {
case TEXT(' '): { fToggle = TRUE; break; }
case TEXT('+'):
case TEXT('='): { fSet = TRUE; break; }
case TEXT('-'): { fClear = TRUE; break; }
}
if (!fToggle && !fSet && !fClear) {
CListCtrl::OnChar(nChar, nRepCnt, nFlags);
}
else {
//
// Change the state of all the selected items
//
for (iItem = GetNextItem(-1, LVNI_SELECTED);
iItem != -1;
iItem = GetNextItem(iItem, LVNI_SELECTED)) {
if (fToggle) {
SetCheck(iItem, !GetCheck(iItem));
}
else
if (fSet) {
if (!GetCheck(iItem)) { SetCheck(iItem, TRUE); }
}
else {
if (GetCheck(iItem)) { SetCheck(iItem, FALSE); }
}
}
}
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::OnKeyDown
//
// Handles the 'WM_KEYDOWN' message for the list-control.
// This allows users to change items' checked-states using the keyboard.
//----------------------------------------------------------------------------
VOID
CListCtrlEx::OnKeyDown(
UINT nChar,
UINT nRepCnt,
UINT nFlags
) {
//
// We want the left-arrow treated as an up-arrow
// and the right-arrow treated as a down-arrow.
//
if (nChar == VK_LEFT) {
CListCtrl::OnKeyDown(VK_UP, nRepCnt, nFlags); return;
}
else
if (nChar == VK_RIGHT) {
CListCtrl::OnKeyDown(VK_DOWN, nRepCnt, nFlags); return;
}
CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}
//----------------------------------------------------------------------------
// Function: CListCtrlEx::OnLButtonDown
//
// Handles the 'WM_LBUTTONDOWN' message, changing an item's checked state
// when the user clicks the item's check-image.
//----------------------------------------------------------------------------
VOID
CListCtrlEx::OnLButtonDown(
UINT nFlags,
CPoint pt
) {
INT iItem;
UINT uiFlags;
//
// If the left-mouse button is over the check-box icon,
// we treat it as a toggle on the check-box.
//
uiFlags = 0;
iItem = HitTest(pt, &uiFlags);
if (iItem != -1 && (uiFlags & LVHT_ONITEMSTATEICON)) {
SetCheck(iItem, !GetCheck(iItem));
// Redraw this item
RedrawItems(iItem, iItem);
}
CListCtrl::OnLButtonDown(nFlags, pt);
}
//----------------------------------------------------------------------------
// Function: AdjustColumnWidth
//
// Called to adjust the width of column 'iCol' so that the string 'pszContent'
// can be displayed in the column without truncation.
//
// If 'NULL' is specified for 'pszContent', the function adjusts the column
// so that the first string in the column is displayed without truncation.
//
// Returns the new width of the column.
//----------------------------------------------------------------------------
INT
AdjustColumnWidth(
IN CListCtrl& listCtrl,
IN INT iCol,
IN LPCTSTR pszContent
) {
INT iWidth, iOldWidth;
//
// Compute the minimum width the column needs to be
//
if (pszContent) {
iWidth = listCtrl.GetStringWidth(pszContent);
}
else {
iWidth = listCtrl.GetStringWidth(listCtrl.GetItemText(0, iCol));
}
//
// Adjust 'iWidth' to leave some breathing space
//
iWidth += ::GetSystemMetrics(SM_CXSMICON) +
::GetSystemMetrics(SM_CXEDGE) * 2;
//
// If the column is narrower than 'iWidth', enlarge it.
//
iOldWidth = listCtrl.GetColumnWidth(iCol);
if (iOldWidth < iWidth) {
listCtrl.SetColumnWidth(iCol, iWidth);
iOldWidth = iWidth;
}
return iOldWidth;
}
INT
AdjustColumnWidth(
IN CListCtrl& listCtrl,
IN INT iCol,
IN UINT idsContent
) {
// Needed for Loadstring
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString sCol;
sCol.LoadString(idsContent);
return AdjustColumnWidth(listCtrl, iCol, sCol);
}