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.
902 lines
26 KiB
902 lines
26 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: statsdlg.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
// StatsDlg.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "StatsDlg.h"
|
|
#include "coldlg.h"
|
|
#include "modeless.h" // ModelessThread
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CStatsListCtrl, CListCtrl)
|
|
//{{AFX_MSG_MAP(CStatsListCtrl)
|
|
ON_WM_KEYDOWN()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
void CStatsListCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
BOOL fControlDown;
|
|
BOOL fShiftDown;
|
|
|
|
fControlDown = (GetKeyState(VK_CONTROL) < 0);
|
|
fShiftDown = (GetKeyState(VK_SHIFT) < 0);
|
|
|
|
switch(nChar)
|
|
{
|
|
case 'c':
|
|
case 'C':
|
|
case VK_INSERT:
|
|
if (fControlDown)
|
|
CopyToClipboard();
|
|
break;
|
|
}
|
|
|
|
CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CStatsListCtrl::CopyToClipboard()
|
|
{
|
|
CString strText, strLine, strData;
|
|
int nCount = GetItemCount();
|
|
int nColumns = 0;
|
|
TCHAR szBuffer[256];
|
|
LV_COLUMN ColumnInfo = {0};
|
|
|
|
ColumnInfo.mask = LVCF_TEXT;
|
|
ColumnInfo.pszText = szBuffer;
|
|
ColumnInfo.cchTextMax = sizeof(szBuffer);
|
|
|
|
// build up the column info
|
|
while (GetColumn(nColumns, &ColumnInfo))
|
|
{
|
|
if (!strLine.IsEmpty())
|
|
strLine += _T(",");
|
|
|
|
strLine += ColumnInfo.pszText;
|
|
|
|
nColumns++;
|
|
}
|
|
|
|
strLine += _T("\r\n");
|
|
strData += strLine;
|
|
strLine.Empty();
|
|
|
|
// now get the other data
|
|
for (int i = 0; i < nCount; i++)
|
|
{
|
|
for (int j = 0; j < nColumns; j++)
|
|
{
|
|
if (!strLine.IsEmpty())
|
|
strLine += _T(",");
|
|
|
|
strText = GetItemText(i, j);
|
|
|
|
strLine += strText;
|
|
}
|
|
|
|
strLine += _T("\r\n");
|
|
|
|
strData += strLine;
|
|
strLine.Empty();
|
|
}
|
|
|
|
int nLength = strData.GetLength() + 1;
|
|
nLength *= sizeof(TCHAR);
|
|
|
|
HGLOBAL hMem = GlobalAlloc(GPTR, nLength);
|
|
if (hMem)
|
|
{
|
|
memcpy (hMem, strData, nLength);
|
|
|
|
if (!OpenClipboard())
|
|
{
|
|
GlobalFree(hMem);
|
|
return;
|
|
}
|
|
|
|
EmptyClipboard();
|
|
|
|
SetClipboardData(CF_UNICODETEXT, hMem);
|
|
|
|
CloseClipboard();
|
|
}
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::StatsDialog
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
StatsDialog::StatsDialog(DWORD dwOptions) :
|
|
m_dwOptions(dwOptions),
|
|
m_ulId(0),
|
|
m_pConfig(NULL),
|
|
m_bAfterInitDialog(FALSE)
|
|
{
|
|
m_sizeMinimum.cx = m_sizeMinimum.cy = 0;
|
|
|
|
m_hEventThreadKilled = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
Assert(m_hEventThreadKilled);
|
|
|
|
// Initialize the array of buttons
|
|
::ZeroMemory(m_rgBtn, sizeof(m_rgBtn));
|
|
m_rgBtn[INDEX_CLOSE].m_ulId = IDCANCEL;
|
|
m_rgBtn[INDEX_REFRESH].m_ulId = IDC_STATSDLG_BTN_REFRESH;
|
|
m_rgBtn[INDEX_SELECT].m_ulId = IDC_STATSDLG_BTN_SELECT_COLUMNS;
|
|
m_rgBtn[INDEX_CLEAR].m_ulId = IDC_STATSDLG_BTN_CLEAR;
|
|
|
|
// Bug 134785 - create the ability to default to an ascending
|
|
// rather than a descending sort.
|
|
m_fSortDirection = !((dwOptions & STATSDLG_DEFAULTSORT_ASCENDING) != 0);
|
|
m_fDefaultSortDirection = m_fSortDirection;
|
|
|
|
// Multiply text header width with 2 for width of columns
|
|
m_ColWidthMultiple = 2;
|
|
m_ColWidthAdder = 0;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::~StatsDialog
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
StatsDialog::~StatsDialog()
|
|
{
|
|
if (m_hEventThreadKilled)
|
|
::CloseHandle(m_hEventThreadKilled);
|
|
m_hEventThreadKilled = 0;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::DoDataExchange
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CBaseDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(StatsDialog)
|
|
// NOTE: the ClassWizard will add DDX and DDV calls here
|
|
DDX_Control(pDX, IDC_STATSDLG_LIST, m_listCtrl);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(StatsDialog, CBaseDialog)
|
|
//{{AFX_MSG_MAP(StatsDialog)
|
|
ON_COMMAND(IDC_STATSDLG_BTN_REFRESH, OnRefresh)
|
|
ON_COMMAND(IDC_STATSDLG_BTN_SELECT_COLUMNS, OnSelectColumns)
|
|
ON_WM_MOVE()
|
|
ON_WM_SIZE()
|
|
ON_WM_GETMINMAXINFO()
|
|
ON_WM_CONTEXTMENU()
|
|
ON_NOTIFY(LVN_COLUMNCLICK, IDC_STATSDLG_LIST, OnNotifyListControlClick)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// StatsDialog message handlers
|
|
|
|
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::SetColumnInfo
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT StatsDialog::SetColumnInfo(const ContainerColumnInfo *pColumnInfo, UINT cColumnInfo)
|
|
{
|
|
if (m_pConfig)
|
|
{
|
|
m_pConfig->InitViewInfo(m_ulId, TRUE, cColumnInfo, m_fDefaultSortDirection, pColumnInfo);
|
|
}
|
|
else
|
|
{
|
|
m_viewInfo.InitViewInfo(cColumnInfo, TRUE, m_fDefaultSortDirection, pColumnInfo);
|
|
}
|
|
return hrOK;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::MapColumnToSubitem
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
int StatsDialog::MapColumnToSubitem(UINT nColumnId)
|
|
{
|
|
if (m_pConfig)
|
|
return m_pConfig->MapColumnToSubitem(m_ulId, nColumnId);
|
|
else
|
|
return m_viewInfo.MapColumnToSubitem(nColumnId);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::MapSubitemToColumn
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
int StatsDialog::MapSubitemToColumn(UINT nSubitemId)
|
|
{
|
|
if (m_pConfig)
|
|
return m_pConfig->MapSubitemToColumn(m_ulId, nSubitemId);
|
|
else
|
|
return m_viewInfo.MapSubitemToColumn(nSubitemId);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::IsSubitemVisible
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
BOOL StatsDialog::IsSubitemVisible(UINT nSubitemId)
|
|
{
|
|
if (m_pConfig)
|
|
return m_pConfig->IsSubitemVisible(m_ulId, nSubitemId);
|
|
else
|
|
return m_viewInfo.IsSubitemVisible(nSubitemId);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::RefreshData
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT StatsDialog::RefreshData(BOOL fGrabNewData)
|
|
{
|
|
return hrOK;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::OnInitDialog
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
BOOL StatsDialog::OnInitDialog()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
RECT rcWnd, rcBtn;
|
|
|
|
CBaseDialog::OnInitDialog();
|
|
|
|
m_bAfterInitDialog = TRUE;
|
|
|
|
// If this is the first time, get the location of the buttons and
|
|
// list control relative to the edge of the screen
|
|
if (m_sizeMinimum.cx == 0)
|
|
{
|
|
::GetWindowRect(GetSafeHwnd(), &rcWnd);
|
|
// m_sizeMinimum.cx = rcWnd.right - rcWnd.left;
|
|
// m_sizeMinimum.cy = rcWnd.bottom - rcWnd.top;
|
|
m_sizeMinimum.cx = 100;
|
|
m_sizeMinimum.cy = 100;
|
|
|
|
::GetClientRect(GetSafeHwnd(), &rcWnd);
|
|
|
|
// what are the button locations?
|
|
for (int i=0; i<INDEX_COUNT; i++)
|
|
{
|
|
::GetWindowRect(GetDlgItem(m_rgBtn[i].m_ulId)->GetSafeHwnd(),
|
|
&rcBtn);
|
|
ScreenToClient(&rcBtn);
|
|
m_rgBtn[i].m_rc.left = rcWnd.right - rcBtn.left;
|
|
m_rgBtn[i].m_rc.right = rcWnd.right - rcBtn.right;
|
|
m_rgBtn[i].m_rc.top = rcWnd.bottom - rcBtn.top;
|
|
m_rgBtn[i].m_rc.bottom = rcWnd.bottom - rcBtn.bottom;
|
|
}
|
|
|
|
// what is the list control location?
|
|
// The list control top, left is locked in position
|
|
::GetWindowRect(GetDlgItem(IDC_STATSDLG_LIST)->GetSafeHwnd(), &rcBtn);
|
|
ScreenToClient(&rcBtn);
|
|
m_rcList.left = rcBtn.left;
|
|
m_rcList.top = rcBtn.top;
|
|
|
|
// The bottom, right corner follows the expansion
|
|
m_rcList.right = rcWnd.right - rcBtn.right;
|
|
m_rcList.bottom = rcWnd.bottom - rcBtn.bottom;
|
|
}
|
|
|
|
// If we have a preferred position and size do that
|
|
if (m_pConfig)
|
|
{
|
|
m_pConfig->GetStatsWindowRect(m_ulId, &m_rcPosition);
|
|
m_fSortDirection = m_pConfig->GetSortDirection(m_ulId);
|
|
}
|
|
if (m_pConfig && (m_rcPosition.top != m_rcPosition.bottom))
|
|
{
|
|
MoveWindow(m_rcPosition.left, m_rcPosition.top,
|
|
m_rcPosition.right - m_rcPosition.left,
|
|
m_rcPosition.bottom - m_rcPosition.top);
|
|
}
|
|
|
|
if (m_dwOptions & STATSDLG_FULLWINDOW)
|
|
{
|
|
RECT rcClient;
|
|
|
|
// Resize the list control if needed
|
|
GetClientRect(&rcClient);
|
|
OnSize(SIZE_MAXIMIZED, rcClient.right - rcClient.left,
|
|
rcClient.bottom - rcClient.top);
|
|
|
|
// Disable the buttons also
|
|
for (int i=0; i<INDEX_COUNT; i++)
|
|
{
|
|
GetDlgItem(m_rgBtn[i].m_ulId)->ShowWindow(SW_HIDE);
|
|
|
|
if (i != INDEX_CLOSE)
|
|
GetDlgItem(m_rgBtn[i].m_ulId)->EnableWindow(FALSE);
|
|
}
|
|
}
|
|
|
|
// If we do not have the select columns then we hide and disable
|
|
// the select columns button.
|
|
if ((m_dwOptions & STATSDLG_SELECT_COLUMNS) == 0)
|
|
{
|
|
GetDlgItem(m_rgBtn[INDEX_SELECT].m_ulId)->ShowWindow(SW_HIDE);
|
|
GetDlgItem(m_rgBtn[INDEX_SELECT].m_ulId)->EnableWindow(FALSE);
|
|
}
|
|
|
|
// If we do not have the clear button then we hide and disable
|
|
// the clear button.
|
|
if ((m_dwOptions & STATSDLG_CLEAR) == 0)
|
|
{
|
|
GetDlgItem(m_rgBtn[INDEX_CLEAR].m_ulId)->ShowWindow(SW_HIDE);
|
|
GetDlgItem(m_rgBtn[INDEX_CLEAR].m_ulId)->EnableWindow(FALSE);
|
|
}
|
|
|
|
ListView_SetExtendedListViewStyle(GetDlgItem(IDC_STATSDLG_LIST)->GetSafeHwnd(), LVS_EX_FULLROWSELECT);
|
|
|
|
// Now initialize the headers
|
|
LoadHeaders();
|
|
|
|
RefreshData(TRUE);
|
|
|
|
if (m_pConfig)
|
|
{
|
|
Sort( m_pConfig->GetSortColumn(m_ulId) );
|
|
}
|
|
|
|
if ((m_dwOptions & STATSDLG_FULLWINDOW) == 0)
|
|
{
|
|
GetDlgItem(IDCANCEL)->SetFocus();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::OnOK
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::OnOK()
|
|
{
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::OnCancel
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::OnCancel()
|
|
{
|
|
DeleteAllItems();
|
|
|
|
DestroyWindow();
|
|
|
|
// Explicitly kill this thread.
|
|
AfxPostQuitMessage(0);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::PostNcDestroy
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::PostNcDestroy()
|
|
{
|
|
// Make sure that this is NULL since this is how we detect that
|
|
// the dialog is showing
|
|
m_hWnd = NULL;
|
|
m_bAfterInitDialog = FALSE;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::PreCreateWindow
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
BOOL StatsDialog::PreCreateWindow(CREATESTRUCT& cs)
|
|
{
|
|
// Have to refresh the event
|
|
Verify( ResetEvent(m_hEventThreadKilled) );
|
|
return CBaseDialog::PreCreateWindow(cs);
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::OnRefresh
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::OnRefresh()
|
|
{
|
|
if ((m_dwOptions & STATSDLG_VERTICAL) == 0)
|
|
{
|
|
DeleteAllItems();
|
|
}
|
|
|
|
RefreshData(TRUE);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::OnSelectColumns
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::OnSelectColumns()
|
|
{
|
|
// We should bring up the columns dialog
|
|
ColumnDlg columnDlg(NULL);
|
|
ColumnData *pColumnData;
|
|
ULONG cColumns;
|
|
ULONG cVisible;
|
|
int i;
|
|
DWORD dwWidth;
|
|
|
|
if (m_pConfig)
|
|
{
|
|
cColumns = m_pConfig->GetColumnCount(m_ulId);
|
|
cVisible = m_pConfig->GetVisibleColumns(m_ulId);
|
|
}
|
|
else
|
|
{
|
|
cColumns = m_viewInfo.GetColumnCount();
|
|
cVisible = m_viewInfo.GetVisibleColumns();
|
|
}
|
|
|
|
pColumnData = (ColumnData *) alloca(sizeof(ColumnData) * cColumns);
|
|
|
|
if (m_pConfig)
|
|
m_pConfig->GetColumnData(m_ulId, cColumns, pColumnData);
|
|
else
|
|
m_viewInfo.GetColumnData(cColumns, pColumnData);
|
|
|
|
// Save the column width information
|
|
if ((m_dwOptions & STATSDLG_VERTICAL) == 0)
|
|
{
|
|
for (i=0; i<(int) cVisible; i++)
|
|
{
|
|
dwWidth = m_listCtrl.GetColumnWidth(i);
|
|
if (m_pConfig)
|
|
pColumnData[m_pConfig->MapColumnToSubitem(m_ulId, i)].m_dwWidth = dwWidth;
|
|
else
|
|
pColumnData[m_viewInfo.MapColumnToSubitem(i)].m_dwWidth = dwWidth;
|
|
}
|
|
}
|
|
|
|
columnDlg.Init(m_pConfig ?
|
|
m_pConfig->GetColumnInfo(m_ulId) :
|
|
m_viewInfo.GetColumnInfo(),
|
|
cColumns,
|
|
pColumnData
|
|
);
|
|
|
|
if (columnDlg.DoModal() == IDOK)
|
|
{
|
|
if (m_dwOptions & STATSDLG_VERTICAL)
|
|
{
|
|
//$ HACK HACK
|
|
// To save the column info for vertical columns we will save the
|
|
// width data in the first two "columns"
|
|
pColumnData[0].m_dwWidth = m_listCtrl.GetColumnWidth(0);
|
|
pColumnData[1].m_dwWidth = m_listCtrl.GetColumnWidth(1);
|
|
}
|
|
|
|
// Set the information back in
|
|
if (m_pConfig)
|
|
m_pConfig->SetColumnData(m_ulId, cColumns, pColumnData);
|
|
else
|
|
m_viewInfo.SetColumnData(cColumns, pColumnData);
|
|
|
|
// Clear out the data
|
|
DeleteAllItems();
|
|
|
|
// Remove all of the columns
|
|
if (m_dwOptions & STATSDLG_VERTICAL)
|
|
{
|
|
m_listCtrl.DeleteColumn(1);
|
|
m_listCtrl.DeleteColumn(0);
|
|
}
|
|
else
|
|
{
|
|
for (i=(int) cVisible; --i >= 0; )
|
|
m_listCtrl.DeleteColumn(i);
|
|
}
|
|
|
|
// Readd all of the columns
|
|
LoadHeaders();
|
|
|
|
// Do a refresh
|
|
RefreshData(FALSE);
|
|
}
|
|
}
|
|
|
|
void StatsDialog::OnMove(int x, int y)
|
|
{
|
|
if (!m_bAfterInitDialog)
|
|
return;
|
|
|
|
GetWindowRect(&m_rcPosition);
|
|
if (m_pConfig)
|
|
m_pConfig->SetStatsWindowRect(m_ulId, m_rcPosition);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::OnSize
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
RECT rcWnd;
|
|
RECT rcBtn;
|
|
RECT rcDlg;
|
|
|
|
if (nType == SIZE_MINIMIZED)
|
|
return;
|
|
|
|
if (m_dwOptions & STATSDLG_FULLWINDOW)
|
|
{
|
|
// If we're full window, resize the list control to fill
|
|
// the entire client area
|
|
::SetWindowPos(::GetDlgItem(GetSafeHwnd(), IDC_STATSDLG_LIST), NULL,
|
|
0, 0, cx, cy, SWP_NOZORDER);
|
|
}
|
|
else if (m_sizeMinimum.cx)
|
|
{
|
|
|
|
::GetClientRect(GetSafeHwnd(), &rcDlg);
|
|
|
|
// reposition the buttons
|
|
|
|
// The widths are caluclated opposite of the normal order
|
|
// since the positions are relative to the right and bottom.
|
|
for (int i=0; i<INDEX_COUNT; i++)
|
|
{
|
|
::SetWindowPos(::GetDlgItem(GetSafeHwnd(), m_rgBtn[i].m_ulId),
|
|
NULL,
|
|
rcDlg.right - m_rgBtn[i].m_rc.left,
|
|
rcDlg.bottom - m_rgBtn[i].m_rc.top,
|
|
m_rgBtn[i].m_rc.left - m_rgBtn[i].m_rc.right,
|
|
m_rgBtn[i].m_rc.top - m_rgBtn[i].m_rc.bottom,
|
|
SWP_NOZORDER);
|
|
}
|
|
|
|
// resize the list control
|
|
|
|
::SetWindowPos(::GetDlgItem(GetSafeHwnd(), IDC_STATSDLG_LIST),
|
|
NULL,
|
|
m_rcList.left,
|
|
m_rcList.top,
|
|
rcDlg.right - m_rcList.right - m_rcList.left,
|
|
rcDlg.bottom - m_rcList.bottom - m_rcList.top,
|
|
SWP_NOZORDER);
|
|
}
|
|
|
|
|
|
if (m_bAfterInitDialog)
|
|
{
|
|
GetWindowRect(&m_rcPosition);
|
|
if (m_pConfig)
|
|
m_pConfig->SetStatsWindowRect(m_ulId, m_rcPosition);
|
|
}
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::OnGetMinMaxInfo
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::OnGetMinMaxInfo(MINMAXINFO *pMinMax)
|
|
{
|
|
pMinMax->ptMinTrackSize.x = m_sizeMinimum.cx;
|
|
pMinMax->ptMinTrackSize.y = m_sizeMinimum.cy;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::LoadHeaders
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::LoadHeaders()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
ULONG cVis;
|
|
ULONG i, iPos;
|
|
ULONG ulId;
|
|
CString st;
|
|
DWORD dwWidth;
|
|
ColumnData rgColumnData[2]; // used for vertical format
|
|
|
|
// Load those headers that we have data for
|
|
|
|
// Go through the column data finding the headers that we have
|
|
if (m_pConfig)
|
|
cVis = m_pConfig->GetVisibleColumns(m_ulId);
|
|
else
|
|
cVis = m_viewInfo.GetVisibleColumns();
|
|
|
|
if (m_dwOptions & STATSDLG_VERTICAL)
|
|
{
|
|
if (m_pConfig)
|
|
m_pConfig->GetColumnData(m_ulId, 2, rgColumnData);
|
|
else
|
|
m_viewInfo.GetColumnData(2, rgColumnData);
|
|
|
|
// For the vertical format, the data is on a column
|
|
// Thus we add two columns and fill in the data for the
|
|
// first column
|
|
st.LoadString(IDS_STATSDLG_DESCRIPTION);
|
|
dwWidth = rgColumnData[0].m_dwWidth;
|
|
if (dwWidth == AUTO_WIDTH)
|
|
{
|
|
dwWidth = m_ColWidthAdder + static_cast<DWORD>(m_ColWidthMultiple*m_listCtrl.GetStringWidth((LPCTSTR) st));
|
|
}
|
|
m_listCtrl.InsertColumn(0, st, rgColumnData[0].fmt, dwWidth, 0);
|
|
|
|
st.LoadString(IDS_STATSDLG_DETAILS);
|
|
dwWidth = rgColumnData[1].m_dwWidth;
|
|
if (dwWidth == AUTO_WIDTH)
|
|
{
|
|
dwWidth = m_ColWidthAdder + static_cast<DWORD>(m_ColWidthMultiple*m_listCtrl.GetStringWidth((LPCTSTR) st));
|
|
}
|
|
m_listCtrl.InsertColumn(1, st, rgColumnData[1].fmt, dwWidth, 1);
|
|
|
|
// Now go through and add the rows for each of our "columns"
|
|
for (i=0; i<cVis; i++)
|
|
{
|
|
// Now get the info for iPos
|
|
if (m_pConfig)
|
|
ulId = m_pConfig->GetStringId(m_ulId, i);
|
|
else
|
|
ulId = m_viewInfo.GetStringId(i);
|
|
st.LoadString(ulId);
|
|
Assert(st.GetLength());
|
|
|
|
m_listCtrl.InsertItem(i, _T(""));
|
|
m_listCtrl.SetItemText(i, 0, (LPCTSTR) st);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// For the normal horizontal format, the data is on a row
|
|
// so we need to add the various columnar data
|
|
for (i=0; i<cVis; i++)
|
|
{
|
|
int fmt = LVCFMT_LEFT;
|
|
|
|
iPos = MapColumnToSubitem(i);
|
|
|
|
// Now get the info for iPos
|
|
if (m_pConfig)
|
|
ulId = m_pConfig->GetStringId(m_ulId, i);
|
|
else
|
|
ulId = m_viewInfo.GetStringId(i);
|
|
|
|
st.LoadString(ulId);
|
|
Assert(st.GetLength());
|
|
|
|
if (m_pConfig)
|
|
{
|
|
dwWidth = m_pConfig->GetColumnWidth(m_ulId, i);
|
|
m_pConfig->GetColumnData(m_ulId, i, 1, rgColumnData);
|
|
fmt = rgColumnData[0].fmt;
|
|
}
|
|
else
|
|
{
|
|
dwWidth = m_viewInfo.GetColumnWidth(i);
|
|
m_viewInfo.GetColumnData(i, 1, rgColumnData);
|
|
fmt = rgColumnData[0].fmt;
|
|
}
|
|
|
|
if (dwWidth == AUTO_WIDTH)
|
|
{
|
|
dwWidth = m_ColWidthAdder + static_cast<DWORD>(m_ColWidthMultiple*m_listCtrl.GetStringWidth((LPCTSTR) st));
|
|
}
|
|
m_listCtrl.InsertColumn(i, st, fmt, dwWidth, iPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT StatsDialog::AddToContextMenu(CMenu* pMenu)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::OnContextMenu
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::OnContextMenu(CWnd *pWnd, CPoint pos)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
CMenu menu;
|
|
CString st;
|
|
|
|
if ((m_dwOptions & STATSDLG_CONTEXTMENU) == 0)
|
|
return;
|
|
|
|
if (pWnd->GetDlgCtrlID() != IDC_STATSDLG_LIST)
|
|
return;
|
|
|
|
// Bring up a context menu if we need to
|
|
menu.CreatePopupMenu();
|
|
|
|
st.LoadString(IDS_STATSDLG_MENU_REFRESH);
|
|
menu.AppendMenu(MF_STRING, IDC_STATSDLG_BTN_REFRESH, st);
|
|
|
|
if (m_dwOptions & STATSDLG_SELECT_COLUMNS)
|
|
{
|
|
st.LoadString(IDS_STATSDLG_MENU_SELECT);
|
|
menu.AppendMenu(MF_STRING, IDC_STATSDLG_BTN_SELECT_COLUMNS, st);
|
|
}
|
|
|
|
//virtual override to add additional context menus
|
|
AddToContextMenu(&menu);
|
|
|
|
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
|
|
pos.x,
|
|
pos.y,
|
|
this,
|
|
NULL);
|
|
}
|
|
|
|
|
|
void StatsDialog::OnNotifyListControlClick(NMHDR *pNmHdr, LRESULT *pResult)
|
|
{
|
|
NM_LISTVIEW * pnmlv = reinterpret_cast<NM_LISTVIEW *>(pNmHdr);
|
|
|
|
if (m_pConfig)
|
|
m_pConfig->SetSortColumn(m_ulId, pnmlv->iSubItem);
|
|
|
|
// Call through to the user to sort
|
|
Sort(pnmlv->iSubItem);
|
|
|
|
if (m_pConfig)
|
|
m_pConfig->SetSortDirection(m_ulId, m_fSortDirection);
|
|
}
|
|
|
|
|
|
void StatsDialog::Sort(UINT nColumn)
|
|
{
|
|
// Default is to do nothing
|
|
}
|
|
|
|
void StatsDialog::PreDeleteAllItems()
|
|
{
|
|
}
|
|
|
|
void StatsDialog::DeleteAllItems()
|
|
{
|
|
PreDeleteAllItems();
|
|
m_listCtrl.DeleteAllItems();
|
|
}
|
|
|
|
void StatsDialog::PostRefresh()
|
|
{
|
|
if (GetSafeHwnd())
|
|
PostMessage(WM_COMMAND, IDC_STATSDLG_BTN_REFRESH);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
StatsDialog::SetColumnWidths
|
|
Loops through all items and calculates the max width for columns
|
|
in a listbox.
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
void StatsDialog::SetColumnWidths(UINT uNumColumns)
|
|
{
|
|
// Set the default column widths to the width of the widest column
|
|
int * aColWidth = (int *) alloca(uNumColumns * sizeof(int));
|
|
int nRow, nCol;
|
|
CString strTemp;
|
|
|
|
ZeroMemory(aColWidth, uNumColumns * sizeof(int));
|
|
|
|
// for each item, loop through each column and calculate the max width
|
|
for (nRow = 0; nRow < m_listCtrl.GetItemCount(); nRow++)
|
|
{
|
|
for (nCol = 0; nCol < (int) uNumColumns; nCol++)
|
|
{
|
|
strTemp = m_listCtrl.GetItemText(nRow, nCol);
|
|
if (aColWidth[nCol] < m_listCtrl.GetStringWidth(strTemp))
|
|
aColWidth[nCol] = m_listCtrl.GetStringWidth(strTemp);
|
|
}
|
|
}
|
|
|
|
// now update the column widths based on what we calculated
|
|
for (nCol = 0; nCol < (int) uNumColumns; nCol++)
|
|
{
|
|
// GetStringWidth doesn't seem to report the right thing,
|
|
// so we have to add a fudge factor of 15.... oh well.
|
|
m_listCtrl.SetColumnWidth(nCol, aColWidth[nCol] + 15);
|
|
}
|
|
}
|
|
|
|
|
|
void StatsDialog::SetConfigInfo(ConfigStream *pConfig, ULONG ulId)
|
|
{
|
|
m_pConfig = pConfig;
|
|
m_ulId = ulId;
|
|
}
|
|
|
|
void StatsDialog::SetPosition(RECT rc)
|
|
{
|
|
m_rcPosition = rc;
|
|
}
|
|
|
|
void StatsDialog::GetPosition(RECT *prc)
|
|
{
|
|
*prc = m_rcPosition;
|
|
}
|
|
|
|
void CreateNewStatisticsWindow(StatsDialog *pWndStats,
|
|
HWND hWndParent,
|
|
UINT nIDD)
|
|
{
|
|
ModelessThread * pMT;
|
|
|
|
// If the dialog is still up, don't create a new one
|
|
if (pWndStats->GetSafeHwnd())
|
|
{
|
|
::SetActiveWindow(pWndStats->GetSafeHwnd());
|
|
return;
|
|
}
|
|
|
|
pMT = new ModelessThread(hWndParent,
|
|
nIDD,
|
|
pWndStats->GetSignalEvent(),
|
|
pWndStats);
|
|
pMT->CreateThread();
|
|
}
|
|
|
|
void WaitForStatisticsWindow(StatsDialog *pWndStats)
|
|
{
|
|
if (pWndStats->GetSafeHwnd())
|
|
{
|
|
// Post a cancel to that window
|
|
// Do an explicit post so that it executes on the other thread
|
|
pWndStats->PostMessage(WM_COMMAND, IDCANCEL, 0);
|
|
|
|
// Now we need to wait for the event to be signalled so that
|
|
// its memory can be cleaned up
|
|
WaitForSingleObject(pWndStats->GetSignalEvent(), INFINITE);
|
|
}
|
|
|
|
}
|
|
|