///////////////////////////////////////////////////////////////////////////// // Copyright (C) 1993-1998 Microsoft Corporation. All Rights Reserved. // // MODULE: finder.cpp // // PURPOSE: // #include "pch.hxx" #include #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; }