Leaked source code of windows server 2003
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.
 
 
 
 
 
 

4374 lines
104 KiB

// FolderListView.cpp : implementation file
//
#include "stdafx.h"
#define __FILE_ID__ 22
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include <dlgprnt2.cpp>
extern CClientConsoleApp theApp;
//
// Static members:
//
CFolderListView * CFolderListView::m_psCurrentViewBeingSorted = NULL;
CImageList CFolderListView::m_sImgListDocIcon;
CImageList CFolderListView::m_sReportIcons;
/////////////////////////////////////////////////////////////////////////////
// CFolderListView
IMPLEMENT_DYNCREATE(CFolderListView, CListView)
BEGIN_MESSAGE_MAP(CFolderListView, CListView)
//{{AFX_MSG_MAP(CFolderListView)
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
ON_WM_SETCURSOR()
ON_MESSAGE (WM_FOLDER_REFRESH_ENDED, OnFolderRefreshEnded)
ON_MESSAGE (WM_FOLDER_ADD_CHUNK, OnFolderAddChunk)
ON_MESSAGE (WM_FOLDER_INVALIDATE, OnFolderInvalidate)
ON_NOTIFY_REFLECT(NM_RCLICK, OnItemRightClick)
ON_WM_CONTEXTMENU()
ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged)
ON_WM_SETCURSOR()
ON_WM_CHAR()
//}}AFX_MSG_MAP
ON_UPDATE_COMMAND_UI(ID_SELECT_ALL, OnUpdateSelectAll)
ON_UPDATE_COMMAND_UI(ID_SELECT_NONE, OnUpdateSelectNone)
ON_UPDATE_COMMAND_UI(ID_SELECT_INVERT, OnUpdateSelectInvert)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_VIEW, OnUpdateFolderItemView)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_PRINT, OnUpdateFolderItemPrint)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_COPY, OnUpdateFolderItemCopy)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_MAIL_TO, OnUpdateFolderItemSendMail)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_PROPERTIES, OnUpdateFolderItemProperties)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_DELETE, OnUpdateFolderItemDelete)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_PAUSE, OnUpdateFolderItemPause)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_RESUME, OnUpdateFolderItemResume)
ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_RESTART, OnUpdateFolderItemRestart)
ON_COMMAND(ID_SELECT_ALL, OnSelectAll)
ON_COMMAND(ID_SELECT_NONE, OnSelectNone)
ON_COMMAND(ID_SELECT_INVERT, OnSelectInvert)
ON_COMMAND(ID_FOLDER_ITEM_VIEW, OnFolderItemView)
ON_COMMAND(ID_FOLDER_ITEM_PRINT, OnFolderItemPrint)
ON_COMMAND(ID_FOLDER_ITEM_COPY, OnFolderItemCopy)
ON_COMMAND(ID_FOLDER_ITEM_MAIL_TO, OnFolderItemMail)
ON_COMMAND(ID_FOLDER_ITEM_PRINT, OnFolderItemPrint)
ON_COMMAND(ID_FOLDER_ITEM_PROPERTIES, OnFolderItemProperties)
ON_COMMAND(ID_FOLDER_ITEM_DELETE, OnFolderItemDelete)
ON_COMMAND(ID_FOLDER_ITEM_PAUSE, OnFolderItemPause)
ON_COMMAND(ID_FOLDER_ITEM_RESUME, OnFolderItemResume)
ON_COMMAND(ID_FOLDER_ITEM_RESTART, OnFolderItemRestart)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblClk)
END_MESSAGE_MAP()
BOOL CFolderListView::PreCreateWindow(CREATESTRUCT& cs)
{
return CListView::PreCreateWindow(cs);
}
BOOL
CFolderListView::OnSetCursor(
CWnd* pWnd,
UINT nHitTest,
UINT message
)
{
if (m_bInMultiItemsOperation || m_bSorting)
{
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
return TRUE;
}
CClientConsoleDoc* pDoc = GetDocument();
if (pDoc && pDoc->IsFolderRefreshing(m_Type))
{
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_APPSTARTING));
return TRUE;
}
else
{
return CView::OnSetCursor(pWnd, nHitTest, message);
}
} // CFolderListView::OnSetCursor
BOOL
CFolderListView::IsSelected (
int iItem
)
/*++
Routine name : CFolderListView::IsSelected
Routine description:
Checks if an item is selected in the list
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
iItem [in] - Item index
Return Value:
TRUE if item is selected in the list, FALSE otherwise.
--*/
{
BOOL bRes = FALSE;
DBG_ENTER(TEXT("CFolderListView::IsSelected"), bRes);
CListCtrl &refCtrl = GetListCtrl();
ASSERTION (refCtrl.GetItemCount() > iItem);
DWORD dwState = refCtrl.GetItemState (iItem , LVIS_SELECTED);
if (LVIS_SELECTED & dwState)
{
bRes = TRUE;
}
return bRes;
}
void
CFolderListView::Select (
int iItem,
BOOL bSelect
)
/*++
Routine name : CFolderListView::Select
Routine description:
Selects / unselects an item in the list
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
iItem [in] - Item index
bSelect [in] - TRUE if select, FALSE unselect
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::Select"), TEXT("%d"), bSelect);
CListCtrl &refCtrl = GetListCtrl();
ASSERTION (refCtrl.GetItemCount() > iItem);
refCtrl.SetItemState (iItem,
bSelect ? (LVIS_SELECTED | LVIS_FOCUSED) : 0,
LVIS_SELECTED | LVIS_FOCUSED);
}
void
CFolderListView::OnSelectAll ()
/*++
Routine name : CFolderListView::OnSelectAll
Routine description:
Select all list items
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnSelectAll"),
TEXT("Type=%d"),
m_Type);
LV_ITEM lvItem;
CListCtrl &refCtrl = GetListCtrl();
ASSERTION (refCtrl.GetItemCount() > refCtrl.GetSelectedCount());
lvItem.mask = LVIF_STATE;
lvItem.iItem = -1; // Specifies "All items"
lvItem.iSubItem = 0;
lvItem.state = LVIS_SELECTED;
lvItem.stateMask= LVIS_SELECTED;
m_bInMultiItemsOperation = TRUE;
refCtrl.SetItemState(-1, &lvItem);
m_bInMultiItemsOperation = FALSE;
RecalcPossibleOperations();
} // CFolderListView::OnSelectAll
void
CFolderListView::OnSelectNone ()
/*++
Routine name : CFolderListView::OnSelectNone
Routine description:
Unselect all list items
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnSelectNone"),
TEXT("Type=%d"),
m_Type);
LV_ITEM lvItem;
CListCtrl &refCtrl = GetListCtrl();
lvItem.mask = LVIF_STATE;
lvItem.iItem = -1; // Specifies "All items"
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask= LVIS_SELECTED;
m_bInMultiItemsOperation = TRUE;
refCtrl.SetItemState(-1, &lvItem);
m_bInMultiItemsOperation = FALSE;
RecalcPossibleOperations();
} // CFolderListView::OnSelectNone
void
CFolderListView::OnSelectInvert ()
/*++
Routine name : CFolderListView::OnSelectInvert
Routine description:
Invert list items selection
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnSelectInvert"),
TEXT("Type=%d"),
m_Type);
CListCtrl &refCtrl = GetListCtrl();
DWORD dwItemsCount = refCtrl.GetItemCount();
m_bInMultiItemsOperation = TRUE;
for (DWORD dw = 0; dw < dwItemsCount; dw++)
{
Select (dw, !IsSelected (dw));
}
m_bInMultiItemsOperation = FALSE;
RecalcPossibleOperations();
} // CFolderListView::OnSelectInvert
void CFolderListView::OnDraw(CDC* pDC)
{
CListView::OnDraw (pDC);
}
void CFolderListView::OnInitialUpdate()
{
//
// Refresh the image list (only if they are empty)
//
RefreshImageLists(FALSE);
CListView::OnInitialUpdate();
}
/////////////////////////////////////////////////////////////////////////////
// CFolderListView diagnostics
#ifdef _DEBUG
void CFolderListView::AssertValid() const
{
CListView::AssertValid();
}
void CFolderListView::Dump(CDumpContext& dc) const
{
CListView::Dump(dc);
}
CClientConsoleDoc* CFolderListView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CClientConsoleDoc)));
return (CClientConsoleDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CFolderListView message handlers
DWORD
CFolderListView::InitColumns (
int *pColumnsUsed,
DWORD dwDefaultColNum
)
/*++
Routine name : CFolderListView::InitColumns
Routine description:
Inits the columns of the view.
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
pColumnsUsed [in] - Pointer to the list of ids to place in the columns.
Must be a statically allocated list.
dwDefaultColNum [in] - default column number
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::InitColumns"), dwRes);
if (m_bColumnsInitialized)
{
return dwRes;
}
m_dwDefaultColNum = dwDefaultColNum;
//
// Count the number of columns provided
//
CountColumns (pColumnsUsed);
int nItemIndex, nRes;
CString cstrColumnText;
DWORD dwCount = GetLogicalColumnsCount();
for (DWORD dw = 0; dw < dwCount; ++dw)
{
nItemIndex = ItemIndexFromLogicalColumnIndex(dw);
if(IsItemIcon(nItemIndex))
{
//
// Init icon column - insert an empty string
//
nRes = GetListCtrl().InsertColumn (dw, TEXT(""), LVCFMT_LEFT);
if (nRes < 0)
{
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::InsertColumn"), dwRes);
return dwRes;
}
//
// Set the header control's bitmap
//
CHeaderCtrl *pHeader = GetListCtrl().GetHeaderCtrl();
HDITEM hdItem;
hdItem.mask = HDI_IMAGE | HDI_FORMAT;
hdItem.fmt = HDF_LEFT | HDF_IMAGE;
hdItem.iImage = 0; // Use first (and only) image from image list
if (!pHeader->SetItem (dw, &hdItem))
{
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (WINDOW_ERR, TEXT("CHeaderCtrl::SetItem"), dwRes);
return dwRes;
}
}
else
{
//
// init string column
//
dwRes = GetColumnHeaderString (cstrColumnText, nItemIndex);
if (ERROR_SUCCESS != dwRes)
{ return dwRes; }
nRes = GetListCtrl().InsertColumn (dw,
cstrColumnText,
GetColumnHeaderAlignment (nItemIndex));
}
if (nRes < 0)
{
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::InsertColumn"), dwRes);
return dwRes;
}
}
m_bColumnsInitialized = TRUE;
return dwRes;
} // CFolderListView::InitColumns
void
CFolderListView::AutoFitColumns ()
/*++
Routine name : CFolderListView::AutoFitColumns
Routine description:
Sets the column width to fit the contents of the column and the header
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::AutoFitColumns"));
CHeaderCtrl *pHeader = GetListCtrl().GetHeaderCtrl ();
ASSERTION (pHeader);
DWORD dwCount = pHeader->GetItemCount();
for (DWORD dwCol = 0; dwCol <= dwCount; dwCol++)
{
GetListCtrl().SetColumnWidth (dwCol, LVSCW_AUTOSIZE);
int wc1 = GetListCtrl().GetColumnWidth (dwCol);
GetListCtrl().SetColumnWidth (dwCol, LVSCW_AUTOSIZE_USEHEADER);
int wc2 = GetListCtrl().GetColumnWidth (dwCol);
int wc = max(20,max(wc1,wc2));
GetListCtrl().SetColumnWidth (dwCol, wc);
}
} // CFolderListView::AutoFitColumns
DWORD
CFolderListView::UpdateLineTextAndIcon (
DWORD dwLineIndex,
CViewRow &row
)
/*++
Routine name : CFolderListView::UpdateLineTextAndIcon
Routine description:
Updates the icon and text in each column of a line item in the list
Author:
Eran Yariv (EranY), Feb, 2000
Arguments:
dwLineIndex [in] - Line index
row [in] - Display information
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::UpdateLineTextAndIcon"), dwRes);
//
// Start by setting the icon
//
LVITEM lvItem = {0};
lvItem.mask = LVIF_IMAGE;
lvItem.iItem = dwLineIndex;
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.pszText = NULL;
lvItem.cchTextMax = 0;
lvItem.lParam = NULL;
lvItem.iImage = row.GetIcon();
lvItem.iIndent = 0;
CListCtrl &refCtrl = GetListCtrl();
if (!refCtrl.SetItem (&lvItem))
{
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::SetItem"), dwRes);
return dwRes;
}
//
// Set columns text
//
DWORD dwItemIndex;
DWORD dwCount = GetLogicalColumnsCount();
for (DWORD dwCol = 0; dwCol < dwCount; ++dwCol)
{
dwItemIndex = ItemIndexFromLogicalColumnIndex (dwCol);
if(IsItemIcon(dwItemIndex))
{
continue;
}
//
// Get text from column
//
const CString &cstrColumn = row.GetItemString (dwItemIndex);
//
// Set the text in the control
//
if (!refCtrl.SetItemText (dwLineIndex, dwCol, cstrColumn))
{
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (WINDOW_ERR, TEXT("ListCtrl::SetItemText"), dwRes);
return dwRes;
}
}
ASSERTION (ERROR_SUCCESS == dwRes);
return dwRes;
} // CFolderListView::UpdateLineTextAndIcon
DWORD
CFolderListView::AddItem (
DWORD dwLineIndex,
CViewRow &row,
LPARAM lparamItemData,
PINT pintItemIndex
)
/*++
Routine name : CFolderListView::AddItem
Routine description:
Adds an item to the list
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
dwLineIndex [in] - Index of addition
row [in] - Row of item view information
lparamItemData [in] - Item associated data
pintItemIndex [out] - Item index in the list
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::AddItem"), dwRes, TEXT("%ld"), dwLineIndex);
//
// Insert the item: only state, indention and lParam are set.
//
LVITEM lvItem = {0};
lvItem.mask = LVIF_PARAM | LVIF_STATE | LVIF_INDENT;
lvItem.iItem = dwLineIndex;
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.pszText = NULL;
lvItem.cchTextMax = 0;
lvItem.lParam = lparamItemData;
lvItem.iImage = 0;
lvItem.iIndent = 0;
*pintItemIndex = ListView_InsertItem (GetListCtrl().m_hWnd, &lvItem);
if (-1 == *pintItemIndex)
{
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::InsertItem"), dwRes);
return dwRes;
}
dwRes = UpdateLineTextAndIcon (*pintItemIndex, row);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("UpdateLineTextAndIcon"), dwRes);
return dwRes;
}
ASSERTION (ERROR_SUCCESS == dwRes);
return dwRes;
} // CFolderListView::AddItem
LRESULT
CFolderListView::OnFolderAddChunk(
WPARAM wParam, // Error code
LPARAM lParam // MSGS_MAP pointer
)
/*++
Routine name : CFolderListView::OnFolderAddChunk
Routine description:
Called when a background folder thread brings a chunk of messages
Arguments:
wParam [in] - Thread error code
lParam [in] - Pointer to MSGS_MAP.
Return Value:
Standard result code
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderAddChunk"));
DWORD dwRes = (DWORD) wParam;
CObject* pObj = (CObject*)lParam;
if (ERROR_SUCCESS == dwRes)
{
OnUpdate (NULL, UPDATE_HINT_ADD_CHUNK, pObj);
}
else
{
PopupError (dwRes);
}
return 0;
}
LRESULT
CFolderListView::OnFolderRefreshEnded (
WPARAM wParam, // Error code
LPARAM lParam // CFolder pointer
)
/*++
Routine name : CFolderListView::OnFolderRefreshEnded
Routine description:
Called when a background folder thread finishes its work.
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
wParam [in] - Thread error code
lParam [in] - Pointer to CFolder that started the thread.
Return Value:
Standard result code
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderRefreshEnded"));
DWORD dwRes = (DWORD) wParam;
CFolder *pFolder = (CFolder *) lParam;
if (ERROR_SUCCESS == dwRes)
{
CListCtrl &refCtrl = GetListCtrl();
m_HeaderCtrl.SetListControl (refCtrl.m_hWnd);
DoSort();
if(refCtrl.GetItemCount() > 0)
{
int iIndex = refCtrl.GetNextItem (-1, LVNI_SELECTED);
if (-1 == iIndex)
{
//
// If there is no selection, set focus on the first item.
//
refCtrl.SetItemState (0, LVIS_FOCUSED, LVIS_FOCUSED);
}
else
{
//
// After sort, ensure the first selected item is visible
//
refCtrl.EnsureVisible (iIndex, FALSE);
}
}
}
else
{
PopupError (dwRes);
}
return 0;
} // CFolderListView::OnFolderRefreshEnded
LRESULT
CFolderListView::OnFolderInvalidate (
WPARAM wParam, // not in use
LPARAM lParam // CFolder pointer
)
/*++
Routine name : CFolderListView::OnFolderRefreshEnded
Routine description:
Called by a background folder thread in order to remove the all its fax messages.
Arguments:
wParam [in] - Not in use
lParam [in] - Pointer to CFolder that started the thread.
Return Value:
Standard result code
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderInvalidate"));
CFolder *pFolder = (CFolder *) lParam;
if(!pFolder)
{
ASSERTION_FAILURE;
return 0;
}
int iIndex; // View item index
CListCtrl &refCtrl = GetListCtrl();
LVFINDINFO lvfi = {0};
lvfi.flags = LVFI_PARAM;
CFaxMsg* pMsg;
MSGS_MAP &msgMap = pFolder->GetData ();
pFolder->EnterData ();
//
// Go through the folder's message map
//
for (MSGS_MAP::iterator it = msgMap.begin(); it != msgMap.end(); ++it)
{
pMsg = (*it).second;
//
// Delete the fax message from the view
//
lvfi.lParam = (LPARAM)pMsg;
iIndex = refCtrl.FindItem (&lvfi);
if(-1 != iIndex)
{
refCtrl.DeleteItem (iIndex);
}
//
// Delete a fax message object
//
SAFE_DELETE (pMsg);
}
msgMap.clear();
pFolder->LeaveData ();
RecalcPossibleOperations ();
return 0;
} // CFolderListView::OnFolderInvalidate
/***********************************
* *
* Columns sort support *
* *
***********************************/
int
CFolderListView::CompareListItems (
CFaxMsg* pFaxMsg1,
CFaxMsg* pFaxMsg2
)
/*++
Routine name : CFolderListView::CompareListItems
Routine description:
Compares two items in the list (callback)
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
pFaxMsg1 [in] - Item 1
pFaxMsg2 [in] - Item 2
Return Value:
-1 if item1 is smaler than item2
0 if identical
+1 if item1 is bigger than item2
--*/
{
DBG_ENTER(TEXT("CFolderListView::CompareListItems"));
//
// Make sure the we're sorting a valid column here
//
ASSERTION (m_nSortedCol >= 0);
ASSERTION (m_nSortedCol <= GetLogicalColumnsCount());
//
// Get item index to sort by
//
DWORD dwItemIndex = ItemIndexFromLogicalColumnIndex (m_nSortedCol);
//
// Get comparison result
//
int iRes = m_bSortAscending ? CompareItems (pFaxMsg1, pFaxMsg2, dwItemIndex) :
CompareItems (pFaxMsg2, pFaxMsg1, dwItemIndex);
return iRes;
}
void CFolderListView::OnColumnClick(
NMHDR* pNMHDR,
LRESULT* pResult
)
/*++
Routine name : CFolderListView::OnColumnClick
Routine description:
Handle mouse click on list header column (sort)
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
pNMHDR [in] - Header column information
pResult [out] - Result
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnColumnClick"),
TEXT("Type=%d"),
m_Type);
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
DWORD dwItemIndex = ItemIndexFromLogicalColumnIndex (pNMListView->iSubItem);
if(IsItemIcon(dwItemIndex))
{
//
// no sort by icon
//
return;
}
if( pNMListView->iSubItem == m_nSortedCol )
{
m_bSortAscending = !m_bSortAscending;
}
else
{
m_bSortAscending = TRUE;
}
m_nSortedCol = pNMListView->iSubItem;
DoSort();
*pResult = 0;
} // CFolderListView::OnColumnClick
int
CALLBACK
CFolderListView::ListViewItemsCompareProc (
LPARAM lParam1,
LPARAM lParam2,
LPARAM lParamSort
)
{
DBG_ENTER(TEXT("CFolderListView::ListViewItemsCompareProc"));
ASSERTION(m_psCurrentViewBeingSorted);
ASSERTION(lParam1);
ASSERTION(lParam2);
CFaxMsg* pFaxMsg1 = (CFaxMsg*)lParam1;
CFaxMsg* pFaxMsg2 = (CFaxMsg*)lParam2;
DWORDLONG dwlId;
try
{
dwlId = pFaxMsg1->GetId();
dwlId = pFaxMsg2->GetId();
}
catch(...)
{
//
// The list control has invalid item
//
VERBOSE (DBG_MSG, TEXT("List control has invalid item"));
ASSERTION(FALSE);
return 0;
}
return m_psCurrentViewBeingSorted->CompareListItems (pFaxMsg1, pFaxMsg2);
}
DWORD
CFolderListView::RefreshImageLists (
BOOL bForce
)
/*++
Routine name : CFolderListView::RefreshImageLists
Routine description:
Loads the static list of images (icons) for the list control
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
bForce - [in] If TRUE, any existing image list is destroyed and replaced with new ones.
If FALSE, existing image lists remain unchanged.
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::RefreshImageLists"), dwRes);
CListCtrl& refCtrl = GetListCtrl();
if (bForce || (NULL == m_sReportIcons.m_hImageList))
{
//
// Load image list of list view icons - 256 colors, pixel at 0,0 is mapped to background color during load
//
if(m_sReportIcons.m_hImageList)
{
ImageList_Destroy(m_sReportIcons.Detach());
}
HIMAGELIST himl = ImageList_LoadImage(
AfxGetResourceHandle(),
MAKEINTRESOURCE(IDB_LIST_IMAGES),
16,
0,
RGB(0, 255, 0),
IMAGE_BITMAP,
LR_LOADTRANSPARENT | LR_CREATEDIBSECTION);
if (NULL == himl)
{
dwRes = GetLastError();
CALL_FAIL (RESOURCE_ERR, TEXT("ImageList_LoadImage"), dwRes);
PopupError (dwRes);
return dwRes;
}
m_sReportIcons.Attach (himl);
}
if (bForce || (NULL == m_sImgListDocIcon.m_hImageList))
{
//
// Load the image list for the icons column and the up/down sort images - 16 colors.
//
if(m_sImgListDocIcon.m_hImageList)
{
ImageList_Destroy(m_sImgListDocIcon.Detach());
}
dwRes = LoadDIBImageList (m_sImgListDocIcon,
IDB_DOC_ICON,
16,
RGB (214, 214, 214));
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (RESOURCE_ERR, TEXT("LoadDIBImageList"), dwRes);
PopupError (dwRes);
return dwRes;
}
}
refCtrl.SetExtendedStyle (LVS_EX_FULLROWSELECT | // Entire row is selected
LVS_EX_INFOTIP);
refCtrl.SetImageList (&m_sReportIcons, LVSIL_SMALL);
//
// Attach our custom header-control to the window of the list's header.
//
m_HeaderCtrl.SubclassWindow(refCtrl.GetHeaderCtrl()->m_hWnd);
m_HeaderCtrl.SetImageList (&m_sImgListDocIcon);
m_HeaderCtrl.SetListControl (refCtrl.m_hWnd);
COLORREF crBkColor = ::GetSysColor(COLOR_WINDOW);
refCtrl.SetBkColor(crBkColor);
return dwRes;
} // CFolderListView::RefreshImageLists
void
CFolderListView::OnItemRightClick(
NMHDR* pNMHDR,
LRESULT* pResult
)
/*++
Routine name : CFolderListView::OnItemRightClick
Routine description:
Handle mouse right-click on list items (popup context sensitive menu)
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
pNMHDR [in] - Item information
pResult [out] - Result
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnItemRightClick"),
TEXT("Type=%d"),
m_Type);
//
// Send WM_CONTEXTMENU to self
//
SendMessage(WM_CONTEXTMENU, (WPARAM) m_hWnd, GetMessagePos());
//
// Mark message as handled and suppress default handling
//
*pResult = 1;
} // CFolderListView::OnItemRightClick
DWORD
CFolderListView::GetServerPossibleOperations (
CFaxMsg* pMsg
)
/*++
Routine name : CFolderListView::GetServerPossibleOperations
Routine description:
Retrieves operations possible on items according to server's security configuration.
Author:
Eran Yariv (EranY), Feb, 2000
Arguments:
Return Value:
Possible operations (JOB_OP*)
--*/
{
DWORD dwRes = FAX_JOB_OP_ALL;
DBG_ENTER(TEXT("CFolderListView::GetServerPossibleOperations"), dwRes);
ASSERTION(pMsg);
CServerNode* pServer = pMsg->GetServer();
ASSERTION (pServer);
switch (m_Type)
{
case FOLDER_TYPE_INBOX:
if (!pServer->CanManageInbox())
{
//
// User cannot perform operations on the inbox
//
dwRes &= ~FAX_JOB_OP_DELETE;
}
break;
case FOLDER_TYPE_INCOMING:
if (!pServer->CanManageAllJobs ())
{
//
// User cannot perform operations on the incoming queue folder
//
dwRes &= ~(FAX_JOB_OP_DELETE | FAX_JOB_OP_PAUSE |
FAX_JOB_OP_RESUME | FAX_JOB_OP_RESTART);
}
break;
case FOLDER_TYPE_OUTBOX:
case FOLDER_TYPE_SENT_ITEMS:
//
// User can do anything here
//
break;
default:
ASSERTION_FAILURE;
dwRes = 0;
}
return dwRes;
} // CFolderListView::GetServerPossibleOperations
void CFolderListView::OnItemChanged(
NMHDR* pNMHDR,
LRESULT* pResult
)
/*++
Routine name : CFolderListView::OnItemChanged
Routine description:
Handle selection changes of on list items
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
pNMHDR [in] - Item information
pResult [out] - Result
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnItemChanged"),
TEXT("Type=%d"),
m_Type);
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
*pResult = 0;
if(m_bInMultiItemsOperation)
{
return;
}
//
// Find out if a new item is selected or unselected.
//
if (pNMListView->iItem < 0)
{
//
// No item reported
//
return;
}
if (!(LVIF_STATE & (pNMListView->uChanged)))
{
//
// This is not a selection change report
//
return;
}
if ( ((pNMListView->uNewState) & LVIS_SELECTED) &&
!((pNMListView->uOldState) & LVIS_SELECTED))
{
//
// Item changed from not-selected to selected.
// Change the possible operations the user can perform on selected items.
//
OnItemSelected((CFaxMsg*)pNMListView->lParam);
//
// If the folder is still refreshing and a command line argument asks for a specific
// message to be selected in this folder, then we mark that message in m_dwlMsgToSelect.
// Since the user just performed a manual selection of items, we no longer have to select anything for him.
//
m_dwlMsgToSelect = 0;
}
else if (!((pNMListView->uNewState) & LVIS_SELECTED) &&
((pNMListView->uOldState) & LVIS_SELECTED))
{
//
// Item changed from selected to not-selected
// Recalculate the possible operations the user can do on selected item.
OnItemUnSelected((CFaxMsg*)pNMListView->lParam);
//
// If the folder is still refreshing and a command line argument asks for a specific
// message to be selected in this folder, then we mark that message in m_dwlMsgToSelect.
// Since the user just performed a manual selection of items, we no longer have to select anything for him.
//
m_dwlMsgToSelect = 0;
}
} // CFolderListView::OnItemChanged
void
CFolderListView::RecalcPossibleOperations ()
/*++
Routine name : CFolderListView::RecalcPossibleOperations
Routine description:
Recalculates the possible operation on the set of currently selected items.
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::RecalcPossibleOperations"));
CListCtrl &refCtrl = GetListCtrl();
int iInd = -1;
DWORD dwSelectedCount = refCtrl.GetSelectedCount ();
m_dwPossibleOperationsOnSelectedItems = 0;
ZeroMemory((PVOID)m_nImpossibleOperationsCounts, sizeof(m_nImpossibleOperationsCounts));
CFaxMsg* pFaxMsg = NULL;
for (DWORD dwItems = 0; dwItems < dwSelectedCount; dwItems++)
{
iInd = refCtrl.GetNextItem (iInd, LVNI_SELECTED);
if(iInd < 0)
{
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
break;
}
LPARAM lparam = (LPARAM) refCtrl.GetItemData (iInd);
OnItemSelected((CFaxMsg*)lparam);
}
} // CFolderListView::RecalcPossibleOperations
void
CFolderListView::OnItemSelected(CFaxMsg* pFaxMsg)
/*++
Routine name : CFolderListView::OnItemSelected
Routine description:
Recalculates the possible operation due to item selection
Arguments:
pFaxMsg [in] selected fax message
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnItemSelected"));
//
// Item changed from not-selected to selected.
// Change the possible operations the user can perform on selected items.
//
if(0 == m_dwPossibleOperationsOnSelectedItems)
{
m_dwPossibleOperationsOnSelectedItems = 0xFFFF;
}
DWORD dwItemOperations = GetServerPossibleOperations(pFaxMsg) &
pFaxMsg->GetPossibleOperations();
if (GetListCtrl().GetSelectedCount() > 1)
{
//
// If more than one item is selected, disable view and properties.
//
dwItemOperations &= ~(FAX_JOB_OP_VIEW | FAX_JOB_OP_PROPERTIES);
}
m_dwPossibleOperationsOnSelectedItems &= dwItemOperations;
//
// Update impossible operations counts
//
DWORD dw;
for(dw=0; dw < ARR_SIZE(m_nImpossibleOperationsCounts); ++dw)
{
if((dwItemOperations & 1) == 0)
{
//
// The operation is disabled.
//
m_nImpossibleOperationsCounts[dw]++;
}
dwItemOperations = dwItemOperations >> 1;
}
} // CFolderListView::OnItemSelected
void
CFolderListView::OnItemUnSelected(CFaxMsg* pFaxMsg)
/*++
Routine name : CFolderListView::OnItemUnSelected
Routine description:
Recalculates the possible operation due to item unselect
Arguments:
pFaxMsg [in] unselected fax message
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnItemUnSelected"));
CListCtrl &refCtrl = GetListCtrl();
DWORD dwSelectedCount = refCtrl.GetSelectedCount ();
if(dwSelectedCount <= 1)
{
m_dwPossibleOperationsOnSelectedItems = 0;
ZeroMemory((PVOID)m_nImpossibleOperationsCounts, sizeof(m_nImpossibleOperationsCounts));
if(1 == dwSelectedCount)
{
int iInd = refCtrl.GetNextItem (-1, LVNI_SELECTED);
OnItemSelected((CFaxMsg*)refCtrl.GetItemData (iInd));
}
return;
}
DWORD dwItemOperations = GetServerPossibleOperations(pFaxMsg) &
pFaxMsg->GetPossibleOperations();
DWORD dw;
for(dw=0; dw < ARR_SIZE(m_nImpossibleOperationsCounts); ++dw)
{
if((dwItemOperations & 1) == 0)
{
//
// The operation is disabled for unselected item.
//
m_nImpossibleOperationsCounts[dw]--;
ASSERTION(m_nImpossibleOperationsCounts[dw] >= 0);
if(m_nImpossibleOperationsCounts[dw] == 0)
{
//
// Enable this operation
//
m_dwPossibleOperationsOnSelectedItems |= (1 << dw);
}
}
dwItemOperations = dwItemOperations >> 1;
}
} // CFolderListView::OnItemUnSelected
void
CFolderListView::OnFolderItemView ()
/*++
Routine name : CFolderListView::OnFolderItemView
Routine description:
Handles message view commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderItemView"),
TEXT("Type=%d"),
m_Type);
if(!(m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_VIEW))
{
//
// there is no TIF associated application
//
return;
}
CString cstrTiff;
DWORD dwRes = FetchTiff (cstrTiff);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::FetchTiff"), dwRes);
PopupError (dwRes);
return;
}
//
// Open the TIFF with associated application.
// All preview files are automatically removed once the application is shut down.
//
dwRes = ViewFile(cstrTiff);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("ViewFile"), dwRes);
if(ERROR_NO_ASSOCIATION == dwRes)
{
AlignedAfxMessageBox(IDS_NO_OPEN_ASSOCIATION, MB_ICONSTOP);
}
else
{
PopupError (dwRes);
}
}
else
{
if(FOLDER_TYPE_INBOX == m_Type)
{
theApp.InboxViewed();
}
}
} // CFolderListView::OnFolderItemView
void
CFolderListView::OnFolderItemPrint ()
/*++
Routine name : CFolderListView::OnFolderItemPrint
Routine description:
Handles message print commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DWORD dwRes;
DBG_ENTER(TEXT("CFolderListView::OnFolderItemPrint"),
TEXT("Type=%d"),
m_Type);
HDC hPrinter;
if (IsWinXPOS())
{
//
// Use new look of printer selection dialog
//
C_PrintDialogEx prnDlg(FALSE,
PD_ALLPAGES |
PD_USEDEVMODECOPIES |
PD_NOPAGENUMS |
PD_NOSELECTION |
PD_RETURNDC);
if(IDOK != prnDlg.DoModal())
{
CALL_FAIL (GENERAL_ERR, TEXT("C_PrintDialogEx::DoModal"), CommDlgExtendedError());
return;
}
hPrinter = prnDlg.GetPrinterDC();
if(!hPrinter)
{
dwRes = ERROR_CAN_NOT_COMPLETE;
CALL_FAIL (GENERAL_ERR, TEXT("C_PrintDialogEx::GetPrinterDC"), dwRes);
return;
}
}
else
{
//
// Use legacy printer selection dialog
//
CPrintDialog prnDlg(FALSE);
if(IDOK != prnDlg.DoModal())
{
return;
}
hPrinter = prnDlg.GetPrinterDC();
if(!hPrinter)
{
dwRes = ERROR_CAN_NOT_COMPLETE;
CALL_FAIL (GENERAL_ERR, TEXT("CPrintDialog::GetPrinterDC"), dwRes);
return;
}
}
CString cstrTiff;
dwRes = FetchTiff (cstrTiff);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::FetchTiff"), dwRes);
PopupError (dwRes);
return;
}
if(!TiffPrintDC(cstrTiff, hPrinter))
{
dwRes = GetLastError();
CALL_FAIL (GENERAL_ERR, TEXT("TiffPrintDC"), dwRes);
goto exit;
}
exit:
if(hPrinter)
{
CDC::FromHandle(hPrinter)->DeleteDC();
}
if (!DeleteFile (cstrTiff))
{
dwRes = GetLastError ();
CALL_FAIL (FILE_ERR, TEXT("DeleteFile"), dwRes);
}
} // CFolderListView::OnFolderItemPrint
void
CFolderListView::OnFolderItemCopy ()
/*++
Routine name : CFolderListView::OnFolderItemCopy
Routine description:
Handles message copy commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderItemCopy"),
TEXT("Type=%d"),
m_Type);
CString cstrTiff;
DWORD dwRes = FetchTiff (cstrTiff);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::FetchTiff"), dwRes);
PopupError (dwRes);
return;
}
CString cstrFileName;
CString cstrFilterFormat;
TCHAR szFile[MAX_PATH] = {0};
TCHAR szFilter[MAX_PATH] = {0};
OPENFILENAME ofn = {0};
//
// get tif file name
//
int nFileNamePos = cstrTiff.ReverseFind(TEXT('\\'));
ASSERTION(nFileNamePos > 0);
nFileNamePos++;
try
{
cstrFileName = cstrTiff.Right(cstrTiff.GetLength() - nFileNamePos);
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("CString::operator="), dwRes);
PopupError (dwRes);
goto del_file;
}
_tcscpy(szFile, cstrFileName);
dwRes = LoadResourceString(cstrFilterFormat, IDS_SAVE_AS_FILTER_FORMAT);
if (ERROR_SUCCESS != dwRes)
{
ASSERTION_FAILURE;
CALL_FAIL (RESOURCE_ERR, TEXT("LoadResourceString"), dwRes);
goto del_file;
}
_stprintf(szFilter, cstrFilterFormat, FAX_TIF_FILE_MASK, 0, FAX_TIF_FILE_MASK, 0);
ofn.lStructSize = GetOpenFileNameStructSize();
ofn.hwndOwner = m_hWnd;
ofn.lpstrFilter = szFilter;
ofn.lpstrFile = szFile;
ofn.nMaxFile = ARR_SIZE(szFile);
ofn.lpstrDefExt = FAX_TIF_FILE_EXT;
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
ofn.lpfnHook = OFNHookProc;
if(!GetSaveFileName(&ofn))
{
goto del_file;
}
{
//
// SHFILEOPSTRUCT::pFrom should ends with double NULL
//
TCHAR tszSrcFile[MAX_PATH+1] = {0};
_tcsncpy(tszSrcFile, cstrTiff, MAX_PATH);
//
// move the file
//
SHFILEOPSTRUCT shFileOpStruct = {0};
shFileOpStruct.wFunc = FO_MOVE;
shFileOpStruct.fFlags = FOF_SILENT; // Don't display file move progress dialog
shFileOpStruct.pFrom = tszSrcFile;
shFileOpStruct.pTo = szFile;
if(!SHFileOperation(&shFileOpStruct))
{
//
// success
//
return;
}
else
{
dwRes = ERROR_CAN_NOT_COMPLETE;
CALL_FAIL (GENERAL_ERR, TEXT("SHFileOperation"), dwRes);
goto del_file;
}
}
del_file:
if (!DeleteFile (cstrTiff))
{
dwRes = GetLastError ();
CALL_FAIL (FILE_ERR, TEXT("DeleteFile"), dwRes);
}
} // CFolderListView::OnFolderItemCopy
void
CFolderListView::OnUpdateFolderItemSendMail(
CCmdUI* pCmdUI
)
{
pCmdUI->Enable( (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_VIEW) &&
(m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_PROPERTIES) &&
theApp.IsMapiEnable());
}
void
CFolderListView::OnUpdateFolderItemView(
CCmdUI* pCmdUI
)
{
OnUpdateFolderItemPrint(pCmdUI);
}
void
CFolderListView::OnUpdateFolderItemPrint(
CCmdUI* pCmdUI
)
{
pCmdUI->Enable( (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_VIEW) &&
(m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_PROPERTIES));
}
void
CFolderListView::OnUpdateFolderItemCopy(
CCmdUI* pCmdUI
)
{
pCmdUI->Enable( (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_VIEW) &&
(m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_PROPERTIES));
}
void
CFolderListView::OnFolderItemMail ()
/*++
Routine name : CFolderListView::OnFolderItemMail
Routine description:
Handles message mail commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderItemMail"),
TEXT("Type=%d"),
m_Type);
CString cstrTiff;
DWORD dwRes = FetchTiff (cstrTiff);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::FetchTiff"), dwRes);
PopupError (dwRes);
return;
}
//
// create a new mail message with tif file attached
//
dwRes = theApp.SendMail(cstrTiff);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CClientConsoleApp::SendMail"), dwRes);
PopupError (dwRes);
}
if (!DeleteFile (cstrTiff))
{
dwRes = GetLastError ();
CALL_FAIL (FILE_ERR, TEXT("DeleteFile"), dwRes);
}
} // CFolderListView::OnFolderItemMail
void
CFolderListView::OnFolderItemProperties ()
/*++
Routine name : CFolderListView::OnFolderItemProperties
Routine description:
Handles message properties commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderItemProperties"),
TEXT("Type=%d"),
m_Type);
//
// Make sure there's exaclty one elemented selected
//
CListCtrl &refCtrl = GetListCtrl();
ASSERTION (1 == refCtrl.GetSelectedCount());
int iInd = refCtrl.GetNextItem (-1, LVNI_SELECTED);
ASSERTION (0 <= iInd);
CFaxMsg* pMsg = (CFaxMsg*)(refCtrl.GetItemData (iInd));
ASSERTION (pMsg);
CServerNode* pServer = pMsg->GetServer();
ASSERTION (pServer);
CItemPropSheet propSheet(IDS_PROPERTIES_SHEET_CAPTION);
DWORD dwRes = propSheet.Init(pServer->GetFolder(m_Type), pMsg);
if(ERROR_SUCCESS != dwRes)
{
PopupError (dwRes);
return;
}
dwRes = propSheet.DoModal();
if(IDABORT == dwRes)
{
PopupError (propSheet.GetLastError());
}
} // CFolderListView::OnFolderItemProperties
DWORD
CFolderListView::OpenSelectColumnsDlg()
/*++
Routine name : CFolderListView::OpenSelectColumnsDlg
Routine description:
opens column select dialog and reorders the columns
Author:
Alexander Malysh (AlexMay), Jan, 2000
Arguments:
Return Value:
Error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::OpenSelectColumnsDlg"),
TEXT("Type=%d"),
m_Type);
ASSERTION(NULL != m_pnColumnsOrder);
ASSERTION(NULL != m_pViewColumnInfo);
DWORD dwCount = GetLogicalColumnsCount();
//
// init header string array
//
CString* pcstrHeaders;
try
{
pcstrHeaders = new CString[dwCount];
}
catch (...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT ("new CString[dwCount]"), dwRes);
return dwRes;
}
int nItemIndex;
for (DWORD dw = 0; dw < dwCount; ++dw)
{
nItemIndex = ItemIndexFromLogicalColumnIndex(dw);
dwRes = GetColumnHeaderString (pcstrHeaders[dw], nItemIndex);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("GetColumnHeaderString"), dwRes);
delete[] pcstrHeaders;
return dwRes;
}
}
//
// save width
//
int nIndex;
for (dw = 0; dw < m_dwDisplayedColumns; ++dw)
{
nIndex = m_pnColumnsOrder[dw];
ASSERTION(nIndex >= 0 && nIndex < dwCount);
m_pViewColumnInfo[nIndex].nWidth = GetListCtrl().GetColumnWidth(nIndex);
}
//
// start column select dialog
//
CColumnSelectDlg dlg(pcstrHeaders, m_pnColumnsOrder, dwCount, m_dwDisplayedColumns);
if(IDOK == dlg.DoModal())
{
for (dw = 0; dw < dwCount; ++dw)
{
nIndex = m_pnColumnsOrder[dw];
ASSERTION(nIndex >= 0 && nIndex < dwCount);
m_pViewColumnInfo[nIndex].dwOrder = dw;
m_pViewColumnInfo[nIndex].bShow = (dw < m_dwDisplayedColumns);
}
//
// if sorted column is hidden then no sort
//
if(m_nSortedCol >= 0)
{
ASSERTION(m_nSortedCol < dwCount);
if(!m_pViewColumnInfo[m_nSortedCol].bShow)
{
m_nSortedCol = -1;
}
}
ColumnsToLayout();
}
delete[] pcstrHeaders;
return dwRes;
} // CFolderListView::OpenSelectColumnsDlg
DWORD
CFolderListView::ColumnsToLayout()
/*++
Routine name : CFolderListView::ColumnsToLayout
Routine description:
reorders columns according to saved layout
Author:
Alexander Malysh (AlexMay), Jan, 2000
Arguments:
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::ColumnsToLayout"), dwRes);
ASSERTION(NULL != m_pnColumnsOrder);
ASSERTION(NULL != m_pViewColumnInfo);
CListCtrl &refCtrl = GetListCtrl();
DWORD dwCount = GetLogicalColumnsCount();
CSize size;
CDC* pHdrDc = refCtrl.GetHeaderCtrl()->GetDC();
//
// set column order
//
if(!refCtrl.SetColumnOrderArray(dwCount, m_pnColumnsOrder))
{
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::SetColumnOrderArray"), dwRes);
return dwRes;
}
//
// set column width
//
DWORD dwItemIndex;
CString cstrColumnText;
for (DWORD dwCol = 0; dwCol < dwCount; ++dwCol)
{
if(m_pViewColumnInfo[dwCol].bShow)
{
if(m_pViewColumnInfo[dwCol].nWidth < 0)
{
dwItemIndex = ItemIndexFromLogicalColumnIndex(dwCol);
dwRes = GetColumnHeaderString (cstrColumnText, dwItemIndex);
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("GetColumnHeaderString"), dwRes);
return dwRes;
}
size = pHdrDc->GetTextExtent(cstrColumnText);
refCtrl.SetColumnWidth (dwCol, size.cx * 1.5);
}
else
{
refCtrl.SetColumnWidth (dwCol, m_pViewColumnInfo[dwCol].nWidth);
}
}
else
{
refCtrl.SetColumnWidth (dwCol, 0);
}
}
Invalidate();
return dwRes;
} // CFolderListView::ColumnsToLayout
DWORD
CFolderListView::ReadLayout(
LPCTSTR lpszViewName
)
/*++
Routine name : CFolderListView::ReadLayout
Routine description:
reads column layout from registry
Author:
Alexander Malysh (AlexMay), Jan, 2000
Arguments:
lpszSection [in] - registry section
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::ReadLayout"),
dwRes,
TEXT("Type=%d"),
m_Type);
ASSERTION(NULL == m_pnColumnsOrder);
ASSERTION(NULL == m_pViewColumnInfo);
//
// columns order array allocation
//
DWORD dwCount = GetLogicalColumnsCount();
try
{
m_pnColumnsOrder = new int[dwCount];
}
catch (...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT ("m_pdwColumnsOrder = new int[dwCount]"), dwRes);
return dwRes;
}
for(DWORD dw=0; dw < dwCount; ++dw)
{
m_pnColumnsOrder[dw] = -1;
}
//
// columns info array allocation
//
try
{
m_pViewColumnInfo = new TViewColumnInfo[dwCount];
}
catch (...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT ("new CString[dwCount]"), dwRes);
return dwRes;
}
//
// reads columns layout from registry
//
CString cstrSection;
m_dwDisplayedColumns = 0;
for(dw=0; dw < dwCount; ++dw)
{
try
{
cstrSection.Format(TEXT("%s\\%s\\%02d"), lpszViewName, CLIENT_VIEW_COLUMNS, dw);
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("CString::Format"), dwRes);
return dwRes;
}
m_pViewColumnInfo[dw].bShow = theApp.GetProfileInt(cstrSection,
CLIENT_VIEW_COL_SHOW,
(dw < m_dwDefaultColNum) ? 1 : 0);
if(m_pViewColumnInfo[dw].bShow)
{
++m_dwDisplayedColumns;
}
m_pViewColumnInfo[dw].nWidth = theApp.GetProfileInt(cstrSection,
CLIENT_VIEW_COL_WIDTH, -1);
m_pViewColumnInfo[dw].dwOrder = theApp.GetProfileInt(cstrSection,
CLIENT_VIEW_COL_ORDER, dw);
if(m_pViewColumnInfo[dw].dwOrder < dwCount)
{
m_pnColumnsOrder[m_pViewColumnInfo[dw].dwOrder] = dw;
}
else
{
ASSERTION_FAILURE;
}
}
//
// check column order consistence
//
for(dw=0; dw < dwCount; ++dw)
{
ASSERTION(m_pnColumnsOrder[dw] >= 0);
}
//
// read sort parameters
//
m_bSortAscending = theApp.GetProfileInt(lpszViewName, CLIENT_VIEW_SORT_ASCENDING, 1);
m_nSortedCol = theApp.GetProfileInt(lpszViewName, CLIENT_VIEW_SORT_COLUMN, 1);
if(m_nSortedCol >= dwCount)
{
m_nSortedCol = 0;
}
return dwRes;
} // CFolderListView::ReadLayout
DWORD
CFolderListView::SaveLayout(
LPCTSTR lpszViewName
)
/*++
Routine name : CFolderListView::SaveLayout
Routine description:
saves column layout to registry
Author:
Alexander Malysh (AlexMay), Jan, 2000
Arguments:
lpszSection [in] - registry section
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::SaveLayout"),
dwRes,
TEXT("Type=%d"),
m_Type);
if(!m_bColumnsInitialized)
{
return dwRes;
}
ASSERTION(m_pViewColumnInfo != NULL);
//
// save column layout to registry
//
BOOL bRes;
DWORD dwWidth;
CString cstrSection;
DWORD dwCount = GetLogicalColumnsCount();
for(DWORD dw=0; dw < dwCount; ++dw)
{
try
{
cstrSection.Format(TEXT("%s\\%s\\%02d"), lpszViewName, CLIENT_VIEW_COLUMNS, dw);
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("CString::Format"), dwRes);
return dwRes;
}
bRes = theApp.WriteProfileInt(cstrSection, CLIENT_VIEW_COL_SHOW,
m_pViewColumnInfo[dw].bShow);
bRes = theApp.WriteProfileInt(cstrSection, CLIENT_VIEW_COL_ORDER,
m_pViewColumnInfo[dw].dwOrder);
dwWidth = m_pViewColumnInfo[dw].bShow ? GetListCtrl().GetColumnWidth(dw) : -1;
bRes = theApp.WriteProfileInt(cstrSection, CLIENT_VIEW_COL_WIDTH, dwWidth);
}
//
// save sort parameters
//
bRes = theApp.WriteProfileInt(lpszViewName, CLIENT_VIEW_SORT_ASCENDING, m_bSortAscending);
bRes = theApp.WriteProfileInt(lpszViewName, CLIENT_VIEW_SORT_COLUMN, m_nSortedCol);
return dwRes;
} // CFolderListView::SaveLayout
BOOL
CFolderListView::OnNotify(
WPARAM wParam,
LPARAM lParam,
LRESULT* pResult
)
/*++
Routine name : CFolderListView::OnNotify
Routine description:
disables resizing of hidden columns
Author:
Alexander Malysh (AlexMay), Jan, 2000
Arguments:
wParam [in] - Identifies the control that sends the message
lParam [in] - NMHEADER*
pResult [out] - result
Return Value:
TRUE if message processed, FALSE otherwise.
--*/
{
int i=0;
switch (((NMHEADER*)lParam)->hdr.code)
{
case HDN_BEGINTRACKA:
case HDN_BEGINTRACKW:
case HDN_DIVIDERDBLCLICKA:
case HDN_DIVIDERDBLCLICKW:
DBG_ENTER(TEXT("CFolderListView::OnNotify"));
//
// get column index
//
DWORD dwIndex = ((NMHEADER*)lParam)->iItem;
ASSERTION(NULL != m_pViewColumnInfo);
ASSERTION(dwIndex < GetLogicalColumnsCount());
//
// ignore if hidden column
//
if(!m_pViewColumnInfo[dwIndex].bShow )
{
*pResult = TRUE;
return TRUE;
}
}
return CListView::OnNotify(wParam, lParam, pResult );
} // CFolderListView::OnNotify
void
CFolderListView::DoSort()
{
if (m_bSorting || m_nSortedCol < 0)
{
//
// Already sorting or no sorting column
//
return;
}
CWaitCursor waitCursor;
m_bSorting = TRUE;
CMainFrame *pFrm = GetFrm();
if (!pFrm)
{
//
// Shutdown in progress
//
}
else
{
pFrm->RefreshStatusBar ();
}
m_psCurrentViewBeingSorted = this;
GetListCtrl().SortItems (ListViewItemsCompareProc, 0);
m_HeaderCtrl.SetSortImage( m_nSortedCol, m_bSortAscending );
m_bSorting = FALSE;
}
DWORD
CFolderListView::RemoveItem (
LPARAM lparam,
int iIndex /* = -1 */
)
/*++
Routine name : CFolderListView::RemoveItem
Routine description:
Removes an item from the list by its message / job pointer
Author:
Eran Yariv (EranY), Feb, 2000
Arguments:
lparam [in] - Message / Job pointer
iIndex [in] - Optional item index in the control (for optimization)
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::RemoveItem"),
dwRes,
TEXT("Type=%d"),
m_Type);
CListCtrl &refCtrl = GetListCtrl();
if (-1 == iIndex)
{
//
// Item index no supplied - search for it
//
LVFINDINFO lvfi;
lvfi.flags = LVFI_PARAM;
lvfi.lParam = lparam;
iIndex = refCtrl.FindItem (&lvfi);
}
if (-1 == iIndex)
{
//
// item already removed
//
CALL_FAIL (RESOURCE_ERR, TEXT("CListCtrl::FindItem"), dwRes);
return dwRes;
}
BOOL bItemSelected = IsSelected (iIndex);
//
// Now erase the item
//
if (!refCtrl.DeleteItem (iIndex))
{
//
// Failed to delete the item
//
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (RESOURCE_ERR, TEXT("CListCtrl::DeleteItem"), dwRes);
return dwRes;
}
if (bItemSelected)
{
//
// If the item that we just removed was selected, we have to re-compute
// the possible operations on the rest of the selected items.
//
if (!m_bInMultiItemsOperation)
{
//
// Only recalc if we operate on few items.
//
RecalcPossibleOperations ();
}
}
ASSERTION (ERROR_SUCCESS == dwRes);
return dwRes;
} // CFolderListView::RemoveItem
DWORD
CFolderListView::FindInsertionIndex (
LPARAM lparamItemData,
DWORD &dwResultIndex
)
/*++
Routine name : CFolderListView::FindInsertionIndex
Routine description:
Finds an insertion index for a new item to the list, according to sort settings.
This function must be called when the data critical section is held.
Author:
Eran Yariv (EranY), Feb, 2000
Arguments:
lparamItemData [in] - Pointer to item
dwResultIndex [out] - Insertion index
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::FindInsertionIndex"),
dwRes,
TEXT("Type=%d"),
m_Type);
CListCtrl &refCtrl = GetListCtrl();
DWORD dwNumItems = refCtrl.GetItemCount ();
if (!dwNumItems || (-1 == m_nSortedCol))
{
//
// List is not sorted or is empty, always add at the end
//
VERBOSE (DBG_MSG, TEXT("Insertion point at index %ld"), dwResultIndex);
dwResultIndex = dwNumItems;
return dwRes;
}
//
// Get item index to sort by
//
DWORD dwItemIndex = ItemIndexFromLogicalColumnIndex (m_nSortedCol);
//
// Check if item can be placed in beginning of list (no search required)
//
LPARAM lparamTop = refCtrl.GetItemData (0); // Pointer to item in top index
LPARAM lparamBottom = refCtrl.GetItemData (dwNumItems - 1); // Pointer to item in bottom index
ASSERTION (lparamTop && lparamBottom);
//
// Get comparison result against top index
//
int iRes = CompareItems ((CFaxMsg*)lparamItemData, (CFaxMsg*)lparamTop, dwItemIndex);
ASSERTION ((-1 <= iRes) && (+1 >= iRes));
if (!m_bSortAscending)
{
iRes *= -1;
}
switch (iRes)
{
case -1: // Item is smaller than top
case 0: // Item is identical to top
//
// Insert new item before top index
//
dwResultIndex = 0;
VERBOSE (DBG_MSG, TEXT("Insertion point at index %ld"), dwResultIndex);
return dwRes;
default: // Item is bigger than top
//
// Do nothing
//
break;
}
//
// Check if item can be placed in bottom of list (no search required)
//
//
// Get comparison result against bottom index
//
iRes = CompareItems ((CFaxMsg*)lparamItemData, (CFaxMsg*)lparamBottom, dwItemIndex);
ASSERTION ((-1 <= iRes) && (+1 >= iRes));
if (!m_bSortAscending)
{
iRes *= -1;
}
switch (iRes)
{
case +1: // Item is bigger than bottom
case 0: // Item is identical to bottom
//
// Insert new item at the bottom index
//
dwResultIndex = dwNumItems;
VERBOSE (DBG_MSG, TEXT("Insertion point at index %ld"), dwResultIndex);
return dwRes;
default: // Item is smaller than bottom
//
// Do nothing
//
break;
}
//
// Search for insertion point
//
dwRes = BooleanSearchInsertionPoint (0,
dwNumItems - 1,
lparamItemData,
dwItemIndex,
dwResultIndex);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("BooleanSearchInsertionPoint"), dwRes);
return dwRes;
}
return dwRes;
} // CFolderListView::FindInsertionIndex
DWORD
CFolderListView::BooleanSearchInsertionPoint (
DWORD dwTopIndex,
DWORD dwBottomIndex,
LPARAM lparamItemData,
DWORD dwItemIndex,
DWORD &dwResultIndex
)
/*++
Routine name : CFolderListView::BooleanSearchInsertionPoint
Routine description:
Recursively searches an insertion point for a list item.
Performs a boolean search.
This function must be called when the data critical section is held.
Author:
Eran Yariv (EranY), Feb, 2000
Arguments:
dwTopIndex [in] - Top list index
dwBottomIndex [in] - Bottom list index
lparamItemData [in] - Pointer to item
dwItemIndex [in] - Logical column item to compare by
dwResultIndex [out] - Insertion index
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::BooleanSearchInsertionPoint"), dwRes);
ASSERTION (dwTopIndex <= dwBottomIndex);
if ((dwTopIndex == dwBottomIndex) || (dwTopIndex + 1 == dwBottomIndex))
{
dwResultIndex = dwBottomIndex;
VERBOSE (DBG_MSG, TEXT("Insertion point at index %ld"), dwResultIndex);
return dwRes;
}
DWORD dwMiddleIndex = dwTopIndex + (dwBottomIndex - dwTopIndex) / 2;
ASSERTION ((dwMiddleIndex != dwBottomIndex) && (dwMiddleIndex != dwTopIndex));
CListCtrl &refCtrl = GetListCtrl();
LPARAM lparamMiddle = refCtrl.GetItemData (dwMiddleIndex); // Pointer to item in middle index
ASSERTION (lparamMiddle);
//
// Get comparison result against middle index
//
int iRes = CompareItems ((CFaxMsg*)lparamItemData, (CFaxMsg*)lparamMiddle, dwItemIndex);
ASSERTION ((-1 <= iRes) && (+1 >= iRes));
if (!m_bSortAscending)
{
iRes *= -1;
}
switch (iRes)
{
case -1: // Item is smaller than middle
case 0: // Item is identical to middle
//
// Search between top and middle
//
dwRes = BooleanSearchInsertionPoint (dwTopIndex,
dwMiddleIndex,
lparamItemData,
dwItemIndex,
dwResultIndex);
break;
default: // Item is bigger than middle
//
// Search between middle and bottom
//
dwRes = BooleanSearchInsertionPoint (dwMiddleIndex,
dwBottomIndex,
lparamItemData,
dwItemIndex,
dwResultIndex);
break;
}
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("BooleanSearchInsertionPoint"), dwRes);
}
return dwRes;
} // CFolderListView::BooleanSearchInsertionPoint
DWORD
CFolderListView::AddSortedItem (
CViewRow &row,
LPARAM lparamItemData
)
/*++
Routine name : CFolderListView::AddSortedItem
Routine description:
Adds an item to the list, preserving list sort order.
This function must be called when the data critical section is held.
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
row [in] - Row of item view information
lparamItemData [in] - Item associated data
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::AddSortedItem"),
dwRes,
TEXT("Type=%d"),
m_Type);
DWORD dwResultIndex;
//
// Find insertion index according to sort order
//
dwRes = FindInsertionIndex (lparamItemData, dwResultIndex);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("FindInsertionIndex"), dwRes);
return dwRes;
}
//
// Add new item in insertion index
//
int iItemIndex;
dwRes = AddItem (dwResultIndex, row, lparamItemData, &iItemIndex);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("AddItem"), dwRes);
return dwRes;
}
ASSERTION (ERROR_SUCCESS == dwRes);
return dwRes;
} // CFolderListView::AddSortedItem
DWORD
CFolderListView::UpdateSortedItem (
CViewRow &row,
LPARAM lparamItemData
)
/*++
Routine name : CFolderListView::UpdateSortedItem
Routine description:
Updates an item in the list, preserving list sort order.
This function must be called when the data critical section is held.
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
row [in] - Row of item view information
lparamItemData [in] - Item associated data
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::UpdateSortedItem"),
dwRes,
TEXT("Type=%d"),
m_Type);
//
// Find the item in the list
//
CListCtrl &refCtrl = GetListCtrl();
LVFINDINFO lvfi;
lvfi.flags = LVFI_PARAM;
lvfi.lParam = lparamItemData;
int iCurIndex = refCtrl.FindItem (&lvfi);
if (-1 == iCurIndex)
{
dwRes = ERROR_NOT_FOUND;
CALL_FAIL (RESOURCE_ERR, TEXT("CListCtrl::FindItem"), dwRes);
return dwRes;
}
#ifdef _DEBUG
LPARAM lparamCurrentItem = refCtrl.GetItemData (iCurIndex);
ASSERTION (lparamCurrentItem == lparamItemData);
#endif
BOOL bJustUpdate = TRUE; // If TRUE, we don't move the item in the list
if (0 <= m_nSortedCol)
{
//
// List is sorted.
// See if the displayed text is different than the updated text
//
CString cstrDisplayedCell;
try
{
cstrDisplayedCell = refCtrl.GetItemText (iCurIndex, m_nSortedCol);
}
catch (...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT ("CString::operator ="), dwRes);
return dwRes;
}
//
// Get item index to sort by
//
DWORD dwItemIndex = ItemIndexFromLogicalColumnIndex (m_nSortedCol);
const CString &cstrUpdatedString = row.GetItemString(dwItemIndex);
if (cstrUpdatedString.Compare (cstrDisplayedCell))
{
//
// Text in the sorted column is about to change.
// Sorry, but we must:
// 1. Remove old item from list
// 2. Insert new item (sorted)
//
bJustUpdate = FALSE;
}
}
if (bJustUpdate)
{
//
// All we need to do is update the text of the list item (all sub items) and its icon
//
dwRes = UpdateLineTextAndIcon (iCurIndex, row);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (RESOURCE_ERR, TEXT("UpdateLineTextAndIcon"), dwRes);
return dwRes;
}
}
else
{
//
// Since the text in the sorted column is different than the new text,
// we must remove the current item and insert a new (sorted) item.
//
BOOL bItemSelected = IsSelected (iCurIndex);
refCtrl.SetRedraw (FALSE);
if (!refCtrl.DeleteItem (iCurIndex))
{
//
// Failed to delete the item
//
dwRes = ERROR_GEN_FAILURE;
refCtrl.SetRedraw (TRUE);
CALL_FAIL (RESOURCE_ERR, TEXT("CListCtrl::DeleteItem"), dwRes);
return dwRes;
}
dwRes = AddSortedItem (row, lparamItemData);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (RESOURCE_ERR, TEXT("AddSortedItem"), dwRes);
refCtrl.SetRedraw (TRUE);
return dwRes;
}
if (bItemSelected)
{
//
// Since the item we removed was selected, we must also selected the new item
// we just added.
// Recalculate the possible operations the user can do on selected item.
//
Select (iCurIndex, TRUE);
RecalcPossibleOperations ();
}
refCtrl.SetRedraw (TRUE);
}
ASSERTION (ERROR_SUCCESS == dwRes);
return dwRes;
} // CFolderListView::UpdateSortedItem
DWORD
CFolderListView::ConfirmItemDelete(
BOOL& bConfirm
)
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::ConfirmItemDelete"), dwRes);
//
// do we should ask to confirm ?
//
BOOL bAsk = theApp.GetProfileInt(CLIENT_CONFIRM_SEC, CLIENT_CONFIRM_ITEM_DEL, 1);
if(!bAsk)
{
bConfirm = TRUE;
return dwRes;
}
CListCtrl &refCtrl = GetListCtrl();
DWORD dwSelected = refCtrl.GetSelectedCount();
ASSERTION (dwSelected > 0);
//
// prepare message string
//
CString cstrMsg;
if(1 == dwSelected)
{
dwRes = LoadResourceString(cstrMsg, IDS_SURE_DELETE_ONE);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (RESOURCE_ERR, TEXT("LoadResourceString"), dwRes);
return dwRes;
}
}
else
{
//
// more then 1 selected
//
CString cstrCount;
try
{
cstrCount.Format(TEXT("%d"), dwSelected);
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("CString::Format"), dwRes);
return dwRes;
}
try
{
AfxFormatString1(cstrMsg, IDS_SURE_DELETE_MANY, cstrCount);
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("AfxFormatString1"), dwRes);
return dwRes;
}
}
//
// are you sure ?
//
DWORD dwAskRes = AlignedAfxMessageBox(cstrMsg, MB_YESNO | MB_ICONQUESTION);
bConfirm = (IDYES == dwAskRes);
return dwRes;
} // CFolderListView::ConfirmItemDelete
void
CFolderListView::OnDblClk(
NMHDR* pNMHDR,
LRESULT* pResult
)
{
DWORD nItem = ((NM_LISTVIEW*)pNMHDR)->iItem;
CListCtrl &refCtrl = GetListCtrl();
DWORD dwSelected = refCtrl.GetSelectedCount();
DWORD dwSelItem = refCtrl.GetNextItem (-1, LVNI_SELECTED);
if(1 == dwSelected && dwSelItem == nItem)
{
OnFolderItemView();
}
*pResult = 0;
}
DWORD
CFolderListView::FetchTiff (
CString &cstrTiff
)
/*++
Routine name : CFolderListView::FetchTiff
Routine description:
Fetches the TIFF image of the selected list item
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
cstrTiff [out] - Name of local TIFF file
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::FetchTiff"), dwRes);
//
// Make sure there's exaclty one elemented selected
//
CListCtrl &refCtrl = GetListCtrl();
if (1 != refCtrl.GetSelectedCount())
{
return ERROR_CANTOPEN;
}
int iInd = refCtrl.GetNextItem (-1, LVNI_SELECTED);
if (0 > iInd)
{
return ERROR_CANTOPEN;
}
CFaxMsg *pMsg = (CFaxMsg *) refCtrl.GetItemData (iInd);
if (pMsg == NULL)
{
return ERROR_CANTOPEN;
}
//
// Ask message to fetch the TIFF
//
dwRes = pMsg->GetTiff (cstrTiff);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (RPC_ERR, TEXT("CFaxMsg::GetTIFF"), dwRes);
}
return dwRes;
} // CFolderListView::FetchTiff
void
CFolderListView::OnFolderItemDelete ()
/*++
Routine name : CFolderListView::OnFolderItemDelete
Routine description:
Handles message delete commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderItemDelete"),
TEXT("Type=%d"),
m_Type);
//
// are you sure ?
//
BOOL bConfirm;
DWORD dwRes = ConfirmItemDelete(bConfirm);
if (ERROR_SUCCESS != dwRes)
{
PopupError (dwRes);
CALL_FAIL (GENERAL_ERR, TEXT("ConfirmItemDelete"), dwRes);
return;
}
if(!bConfirm)
{
//
// not sure.
//
return;
}
CWaitCursor waitCursor;
CClientConsoleDoc* pDoc = GetDocument();
ASSERTION (pDoc);
CServerNode* pServer = NULL;
CFolder* pFolder = NULL;
//
// Iterate set of selected messages, deleting each message in the set
//
CListCtrl &refCtrl = GetListCtrl();
DWORD dwSelected = refCtrl.GetSelectedCount();
if(0 == dwSelected)
{
return;
}
if (dwSelected > 1)
{
//
// Disable refresh while deleting
//
refCtrl.SetRedraw (FALSE);
//
// Prevent costy re-calc on every deletion
//
m_bInMultiItemsOperation = TRUE;
JobOpProgressDlgStart(FAX_JOB_OP_DELETE, dwSelected);
}
int iInd;
CFaxMsg* pMsg;
DWORDLONG dwlMsgId;
for (DWORD dwItem = 0; dwItem < dwSelected && !m_bJobOpCancel; ++dwItem)
{
iInd = refCtrl.GetNextItem (-1, LVNI_SELECTED);
if(iInd < 0)
{
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
break;
}
pMsg = (CFaxMsg *) refCtrl.GetItemData (iInd);
ASSERTION (pMsg);
dwlMsgId = pMsg->GetId();
//
// Ask message to delete
//
dwRes = pMsg->Delete ();
if (ERROR_SUCCESS != dwRes)
{
PopupError (dwRes);
CALL_FAIL (RPC_ERR, TEXT("CArchiveMsg::Delete"), dwRes);
//
// We exit upon first error
//
goto exit;
}
//
// delete a message from the data map and from the view
//
pServer = pMsg->GetServer();
ASSERTION (pServer);
pFolder = pServer->GetFolder(m_Type);
ASSERTION (pFolder);
dwRes = pFolder->OnJobRemoved(dwlMsgId, pMsg);
if (ERROR_SUCCESS != dwRes)
{
PopupError (dwRes);
CALL_FAIL (RPC_ERR, TEXT("CMessageFolder::OnJobRemoved"), dwRes);
goto exit;
}
if(m_bInMultiItemsOperation)
{
JobOpProgressDlgInc();
}
}
exit:
if (m_bInMultiItemsOperation)
{
JobOpProgressDlgStop();
//
// Re-enable redraw
//
refCtrl.SetRedraw (TRUE);
//
// Ask for visual refresh of view
//
refCtrl.Invalidate ();
m_bInMultiItemsOperation = FALSE;
RecalcPossibleOperations ();
}
if(FOLDER_TYPE_INBOX == m_Type)
{
theApp.InboxViewed();
}
} // CFolderListView::OnFolderItemDelete
void
CFolderListView::CountColumns (
int *lpItems
)
/*++
Routine name : CFolderListView::CountColumns
Routine description:
Sets the items to be seen in the view.
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
lpItems [in] - List of items. ends with MSG_VIEW_ITEM_END
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::CountColumns"));
m_dwAvailableColumnsNum = 0;
MsgViewItemType *pItems = (MsgViewItemType *)lpItems;
m_pAvailableColumns = pItems;
while (MSG_VIEW_ITEM_END != *pItems)
{
ASSERTION (*pItems < MSG_VIEW_ITEM_END);
++m_dwAvailableColumnsNum;
++pItems;
}
ASSERTION (m_dwAvailableColumnsNum);
} // CFolderListView::CountColumns
int
CFolderListView::CompareItems (
CFaxMsg* pFaxMsg1,
CFaxMsg* pFaxMsg2,
DWORD dwItemIndex
) const
/*++
Routine name : CFolderListView::CompareItems
Routine description:
Compares two archive items
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
pFaxMsg1 [in] - Pointer to 1st message
pFaxMsg2 [in] - Pointer to 2nd message
dwItemIndex [in] - Item (in the message) to comapre by
Return Value:
-1 if message1 < message2, 0 if identical, +1 if message1 > message2
--*/
{
DBG_ENTER(TEXT("CFolderListView::CompareItems"));
ASSERTION (dwItemIndex < MSG_VIEW_ITEM_END);
static CViewRow rowView1;
static CViewRow rowView2;
DWORD dwRes = rowView1.AttachToMsg (pFaxMsg1, FALSE);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
return 0;
}
dwRes = rowView2.AttachToMsg (pFaxMsg2, FALSE);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
return 0;
}
return rowView1.CompareByItem (rowView2, dwItemIndex);
}
DWORD
CFolderListView::AddMsgMapToView(
MSGS_MAP* pMap
)
/*++
Routine name : CFolderListView::AddMsgMapToView
Routine description:
Add messages from the map to the view
Arguments:
pMap [in] - masage map
Return Value:
error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CFolderListView::AddMsgMapToView"));
ASSERTION(pMap);
CListCtrl &listCtrl = GetListCtrl();
DWORD dwCount = listCtrl.GetItemCount();
listCtrl.SetRedraw (FALSE);
CFaxMsg* pMsg;
CViewRow viewRow;
int iIndexToSelect = -1;
for (MSGS_MAP::iterator it = pMap->begin(); it != pMap->end(); ++it)
{
int iItemIndex;
pMsg = (*it).second;
dwRes = viewRow.AttachToMsg (pMsg);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
break;
}
dwRes = AddItem (dwCount++, viewRow, (LPARAM)pMsg, &iItemIndex);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::AddItem"), dwRes);
break;
}
if ((-1 == iIndexToSelect) && // No item selected yet and
m_dwlMsgToSelect && // We should keep our eyes open for an item to select and
(pMsg->GetId () == m_dwlMsgToSelect)) // Match found !!
{
//
// This is the startup selected item.
// Save the item index
//
iIndexToSelect = iItemIndex;
}
}
if (-1 != iIndexToSelect)
{
//
// We have the user-specified-item-to-select in the list now
//
SelectItemByIndex (iIndexToSelect);
}
listCtrl.SetRedraw ();
return dwRes;
} // CFolderListView::AddMsgMapToView
void
CFolderListView::OnUpdate (
CView* pSender,
LPARAM lHint,
CObject* pHint
)
/*++
Routine name : CFolderListView::OnUpdate
Routine description:
Receives a notification that the view should update itself
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
pSender [in] - Unused
lHint [in] - Hint of update operation
pHint [in] - If lHint is UPDATE_HINT_CLEAR_VIEW or UPDATE_HINT_FILL_VIEW
then pHint is a pointer to the folder that requested an update.
If lHint is UPDATE_HINT_REMOVE_ITEM, UPDATE_HINT_ADD_ITEM, or
UPDATE_HINT_UPDATE_ITEM,
then pHint is a pointer to the job to remove / add / update.
Otherwise, pHint is undefined.
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnUpdate"),
TEXT("Hint=%ld, Type=%d"),
lHint,
m_Type);
OnUpdateHintType hint = (OnUpdateHintType) lHint;
DWORD dwRes;
CListCtrl &listCtrl = GetListCtrl();
switch (hint)
{
case UPDATE_HINT_CREATION:
//
// Do nothing
//
break;
case UPDATE_HINT_CLEAR_VIEW:
//
// Clear the entire list control now
//
if (!listCtrl.DeleteAllItems ())
{
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::DeleteAllItems"), ERROR_GEN_FAILURE);
}
ClearPossibleOperations ();
break;
case UPDATE_HINT_ADD_CHUNK:
{
ASSERTION (pHint);
MSGS_MAP* pMap = (MSGS_MAP*) pHint;
dwRes = AddMsgMapToView(pMap);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::AddMsgMapToView"), dwRes);
}
}
break;
case UPDATE_HINT_FILL_VIEW:
//
// Fill the list control with my parents data
//
{
ASSERTION (pHint);
CFolder *pFolder = (CFolder *) pHint;
pFolder->EnterData ();
MSGS_MAP &ParentMap = pFolder->GetData ();
dwRes = AddMsgMapToView(&ParentMap);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::AddMsgMapToView"), dwRes);
}
pFolder->LeaveData ();
}
break;
case UPDATE_HINT_REMOVE_ITEM:
//
// The data critical section must be held.
//
{
CFaxMsg* pMsg = (CFaxMsg*)pHint;
ASSERTION(pMsg);
dwRes = RemoveItem ((LPARAM)pMsg);
if (ERROR_SUCCESS != dwRes)
{
//
// Failed to remove item from list
//
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::RemoveItem"), dwRes);
ASSERTION_FAILURE;
}
}
break;
case UPDATE_HINT_ADD_ITEM:
//
// The data critical section must be held.
//
{
CFaxMsg* pMsg = (CFaxMsg*)pHint;
ASSERTION(pMsg);
CViewRow viewRow;
dwRes = viewRow.AttachToMsg (pMsg);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
return;
}
dwRes = AddSortedItem (viewRow, (LPARAM)pMsg);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::AddSortedItem"), dwRes);
return;
}
}
break;
case UPDATE_HINT_UPDATE_ITEM:
//
// The data critical section must be held.
//
{
CFaxMsg* pMsg = (CFaxMsg*)pHint;
ASSERTION(pMsg);
CViewRow viewRow;
dwRes = viewRow.AttachToMsg (pMsg);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
return;
}
dwRes = UpdateSortedItem (viewRow, (LPARAM)pMsg);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::UpdateSortedItem"), dwRes);
return;
}
}
break;
default:
//
// Unsupported hint
//
ASSERTION_FAILURE;
}
if(!m_bInMultiItemsOperation)
{
RecalcPossibleOperations ();
}
CMainFrame *pFrm = GetFrm();
if (pFrm)
{
pFrm->RefreshStatusBar();
}
} // CFolderListView::OnUpdate
int
CFolderListView::GetPopupMenuResource () const
{
DBG_ENTER(TEXT("CFolderListView::GetPopupMenuResource"));
int nMenuRes=0;
switch(m_Type)
{
case FOLDER_TYPE_INCOMING:
nMenuRes = IDM_INCOMING;
break;
case FOLDER_TYPE_INBOX:
nMenuRes = IDM_INBOX;
break;
case FOLDER_TYPE_SENT_ITEMS:
nMenuRes = IDM_SENTITEMS;
break;
case FOLDER_TYPE_OUTBOX:
nMenuRes = IDM_OUTBOX;
break;
default:
ASSERTION_FAILURE
break;
}
return nMenuRes;
}
void
CFolderListView::OnFolderItemPause ()
/*++
Routine name : CFolderListView::OnFolderItemPause
Routine description:
Handles job pause commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderItemPause"),
TEXT("Type=%d"),
m_Type);
CWaitCursor waitCursor;
//
// Iterate set of selected jobs, pausing each job in the set
//
CListCtrl &refCtrl = GetListCtrl();
DWORD dwSelected = refCtrl.GetSelectedCount();
ASSERTION (dwSelected);
int iInd = -1;
if(dwSelected > 1)
{
m_bInMultiItemsOperation = TRUE;
JobOpProgressDlgStart(FAX_JOB_OP_PAUSE, dwSelected);
}
for (DWORD dwItem = 0; dwItem < dwSelected && !m_bJobOpCancel; ++dwItem)
{
iInd = refCtrl.GetNextItem (iInd, LVNI_SELECTED);
if(iInd < 0)
{
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
break;
}
CFaxMsg* pJob = (CFaxMsg*) refCtrl.GetItemData (iInd);
ASSERT_KINDOF(CJob, pJob);
//
// Ask job to pause
//
DWORD dwRes = pJob->Pause ();
if (ERROR_SUCCESS != dwRes)
{
PopupError (dwRes);
CALL_FAIL (RPC_ERR, TEXT("CJob::Pause"), dwRes);
//
// We exit upon first error
//
goto exit;
}
//
// update the view
//
OnUpdate (NULL, UPDATE_HINT_UPDATE_ITEM, pJob);
if(m_bInMultiItemsOperation)
{
JobOpProgressDlgInc();
}
}
exit:
if(m_bInMultiItemsOperation)
{
m_bInMultiItemsOperation = FALSE;
JobOpProgressDlgStop();
RecalcPossibleOperations();
}
} // CFolderListView::OnFolderItemPause
void CFolderListView::OnFolderItemResume ()
/*++
Routine name : CFolderListView::OnFolderItemResume
Routine description:
Handles job resume commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderItemResume"),
TEXT("Type=%d"),
m_Type);
CWaitCursor waitCursor;
//
// Iterate set of selected jobs, resuming each job in the set
//
CListCtrl &refCtrl = GetListCtrl();
DWORD dwSelected = refCtrl.GetSelectedCount();
ASSERTION (dwSelected);
if(dwSelected > 1)
{
m_bInMultiItemsOperation = TRUE;
JobOpProgressDlgStart(FAX_JOB_OP_RESUME, dwSelected);
}
int iInd = -1;
for (DWORD dwItem = 0; dwItem < dwSelected && !m_bJobOpCancel; ++dwItem)
{
iInd = refCtrl.GetNextItem (iInd, LVNI_SELECTED);
if(iInd < 0)
{
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
break;
}
CFaxMsg* pJob = (CFaxMsg*) refCtrl.GetItemData (iInd);
ASSERT_KINDOF(CJob, pJob);
//
// Ask job to resume
//
DWORD dwRes = pJob->Resume ();
if (ERROR_SUCCESS != dwRes)
{
PopupError (dwRes);
CALL_FAIL (RPC_ERR, TEXT("CJob::Resume"), dwRes);
//
// We exit upon first error
//
goto exit;
}
//
// update the view
//
OnUpdate (NULL, UPDATE_HINT_UPDATE_ITEM, pJob);
if(m_bInMultiItemsOperation)
{
JobOpProgressDlgInc();
}
}
exit:
if(m_bInMultiItemsOperation)
{
m_bInMultiItemsOperation = FALSE;
JobOpProgressDlgStop();
RecalcPossibleOperations();
}
} // CFolderListView::OnFolderItemResume
void
CFolderListView::OnFolderItemRestart ()
/*++
Routine name : CFolderListView::OnFolderItemRestart
Routine description:
Handles job restart commands
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::OnFolderItemRestart"),
TEXT("Type=%d"),
m_Type);
CWaitCursor waitCursor;
//
// Iterate set of selected jobs, restarting each job in the set
//
CListCtrl &refCtrl = GetListCtrl();
DWORD dwSelected = refCtrl.GetSelectedCount();
ASSERTION (dwSelected);
if(dwSelected > 1)
{
m_bInMultiItemsOperation = TRUE;
JobOpProgressDlgStart(FAX_JOB_OP_RESTART, dwSelected);
}
int iInd = -1;
for (DWORD dwItem = 0; dwItem < dwSelected && !m_bJobOpCancel; ++dwItem)
{
iInd = refCtrl.GetNextItem (iInd, LVNI_SELECTED);
if(iInd < 0)
{
CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
break;
}
CFaxMsg* pJob = (CFaxMsg*) refCtrl.GetItemData (iInd);
ASSERT_KINDOF(CJob, pJob);
//
// Ask job to restart
//
DWORD dwRes = pJob->Restart ();
if (ERROR_SUCCESS != dwRes)
{
PopupError (dwRes);
CALL_FAIL (RPC_ERR, TEXT("CJob::Restart"), dwRes);
//
// We exit upon first error
//
goto exit;
}
//
// update the view
//
OnUpdate (NULL, UPDATE_HINT_UPDATE_ITEM, pJob);
if(m_bInMultiItemsOperation)
{
JobOpProgressDlgInc();
}
}
exit:
if(m_bInMultiItemsOperation)
{
m_bInMultiItemsOperation = FALSE;
JobOpProgressDlgStop();
RecalcPossibleOperations();
}
} // CFolderListView::OnFolderItemRestart
void
CFolderListView::OnChar(
UINT nChar,
UINT nRepCnt,
UINT nFlags
)
/*++
Routine name : CFolderListView::OnChar
Routine description:
The framework calls this member function when a keystroke translates
to a nonsystem character
Arguments:
nChar [in] - Contains the character code value of the key.
nRepCnt [in] - Contains the repeat count
nFlags [in] - Contains the scan code
Return Value:
None.
--*/
{
if(VK_TAB == nChar)
{
CMainFrame *pFrm = GetFrm();
if (!pFrm)
{
//
// Shutdown in progress
//
return;
}
CLeftView* pLeftView = pFrm->GetLeftView();
if(pLeftView)
{
pLeftView->SetFocus();
}
}
else
{
CListView::OnChar(nChar, nRepCnt, nFlags);
}
}
afx_msg void
CFolderListView::OnContextMenu(
CWnd *pWnd,
CPoint pos
)
{
DBG_ENTER(TEXT("CFolderListView::OnContextMenu"),
TEXT("Type=%d"),
m_Type);
CListCtrl &refCtrl = GetListCtrl();
DWORD dwSelected = refCtrl.GetSelectedCount();
if (!dwSelected)
{
//
// If no item is selected, this is equivalent to right-clicking an empty area in the list view
// which does nothing.
//
return;
}
if (pos.x == -1 && pos.y == -1)
{
//
// Keyboard (VK_APP or Shift + F10)
//
//
// Pop the context menu near the mouse cursor
//
pos = (CPoint) GetMessagePos();
}
int iMenuResource = GetPopupMenuResource ();
if(0 == iMenuResource)
{
ASSERTION_FAILURE;
return;
}
ScreenToClient(&pos);
CMenu mnuContainer;
if (!mnuContainer.LoadMenu (iMenuResource))
{
CALL_FAIL (RESOURCE_ERR, TEXT("CMenu::LoadMenu"), ERROR_GEN_FAILURE);
return;
}
CMenu *pmnuPopup = mnuContainer.GetSubMenu (0);
ASSERTION (pmnuPopup);
ClientToScreen(&pos);
if (!pmnuPopup->TrackPopupMenu (TPM_LEFTALIGN,
pos.x,
pos.y,
theApp.m_pMainWnd))
{
CALL_FAIL (RESOURCE_ERR, TEXT("CMenu::TrackPopupMenu"), ERROR_GEN_FAILURE);
}
} // CFolderListView::OnContextMenu
void
CFolderListView::SelectItemById (
DWORDLONG dwlMsgId
)
/*++
Routine name : CFolderListView::SelectItemById
Routine description:
Selects an item in the list control, by its message id
Author:
Eran Yariv (EranY), May, 2001
Arguments:
dwlMsgId [in] - Message id
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::SelectItemById"),
TEXT("Message id=%0xI64d"),
dwlMsgId);
ASSERTION (dwlMsgId);
int iMsgIndex = FindItemIndexFromID (dwlMsgId);
if (-1 == iMsgIndex)
{
//
// Message could not be found in the list.
// This usually happens when we handle a WM_CONSOLE_SELECT_ITEM message sent to the main frame
// but the folder is in the middle of refresh and the requested message might not be there yet.
//
// By setting m_dwlMsgToSelect = dwlMsgId we signal the OnFolderRefreshEnded() funtion to call us again
// once refresh has ended.
//
VERBOSE (DBG_MSG, TEXT("Item not found - doing nothing"));
m_dwlMsgToSelect = dwlMsgId;
return;
}
SelectItemByIndex (iMsgIndex);
} // CFolderListView::SelectItemById
void
CFolderListView::SelectItemByIndex (
int iMsgIndex
)
/*++
Routine name : CFolderListView::SelectItemByIndex
Routine description:
Selects an item in the list control, by its list item index
Author:
Eran Yariv (EranY), May, 2001
Arguments:
dwlMsgId [in] - List item index
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::SelectItemByIndex"),
TEXT("Index = %ld"),
iMsgIndex);
CListCtrl &refCtrl = GetListCtrl();
ASSERTION (iMsgIndex >= 0 && iMsgIndex < refCtrl.GetItemCount());
OnSelectNone();
refCtrl.SetItemState (iMsgIndex,
LVIS_SELECTED | LVIS_FOCUSED,
LVIS_SELECTED | LVIS_FOCUSED);
refCtrl.EnsureVisible (iMsgIndex, FALSE);
refCtrl.SetFocus();
//
// Make sure this item won't be selected again
//
m_dwlMsgToSelect = 0;
} // CFolderListView::SelectItemByIndex
int
CFolderListView::FindItemIndexFromID (
DWORDLONG dwlMsgId
)
/*++
Routine name : CFolderListView::FindItemIndexFromID
Routine description:
Finds the list view item index of a message by a message id
Author:
Eran Yariv (EranY), May, 2001
Arguments:
dwlMsgId [in] - Message id
Return Value:
Item index. -1 if not found
--*/
{
DBG_ENTER(TEXT("CFolderListView::FindItemIndexFromID"),
TEXT("Message id=%0xI64d"),
dwlMsgId);
CListCtrl &refCtrl = GetListCtrl();
int iItemCount = refCtrl.GetItemCount();
//
// We must traverse the entire list and look for the message that matches the id.
//
for (int iIndex = 0; iIndex < iItemCount; iIndex++)
{
CFaxMsg *pMsg = (CFaxMsg*)refCtrl.GetItemData (iIndex);
if (dwlMsgId == pMsg->GetId())
{
//
// Found it
//
return iIndex;
}
}
return -1;
} // CFolderListView::FindItemIndexFromID
INT_PTR
CALLBACK
CFolderListView::JobOpProgressDlgProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
/*++
Routine description:
Job operation progress dialog
Arguments:
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
Return Value:
return TRUE if it processed the message
--*/
{
static CFolderListView* pFolderView = NULL;
switch (uMsg)
{
case WM_INITDIALOG:
pFolderView = (CFolderListView*)lParam;
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
pFolderView->m_bJobOpCancel = TRUE;
::EnableWindow(::GetDlgItem(hwndDlg, IDCANCEL), FALSE);
return TRUE;
}
break;
}
return FALSE;
} // CFolderListView::JobOpProgressDlgProc
BOOL
CFolderListView::JobOpProgressDlgStart(
FAX_ENUM_JOB_OP opJob,
DWORD dwItems
)
/*++
Routine name : CFolderListView::JobOpProgressDlgStart
Routine description:
Open and initialize multi job operation dialog
Arguments:
opJob [in]- operation type FAX_ENUM_JOB_OP enum
dwItems [in]- number of iterations
Return Value:
TRUE if success
FALSE otherwise
--*/
{
DBG_ENTER(TEXT("CFolderListView::JobOpProgressDlgStart"));
HWND hProgressDlg = CreateDialogParam(GetResourceHandle(), // handle to module
MAKEINTRESOURCE(IDD_FAX_PROGRESS), // dialog box template name
theApp.m_pMainWnd->m_hWnd, // handle to owner window
JobOpProgressDlgProc, // dialog box procedure
(LPARAM)this); // initialization value
if(!hProgressDlg)
{
CALL_FAIL (WINDOW_ERR, TEXT("CreateDialog"), GetLastError());
return FALSE;
}
//
// Set title string
//
DWORD dwTitleID=0;
TCHAR szTitle[MAX_PATH]={0};
switch(opJob)
{
case FAX_JOB_OP_PAUSE:
dwTitleID = IDS_PROGRESS_PAUSE;
break;
case FAX_JOB_OP_RESUME:
dwTitleID = IDS_PROGRESS_RESUME;
break;
case FAX_JOB_OP_RESTART:
dwTitleID = IDS_PROGRESS_RESTART;
break;
case FAX_JOB_OP_DELETE:
dwTitleID = IDS_PROGRESS_DELETE;
break;
default:
ASSERTION_FAILURE;
break;
}
if(LoadString(GetResourceHandle(), dwTitleID, szTitle, ARR_SIZE(szTitle)))
{
::SetDlgItemText(hProgressDlg, IDC_PROGRESS_TITLE, szTitle);
}
else
{
CALL_FAIL (RESOURCE_ERR, TEXT("LoadString"), GetLastError());
}
//
// Init progress bar
//
m_dwJobOpPos = 0;
m_dwJobOpItems = dwItems;
::SendDlgItemMessage(hProgressDlg, IDC_PROGRESS_BAR, PBM_SETRANGE32, 0, dwItems);
::SendDlgItemMessage(hProgressDlg, IDC_PROGRESS_BAR, PBM_SETSTEP, 1, 0);
theApp.m_pMainWnd->EnableWindow(FALSE);
m_hJobOpProgressDlg = hProgressDlg;
return TRUE;
} // CFolderListView::JobOpProgressDlgStart
void
CFolderListView::JobOpProgressDlgInc()
/*++
Routine name : CFolderListView::JobOpProgressDlgInc
Routine description:
Multi job operation progress dialog increment
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::JobOpProgressDlgInc"));
if(!m_hJobOpProgressDlg)
{
return;
}
++m_dwJobOpPos;
//
// Increment progress bar
//
::SendDlgItemMessage(m_hJobOpProgressDlg, IDC_PROGRESS_BAR, PBM_STEPIT, 0, 0);
//
// Compose and set progress string
//
TCHAR szFormat[MAX_PATH] = {0};
TCHAR szText[MAX_PATH] = {0};
DWORD dwParam[2];
dwParam[0] = m_dwJobOpPos;
dwParam[1] = m_dwJobOpItems;
if(LoadString(GetResourceHandle(),
IDS_PROGRESS_NUMBER,
szFormat,
ARR_SIZE(szFormat)))
{
if(FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCVOID)szFormat,
0,
0,
szText,
ARR_SIZE(szText),
(va_list*)dwParam))
{
::SetDlgItemText(m_hJobOpProgressDlg, IDC_PROGRESS_NUMBER, szText);
}
else
{
CALL_FAIL (GENERAL_ERR, TEXT ("FormatMessage"), GetLastError());
}
}
else
{
CALL_FAIL (RESOURCE_ERR, TEXT ("LoadString(IDS_PROGRESS_NUMBER)"), GetLastError());
}
//
// MFC message pump
// Taken from MSDN Q99999
// INFO: Background Processing in an MFC Application
//
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (!theApp.PreTranslateMessage(&msg))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
theApp.OnIdle(0); // updates user interface
theApp.OnIdle(1); // frees temporary objects
}
} // CFolderListView::JobOpProgressDlgInc
void
CFolderListView::JobOpProgressDlgStop()
/*++
Routine name : CFolderListView::JobOpProgressDlgStop
Routine description:
Close multi job operation progress dialog
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CFolderListView::JobOpProgressDlgStop"));
if(!m_hJobOpProgressDlg)
{
return;
}
::DestroyWindow(m_hJobOpProgressDlg);
m_hJobOpProgressDlg = NULL;
m_bJobOpCancel = FALSE;
m_dwJobOpItems = 0;
m_dwJobOpPos = 0;
theApp.ReturnFromModal();
} // CFolderListView::JobOpProgressDlgStop