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.
2664 lines
80 KiB
2664 lines
80 KiB
/////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) 1993-1998 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// MODULE: finder.cpp
|
|
//
|
|
// PURPOSE:
|
|
//
|
|
|
|
#include "pch.hxx"
|
|
#include <process.h>
|
|
#include "resource.h"
|
|
#include "error.h"
|
|
#include "finder.h"
|
|
#include "goptions.h"
|
|
#include "menuutil.h"
|
|
#include "statbar.h"
|
|
#include "imnact.h"
|
|
#include "note.h"
|
|
#include "mailutil.h"
|
|
#include "statnery.h"
|
|
#include "instance.h"
|
|
#include "msoeobj.h"
|
|
#include "msglist.h"
|
|
#include "storutil.h"
|
|
#include "menures.h"
|
|
#include "findres.h"
|
|
#include "multiusr.h"
|
|
#include "newsutil.h"
|
|
#include "ruleutil.h"
|
|
#include "instance.h"
|
|
#include "shlwapip.h"
|
|
#include "demand.h"
|
|
#include "dllmain.h"
|
|
#include "order.h"
|
|
|
|
ASSERTDATA
|
|
|
|
#define MF_ENABLEFLAGS(b) (MF_BYCOMMAND|(b ? MF_ENABLED : MF_GRAYED | MF_DISABLED))
|
|
|
|
|
|
typedef struct _ThreadList
|
|
{
|
|
DWORD dwThreadID;
|
|
struct _ThreadList * pPrev;
|
|
struct _ThreadList * pNext;
|
|
} OETHREADLIST;
|
|
|
|
OETHREADLIST * g_pOEThrList = NULL;
|
|
|
|
// Add thread to list
|
|
OETHREADLIST * AddThreadToList(DWORD uiThreadId, OETHREADLIST * pThrList)
|
|
{
|
|
if(!pThrList)
|
|
{
|
|
if(MemAlloc((LPVOID *) &pThrList, sizeof(OETHREADLIST)))
|
|
{
|
|
|
|
pThrList->pPrev = NULL;
|
|
pThrList->pNext = NULL;
|
|
pThrList->dwThreadID = uiThreadId;
|
|
}
|
|
}
|
|
else
|
|
pThrList->pNext = AddThreadToList(uiThreadId, pThrList->pNext);
|
|
|
|
return(pThrList);
|
|
}
|
|
|
|
// Remove thread from list
|
|
OETHREADLIST * DelThreadToList(DWORD uiThreadId, OETHREADLIST * pThrList)
|
|
{
|
|
OETHREADLIST * pLst = NULL;
|
|
|
|
if(!pThrList)
|
|
return(NULL);
|
|
else if(pThrList->dwThreadID == uiThreadId)
|
|
{
|
|
if(pThrList->pPrev)
|
|
{
|
|
pThrList->pPrev->pNext = pThrList->pNext;
|
|
pLst = pThrList->pPrev;
|
|
}
|
|
if(pThrList->pNext)
|
|
{
|
|
pThrList->pNext->pPrev = pThrList->pPrev;
|
|
if(!pLst)
|
|
pLst = pThrList->pNext;
|
|
}
|
|
|
|
MemFree(pThrList);
|
|
pThrList = NULL;
|
|
}
|
|
else
|
|
pThrList->pNext = DelThreadToList(uiThreadId, pThrList->pNext);
|
|
|
|
return pLst;
|
|
}
|
|
|
|
// Close all Finder windows
|
|
void CloseAllFindWnds(HWND hwnd, OETHREADLIST * pThrList)
|
|
{
|
|
while(pThrList)
|
|
{
|
|
CloseThreadWindows(hwnd, pThrList->dwThreadID);
|
|
pThrList = pThrList->pNext;
|
|
}
|
|
}
|
|
|
|
|
|
void CloseFinderTreads()
|
|
{
|
|
CloseAllFindWnds(NULL, g_pOEThrList);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Thread entry point for the finder
|
|
//
|
|
unsigned int __stdcall FindThreadProc(LPVOID lpvUnused);
|
|
|
|
|
|
HRESULT CPumpRefCount::QueryInterface(REFIID riid, LPVOID *ppvObj)
|
|
{
|
|
TraceCall("CPumpRefCount::QueryInterface");
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*ppvObj = (LPVOID) (IUnknown *)this;
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return (S_OK);
|
|
}
|
|
|
|
return (E_NOINTERFACE);
|
|
}
|
|
|
|
|
|
ULONG CPumpRefCount::AddRef(void)
|
|
{
|
|
TraceCall("CPumpRefCount::AddRef");
|
|
return ((ULONG) InterlockedIncrement((LONG *) &m_cRef));
|
|
}
|
|
|
|
|
|
ULONG CPumpRefCount::Release(void)
|
|
{
|
|
TraceCall("CPumpRefCount::Release");
|
|
|
|
if (0 == InterlockedDecrement((LONG *) &m_cRef))
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return (m_cRef);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: FreeFindInfo
|
|
//
|
|
void FreeFindInfo(FINDINFO *pFindInfo)
|
|
{
|
|
SafeMemFree(pFindInfo->pszFrom);
|
|
SafeMemFree(pFindInfo->pszSubject);
|
|
SafeMemFree(pFindInfo->pszTo);
|
|
SafeMemFree(pFindInfo->pszBody);
|
|
ZeroMemory(pFindInfo, sizeof(FINDINFO));
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CopyFindInfo
|
|
//
|
|
HRESULT CopyFindInfo(FINDINFO *pFindSrc, FINDINFO *pFindDst)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
|
|
// Zero
|
|
ZeroMemory(pFindDst, sizeof(FINDINFO));
|
|
|
|
// Duplicate
|
|
pFindDst->mask = pFindSrc->mask;
|
|
pFindDst->ftDateFrom = pFindSrc->ftDateFrom;
|
|
pFindDst->ftDateTo = pFindSrc->ftDateTo;
|
|
pFindDst->fSubFolders = pFindSrc->fSubFolders;
|
|
|
|
// pszFrom
|
|
if (pFindSrc->pszFrom)
|
|
{
|
|
// Duplicate the String
|
|
IF_NULLEXIT(pFindDst->pszFrom = PszDupA(pFindSrc->pszFrom));
|
|
}
|
|
|
|
// pszTo
|
|
if (pFindSrc->pszTo)
|
|
{
|
|
// Duplicate the String
|
|
IF_NULLEXIT(pFindDst->pszTo = PszDupA(pFindSrc->pszTo));
|
|
}
|
|
|
|
// pszSubject
|
|
if (pFindSrc->pszSubject)
|
|
{
|
|
// Duplicate the String
|
|
IF_NULLEXIT(pFindDst->pszSubject = PszDupA(pFindSrc->pszSubject));
|
|
}
|
|
|
|
// pszBody
|
|
if (pFindSrc->pszBody)
|
|
{
|
|
// Duplicate the String
|
|
IF_NULLEXIT(pFindDst->pszBody = PszDupA(pFindSrc->pszBody));
|
|
}
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: DoFindMsg()
|
|
//
|
|
// PURPOSE: Instantiates the finder object on a separate thread.
|
|
//
|
|
// PARAMETERS:
|
|
// [in] pidl - Folder to default the search in
|
|
// [in] ftType - Type of folders being searched
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT DoFindMsg(FOLDERID idFolder, FOLDERTYPE ftType)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HTHREAD hThread = NULL;
|
|
DWORD uiThreadId = 0;
|
|
FINDERPARAMS * pFindParams = NULL;
|
|
|
|
// Allocate a structure to hold the initialization information that we can
|
|
// pass to the other thread.
|
|
|
|
IF_NULLEXIT(pFindParams = new FINDERPARAMS);
|
|
|
|
// Initialzie the find
|
|
pFindParams->idFolder = idFolder;
|
|
pFindParams->ftType = ftType;
|
|
|
|
// Create another thread to do the search on
|
|
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FindThreadProc, (LPVOID) pFindParams, 0, &uiThreadId);
|
|
if (NULL == hThread)
|
|
IF_FAILEXIT(hr = E_FAIL);
|
|
|
|
// NULL this out so we don't free it later. The other thread owns freeing
|
|
// this.
|
|
pFindParams = NULL;
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
// Close the thread handle
|
|
if (NULL != hThread)
|
|
CloseHandle(hThread);
|
|
|
|
// Free the find parameters if we still have a pointer to them.
|
|
if (NULL != pFindParams)
|
|
delete pFindParams;
|
|
return hr;
|
|
}
|
|
|
|
|
|
unsigned int __stdcall LOADDS_16 FindThreadProc(LPVOID lpv)
|
|
{
|
|
CFindDlg *pFindDlg = NULL;
|
|
MSG msg;
|
|
FINDERPARAMS *pFindParams = (FINDERPARAMS *) lpv;
|
|
DWORD uiThreadId = 0;
|
|
|
|
// Make sure this new thread has all the initialization performed
|
|
// correctly.
|
|
OleInitialize(0);
|
|
CoIncrementInit("FindThreadProc", MSOEAPI_START_SHOWERRORS, NULL, NULL);
|
|
|
|
EnterCriticalSection(&g_csThreadList);
|
|
|
|
uiThreadId = GetCurrentThreadId();
|
|
g_pOEThrList = AddThreadToList(uiThreadId, g_pOEThrList );
|
|
|
|
LeaveCriticalSection(&g_csThreadList);
|
|
|
|
// Create the finder
|
|
pFindDlg = new CFindDlg();
|
|
if (pFindDlg)
|
|
{
|
|
// Show the find dialog. This function will return when the user is
|
|
// done.
|
|
pFindDlg->Show(pFindParams);
|
|
|
|
// Message Loop
|
|
while (GetMessageWrapW(&msg, NULL, 0, 0))
|
|
pFindDlg->HandleMessage(&msg);
|
|
|
|
pFindDlg->Release();
|
|
}
|
|
|
|
// Free this information
|
|
if (NULL != pFindParams)
|
|
delete pFindParams;
|
|
|
|
// Uninitialize the thread
|
|
EnterCriticalSection(&g_csThreadList);
|
|
|
|
g_pOEThrList = DelThreadToList(uiThreadId, g_pOEThrList);
|
|
|
|
LeaveCriticalSection(&g_csThreadList);
|
|
|
|
CoDecrementInit("FindThreadProc", NULL);
|
|
OleUninitialize();
|
|
return 0;
|
|
}
|
|
|
|
|
|
CFindDlg::CFindDlg()
|
|
{
|
|
m_cRef = 1;
|
|
m_hwnd = NULL;
|
|
ZeroMemory(&m_rFindInfo, sizeof(m_rFindInfo));
|
|
m_hwndList = NULL;
|
|
m_hTimeout = NULL;
|
|
m_hAccel = NULL;
|
|
|
|
m_pStatusBar = NULL;
|
|
m_pMsgList = NULL;
|
|
m_pMsgListCT = NULL;
|
|
m_pCancel = NULL;
|
|
m_pPumpRefCount = NULL;
|
|
ZeroMemory(&m_hlDisabled, sizeof(HWNDLIST));
|
|
|
|
m_fShowResults = FALSE;
|
|
m_fAbort = FALSE;
|
|
m_fClose = FALSE;
|
|
m_fInProgress = FALSE;
|
|
m_ulPct = 0;
|
|
m_fFindComplete = FALSE;
|
|
|
|
m_hIcon = NULL;
|
|
m_hIconSm = NULL;
|
|
|
|
m_dwCookie = 0;
|
|
m_fProgressBar = FALSE;
|
|
m_fInternal = 0;
|
|
m_dwIdentCookie = 0;
|
|
|
|
m_pViewMenu = NULL;
|
|
}
|
|
|
|
|
|
CFindDlg::~CFindDlg()
|
|
{
|
|
SafeRelease(m_pViewMenu);
|
|
_FreeFindInfo(&m_rFindInfo);
|
|
SafeRelease(m_pStatusBar);
|
|
SafeRelease(m_pMsgList);
|
|
SafeRelease(m_pMsgListCT);
|
|
SafeRelease(m_pCancel);
|
|
AssertSz(!m_pPumpRefCount, "This should have been freed");
|
|
|
|
if (m_hIcon)
|
|
SideAssert(DestroyIcon(m_hIcon));
|
|
|
|
if (m_hIconSm)
|
|
SideAssert(DestroyIcon(m_hIconSm));
|
|
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::QueryInterface()
|
|
//
|
|
// PURPOSE: Allows caller to retrieve the various interfaces supported by
|
|
// this class.
|
|
//
|
|
HRESULT CFindDlg::QueryInterface(REFIID riid, LPVOID *ppvObj)
|
|
{
|
|
TraceCall("CFindDlg::QueryInterface");
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*ppvObj = (LPVOID) (IUnknown *) (IDispatch *) this;
|
|
else if (IsEqualIID(riid, IID_IDispatch))
|
|
*ppvObj = (LPVOID) (IDispatch *) this;
|
|
else if (IsEqualIID(riid, DIID__MessageListEvents))
|
|
*ppvObj = (LPVOID) (IDispatch *) this;
|
|
else if (IsEqualIID(riid, IID_IStoreCallback))
|
|
*ppvObj = (LPVOID) (IStoreCallback *) this;
|
|
else if (IsEqualIID(riid, IID_ITimeoutCallback))
|
|
*ppvObj = (LPVOID) (ITimeoutCallback *) this;
|
|
else if (IsEqualIID(riid, IID_IIdentityChangeNotify))
|
|
*ppvObj = (LPVOID) (IIdentityChangeNotify *) this;
|
|
else if (IsEqualIID(riid, IID_IOleCommandTarget))
|
|
*ppvObj = (LPVOID) (IOleCommandTarget *) this;
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return (S_OK);
|
|
}
|
|
|
|
return (E_NOINTERFACE);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::AddRef()
|
|
//
|
|
// PURPOSE: Adds a reference count to this object.
|
|
//
|
|
ULONG CFindDlg::AddRef(void)
|
|
{
|
|
TraceCall("CFindDlg::AddRef");
|
|
return ((ULONG) InterlockedIncrement((LONG *) &m_cRef));
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::Release()
|
|
//
|
|
// PURPOSE: Releases a reference on this object.
|
|
//
|
|
ULONG CFindDlg::Release(void)
|
|
{
|
|
TraceCall("CFindDlg::Release");
|
|
|
|
if (0 == InterlockedDecrement((LONG *) &m_cRef))
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return (m_cRef);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::Show()
|
|
//
|
|
// PURPOSE: Shows the finder dialog and provides a message pump for this
|
|
// new thread.
|
|
//
|
|
void CFindDlg::Show(PFINDERPARAMS pFindParams)
|
|
{
|
|
// Validate this
|
|
if (NULL == pFindParams)
|
|
return;
|
|
|
|
// Load the acclereator table for the finder
|
|
if (NULL == m_hAccel)
|
|
m_hAccel = LoadAcceleratorsWrapW(g_hLocRes, MAKEINTRESOURCEW(IDA_FIND_ACCEL));
|
|
|
|
// Create the finder dialog
|
|
m_hwnd = CreateDialogParamWrapW(g_hLocRes, MAKEINTRESOURCEW(IDD_FIND),
|
|
NULL, ExtFindMsgDlgProc, (LPARAM) this);
|
|
if (NULL == m_hwnd)
|
|
return;
|
|
|
|
// Create the message list
|
|
HRESULT hr = CreateMessageList(NULL, &m_pMsgList);
|
|
if (FAILED(hr))
|
|
return;
|
|
|
|
// Get some interfaces pointers from the message list that we'll need
|
|
// later
|
|
m_pMsgList->QueryInterface(IID_IOleCommandTarget, (LPVOID *) &m_pMsgListCT);
|
|
AtlAdvise(m_pMsgList, (IUnknown *) (IDispatch *) this, DIID__MessageListEvents, &m_dwCookie);
|
|
|
|
// Display the message list
|
|
if (FAILED(m_pMsgList->CreateList(m_hwnd, (IDispatch *) this, &m_hwndList)))
|
|
return;
|
|
ShowWindow(m_hwndList, SW_HIDE);
|
|
|
|
// Have the dialog redraw once or twice
|
|
UpdateWindow(m_hwnd);
|
|
|
|
// Fill in the folder list
|
|
if (FAILED(InitFolderPickerEdit(GetDlgItem(m_hwnd, IDC_FOLDER), pFindParams->idFolder)))
|
|
return;
|
|
|
|
// Will be released in the WM_NCDESTROY message
|
|
m_pPumpRefCount = new CPumpRefCount;
|
|
if (!m_pPumpRefCount)
|
|
return;
|
|
}
|
|
|
|
|
|
void CFindDlg::HandleMessage(LPMSG lpmsg)
|
|
{
|
|
HWND hwndTimeout;
|
|
|
|
CNote *pNote = GetTlsGlobalActiveNote();
|
|
|
|
// Give it to the active note if a note has focus, call it's XLateAccelerator...
|
|
if (pNote && pNote->TranslateAccelerator(lpmsg) == S_OK)
|
|
return;
|
|
|
|
if (pNote && (pNote->IsMenuMessage(lpmsg) == S_OK))
|
|
return;
|
|
|
|
// Get Timeout Window for this thread
|
|
hwndTimeout = (HWND)TlsGetValue(g_dwTlsTimeout);
|
|
|
|
// Check for Is modeless timeout dialog window message
|
|
if (hwndTimeout && TRUE == IsDialogMessageWrapW(hwndTimeout, lpmsg))
|
|
return;
|
|
|
|
if (m_hwnd)
|
|
{
|
|
// We have to do a little voodoo to get some keystrokes down to the
|
|
// message list before IsDialogMessage() get's 'em
|
|
if (lpmsg->message == WM_KEYDOWN)
|
|
{
|
|
if ((lpmsg->wParam == VK_DELETE) && m_pMsgList && (S_OK != m_pMsgList->HasFocus()))
|
|
{
|
|
if (!IsDialogMessageWrapW(m_hwnd, lpmsg))
|
|
{
|
|
TranslateMessage(lpmsg);
|
|
DispatchMessageWrapW(lpmsg);
|
|
}
|
|
return;
|
|
}
|
|
if ((lpmsg->wParam == VK_RETURN) && m_pMsgList && (S_OK == m_pMsgList->HasFocus()))
|
|
{
|
|
if (!TranslateAcceleratorWrapW(m_hwnd, m_hAccel, lpmsg))
|
|
{
|
|
TranslateMessage(lpmsg);
|
|
DispatchMessageWrapW(lpmsg);
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (m_hAccel && TranslateAcceleratorWrapW(m_hwnd, m_hAccel, lpmsg))
|
|
return;
|
|
|
|
if (IsDialogMessageWrapW(m_hwnd, lpmsg))
|
|
return;
|
|
}
|
|
|
|
TranslateMessage(lpmsg);
|
|
DispatchMessageWrapW(lpmsg);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::Invoke()
|
|
//
|
|
// PURPOSE: Called by the message list to pass us progress and other
|
|
// status / error messages.
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT CFindDlg::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
|
|
WORD wFlags, DISPPARAMS* pDispParams,
|
|
VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
|
|
unsigned int* puArgErr)
|
|
{
|
|
switch (dispIdMember)
|
|
{
|
|
// Fired whenever the selection in the ListView changes
|
|
case DISPID_LISTEVENT_SELECTIONCHANGED:
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Fired when the number of messages or unread messages changes
|
|
case DISPID_LISTEVENT_COUNTCHANGED:
|
|
{
|
|
if (!m_fProgressBar && m_pStatusBar)
|
|
{
|
|
TCHAR szStatus[CCHMAX_STRINGRES + 20];
|
|
TCHAR szFmt[CCHMAX_STRINGRES];
|
|
DWORD ids;
|
|
|
|
if (m_fFindComplete)
|
|
{
|
|
AthLoadString(idsXMsgsYUnreadFind, szFmt, ARRAYSIZE(szFmt));
|
|
wnsprintf(szStatus, ARRAYSIZE(szStatus), szFmt, pDispParams->rgvarg[0].lVal, pDispParams->rgvarg[1].lVal);
|
|
}
|
|
else
|
|
{
|
|
AthLoadString(idsXMsgsYUnread, szFmt, ARRAYSIZE(szFmt));
|
|
wnsprintf(szStatus, ARRAYSIZE(szStatus), szFmt, pDispParams->rgvarg[0].lVal, pDispParams->rgvarg[1].lVal);
|
|
}
|
|
|
|
m_pStatusBar->SetStatusText(szStatus);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Fired when the user double clicks an item in the ListView
|
|
case DISPID_LISTEVENT_ITEMACTIVATE:
|
|
{
|
|
CmdOpen(ID_OPEN, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CMessageView::QueryStatus()
|
|
//
|
|
// PURPOSE: Called by the browser to determine if a list of commands should
|
|
// should be enabled or disabled.
|
|
//
|
|
// PARAMETERS:
|
|
// [in] pguidCmdGroup - Group the commands are part of (unused)
|
|
// [in] cCmds - Number of commands to be evaluated
|
|
// [in] prgCmds - List of commands
|
|
// [out] pCmdText - Description text for a command
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT CFindDlg::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[],
|
|
OLECMDTEXT *pCmdText)
|
|
{
|
|
DWORD cSel;
|
|
HRESULT hr;
|
|
DWORD *rgSelected = 0;
|
|
DWORD cFocus;
|
|
|
|
MenuUtil_NewMessageIDsQueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText, TRUE);
|
|
|
|
// Up front some work
|
|
m_pMsgList->GetSelected(&cFocus, &cSel, &rgSelected);
|
|
|
|
// Now loop through the commands in the prgCmds array looking for ones the
|
|
// sub objects didn't handle.
|
|
for (UINT i = 0; i < cCmds; i++)
|
|
{
|
|
if (prgCmds[i].cmdf == 0)
|
|
{
|
|
// If this command is from the language menu
|
|
if (prgCmds[i].cmdID >= ID_LANG_FIRST && prgCmds[i].cmdID <= ID_LANG_LAST)
|
|
{
|
|
// Enable only the supported languages
|
|
if (prgCmds[i].cmdID < (UINT) (ID_LANG_FIRST + GetIntlCharsetLanguageCount()))
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
else
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
|
|
continue;
|
|
}
|
|
|
|
// if the command id from the View.Current View menu
|
|
if ((ID_VIEW_FILTER_FIRST <= prgCmds[i].cmdID) && (ID_VIEW_FILTER_LAST >= prgCmds[i].cmdID))
|
|
{
|
|
if (NULL == m_pViewMenu)
|
|
{
|
|
// Create the view menu
|
|
HrCreateViewMenu(VMF_FINDER, &m_pViewMenu);
|
|
}
|
|
|
|
if (NULL != m_pViewMenu)
|
|
{
|
|
m_pViewMenu->QueryStatus(m_pMsgList, &(prgCmds[i]));
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// Look to see if it's a command we provide
|
|
switch (prgCmds[i].cmdID)
|
|
{
|
|
case ID_OPEN:
|
|
{
|
|
// Enabled only if the focus is in the ListView and there
|
|
// is at least one item selected.
|
|
m_pMsgList->GetSelectedCount(&cSel);
|
|
if (cSel)
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
else
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
case ID_OPEN_CONTAINING_FOLDER:
|
|
{
|
|
if (cSel == 1)
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
else
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
case ID_REPLY:
|
|
case ID_REPLY_ALL:
|
|
{
|
|
// Enabled only if the focus is in the ListView and there
|
|
// is only one item selected
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
|
|
if (cSel == 1)
|
|
{
|
|
// The message's body must also be downloaded
|
|
LPMESSAGEINFO pInfo;
|
|
|
|
if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
|
|
{
|
|
if (pInfo->dwFlags & ARF_HASBODY)
|
|
prgCmds[i].cmdf |= OLECMDF_ENABLED;
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ID_FORWARD:
|
|
case ID_FORWARD_AS_ATTACH:
|
|
{
|
|
// Enabled only if the focus is in the ListView and there
|
|
// is only one item selected
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
|
|
if (cSel > 0)
|
|
{
|
|
// The message's body must also be downloaded
|
|
LPMESSAGEINFO pInfo;
|
|
|
|
// Default to success
|
|
prgCmds[i].cmdf |= OLECMDF_ENABLED;
|
|
for (DWORD iItem = 0; iItem < cSel && (prgCmds[i].cmdf & OLECMDF_ENABLED); iItem++)
|
|
{
|
|
if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[iItem], &pInfo)))
|
|
{
|
|
if (0 == (pInfo->dwFlags & ARF_HASBODY))
|
|
{
|
|
prgCmds[i].cmdf &= ~OLECMDF_ENABLED;
|
|
}
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ID_REPLY_GROUP:
|
|
{
|
|
// Enabled only if there is one news message selected
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
|
|
if (cSel == 1)
|
|
{
|
|
// The message's body must also be downloaded
|
|
LPMESSAGEINFO pInfo;
|
|
|
|
if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
|
|
{
|
|
if ((pInfo->dwFlags & ARF_HASBODY) && (pInfo->dwFlags & ARF_NEWSMSG))
|
|
prgCmds[i].cmdf |= OLECMDF_ENABLED;
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ID_POPUP_FILTER:
|
|
case ID_COLUMNS:
|
|
case ID_POPUP_NEXT:
|
|
case ID_POPUP_SORT:
|
|
{
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED | (m_fShowResults ? OLECMDF_ENABLED : 0);
|
|
break;
|
|
}
|
|
|
|
case ID_POPUP_NEW:
|
|
case ID_CLOSE:
|
|
{
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
break;
|
|
}
|
|
|
|
case ID_REFRESH:
|
|
{
|
|
if (m_fShowResults && IsWindowEnabled(GetDlgItem(m_hwnd, IDC_FIND_NOW)))
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
else
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
case ID_BLOCK_SENDER:
|
|
{
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
|
|
// Enabled only if there is only one item selected and
|
|
// we have access to the from address
|
|
if (cSel == 1)
|
|
{
|
|
// The message's body must also be downloaded
|
|
LPMESSAGEINFO pInfo;
|
|
|
|
if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
|
|
{
|
|
if (((NULL != pInfo->pszEmailFrom) && ('\0' != pInfo->pszEmailFrom[0])) || (0 != pInfo->faStream))
|
|
prgCmds[i].cmdf |= OLECMDF_ENABLED;
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ID_CREATE_RULE_FROM_MESSAGE:
|
|
{
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
|
|
// Enabled only if there is only one item selected
|
|
if (cSel == 1)
|
|
{
|
|
// Make sure we have a message info
|
|
LPMESSAGEINFO pInfo;
|
|
|
|
if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
|
|
{
|
|
prgCmds[i].cmdf |= OLECMDF_ENABLED;
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ID_COMBINE_AND_DECODE:
|
|
{
|
|
// Enabled only if the focus is in the ListView and there
|
|
// is at least one item selected.
|
|
if (cSel > 1)
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
else
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
case ID_CANCEL_MESSAGE:
|
|
{
|
|
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
|
|
|
|
if (DwGetOption(OPT_CANCEL_ALL_NEWS))
|
|
prgCmds[i].cmdf |= OLECMDF_ENABLED;
|
|
else
|
|
{
|
|
if (cSel == 1)
|
|
{
|
|
FOLDERID idFolder;
|
|
LPMESSAGEINFO pInfo;
|
|
|
|
if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
|
|
{
|
|
if (SUCCEEDED(m_pMsgList->GetRowFolderId(rgSelected[0], &idFolder)))
|
|
{
|
|
if (NewsUtil_FCanCancel(idFolder, pInfo))
|
|
{
|
|
prgCmds[i].cmdf |= OLECMDF_ENABLED;
|
|
}
|
|
}
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MemFree(rgSelected);
|
|
|
|
// Let the sub objects look last, so we can get ID_REFRESH before them
|
|
if (m_pMsgListCT)
|
|
{
|
|
hr = m_pMsgListCT->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
|
|
}
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CMessageView::Exec()
|
|
//
|
|
// PURPOSE: Called to execute a verb that this view supports
|
|
//
|
|
// PARAMETERS:
|
|
// [in] pguidCmdGroup - unused
|
|
// [in] nCmdID - ID of the command to execute
|
|
// [in] nCmdExecOpt - Options that define how the command should execute
|
|
// [in] pvaIn - Any arguments for the command
|
|
// [out] pvaOut - Any return values for the command
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
//
|
|
HRESULT CFindDlg::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,
|
|
VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
// If the sub objects didn't support the command, then we should see if
|
|
// it's one of ours
|
|
|
|
// Language menu first
|
|
if (nCmdID >= ID_LANG_FIRST && nCmdID <= ID_LANG_LAST)
|
|
{
|
|
// $REVIEW - Not implemented
|
|
// SwitchLanguage(nCmdID, TRUE);
|
|
return (S_OK);
|
|
}
|
|
|
|
// Handle the View.Current View menu
|
|
if ((ID_VIEW_FILTER_FIRST <= nCmdID) && (ID_VIEW_FILTER_LAST >= nCmdID))
|
|
{
|
|
if (NULL == m_pViewMenu)
|
|
{
|
|
// Create the view menu
|
|
HrCreateViewMenu(VMF_FINDER, &m_pViewMenu);
|
|
}
|
|
|
|
if (NULL != m_pViewMenu)
|
|
{
|
|
if (SUCCEEDED(m_pViewMenu->Exec(m_hwnd, nCmdID, m_pMsgList, pvaIn, pvaOut)))
|
|
{
|
|
return (S_OK);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (MenuUtil_HandleNewMessageIDs(nCmdID, m_hwnd, FOLDERID_INVALID, TRUE, FALSE, (IUnknown *) (IDispatch *) this))
|
|
return S_OK;
|
|
|
|
|
|
// Go through the rest of the commands
|
|
switch (nCmdID)
|
|
{
|
|
case ID_OPEN:
|
|
return CmdOpen(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case ID_OPEN_CONTAINING_FOLDER:
|
|
return CmdOpenFolder(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case ID_REPLY:
|
|
case ID_REPLY_ALL:
|
|
case ID_FORWARD:
|
|
case ID_FORWARD_AS_ATTACH:
|
|
case ID_REPLY_GROUP:
|
|
return CmdReplyForward(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case ID_REFRESH:
|
|
case IDC_FIND_NOW:
|
|
return CmdFindNow(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case IDC_STOP:
|
|
return CmdStop(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case IDC_BROWSE_FOLDER:
|
|
return CmdBrowseForFolder(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case IDC_RESET:
|
|
return CmdReset(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case ID_BLOCK_SENDER:
|
|
return CmdBlockSender(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case ID_CREATE_RULE_FROM_MESSAGE:
|
|
return CmdCreateRule(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case ID_COMBINE_AND_DECODE:
|
|
return CmdCombineAndDecode(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
|
|
case ID_CLOSE:
|
|
case IDCANCEL:
|
|
{
|
|
if (m_fInProgress)
|
|
{
|
|
CmdStop(ID_STOP, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
|
|
m_fClose = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DestroyWindow(m_hwnd);
|
|
}
|
|
return (S_OK);
|
|
}
|
|
|
|
case ID_CANCEL_MESSAGE:
|
|
return CmdCancelMessage(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
|
|
}
|
|
|
|
// See if our message list wants the command
|
|
if (m_pMsgListCT)
|
|
{
|
|
if (OLECMDERR_E_NOTSUPPORTED != m_pMsgListCT->Exec(pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn, pvaOut))
|
|
return (S_OK);
|
|
}
|
|
|
|
return (OLECMDERR_E_NOTSUPPORTED);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnBegin()
|
|
//
|
|
// PURPOSE: Called whenever the store is about to start some operation.
|
|
//
|
|
HRESULT CFindDlg::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo,
|
|
IOperationCancel *pCancel)
|
|
{
|
|
TraceCall("CFindDlg::OnBegin");
|
|
|
|
Assert(pCancel != NULL);
|
|
Assert(m_pCancel == NULL);
|
|
|
|
m_pCancel = pCancel;
|
|
m_pCancel->AddRef();
|
|
|
|
if (m_fAbort)
|
|
m_pCancel->Cancel(CT_CANCEL);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnProgress()
|
|
//
|
|
// PURPOSE: Called during the find, download, etc.
|
|
//
|
|
HRESULT CFindDlg::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent,
|
|
DWORD dwMax, LPCSTR pszStatus)
|
|
{
|
|
MSG msg;
|
|
|
|
TraceCall("CFindDlg::OnProgress");
|
|
|
|
// If we had a timeout dialog up, we can close it since data just became
|
|
// available.
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// If it's find, show progress
|
|
if (SOT_SEARCHING == tyOperation)
|
|
{
|
|
if (m_pStatusBar && pszStatus)
|
|
{
|
|
TCHAR szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES];
|
|
AthLoadString(idsSearching, szRes, ARRAYSIZE(szRes));
|
|
wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, pszStatus);
|
|
m_pStatusBar->SetStatusText((LPTSTR) szBuf);
|
|
}
|
|
|
|
if (!m_fProgressBar && m_pStatusBar)
|
|
{
|
|
m_pStatusBar->ShowProgress(dwMax);
|
|
m_fProgressBar = TRUE;
|
|
}
|
|
|
|
if (m_pStatusBar && dwMax)
|
|
{
|
|
m_pStatusBar->SetProgress(dwCurrent);
|
|
}
|
|
}
|
|
|
|
// Pump messages a bit so the UI is responsive.
|
|
while (PeekMessageWrapW(&msg, NULL, 0, 0, PM_REMOVE))
|
|
HandleMessage(&msg);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnComplete()
|
|
//
|
|
// PURPOSE: Called when the store operation is complete
|
|
//
|
|
HRESULT CFindDlg::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
|
|
{
|
|
TraceCall("CFindDlg::OnComplete");
|
|
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// Display an Error on Failures
|
|
if (FAILED(hrComplete))
|
|
{
|
|
// Call into my swanky utility
|
|
CallbackDisplayError(m_hwnd, hrComplete, pErrorInfo);
|
|
}
|
|
|
|
if (SOT_SEARCHING == tyOperation)
|
|
{
|
|
// Hide the status bar
|
|
if (m_fProgressBar && m_pStatusBar)
|
|
{
|
|
m_pStatusBar->HideProgress();
|
|
m_fProgressBar = FALSE;
|
|
m_fFindComplete = TRUE;
|
|
}
|
|
|
|
Assert(m_pCancel != NULL);
|
|
m_pCancel->Release();
|
|
m_pCancel = NULL;
|
|
}
|
|
|
|
// Update the status text
|
|
IOEMessageList *pList;
|
|
if (SUCCEEDED(m_pMsgList->QueryInterface(IID_IOEMessageList, (LPVOID *) &pList)))
|
|
{
|
|
long lCount, lUnread;
|
|
TCHAR szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES];
|
|
|
|
pList->get_Count(&lCount);
|
|
pList->get_UnreadCount(&lUnread);
|
|
AthLoadString(idsXMsgsYUnreadFind, szRes, ARRAYSIZE(szRes));
|
|
wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, lCount, lUnread);
|
|
m_pStatusBar->SetStatusText(szBuf);
|
|
|
|
pList->Release();
|
|
}
|
|
|
|
// Select the first row
|
|
IListSelector *pSelect;
|
|
if (SUCCEEDED(m_pMsgList->GetListSelector(&pSelect)))
|
|
{
|
|
pSelect->SetActiveRow(0);
|
|
pSelect->Release();
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CFindDlg::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
|
|
{
|
|
// Display a timeout dialog
|
|
return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout);
|
|
}
|
|
|
|
STDMETHODIMP CFindDlg::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
|
|
{
|
|
// Call into general CanConnect Utility
|
|
return CallbackCanConnect(pszAccountId, m_hwnd, FALSE);
|
|
}
|
|
|
|
STDMETHODIMP CFindDlg::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
|
|
{
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// Call into general OnLogonPrompt Utility
|
|
return CallbackOnLogonPrompt(m_hwnd, pServer, ixpServerType);
|
|
}
|
|
|
|
STDMETHODIMP CFindDlg::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
|
|
{
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// Call into my swanky utility
|
|
return CallbackOnPrompt(m_hwnd, hrError, pszText, pszCaption, uType, piUserResponse);
|
|
}
|
|
|
|
STDMETHODIMP CFindDlg::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
|
|
{
|
|
*phwndParent = m_hwnd;
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CFindDlg::OnTimeoutResponse(TIMEOUTRESPONSE eResponse)
|
|
{
|
|
// Call into general timeout response utility
|
|
return CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout);
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK CFindDlg::ExtFindMsgDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CFindDlg *pThis;
|
|
|
|
if (msg == WM_INITDIALOG)
|
|
{
|
|
SetWindowLongPtr(hwnd, DWLP_USER, lParam);
|
|
pThis = (CFindDlg*)lParam;
|
|
}
|
|
else
|
|
pThis = (CFindDlg*)GetWindowLongPtr(hwnd, DWLP_USER);
|
|
|
|
if (pThis)
|
|
return pThis->DlgProc(hwnd, msg, wParam, lParam);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::DlgProc()
|
|
//
|
|
// PURPOSE: Groovy dialog proc.
|
|
//
|
|
INT_PTR CFindDlg::DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hwndActive;
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return (BOOL)HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, OnInitDialog);
|
|
|
|
case WM_PAINT:
|
|
HANDLE_WM_PAINT(hwnd, wParam, lParam, OnPaint);
|
|
return TRUE;
|
|
|
|
case WM_SIZE:
|
|
HANDLE_WM_SIZE(hwnd, wParam, lParam, OnSize);
|
|
return TRUE;
|
|
|
|
case WM_GETMINMAXINFO:
|
|
HANDLE_WM_GETMINMAXINFO(hwnd, wParam, lParam, OnGetMinMaxInfo);
|
|
return TRUE;
|
|
|
|
case WM_INITMENUPOPUP:
|
|
HANDLE_WM_INITMENUPOPUP(hwnd, wParam, lParam, OnInitMenuPopup);
|
|
return TRUE;
|
|
|
|
case WM_MENUSELECT:
|
|
// HANDLE_WM_MENUSELECT() has a bug in it, don't use it.
|
|
if (LOWORD(wParam) >= ID_STATIONERY_RECENT_0 && LOWORD(wParam) <= ID_STATIONERY_RECENT_9)
|
|
m_pStatusBar->ShowSimpleText(MAKEINTRESOURCE(idsRSListGeneralHelp));
|
|
else
|
|
HandleMenuSelect(m_pStatusBar, wParam, lParam);
|
|
return TRUE;
|
|
|
|
case WM_WININICHANGE:
|
|
HANDLE_WM_WININICHANGE(hwnd, wParam, lParam, OnWinIniChange);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
HANDLE_WM_COMMAND(hwnd, wParam, lParam, OnCommand);
|
|
return TRUE;
|
|
|
|
case WM_NOTIFY:
|
|
HANDLE_WM_NOTIFY(hwnd, wParam, lParam, OnNotify);
|
|
return TRUE;
|
|
|
|
case WM_DESTROY:
|
|
// case WM_CLOSE:
|
|
HANDLE_WM_DESTROY(hwnd, wParam, lParam, OnDestroy);
|
|
return TRUE;
|
|
|
|
case WM_NCDESTROY:
|
|
m_pPumpRefCount->Release();
|
|
m_pPumpRefCount = NULL;
|
|
m_hwnd = 0;
|
|
break;
|
|
|
|
case WM_ENABLE:
|
|
if (!m_fInternal)
|
|
{
|
|
Assert (wParam || (m_hlDisabled.cHwnd == NULL && m_hlDisabled.rgHwnd == NULL));
|
|
EnableThreadWindows(&m_hlDisabled, (NULL != wParam), ETW_OE_WINDOWS_ONLY, hwnd);
|
|
g_hwndActiveModal = wParam ? NULL : hwnd;
|
|
}
|
|
break;
|
|
|
|
case WM_ACTIVATEAPP:
|
|
if (wParam && g_hwndActiveModal && g_hwndActiveModal != hwnd &&
|
|
!IsWindowEnabled(hwnd))
|
|
{
|
|
// $MODAL
|
|
// if we are getting activated, and are disabled then
|
|
// bring our 'active' window to the top
|
|
Assert (IsWindow(g_hwndActiveModal));
|
|
PostMessage(g_hwndActiveModal, WM_OE_ACTIVATETHREADWINDOW, 0, 0);
|
|
}
|
|
break;
|
|
|
|
case WM_OE_ACTIVATETHREADWINDOW:
|
|
hwndActive = GetLastActivePopup(hwnd);
|
|
if (hwndActive && IsWindowEnabled(hwndActive) && IsWindowVisible(hwndActive))
|
|
ActivatePopupWindow(hwndActive);
|
|
break;
|
|
|
|
case WM_OE_ENABLETHREADWINDOW:
|
|
m_fInternal = 1;
|
|
EnableWindow(hwnd, (BOOL)wParam);
|
|
m_fInternal = 0;
|
|
break;
|
|
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnInitDialog()
|
|
//
|
|
// PURPOSE: Initializes the UI in the dialog box. Also prep's the sizing
|
|
// info so the dialog can be resized.
|
|
//
|
|
BOOL CFindDlg::OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
|
|
{
|
|
RECT rc, rcClient;
|
|
RECT rcEdit;
|
|
WINDOWPLACEMENT wp;
|
|
HMENU hMenu;
|
|
|
|
TraceCall("CFindDlg::OnInitDialog");
|
|
|
|
// We do this so we can enable and disable correctly when modal windows
|
|
// are visible
|
|
SetProp(hwnd, c_szOETopLevel, (HANDLE)TRUE);
|
|
|
|
// Get some sizing info
|
|
_InitSizingInfo(hwnd);
|
|
|
|
// Hide the status bar until we've been expanded
|
|
ShowWindow(GetDlgItem(hwnd, IDC_STATUS_BAR), SW_HIDE);
|
|
|
|
// Set the title bar icon
|
|
Assert (m_hIconSm == NULL && m_hIcon == NULL);
|
|
m_hIcon = (HICON)LoadImage(g_hLocRes, MAKEINTRESOURCE(idiFind), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0);
|
|
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)m_hIcon);
|
|
m_hIconSm = (HICON)LoadImage(g_hLocRes, MAKEINTRESOURCE(idiFind), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
|
|
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)m_hIconSm);
|
|
|
|
// Set the dialog template fonts correctly
|
|
_SetFindIntlFont(hwnd);
|
|
|
|
// Initialize the find information
|
|
_SetFindValues(hwnd, &m_rFindInfo);
|
|
|
|
// Disable the find and stop buttons
|
|
EnableWindow(GetDlgItem(hwnd, IDC_FIND_NOW), _IsFindEnabled(hwnd));
|
|
EnableWindow(GetDlgItem(hwnd, IDC_STOP), FALSE);
|
|
CheckDlgButton(hwnd, IDC_INCLUDE_SUB, BST_CHECKED);
|
|
|
|
// Create a status bar object for our status bar
|
|
m_pStatusBar = new CStatusBar();
|
|
if (m_pStatusBar)
|
|
m_pStatusBar->Initialize(hwnd, SBI_HIDE_SPOOLER | SBI_HIDE_CONNECTED | SBI_HIDE_FILTERED);
|
|
|
|
// We have menus on this window
|
|
hMenu = LoadMenu(g_hLocRes, MAKEINTRESOURCE(IDR_FIND_MENU));
|
|
MenuUtil_ReplaceNewMsgMenus(hMenu);
|
|
SetMenu(hwnd, hMenu);
|
|
|
|
// Register with identity manager
|
|
if (m_dwIdentCookie == 0)
|
|
SideAssert(SUCCEEDED(MU_RegisterIdentityNotifier((IUnknown *)(IAthenaBrowser *)this, &m_dwIdentCookie)));
|
|
|
|
SetForegroundWindow(hwnd);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnSize()
|
|
//
|
|
// PURPOSE: When the dialog get's sized, we have to move a whole bunch
|
|
// of stuff around. Don't try this at home.
|
|
//
|
|
void CFindDlg::OnSize(HWND hwnd, UINT state, int cx, int cy)
|
|
{
|
|
HDWP hdwp;
|
|
HWND hwndStatus;
|
|
HWND hwndTo;
|
|
int dx;
|
|
|
|
// If we're minimized, don't do anything
|
|
if (state == SIZE_MINIMIZED)
|
|
return;
|
|
|
|
// This is the delta for our horizontal size.
|
|
dx = cx - m_cxDlgDef;
|
|
|
|
// Make sure the status bar get's updated
|
|
hwndStatus = GetDlgItem(hwnd, IDC_STATUS_BAR);
|
|
SendMessage(hwndStatus, WM_SIZE, 0, 0L);
|
|
|
|
if (m_pStatusBar)
|
|
m_pStatusBar->OnSize(cx, cy);
|
|
|
|
// Do all the sizing updates at once to make everything smoother
|
|
hdwp = BeginDeferWindowPos(15);
|
|
if (hdwp)
|
|
{
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_FOLDER), NULL, 0, 0, (dx + m_cxFolder), m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_INCLUDE_SUB), NULL, m_xIncSub + dx, m_yIncSub, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_BROWSE_FOLDER), NULL, m_xBtn + dx, m_yBrowse, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, idcStatic1), NULL, 0, 0, m_cxStatic + dx, 2, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_FIND_NOW), NULL, m_xBtn + dx, m_yBtn, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_STOP), NULL, m_xBtn + dx, m_yBtn + m_dyBtn, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_RESET), NULL, m_xBtn + dx, m_yBtn + 2 * m_dyBtn, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_FROM), NULL, 0, 0, m_cxEdit + dx, m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_TO), NULL, 0, 0, m_cxEdit + dx, m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_SUBJECT), NULL, 0, 0, m_cxEdit + dx, m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
|
|
DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_BODY), NULL, 0, 0, m_cxEdit + dx, m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
|
|
// ALERT:
|
|
// if you add more controls here be sure to UP the value passed
|
|
// to BeginDeferWindowPos otherwise user will REALLOC and passback
|
|
// a new value to hdwp
|
|
EndDeferWindowPos(hdwp);
|
|
}
|
|
// If the bottom is exposed (oh my) resize the message list to fit between the
|
|
// bottom of the dialog and the top of the status bar.
|
|
if (m_fShowResults)
|
|
{
|
|
RECT rcStatus;
|
|
GetClientRect(hwndStatus, &rcStatus);
|
|
MapWindowRect(hwndStatus, hwnd, &rcStatus);
|
|
|
|
rcStatus.bottom = rcStatus.top - m_yView;
|
|
rcStatus.top = m_yView;
|
|
rcStatus.right -= rcStatus.left;
|
|
m_pMsgList->SetRect(rcStatus);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnPaint()
|
|
//
|
|
// PURPOSE: All this just to paint a separator line between the menu bar
|
|
// and the rest of the menu.
|
|
//
|
|
void CFindDlg::OnPaint(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rc;
|
|
|
|
// If we're not minimized
|
|
if (!IsIconic(hwnd))
|
|
{
|
|
// Draw that lovely line
|
|
BeginPaint(hwnd, &ps);
|
|
GetClientRect(hwnd, &rc);
|
|
DrawEdge(ps.hdc, &rc, EDGE_ETCHED, BF_TOP);
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnGetMinMaxInfo()
|
|
//
|
|
// PURPOSE: Called by Windows when we're resizing to see what our minimum
|
|
// and maximum sizes are.
|
|
//
|
|
void CFindDlg::OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpmmi)
|
|
{
|
|
TraceCall("CFindDlg::OnGetMinMaxInfo");
|
|
|
|
// Let Window's do most of the work
|
|
DefWindowProcWrapW(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)lpmmi);
|
|
|
|
// Override the minimum track size to be the size or our template
|
|
lpmmi->ptMinTrackSize = m_ptDragMin;
|
|
|
|
// Make sure to adjust for the height of the message list
|
|
if (!m_fShowResults)
|
|
lpmmi->ptMaxTrackSize.y = m_ptDragMin.y;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnInitMenuPopup()
|
|
//
|
|
// PURPOSE: Called before the menus are displayed.
|
|
//
|
|
void CFindDlg::OnInitMenuPopup(HWND hwnd, HMENU hmenuPopup, UINT uPos, BOOL fSystemMenu)
|
|
{
|
|
MENUITEMINFO mii;
|
|
UINT uIDPopup;
|
|
HMENU hMenu = GetMenu(hwnd);
|
|
|
|
TraceCall("CFindDlg::OnInitMenuPopup");
|
|
|
|
ZeroMemory(&mii, sizeof(mii));
|
|
|
|
mii.cbSize = sizeof(MENUITEMINFO);
|
|
mii.fMask = MIIM_ID | MIIM_SUBMENU;
|
|
|
|
// make sure we recognize the popup as one of ours
|
|
if (hMenu == NULL || !GetMenuItemInfo(hMenu, uPos, TRUE, &mii) || (hmenuPopup != mii.hSubMenu))
|
|
{
|
|
HMENU hMenuDrop = NULL;
|
|
int ulIndex = 0;
|
|
int cMenus = 0;
|
|
|
|
cMenus = GetMenuItemCount(hMenu);
|
|
|
|
// Try to fix up the top level popups
|
|
for (ulIndex = 0; ulIndex < cMenus; ulIndex++)
|
|
{
|
|
// Get the drop down menu
|
|
hMenuDrop = GetSubMenu(hMenu, ulIndex);
|
|
if (NULL == hMenuDrop)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Initialize the menu info
|
|
mii.cbSize = sizeof(MENUITEMINFO);
|
|
mii.fMask = MIIM_ID | MIIM_SUBMENU;
|
|
|
|
if (FALSE == GetMenuItemInfo(hMenuDrop, uPos, TRUE, &mii))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (hmenuPopup == mii.hSubMenu)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Did we find anything?
|
|
if (ulIndex >= cMenus)
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
uIDPopup = mii.wID;
|
|
|
|
// Must have stationery
|
|
switch (uIDPopup)
|
|
{
|
|
case ID_POPUP_MESSAGE:
|
|
AddStationeryMenu(hmenuPopup, ID_POPUP_NEW_MSG, ID_STATIONERY_RECENT_0, ID_STATIONERY_MORE);
|
|
break;
|
|
|
|
case ID_POPUP_FILE:
|
|
DeleteMenu(hmenuPopup, ID_SEND_INSTANT_MESSAGE, MF_BYCOMMAND);
|
|
break;
|
|
|
|
case ID_POPUP_VIEW:
|
|
if (NULL == m_pViewMenu)
|
|
{
|
|
// Create the view menu
|
|
HrCreateViewMenu(VMF_FINDER, &m_pViewMenu);
|
|
}
|
|
|
|
if (NULL != m_pViewMenu)
|
|
{
|
|
mii.cbSize = sizeof(MENUITEMINFO);
|
|
mii.fMask = MIIM_SUBMENU;
|
|
|
|
if (FALSE == GetMenuItemInfo(hmenuPopup, ID_POPUP_FILTER, FALSE, &mii))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Remove the old filter submenu
|
|
if(IsMenu(mii.hSubMenu))
|
|
DestroyMenu(mii.hSubMenu);
|
|
|
|
// Replace the view menu
|
|
if (FAILED(m_pViewMenu->HrReplaceMenu(0, hmenuPopup)))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID_POPUP_FILTER:
|
|
if (NULL != m_pViewMenu)
|
|
{
|
|
m_pViewMenu->UpdateViewMenu(0, hmenuPopup, m_pMsgList);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Let the message list initialize it
|
|
if (m_pMsgList)
|
|
m_pMsgList->OnPopupMenu(hmenuPopup, uIDPopup);
|
|
|
|
// now enable/disable the items
|
|
MenuUtil_EnablePopupMenu(hmenuPopup, this);
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnMenuSelect()
|
|
//
|
|
// PURPOSE: Puts the menu help text on the status bar.
|
|
//
|
|
void CFindDlg::OnMenuSelect(HWND hwnd, HMENU hmenu, int item, HMENU hmenuPopup, UINT flags)
|
|
{
|
|
if (m_pStatusBar)
|
|
{
|
|
// If this is the stationery menu, special case it
|
|
if (item >= ID_STATIONERY_RECENT_0 && item <= ID_STATIONERY_RECENT_9)
|
|
m_pStatusBar->ShowSimpleText(MAKEINTRESOURCE(idsRSListGeneralHelp));
|
|
else
|
|
HandleMenuSelect(m_pStatusBar, MAKEWPARAM(item, flags), hmenu ? (LPARAM) hmenu : (LPARAM) hmenuPopup);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnWinIniChange()
|
|
//
|
|
// PURPOSE: Handles updates of fonts, colors, etc.
|
|
//
|
|
void CFindDlg::OnWinIniChange(HWND hwnd, LPCTSTR lpszSectionName)
|
|
{
|
|
// Forward this off to our date picker controls
|
|
FORWARD_WM_WININICHANGE(GetDlgItem(hwnd, IDC_DATE_FROM), lpszSectionName, SendMessage);
|
|
FORWARD_WM_WININICHANGE(GetDlgItem(hwnd, IDC_DATE_TO), lpszSectionName, SendMessage);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnCommand()
|
|
//
|
|
// PURPOSE: Handles commands generated by the finder.
|
|
//
|
|
void CFindDlg::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// We need to grab some of the notifications sent to us first
|
|
if ((codeNotify == EN_CHANGE) ||
|
|
(codeNotify == BN_CLICKED && (id == IDC_HAS_FLAG || id == IDC_HAS_ATTACH)))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_FIND_NOW), _IsFindEnabled(hwnd) && !m_fInProgress);
|
|
return;
|
|
}
|
|
|
|
// If this is from a menu, then first see if the message list wants
|
|
// to handle it.
|
|
if (NULL == hwndCtl)
|
|
{
|
|
// Check to see if the command is even enabled
|
|
if (id >= ID_FIRST)
|
|
{
|
|
OLECMD cmd;
|
|
cmd.cmdID = id;
|
|
cmd.cmdf = 0;
|
|
|
|
hr = QueryStatus(&CMDSETID_OutlookExpress, 1, &cmd, NULL);
|
|
if (FAILED(hr) || (0 == (cmd.cmdf & OLECMDF_ENABLED)))
|
|
return;
|
|
}
|
|
|
|
if (m_pMsgListCT)
|
|
{
|
|
hr = m_pMsgListCT->Exec(&CMDSETID_OEMessageList, id, OLECMDEXECOPT_DODEFAULT,
|
|
NULL, NULL);
|
|
if (S_OK == hr)
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Otherwise, it goes to the command target
|
|
VARIANTARG va;
|
|
|
|
va.vt = VT_I4;
|
|
va.lVal = codeNotify;
|
|
|
|
hr = Exec(NULL, id, OLECMDEXECOPT_DODEFAULT, &va, NULL);
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnNotify()
|
|
//
|
|
// PURPOSE: Handles notifications from the date pickers
|
|
//
|
|
LRESULT CFindDlg::OnNotify(HWND hwnd, int idFrom, LPNMHDR pnmhdr)
|
|
{
|
|
if (DTN_DATETIMECHANGE == pnmhdr->code)
|
|
EnableWindow(GetDlgItem(hwnd, IDC_FIND_NOW), _IsFindEnabled(hwnd));
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::OnDestroy()
|
|
//
|
|
// PURPOSE: Clean up the message list now that we're being shut down and
|
|
// also save our size etc.
|
|
//
|
|
void CFindDlg::OnDestroy(HWND hwnd)
|
|
{
|
|
WINDOWPLACEMENT wp;
|
|
|
|
// Save the sizing information
|
|
wp.length = sizeof(wp);
|
|
GetWindowPlacement(hwnd, &wp);
|
|
SetOption(OPT_FINDER_POS, (LPBYTE)&wp, sizeof(wp), NULL, 0);
|
|
|
|
// Unregister with Identity manager
|
|
if (m_dwIdentCookie != 0)
|
|
{
|
|
MU_UnregisterIdentityNotifier(m_dwIdentCookie);
|
|
m_dwIdentCookie = 0;
|
|
}
|
|
|
|
// Clean up the property
|
|
RemoveProp(hwnd, c_szOETopLevel);
|
|
|
|
// Stop receieving notifications
|
|
AtlUnadvise(m_pMsgList, DIID__MessageListEvents, m_dwCookie);
|
|
|
|
// Tell the message list to release it's folder
|
|
m_pMsgList->SetFolder(FOLDERID_INVALID, NULL, FALSE, NULL, NOSTORECALLBACK);
|
|
|
|
// Close the message list
|
|
m_pMsgList->OnClose();
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdOpen()
|
|
//
|
|
// PURPOSE: Called when the user want's to open a message that they've found.
|
|
//
|
|
HRESULT CFindDlg::CmdOpen(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn,
|
|
VARIANTARG *pvaOut)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceCall("CMessageView::CmdOpen");
|
|
|
|
// If more than 10 messages are selected, warn the user with a "Don't show
|
|
// me again" dialog that this could be bad.
|
|
DWORD dwSel = 0;
|
|
|
|
m_pMsgList->GetSelectedCount(&dwSel);
|
|
if (dwSel > 10)
|
|
{
|
|
TCHAR szBuffer[CCHMAX_STRINGRES];
|
|
LRESULT lResult;
|
|
|
|
AthLoadString(idsErrOpenManyMessages, szBuffer, ARRAYSIZE(szBuffer));
|
|
lResult = DoDontShowMeAgainDlg(m_hwnd, c_szRegManyMsgWarning,
|
|
MAKEINTRESOURCE(idsAthena), szBuffer,
|
|
MB_OKCANCEL);
|
|
if (IDCANCEL == lResult)
|
|
return (S_OK);
|
|
}
|
|
|
|
// Get the array of selected rows from the message list
|
|
DWORD *rgRows = NULL;
|
|
DWORD cRows = 0;
|
|
|
|
if (FAILED(hr = m_pMsgList->GetSelected(NULL, &cRows, &rgRows)))
|
|
return (hr);
|
|
|
|
// It's possible for the message list to go away while we're doing this.
|
|
// To keep us from crashing, make sure you verify it still exists during
|
|
// the loop.
|
|
|
|
LPMESSAGEINFO pInfo;
|
|
IMessageTable *pTable = NULL;
|
|
|
|
hr = m_pMsgList->GetMessageTable(&pTable);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (DWORD i = 0; (i < cRows && m_pMsgList != NULL); i++)
|
|
{
|
|
if (SUCCEEDED(hr = m_pMsgList->GetMessageInfo(rgRows[i], &pInfo)))
|
|
{
|
|
INIT_MSGSITE_STRUCT initStruct;
|
|
DWORD dwCreateFlags;
|
|
initStruct.initTable.pListSelect = NULL;
|
|
m_pMsgList->GetListSelector(&initStruct.initTable.pListSelect);
|
|
|
|
// Initialize note struct
|
|
initStruct.dwInitType = OEMSIT_MSG_TABLE;
|
|
initStruct.initTable.pMsgTable = pTable;
|
|
if (FAILED(GetFolderIdFromMsgTable(pTable, &initStruct.folderID)))
|
|
initStruct.folderID = FOLDERID_INVALID;
|
|
initStruct.initTable.rowIndex = rgRows[i];
|
|
|
|
// Decide whether it is news or mail
|
|
if (pInfo->dwFlags & ARF_NEWSMSG)
|
|
dwCreateFlags = OENCF_NEWSFIRST;
|
|
else
|
|
dwCreateFlags = 0;
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
|
|
// Create and Open Note
|
|
hr = CreateAndShowNote(OENA_READ, dwCreateFlags, &initStruct, m_hwnd, (IUnknown *)m_pPumpRefCount);
|
|
ReleaseObj(initStruct.initTable.pListSelect);
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
}
|
|
pTable->Release();
|
|
}
|
|
MemFree(rgRows);
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdOpenFolder()
|
|
//
|
|
// PURPOSE: Called when the user want's to open the folder that contains the
|
|
// selected message.
|
|
//
|
|
HRESULT CFindDlg::CmdOpenFolder(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn,
|
|
VARIANTARG *pvaOut)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwFocused;
|
|
DWORD *rgRows = NULL;
|
|
DWORD cRows = 0;
|
|
|
|
if (m_pMsgList)
|
|
{
|
|
// Figure out which message is focused
|
|
if (SUCCEEDED(m_pMsgList->GetSelected(&dwFocused, &cRows, &rgRows)))
|
|
{
|
|
FOLDERID idFolder;
|
|
|
|
// Get some information about the message
|
|
if (g_pInstance && SUCCEEDED(hr = m_pMsgList->GetRowFolderId(dwFocused, &idFolder)))
|
|
{
|
|
g_pInstance->BrowseToObject(SW_SHOWNORMAL, idFolder);
|
|
}
|
|
}
|
|
}
|
|
|
|
MemFree(rgRows);
|
|
return (S_OK);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdReply()
|
|
//
|
|
// PURPOSE: Replies or Reply-All's to the selected message.
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT CFindDlg::CmdReplyForward(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwFocused;
|
|
DWORD *rgRows = NULL;
|
|
DWORD cRows = 0;
|
|
IMessageTable *pTable = NULL;
|
|
|
|
if (m_pMsgList)
|
|
{
|
|
// Figure out which message is focused
|
|
if (SUCCEEDED(m_pMsgList->GetSelected(&dwFocused, &cRows, &rgRows)))
|
|
{
|
|
INIT_MSGSITE_STRUCT rInitSite;
|
|
DWORD dwCreateFlags;
|
|
DWORD dwAction = 0;
|
|
|
|
// Get the message table from the message list. The note will need
|
|
// this to deal with next / prev commands
|
|
hr = m_pMsgList->GetMessageTable(&pTable);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
if ((1 < cRows) && ((ID_FORWARD == nCmdID) || (ID_FORWARD_AS_ATTACH == nCmdID)))
|
|
{
|
|
IMimeMessage *pMsgFwd = NULL;
|
|
BOOL fErrorsOccured = FALSE,
|
|
fCreateNote = TRUE;
|
|
|
|
hr = HrCreateMessage(&pMsgFwd);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
rInitSite.dwInitType = OEMSIT_MSG;
|
|
rInitSite.pMsg = pMsgFwd;
|
|
if (FAILED(GetFolderIdFromMsgTable(pTable, &rInitSite.folderID)))
|
|
rInitSite.folderID = FOLDERID_INVALID;
|
|
|
|
dwCreateFlags = 0;
|
|
dwAction = OENA_COMPOSE;
|
|
|
|
for (DWORD i = 0; i < cRows; i++)
|
|
{
|
|
DWORD iRow = rgRows[i];
|
|
IMimeMessage *pMsg = NULL;
|
|
|
|
// Since this command is
|
|
hr = pTable->OpenMessage(iRow, OPEN_MESSAGE_SECURE, &pMsg, NOSTORECALLBACK);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (FAILED(pMsgFwd->AttachObject(IID_IMimeMessage, (LPVOID)pMsg, NULL)))
|
|
fErrorsOccured = TRUE;
|
|
pMsg->Release();
|
|
}
|
|
else
|
|
fErrorsOccured = TRUE;
|
|
}
|
|
|
|
if (fErrorsOccured)
|
|
{
|
|
if(AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail),
|
|
MAKEINTRESOURCEW(idsErrorAttachingMsgsToNote), NULL, MB_OKCANCEL) == IDCANCEL)
|
|
fCreateNote = FALSE;
|
|
}
|
|
|
|
if (fCreateNote)
|
|
hr = CreateAndShowNote(dwAction, dwCreateFlags, &rInitSite, m_hwnd, (IUnknown *)m_pPumpRefCount);
|
|
pMsgFwd->Release();
|
|
}
|
|
else
|
|
{
|
|
LPMESSAGEINFO pInfo;
|
|
|
|
// Get some information about the message
|
|
if (SUCCEEDED(hr = m_pMsgList->GetMessageInfo(dwFocused, &pInfo)))
|
|
{
|
|
// Determine if this is a news or mail message.
|
|
if (pInfo->dwFlags & ARF_NEWSMSG)
|
|
dwCreateFlags = OENCF_NEWSFIRST;
|
|
else
|
|
dwCreateFlags = 0;
|
|
|
|
// Reply or forward
|
|
if (nCmdID == ID_FORWARD)
|
|
dwAction = OENA_FORWARD;
|
|
else if (nCmdID == ID_FORWARD_AS_ATTACH)
|
|
dwAction = OENA_FORWARDBYATTACH;
|
|
else if (nCmdID == ID_REPLY)
|
|
dwAction = OENA_REPLYTOAUTHOR;
|
|
else if (nCmdID == ID_REPLY_ALL)
|
|
dwAction = OENA_REPLYALL;
|
|
else if (nCmdID == ID_REPLY_GROUP)
|
|
dwAction = OENA_REPLYTONEWSGROUP;
|
|
else
|
|
AssertSz(FALSE, "Didn't ask for a valid action");
|
|
|
|
// Fill out the initialization information
|
|
rInitSite.dwInitType = OEMSIT_MSG_TABLE;
|
|
rInitSite.initTable.pMsgTable = pTable;
|
|
rInitSite.initTable.pListSelect = NULL;
|
|
if (FAILED(GetFolderIdFromMsgTable(pTable, &rInitSite.folderID)))
|
|
rInitSite.folderID = FOLDERID_INVALID;
|
|
rInitSite.initTable.rowIndex = dwFocused;
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
|
|
// Create the note object
|
|
hr = CreateAndShowNote(dwAction, dwCreateFlags, &rInitSite, m_hwnd, (IUnknown *)m_pPumpRefCount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
ReleaseObj(pTable);
|
|
MemFree(rgRows);
|
|
return (S_OK);
|
|
}
|
|
|
|
HRESULT CFindDlg::CmdCancelMessage(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
HRESULT hr;
|
|
FOLDERID idFolder;
|
|
DWORD dwFocused;
|
|
DWORD *rgRows = NULL;
|
|
DWORD cRows = 0;
|
|
|
|
if (m_pMsgList)
|
|
{
|
|
// Figure out which message is focused
|
|
if (SUCCEEDED(m_pMsgList->GetSelected(&dwFocused, &cRows, &rgRows)))
|
|
{
|
|
IMessageTable *pTable = NULL;
|
|
LPMESSAGEINFO pInfo;
|
|
// Get the message table from the message list. The note will need
|
|
// this to deal with next / prev commands
|
|
hr = m_pMsgList->GetMessageTable(&pTable);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
// Get some information about the message
|
|
if (SUCCEEDED(hr = m_pMsgList->GetMessageInfo(dwFocused, &pInfo)))
|
|
{
|
|
if (SUCCEEDED(hr = m_pMsgList->GetRowFolderId(dwFocused, &idFolder)))
|
|
hr = NewsUtil_HrCancelPost(m_hwnd, idFolder, pInfo);
|
|
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
}
|
|
pTable->Release();
|
|
}
|
|
}
|
|
|
|
exit:
|
|
MemFree(rgRows);
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdFindNow()
|
|
//
|
|
// PURPOSE: Start's a new find.
|
|
//
|
|
HRESULT CFindDlg::CmdFindNow(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn,
|
|
VARIANTARG *pvaOut)
|
|
{
|
|
// Start by freeing our current find information if we have any
|
|
_FreeFindInfo(&m_rFindInfo);
|
|
|
|
// Retrieve the find values from the dialog and store them in the
|
|
// m_rFindInfo struct.
|
|
if (_GetFindValues(m_hwnd, &m_rFindInfo))
|
|
{
|
|
// Validate the data. If the user has Date From && Date To set, make
|
|
// sure that to is after from.
|
|
if ((m_rFindInfo.mask & (FIM_DATEFROM | FIM_DATETO)) == (FIM_DATEFROM | FIM_DATETO) &&
|
|
CompareFileTime(&m_rFindInfo.ftDateTo, &m_rFindInfo.ftDateFrom) < 0)
|
|
{
|
|
AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrBadFindParams), NULL, MB_OK | MB_ICONINFORMATION);
|
|
return (E_INVALIDARG);
|
|
}
|
|
|
|
// Case insensitive search
|
|
if (m_rFindInfo.pszFrom)
|
|
CharUpper(m_rFindInfo.pszFrom);
|
|
if (m_rFindInfo.pszSubject)
|
|
CharUpper(m_rFindInfo.pszSubject);
|
|
if (m_rFindInfo.pszTo)
|
|
CharUpper(m_rFindInfo.pszTo);
|
|
if (m_rFindInfo.pszBody)
|
|
CharUpper(m_rFindInfo.pszBody);
|
|
|
|
// Show the bottom portion of the dialog
|
|
_ShowResults(m_hwnd);
|
|
|
|
// Start the find.
|
|
_OnFindNow(m_hwnd);
|
|
}
|
|
else
|
|
{
|
|
// If we couldn't store the information, assume it's becuase
|
|
// their isn't enough memory to
|
|
AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsMemory), NULL, MB_OK | MB_ICONINFORMATION);
|
|
DestroyWindow(m_hwnd);
|
|
}
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdBrowseForFolder()
|
|
//
|
|
// PURPOSE: Bring's up the folder picker dialog
|
|
//
|
|
HRESULT CFindDlg::CmdBrowseForFolder(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn,
|
|
VARIANTARG *pvaOut)
|
|
{
|
|
FOLDERID idFolder;
|
|
return PickFolderInEdit(m_hwnd, GetDlgItem(m_hwnd, IDC_FOLDER), 0, NULL, NULL, &idFolder);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdStop()
|
|
//
|
|
// PURPOSE: Called when the user want's to stop a find in progress.
|
|
//
|
|
HRESULT CFindDlg::CmdStop(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
HWND hwndBtn;
|
|
|
|
m_fAbort = TRUE;
|
|
|
|
hwndBtn = GetDlgItem(m_hwnd, IDC_STOP);
|
|
EnableWindow(hwndBtn, FALSE);
|
|
Button_SetStyle(hwndBtn, BS_PUSHBUTTON, TRUE);
|
|
|
|
hwndBtn = GetDlgItem(m_hwnd, IDC_FIND_NOW);
|
|
EnableWindow(hwndBtn, _IsFindEnabled(m_hwnd));
|
|
Button_SetStyle(hwndBtn, BS_DEFPUSHBUTTON, TRUE);
|
|
|
|
EnableWindow(GetDlgItem(m_hwnd, IDC_RESET), TRUE);
|
|
|
|
UpdateWindow(m_hwnd);
|
|
|
|
if (m_pCancel != NULL)
|
|
m_pCancel->Cancel(CT_CANCEL);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdReset()
|
|
//
|
|
// PURPOSE: Called when the user want's to reset the find criteria
|
|
//
|
|
HRESULT CFindDlg::CmdReset(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
_FreeFindInfo(&m_rFindInfo);
|
|
m_rFindInfo.mask = FIM_FROM | FIM_TO | FIM_SUBJECT | FIM_BODYTEXT;
|
|
_SetFindValues(m_hwnd, &m_rFindInfo);
|
|
EnableWindow(GetDlgItem(m_hwnd, IDC_FIND_NOW), _IsFindEnabled(m_hwnd));
|
|
((CMessageList *) m_pMsgList)->SetFolder(FOLDERID_INVALID, NULL, FALSE, NULL, NOSTORECALLBACK);
|
|
m_fFindComplete = FALSE;
|
|
m_pStatusBar->SetStatusText((LPTSTR) c_szEmpty);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdBlockSender()
|
|
//
|
|
// PURPOSE: Add the sender of the selected messages to the block senders list
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT CFindDlg::CmdBlockSender(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD * rgRows = NULL;
|
|
DWORD cRows = 0;
|
|
LPMESSAGEINFO pInfo = NULL;
|
|
IUnknown * pUnkMessage = NULL;
|
|
IMimeMessage * pMessage = 0;
|
|
LPSTR pszEmailFrom = NULL;
|
|
ADDRESSPROPS rSender = {0};
|
|
CHAR szRes[CCHMAX_STRINGRES];
|
|
LPSTR pszResult = NULL;
|
|
|
|
TraceCall("CFindDlg::CmdBlockSender");
|
|
|
|
IF_FAILEXIT(hr = m_pMsgList->GetSelected(NULL, &cRows, &rgRows));
|
|
|
|
// It's possible for the message list to go away while we're doing this.
|
|
// To keep us from crashing, make sure you verify it still exists during
|
|
// the loop.
|
|
|
|
IF_FAILEXIT(hr = m_pMsgList->GetMessageInfo(rgRows[0], &pInfo));
|
|
|
|
// Do we already have the address?
|
|
if ((NULL != pInfo->pszEmailFrom) && ('\0' != pInfo->pszEmailFrom[0]))
|
|
{
|
|
pszEmailFrom = pInfo->pszEmailFrom;
|
|
}
|
|
else
|
|
{
|
|
// Load that message from the store
|
|
IF_FAILEXIT(hr = m_pMsgList->GetMessage(rgRows[0], FALSE, FALSE, &pUnkMessage));
|
|
|
|
if (NULL == pUnkMessage)
|
|
IF_FAILEXIT(hr = E_FAIL);
|
|
|
|
// Get the IMimeMessage interface from the message
|
|
IF_FAILEXIT(hr = pUnkMessage->QueryInterface(IID_IMimeMessage, (LPVOID *) &pMessage));
|
|
|
|
rSender.dwProps = IAP_EMAIL;
|
|
IF_FAILEXIT(hr = pMessage->GetSender(&rSender));
|
|
|
|
Assert(rSender.pszEmail && ISFLAGSET(rSender.dwProps, IAP_EMAIL));
|
|
pszEmailFrom = rSender.pszEmail;
|
|
}
|
|
|
|
// Bring up the rule editor for this message
|
|
IF_FAILEXIT(hr = RuleUtil_HrAddBlockSender((0 != (pInfo->dwFlags & ARF_NEWSMSG)) ? RULE_TYPE_NEWS : RULE_TYPE_MAIL, pszEmailFrom));
|
|
|
|
// Load the template string
|
|
AthLoadString(idsSenderAdded, szRes, sizeof(szRes));
|
|
|
|
// Allocate the space to hold the final string
|
|
DWORD cchSize = (lstrlen(szRes) + lstrlen(pszEmailFrom) + 1);
|
|
IF_FAILEXIT(hr = HrAlloc((VOID **) &pszResult, sizeof(*pszResult) * cchSize));
|
|
|
|
// Build up the warning string
|
|
wnsprintf(pszResult, cchSize, szRes, pszEmailFrom);
|
|
|
|
// Show the success dialog
|
|
AthMessageBox(m_hwnd, MAKEINTRESOURCE(idsAthena), pszResult, NULL, MB_OK | MB_ICONINFORMATION);
|
|
|
|
exit:
|
|
MemFree(pszResult);
|
|
g_pMoleAlloc->FreeAddressProps(&rSender);
|
|
ReleaseObj(pMessage);
|
|
ReleaseObj(pUnkMessage);
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
MemFree(rgRows);
|
|
if (FAILED(hr))
|
|
{
|
|
AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena),
|
|
MAKEINTRESOURCEW(idsSenderError), NULL, MB_OK | MB_ICONERROR);
|
|
}
|
|
return (hr);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdCreateRule()
|
|
//
|
|
// PURPOSE: Add the sender of the selected messages to the block senders list
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT CFindDlg::CmdCreateRule(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
HRESULT hr;
|
|
DWORD * rgRows = NULL;
|
|
DWORD cRows = 0;
|
|
LPMESSAGEINFO pInfo = NULL;
|
|
IUnknown * pUnkMessage = NULL;
|
|
IMimeMessage * pMessage = 0;
|
|
|
|
TraceCall("CFindDlg::CmdCreateRule");
|
|
|
|
// Get the array of selected rows from the message list
|
|
|
|
if (FAILED(hr = m_pMsgList->GetSelected(NULL, &cRows, &rgRows)))
|
|
return (hr);
|
|
|
|
// It's possible for the message list to go away while we're doing this.
|
|
// To keep us from crashing, make sure you verify it still exists during
|
|
// the loop.
|
|
|
|
if (SUCCEEDED(hr = m_pMsgList->GetMessageInfo(rgRows[0], &pInfo)))
|
|
{
|
|
// Load that message from the store
|
|
if (S_OK == m_pMsgList->GetMessage(rgRows[0], FALSE, FALSE, &pUnkMessage))
|
|
{
|
|
// Get the IMimeMessage interface from the message
|
|
if (NULL != pUnkMessage)
|
|
{
|
|
pUnkMessage->QueryInterface(IID_IMimeMessage, (LPVOID *) &pMessage);
|
|
}
|
|
}
|
|
|
|
// Bring up the rule editor for this message
|
|
hr = HrCreateRuleFromMessage(m_hwnd, (0 != (pInfo->dwFlags & ARF_NEWSMSG)) ?
|
|
CRFMF_NEWS : CRFMF_MAIL, pInfo, pMessage);
|
|
}
|
|
|
|
ReleaseObj(pMessage);
|
|
ReleaseObj(pUnkMessage);
|
|
m_pMsgList->FreeMessageInfo(pInfo);
|
|
MemFree(rgRows);
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::CmdCombineAndDecode()
|
|
//
|
|
// PURPOSE: Combines the selected messages into a single message.
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT CFindDlg::CmdCombineAndDecode(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
FOLDERID idFolder;
|
|
DWORD *rgRows = NULL;
|
|
DWORD cRows = 0;
|
|
CCombineAndDecode *pDecode = NULL;
|
|
HRESULT hr;
|
|
|
|
// Create the decoder object
|
|
pDecode = new CCombineAndDecode();
|
|
if (!pDecode)
|
|
return (S_OK);
|
|
|
|
// Get the array of selected rows from the message list
|
|
if (FAILED(hr = m_pMsgList->GetSelected(NULL, &cRows, &rgRows)))
|
|
{
|
|
pDecode->Release();
|
|
return (hr);
|
|
}
|
|
|
|
// Get a pointer to the message table
|
|
IMessageTable *pTable = NULL;
|
|
if (SUCCEEDED(m_pMsgList->GetMessageTable(&pTable)))
|
|
{
|
|
// Initialize the decoder
|
|
if (SUCCEEDED(GetFolderIdFromMsgTable(pTable, &idFolder)))
|
|
pDecode->Start(m_hwnd, pTable, rgRows, cRows, idFolder);
|
|
|
|
}
|
|
|
|
MemFree(rgRows);
|
|
pDecode->Release();
|
|
pTable->Release();
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
void CFindDlg::_ShowResults(HWND hwnd)
|
|
{
|
|
if (!m_fShowResults)
|
|
{
|
|
RECT rc;
|
|
|
|
m_fShowResults = TRUE;
|
|
|
|
GetWindowRect(hwnd, &rc);
|
|
m_ptDragMin.y = (3 * m_ptDragMin.y) / 2;
|
|
|
|
ShowWindow(GetDlgItem(hwnd, IDC_STATUS_BAR), SW_SHOW);
|
|
ShowWindow(m_hwndList, SW_SHOW);
|
|
|
|
SetWindowPos(hwnd, NULL, 0, 0, rc.right - rc.left, m_cyDlgFull, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
|
|
}
|
|
}
|
|
|
|
|
|
void CFindDlg::_OnFindNow(HWND hwnd)
|
|
{
|
|
HWND hwndBtn;
|
|
|
|
m_fInProgress = TRUE;
|
|
|
|
hwndBtn = GetDlgItem(hwnd, IDC_FIND_NOW);
|
|
EnableWindow(hwndBtn, FALSE);
|
|
Button_SetStyle(hwndBtn, BS_PUSHBUTTON, TRUE);
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_RESET), FALSE);
|
|
|
|
hwndBtn = GetDlgItem(hwnd, IDC_STOP);
|
|
EnableWindow(hwndBtn, TRUE);
|
|
Button_SetStyle(hwndBtn, BS_DEFPUSHBUTTON, TRUE);
|
|
|
|
ShowWindow(m_hwndList, SW_SHOW);
|
|
SetFocus(m_hwndList);
|
|
|
|
UpdateWindow(hwnd);
|
|
|
|
m_fAbort = m_fClose = FALSE;
|
|
|
|
_StartFind(_GetCurSel(hwnd), IsDlgButtonChecked(hwnd, IDC_INCLUDE_SUB));
|
|
|
|
CmdStop(ID_STOP, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
|
|
|
|
if (m_fClose)
|
|
DestroyWindow(m_hwnd);
|
|
|
|
m_fInProgress = FALSE;
|
|
}
|
|
|
|
FOLDERID CFindDlg::_GetCurSel(HWND hwnd)
|
|
{
|
|
return GetFolderIdFromEdit(GetDlgItem(hwnd, IDC_FOLDER));
|
|
}
|
|
|
|
void CFindDlg::_StartFind(FOLDERID idFolder, BOOL fSubFolders)
|
|
{
|
|
// If we're searching subfolders, then set that flag too
|
|
m_rFindInfo.fSubFolders = fSubFolders;
|
|
|
|
// Initialize the Message List
|
|
((CMessageList *)m_pMsgList)->SetFolder(idFolder, NULL, fSubFolders, &m_rFindInfo, (IStoreCallback *)this);
|
|
}
|
|
|
|
|
|
void CFindDlg::_FreeFindInfo(FINDINFO *pfi)
|
|
{
|
|
FreeFindInfo(pfi);
|
|
}
|
|
|
|
void CFindDlg::_SetFindValues(HWND hwnd, FINDINFO *pfi)
|
|
{
|
|
SYSTEMTIME st;
|
|
HWND hwndTo;
|
|
|
|
if (pfi->mask & FIM_FROM)
|
|
{
|
|
Assert(GetDlgItem(hwnd, IDC_FROM));
|
|
Edit_SetText(GetDlgItem(hwnd, IDC_FROM), pfi->pszFrom);
|
|
}
|
|
if (pfi->mask & FIM_TO)
|
|
{
|
|
hwndTo = GetDlgItem(hwnd, IDC_TO);
|
|
if (NULL != hwndTo)
|
|
{
|
|
Edit_SetText(hwndTo, pfi->pszTo);
|
|
}
|
|
}
|
|
if (pfi->mask & FIM_SUBJECT)
|
|
{
|
|
Assert(GetDlgItem(hwnd, IDC_SUBJECT));
|
|
Edit_SetText(GetDlgItem(hwnd, IDC_SUBJECT), pfi->pszSubject);
|
|
}
|
|
if (pfi->mask & FIM_BODYTEXT)
|
|
{
|
|
Assert(GetDlgItem(hwnd, IDC_BODY));
|
|
Edit_SetText(GetDlgItem(hwnd, IDC_BODY), pfi->pszBody);
|
|
}
|
|
|
|
if (GetDlgItem(hwnd, IDC_HAS_ATTACH))
|
|
CheckDlgButton(hwnd, IDC_HAS_ATTACH, (pfi->mask & FIM_ATTACHMENT) ? BST_CHECKED : BST_UNCHECKED);
|
|
|
|
if (GetDlgItem(hwnd, IDC_HAS_FLAG))
|
|
CheckDlgButton(hwnd, IDC_HAS_FLAG, (pfi->mask & FIM_FLAGGED) ? BST_CHECKED : BST_UNCHECKED);
|
|
|
|
FileTimeToSystemTime(&pfi->ftDateFrom, &st);
|
|
DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_DATE_FROM), (pfi->mask & FIM_DATEFROM) ? GDT_VALID : GDT_NONE, &st);
|
|
|
|
FileTimeToSystemTime(&pfi->ftDateTo, &st);
|
|
DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_DATE_TO), (pfi->mask & FIM_DATETO) ? GDT_VALID : GDT_NONE, &st);
|
|
}
|
|
|
|
|
|
BOOL CFindDlg::_GetFindValues(HWND hwnd, FINDINFO *pfi)
|
|
{
|
|
SYSTEMTIME st;
|
|
|
|
pfi->mask = 0;
|
|
|
|
if (!AllocStringFromDlg(hwnd, IDC_FROM, &pfi->pszFrom) ||
|
|
!AllocStringFromDlg(hwnd, IDC_SUBJECT, &pfi->pszSubject) ||
|
|
!AllocStringFromDlg(hwnd, IDC_TO, &pfi->pszTo) ||
|
|
!AllocStringFromDlg(hwnd, IDC_BODY, &pfi->pszBody))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (pfi->pszFrom)
|
|
pfi->mask |= FIM_FROM;
|
|
if (pfi->pszSubject)
|
|
pfi->mask |= FIM_SUBJECT;
|
|
if (pfi->pszTo)
|
|
pfi->mask |= FIM_TO;
|
|
if (pfi->pszBody)
|
|
pfi->mask |= FIM_BODYTEXT;
|
|
|
|
if (IsDlgButtonChecked(hwnd, IDC_HAS_ATTACH))
|
|
pfi->mask |= FIM_ATTACHMENT;
|
|
|
|
if (IsDlgButtonChecked(hwnd, IDC_HAS_FLAG))
|
|
pfi->mask |= FIM_FLAGGED;
|
|
|
|
if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATE_FROM), &st) != GDT_NONE)
|
|
{
|
|
pfi->mask |= FIM_DATEFROM;
|
|
st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0; // start of the day
|
|
SystemTimeToFileTime(&st, &pfi->ftDateFrom);
|
|
}
|
|
|
|
if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATE_TO), &st) != GDT_NONE)
|
|
{
|
|
pfi->mask |= FIM_DATETO;
|
|
|
|
// end of day
|
|
st.wHour = 23;
|
|
st.wMinute = 59;
|
|
st.wSecond = 59;
|
|
st.wMilliseconds = 999;
|
|
SystemTimeToFileTime(&st, &pfi->ftDateTo);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::_IsFindEnabled()
|
|
//
|
|
// PURPOSE: Checks to see if the "Find Now" button should be enabled.
|
|
//
|
|
BOOL CFindDlg::_IsFindEnabled(HWND hwnd)
|
|
{
|
|
BOOL fEnable;
|
|
SYSTEMTIME st;
|
|
HWND hwndBody, hwndAttach, hwndTo;
|
|
|
|
hwndBody = GetDlgItem(hwnd, IDC_BODY);
|
|
hwndAttach = GetDlgItem(hwnd, IDC_HAS_ATTACH);
|
|
hwndTo = GetDlgItem(hwnd, IDC_TO);
|
|
|
|
// If we have content in any of these fields, we can search.
|
|
fEnable = Edit_GetTextLength(GetDlgItem(hwnd, IDC_FROM)) ||
|
|
Edit_GetTextLength(hwndTo) ||
|
|
Edit_GetTextLength(GetDlgItem(hwnd, IDC_SUBJECT)) ||
|
|
Edit_GetTextLength(hwndBody) ||
|
|
IsDlgButtonChecked(hwnd, IDC_HAS_ATTACH) ||
|
|
IsDlgButtonChecked(hwnd, IDC_HAS_FLAG) ||
|
|
(DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATE_FROM), &st) != GDT_NONE) ||
|
|
(DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATE_TO), &st) != GDT_NONE);
|
|
|
|
return fEnable;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::_SetFindIntlFont()
|
|
//
|
|
// PURPOSE: Set's the correct international font for all edit boxes.
|
|
//
|
|
void CFindDlg::_SetFindIntlFont(HWND hwnd)
|
|
{
|
|
HWND hwndT;
|
|
|
|
hwndT = GetDlgItem(hwnd, IDC_FROM);
|
|
if (hwndT != NULL)
|
|
SetIntlFont(hwndT);
|
|
hwndT = GetDlgItem(hwnd, IDC_TO);
|
|
if (hwndT != NULL)
|
|
SetIntlFont(hwndT);
|
|
hwndT = GetDlgItem(hwnd, IDC_SUBJECT);
|
|
if (hwndT != NULL)
|
|
SetIntlFont(hwndT);
|
|
hwndT = GetDlgItem(hwnd, IDC_BODY);
|
|
if (hwndT != NULL)
|
|
SetIntlFont(hwndT);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::_InitSizingInfo()
|
|
//
|
|
// PURPOSE: Grabs all the sizing information we'll need later when the
|
|
// dialog is resized.
|
|
//
|
|
void CFindDlg::_InitSizingInfo(HWND hwnd)
|
|
{
|
|
RECT rc, rcClient;
|
|
RECT rcEdit;
|
|
WINDOWPLACEMENT wp;
|
|
|
|
TraceCall("CFindDlg::_InitSizingInfo");
|
|
|
|
// Get the overall size of the default dialog template
|
|
GetClientRect(hwnd, &rcClient);
|
|
m_cxDlgDef = rcClient.right - rcClient.left;
|
|
m_yView = rcClient.bottom;
|
|
|
|
// Make room for the menu bar and save that for resizing
|
|
AdjustWindowRect(&rcClient, GetWindowStyle(hwnd), TRUE);
|
|
m_ptDragMin.x = rcClient.right - rcClient.left;
|
|
m_ptDragMin.y = rcClient.bottom - rcClient.top;
|
|
|
|
GetWindowRect(GetDlgItem(hwnd, IDC_FOLDER), &rcEdit);
|
|
MapWindowRect(NULL, hwnd, &rcEdit);
|
|
m_xEdit = rcEdit.left;
|
|
m_cxFolder = rcEdit.right - rcEdit.left;
|
|
|
|
GetWindowRect(GetDlgItem(hwnd, IDC_INCLUDE_SUB), &rc);
|
|
MapWindowRect(NULL, hwnd, &rc);
|
|
m_xIncSub = rc.left;
|
|
m_yIncSub = rc.top;
|
|
|
|
GetWindowRect(GetDlgItem(hwnd, idcStatic1), &rc);
|
|
m_cxStatic = rc.right - rc.left;
|
|
|
|
GetWindowRect(GetDlgItem(hwnd, IDC_BROWSE_FOLDER), &rc);
|
|
MapWindowRect(NULL, hwnd, &rc);
|
|
m_yBrowse = rc.top;
|
|
m_dxBtnGap = rc.left - rcEdit.right;
|
|
|
|
GetWindowRect(GetDlgItem(hwnd, IDC_FIND_NOW), &rc);
|
|
MapWindowRect(NULL, hwnd, &rc);
|
|
m_xBtn = rc.left;
|
|
m_dxBtn = rc.right - rc.left;
|
|
m_yBtn = rc.top;
|
|
|
|
GetWindowRect(GetDlgItem(hwnd, IDC_STOP), &rc);
|
|
MapWindowRect(NULL, hwnd, &rc);
|
|
m_dyBtn = rc.top - m_yBtn;
|
|
|
|
GetWindowRect(GetDlgItem(hwnd, IDC_FROM), &rc);
|
|
m_cxEdit = rc.right - rc.left;
|
|
m_cyEdit = rc.bottom - rc.top;
|
|
|
|
SetWindowPos(hwnd, NULL, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
|
|
|
|
if (sizeof(wp) == GetOption(OPT_FINDER_POS, (LPBYTE)&wp, sizeof(wp)))
|
|
{
|
|
if (wp.showCmd != SW_SHOWMAXIMIZED)
|
|
wp.showCmd = SW_SHOWNORMAL;
|
|
m_cyDlgFull = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
|
|
SetWindowPlacement(hwnd, &wp);
|
|
}
|
|
else
|
|
{
|
|
m_cyDlgFull = (3 * m_ptDragMin.y) / 2;
|
|
CenterDialog(hwnd);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::QuerySwitchIdentities()
|
|
//
|
|
// PURPOSE: Determine if it is OK for the identity manager to
|
|
// switch identities now
|
|
//
|
|
HRESULT CFindDlg::QuerySwitchIdentities()
|
|
{
|
|
if (!IsWindowEnabled(m_hwnd))
|
|
return E_PROCESS_CANCELLED_SWITCH;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::SwitchIdentities()
|
|
//
|
|
// PURPOSE: The current identity has switched. Close the window.
|
|
//
|
|
HRESULT CFindDlg::SwitchIdentities()
|
|
{
|
|
if (m_fInProgress)
|
|
{
|
|
CmdStop(ID_STOP, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
|
|
m_fClose = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DestroyWindow(m_hwnd);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CFindDlg::IdentityInformationChanged()
|
|
//
|
|
// PURPOSE: Information about the current identity has changed.
|
|
// This is ignored.
|
|
//
|
|
HRESULT CFindDlg::IdentityInformationChanged(DWORD dwType)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|