📄 outlookcontactlist.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "OutlookContactList.hpp"
#include "Common.hpp"
#include "DisplayItem.hpp"
#include "InfoApp.hpp"
#include <winuserm.h>
#include "PhoneAPI.hpp"
#include "SettingsApi.hpp"
#include "VoIPNotify.hpp"
#define INITIAL_ITEM_THRESHOLD 40
#define ADD_REST_OF_ITEMS_DELAY 900 //wait most of 1 second...
#define USER_RESPONSE_DELAY 250 //wait 1/4th of a second for the user to finish typing
/*------------------------------------------------------------------------------
FilterToLabelId
Convert a filter to a string id
------------------------------------------------------------------------------*/
inline int FilterToLabelId(
OutlookContactListDialog_t::Filter_e filter
)
{
switch (filter)
{
case OutlookContactListDialog_t::FirstName:
return IDS_LABEL_FIRSTNAME;
case OutlookContactListDialog_t::LastName:
return IDS_LABEL_LASTNAME;
case OutlookContactListDialog_t::Predictive:
return IDS_LABEL_PREDICTIVE;
default:
ASSERT(FALSE);
return 0;
}
}
/*------------------------------------------------------------------------------
MatchesFirstName
Does this contact match the first name filter?
------------------------------------------------------------------------------*/
bool MatchesFirstName(
const WCHAR* pToMatch,
int Len,
IContact* pContact
)
{
ASSERT(pToMatch && pContact);
ce::auto_bstr ContactFirstName;
pContact->get_FirstName(&ContactFirstName);
if (! ContactFirstName)
{
return false;
}
return (wcsnicmp(pToMatch, ContactFirstName, Len) == 0);
}
/*------------------------------------------------------------------------------
MatchesLastName
Does this contact match the last name filter?
------------------------------------------------------------------------------*/
bool MatchesLastName(
const WCHAR* pToMatch,
int Len,
IContact* pContact
)
{
ASSERT(pToMatch && pContact);
ce::auto_bstr ContactLastName;
pContact->get_LastName(&ContactLastName);
if (! ContactLastName)
{
return false;
}
return (wcsnicmp(pToMatch, ContactLastName, Len) == 0);
}
/*------------------------------------------------------------------------------
PredictiveMatch
Does the Check string match the predictive filter string?
------------------------------------------------------------------------------*/
bool PredictiveMatch(
const WCHAR* pFilterText,
int TextLen,
const WCHAR* pCheck
)
{
//10 digits...(0-9)
static const WCHAR* s_MatchGroups[10] =
{
L"", //nothing
L"*", //everything
L"abc", // 2
L"def", // 3
L"ghi", // 4
L"jkl", // 5
L"mno", // 6
L"pqrs",// 7
L"tuv", // 8
L"wxyz",// 9
};
if (wcslen(pCheck) < wcslen(pFilterText))
{
return false;
}
const WCHAR* pRead = pCheck;
const WCHAR* pCurrentFilter = pFilterText;
while (*pCurrentFilter)
{
int Value = (*pCurrentFilter - L'0');
//verify this is a digit...
if (Value < 0 || Value >= _countof(s_MatchGroups))
{
return false;
}
//get the possible characters
const WCHAR* pGroup = s_MatchGroups[Value];
if (! pGroup[0])
{
return false;
}
//does it match this group (or wildcard) ?
if (pGroup[0] == L'*' || wcschr(pGroup,towlower(*pRead)))
{
pRead++;
pCurrentFilter++;
continue;
}
return false;
}
return true;
}
/*------------------------------------------------------------------------------
GetHighlightIndex
Parse the "FileAs" attribute of the contact for the appropriate
highlight indices
------------------------------------------------------------------------------*/
void
GetHighlightIndex(
const WCHAR* pMatch,
int FilterLen,
IContact* pContact,
bool IsFirstName,
int* pHighlightStart,
int* pHighlightEnd
)
{
ASSERT(pMatch && pContact && pHighlightEnd && pHighlightStart);
const WCHAR* pSecondWord = NULL;
ce::auto_bstr bstrFileAs;
if (! IsFirstName)
{
goto do_default;
}
pContact->get_FileAs(&bstrFileAs);
if (! bstrFileAs)
{
goto do_default;
}
//skip over the first word...
pSecondWord = bstrFileAs;
while (*pSecondWord && *pSecondWord != L' ' && *pSecondWord != L',')
{
pSecondWord++;
}
if (! *pSecondWord)
{
goto do_default;
}
pSecondWord = wcsstr(pSecondWord, pMatch);
if (! pSecondWord)
{
goto do_default;
}
*pHighlightStart = pSecondWord - (const WCHAR*)bstrFileAs;
*pHighlightEnd = (*pHighlightStart + FilterLen - 1);
return;
do_default:
*pHighlightStart = 0;
*pHighlightEnd = FilterLen-1;
return;
}
/*------------------------------------------------------------------------------
MatchesPredictiveFilter
Does this contact match the predictive filter?
------------------------------------------------------------------------------*/
bool MatchesPredictiveFilter(
const WCHAR* pFilterText,
int TextLen,
IContact* pContact,
int* pHighlightStart,
int* pHighlightEnd
)
{
ce::auto_bstr FirstName;
pContact->get_FirstName(&FirstName);
if (PredictiveMatch(pFilterText, TextLen, FirstName))
{
GetHighlightIndex(FirstName, TextLen, pContact, true, pHighlightStart, pHighlightEnd);
return true;
}
ce::auto_bstr LastName;
pContact->get_LastName(&LastName);
if (PredictiveMatch(pFilterText, TextLen, LastName))
{
GetHighlightIndex(FirstName, TextLen, pContact, false, pHighlightStart, pHighlightEnd);
return true;
}
return false;
}
/*------------------------------------------------------------------------------
MatchesFilter
Does this contact pass the filter?
------------------------------------------------------------------------------*/
inline bool MatchesFilter(
OutlookContactListDialog_t::Filter_e filter,
const WCHAR* pFilterText,
int TextLen,
IContact* pContact,
int* pHighlightStart,
int* pHighlightEnd
)
{
if (!TextLen || ! pFilterText || ! pFilterText[0])
{
return true;
}
switch (filter)
{
case OutlookContactListDialog_t::FirstName:
return MatchesFirstName(pFilterText, TextLen, pContact);
case OutlookContactListDialog_t::LastName:
return MatchesLastName(pFilterText, TextLen, pContact);
case OutlookContactListDialog_t::Predictive:
return MatchesPredictiveFilter(pFilterText, TextLen, pContact, pHighlightStart, pHighlightEnd);
default:
ASSERT(FALSE);
return true;
}
}
/*------------------------------------------------------------------------------
OutlookContactListDialog_t::OutlookContactListDialog_t
Ctor
------------------------------------------------------------------------------*/
OutlookContactListDialog_t::OutlookContactListDialog_t()
{
m_CurrentMenuId = 0;
m_AddItemsTimer = 0;
m_UserResponseTimer = 0;
m_Filter = static_cast<Filter_e>(PHGetSetting(phsContactFilterType));
if(m_Filter >= UnknownFilter)
{
ASSERT(FALSE);
m_Filter = FirstName;
}
}
/*------------------------------------------------------------------------------
OutlookContactListDialog_t::~OutlookContactListDialog_t
Dtor
------------------------------------------------------------------------------*/
OutlookContactListDialog_t::~OutlookContactListDialog_t()
{
PHSetValue(phsContactFilterType, m_Filter);
StopTimer(UserResponseTimer);
StopTimer(AddItemsTimer);
}
/*------------------------------------------------------------------------------
OutlookContactListDialog_t::CreateDialogScreen
Create the dialog screen
------------------------------------------------------------------------------*/
HRESULT
OutlookContactListDialog_t::CreateDialogScreen(
InfoApp_t* pApp
)
{
ASSERT(pApp);
//make sure we can get the POOM instance before loading this page...
HRESULT hr = pApp->GetOutlookApp(&m_cpOutlookApp);
if (FAILED(hr))
{
return hr;
}
m_CurrentMenuId = IDMB_OUTLOOKCONTACTLIST;
return DialogScreen_t::CreateDialogScreen(
PHINFO_OUTLOOK_CONTACT_LIST_SCREEN_ID,
m_CurrentMenuId,
CommonUtilities_t::LoadString(GlobalData_t::s_ModuleInstance, IDS_TITLE_OUTLOOKCONTACTS),
L""
);
}
/*------------------------------------------------------------------------------
OutlookContactListDialog_t::HookProc
Dialog proc callback (handles windows messages)
------------------------------------------------------------------------------*/
BOOL
OutlookContactListDialog_t::HookProc(
HWND hwnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
HRESULT hr = S_OK;
switch (Message)
{
case WM_INITDIALOG:
if (FAILED(OnInitDialog()))
{
DestroyWindow(hwnd);
}
return FALSE;
case WM_TIMER:
hr = OnTimer(wParam);
break;
case WM_VKEYTOITEM:
hr = SetFocusToFirstItem();
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case EN_UPDATE:
UpdateQueryString();
hr = StartTimer(UserResponseTimer);
break;
case LBN_SELCHANGE:
OnSelectionChange();
break;
case 0:
switch (LOWORD(wParam))
{
case IDOK:
hr = DialogScreen_t::Exit();
break;
case IDC_DIAL:
hr = OnDial();
break;
case IDC_DETAILS:
hr = OnDetails();
break;
case IDC_BACKSPACE:
hr = DialogScreen_t::OnBackspace();
break;
case IDC_FILTER_FIRSTNAME:
hr = UpdateFilter(FirstName);
break;
case IDC_FILTER_LASTNAME:
hr = UpdateFilter(LastName);
break;
case IDC_FILTER_PREDICTIVE:
hr = UpdateFilter(Predictive);
break;
default:
return FALSE;
}
break;
}
break;
default:
return FALSE;
}
return SUCCEEDED(hr);
}
/*------------------------------------------------------------------------------
OutlookContactListDialog_t::OnInitDialog
Initialize the dialog
------------------------------------------------------------------------------*/
HRESULT
OutlookContactListDialog_t::OnInitDialog()
{
//add the labeled item
IVoIPDisplayItem* pItem;
HRESULT hr = PHCreateLabeledEditDisplayItem(
CommonUtilities_t::LoadString(GlobalData_t::s_ModuleInstance, FilterToLabelId(m_Filter)),
WS_BORDER | ((m_Filter == Predictive) ? ES_NUMBER : 0),
-1,
&pItem,
-1,
(m_Filter == Predictive) ? EIM_NUMBERS : EIM_SPELL
);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
hr = m_Listbox.AddItem(0, pItem);
if (FAILED(hr))
{
delete pItem;
return hr;
}
//hide the backspace button
UpdateQueryString();
return Refresh(AddBeginningOfItems);
}
HRESULT
OutlookContactListDialog_t::Refresh(
RefreshType_e type
)
{
//disable redrawing...
SendMessage(m_Listbox, WM_SETREDRAW, FALSE, 0);
int ExistingItemCount = m_Listbox.GetCount();
//keep the old items if we are adding the delayed items
if (type != AddRestOfItems)
{
//clear the listbox (except for the first item)
while (ExistingItemCount > 1)
{
SendMessage(m_Listbox, LB_DELETESTRING, 1, 0);
ExistingItemCount--;
}
}
else
{
//make sure there hasn't been a filter change since last time we
//updated...
if (ExistingItemCount != (INITIAL_ITEM_THRESHOLD + 1))
{
return S_FALSE;
}
}
//add each item...
CComPtr<IFolder> cpFolder;
CComPtr<IPOutlookItemCollection> cpItems;
ce::auto_bstr SortOrder;
int TotalItems;
int CurrentItem;
int LastItem;
HRESULT hr;
STATUS_HEADER_PARAMETERS_EX StatusParams;
WCHAR StatusText[MAX_PATH] = L"";
IVoIPDisplayItem* pEditItem = m_Listbox.GetItem(0);
if (! pEditItem)
{
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto exit;
}
//get our contacts from POOM
hr = m_cpOutlookApp->GetDefaultFolder(
olFolderContacts,
&cpFolder
);
if (FAILED(hr))
{
ASSERT(FALSE);
goto exit;
}
hr = cpFolder->get_Items(&cpItems);
if (FAILED(hr))
{
ASSERT(FALSE);
goto exit;
}
//sort the collection by the necessary sort order
SortOrder = SysAllocString(L"[FileAs]");
if (! SortOrder)
{
hr = E_OUTOFMEMORY;
goto exit;
}
hr = cpItems->Sort(SortOrder, VARIANT_FALSE);
if (FAILED(hr))
{
ASSERT(FALSE);
goto exit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -